Решение проблемы с методом 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
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.