Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

«Решение проблемы с методом FindWindow в Delphi на Windows Vista»

Delphi , ОС и Железо , Справочник по сообщениям

Решение проблемы с методом FindWindow в Delphi на Windows Vista

Если вы пытаетесь отправить сообщение Windows в ваше приложение Delphi, но испытываете трудности с методом FindWindow, получая ошибку с кодом 0 от GetLastError, это может быть связано с тем, что ваше окно не найдено. В этом руководстве мы рассмотрим возможные причины этой проблемы и предложим решения, которые помогут вам эффективно устранить неполадки.

Описание проблемы

Вопрос: Я пытаюсь отправить сообщение Windows в мое приложение Delphi, но испытываю проблемы с методом FindWindow. Получаю ошибку с кодом 0 от GetLastError. Я работаю под Windows Vista, и, по моим знаниям, эта ошибкаcommon в XP или более ранних версиях, но должна работать нормально в Vista или Win 7 (может, я неправильно понял?).

Вот код, который я использую, и он находится в файле DLL Delphi, написанном на Delphi 5:

procedure SendData(const copyDataStruct: TCopyDataStruct);
var
  receiverHandle: THandle;
  res: integer;
begin
  receiverHandle := FindWindow(PChar('TMainForm'), PChar('MainForm'));
  if receiverHandle = 0 then
  begin
    ShowMessage(format('Error %x finding MainForm', [GetLastError()]));
    Exit;
  end;

  res := SendMessage(receiverHandle, WM_COPYDATA, Integer(receiverHandle), Integer(@copyDataStruct));
end;

Подтвержденный ответ

Согласно списку системных кодов ошибок, код ошибки 0 означает ERROR_SUCCESS. Это может указывать на то, что ваше окно имеет класс TMainForm, но пустое Caption.

Обратите внимание на комментарии к методу GetWindowText, который используется внутри FindWindow, когда параметр lpWindowName не равен нулю (что в данном случае верно, так как вы передаете "MainForm" в качестве второго параметра). Это может привести к неверным результатам, если Caption вашего окна пуст.

Альтернативный ответ

Если у вас все еще возникают проблемы, рассмотрите альтернативный подход: отправьте пользовательское сообщение всем окнам, и только ваше окно будет знать, как на него ответить. Оно может ответить со своим текущим HWND в другом сообщении, чтобы брокер не имел необходимости искать его вручную. Используйте RegisterWindowMessage() для регистрации уникальных идентификаторов сообщений, которые другие приложения проигнорируют. Например:

Приложение 1:

var
  WM_WHERE_ARE_YOU: UINT = 0;
  WM_HERE_I_AM: UINT = 0;
  App2Wnd: HWND = 0;

procedure TApp1Form.FromCreate(Sender: TObject);
begin
  // Используйте любые строковые имена, которые вам нравятся, главное, чтобы они совпадали с Приложением 2...
  WM_WHERE_ARE_YOU := RegisterWindowMessage("WhereAreYou");
  WM_HERE_I_AM := RegisterWindowMessage("HereIAm");
end;

procedure TApp1Form.WndProc(var Message: TMessage);
begin
  if (Message.Msg = WM_HERE_I_AM) and (WM_HERE_I_AM <> 0) then
    App2Wnd := HWND(Message.LParam)
  else
    inherited;
end;

procedure TApp1Form.SendData(const copyDataStruct: TCopyDataStruct);
var
  res: integer;
  Ignore: DWORD;
begin
  App2Wnd := 0;
  if WM_WHERE_ARE_YOU = 0 then Exit;
  SendMessageTimeout(HWND_BROADCAST, WM_WHERE_ARE_YOU, 0, Longint(Self.Handle), SMTO_NORMAL, 500, Ignore);
  if App2Wnd = 0 then Application.ProcessMessages;
  if App2Wnd = 0 then
  begin
    ShowMessage(Format('Не удается найти MainForm'));
    Exit;
  end;
  res := SendMessage(App2Wnd, WM_COPYDATA, Longint(Self.Handle), Longint(@copyDataStruct));
  ...
end;

Приложение 2:

var
  WM_WHERE_ARE_YOU: UINT = 0;
  WM_HERE_I_AM: UINT = 0;

procedure TApp2Form.FromCreate(Sender: TObject);
begin
  // Используйте любые строковые имена, которые вам нравятся, главное, чтобы они совпадали с Приложением 1...
  WM_WHERE_ARE_YOU := RegisterWindowMessage("WhereAreYou");
  WM_HERE_I_AM := RegisterWindowMessage("HereIAm");
end;

procedure TApp2Form.WndProc(var Message: TMessage);
begin
  case Message.Msg of
    WM_COPYDATA:
    begin
      if PCopyDataStruct(Message.LParam)^.dwData = ... then
      begin
        ...
        Message.Result := 1;
        Exit;
      end;
    end;
    ...
  else
    if (Message.Msg = WM_WHERE_ARE_YOU) and (WM_WHERE_ARE_YOU <> 0) then
    begin
      if WM_HERE_I_AM <> 0 then
        PostMessage(HWND(Message.LParam), WM_HERE_I_AM, 0, Longint(Self.Handle));
      Exit;
    end;
  end;

  inherited;
end;

Этот подход обеспечивает более надежный и гибкий способ обмена данными между приложениями, не полагаясь на чувствительные к UI изменениям механизмы, такие как FindWindow.

Создано по материалам из источника по ссылке.

Решение проблемы с методом FindWindow в Delphi на Windows Vista.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Справочник по сообщениям ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-16 00:59:21/0.0049951076507568/1