-
Есть некая программа... Пишу программу в Delphi Которая может ей управлять (жать на кнопки, заполнять поля и т.д.) Определил Handle главного окна, Handle ToolBar'a (с кнопками на нем пока не разобрался, потому жму по координатам (тем более что расположение кнопок изменить невозможно и их мало ... то есть скакать с места на место у них возможности нет) Итак, жму на кнопку открыть SendMessage(hTBar,WM_LBUTTONDOWN,MK_LBUTTON,MAKELONG(30, 10)); SendMessage(hTBar,WM_LBUTTONUP,MK_LBUTTON,MAKELONG(30, 10)); Выскакивает дилоговое окно открытия файла... Вот тут вопрос, пытался хоть что-то с ним сделать, но моя программа (которую я пишу) упорно ждет закрытия диалогового окна и ничего не делает до этого момента, как обойти?
-
найти хэндл окна диалога и послать ему нажатия клавиш?
-
попробовать 'нажать' enter (VK_RETURN)
-
Это понятно, но в том и дело что исполнение программы, которая дальше должна искать Handle и посылать сообщение встало и ждет пока закроется диалог в чужой программе, и только по его закрытии идет дальше :( unit test;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, XPMan, ShellAPI, StdCtrls, TlHelp32, CommCtrl;
type
TForm1 = class(TForm)
btn1: TButton;
btn2: TButton;
btn3: TButton;
procedure btn1Click(Sender: TObject);
procedure btn2Click(Sender: TObject);
procedure btn3Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
public
end;
var
Form1: TForm1;
hForm, hTBar, hOpenEdit, hTmp, hOpenOpen, hOpenMain: HWND;
hFormRect: TRect;
CurPoint: TPoint;
xyz: PAnsiChar;
x: Cardinal;
a: Integer;
implementation
procedure TForm1.btn1Click(Sender: TObject);
begin
ShellExecute(0,nil,'STBLinkEditor_03.00_1.exe',nil,PAnsiChar(ExtractFilePath(App lication.ExeName)),SW_SHOW);
Sleep(500);
hForm:=FindWindow(0, 'Untitled - STBLink Editor 03.00');
GetWindowRect(hForm,hFormRect);
CurPoint.X:=hFormRect.Left+11;
CurPoint.Y:=hFormRect.Top+55;
hTBar:=WindowFromPoint(CurPoint);
end;
procedure TForm1.btn2Click(Sender: TObject);
begin
if hForm<>0 then
SendMessage(hForm,wm_close,0,0);
Close;
end;
procedure TForm1.btn3Click(Sender: TObject);
begin
SendMessage(hTBar,WM_LBUTTONDOWN,MK_LBUTTON,MAKELONG(30, 10));
SendMessage(hTBar,WM_LBUTTONUP,MK_LBUTTON,MAKELONG(30, 10));
hOpenEdit:=FindWindow(0, 'UserDataBase');
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if hForm<>0 then
SendMessage(hForm,wm_close,0,0);
Application.Terminate;
end;
end.
-
с помощью keybd_event
-
2 Дмитрий Белькевич: Если я пошлю "нажатие Enter", то он будет пытаться открыть дефолтовый файл, а мне надо туда свой сунуть, чего я сделать не могу ,потмоу как софтина чего-то ждет
-
не нужно искать хэндлы, просто 'нажать' программно кнопку
-
PostMessage вместо SendMessage
-
На лишние параметры в var не обращайте внимание, это так следды экспериментов :)
-
Да, PostMessage определенно помог, спасибо, по мере появления вопросов, буду задавать если не найду ответов. Спасибо за участие!
-
софтина ждет закрытия окна диалога. свой файл так просто не всунуть, думается, хотя можно попробовать с помощью tab-shift-tab и нажатий кнопок пошаманить, или хэндл диалога таки искать + хэндл эдита для файла
-
2Дмитрий Белькевич, я вас понял, спасибо. Кнопка в фокусе и она нажмется, но сперва надо найти Handle "текстового окна", чтобы туда имя файла послать или оно тоже без handle можно, если оно в фокусе стоит?
-
Подозреваю, что программа поддерживает открытие файла из параметров запуска: ShellExecute(0,nil,'STBLinkEditor_03.00_1.exe ' + MyFileName,.... Если это так, то нет необходимости управлять диалогом открытия файла.
-
Я тоже так думал, но она в этом случае выдает Error, потому и мудрю :)
-
А не проще будет разобраться с форматом .udb и править файл не этой кривой программой, а своей?
-
Не, он из 5-ти файлов состоит, резать я их научился, два не используются. Оставшиеся три базы данных. Один из них еще сжат непойми чем...... Да и базы для меня что-то темное.... проще так.
-
Правильно ли я пытаюсь поставить Hook на кнопку в тулбаре? Все описано в DLL Запуск хука: idHook:=SetWindowsHookEx(WH_GETMESSAGE, @PressButtonHook, hInstance, GetWindowThreadProcessId(hFrm,nil)) Процедура поиска: function PressButtonHook(CODE, WParam, LParam: DWORD): DWORD; stdcall;
begin
if CODE=HC_ACTION then
begin
if (TMsg(Pointer(lParam)^).wParam=32840) then
begin
ShowMessage('OK');
Result:=CallNextHookEx(idHook, CODE, WParam, LParam);
end
else
Result:=CallNextHookEx(idHook, CODE, WParam, LParam);
end
else
Result := CallNextHookEx(idHook, CODE, WParam, LParam);
end; hFrm - хэндл формы (главного окна) есть еще hTBar - хэндл тулбара, пробовал по нему хук, тоже не находит Пробовал искать if (TMsg(Pointer(lParam)^).hwnd=hTBar) в потоке hFrm... Тоже без успеха :( idButton у меня 32840 (найден Spy++... ну и собственно я его жму успешно командой PostMessage(hFrm, WM_COMMAND, 32840, 0);
-
Переправил вот так: function PressButtonHook(CODE, WParam, LParam: DWORD): DWORD; stdcall;
begin
if CODE=HC_ACTION then
begin
CallNextHookEx(idHook, CODE, WParam, LParam);
if TMsg(Pointer(lParam)^).message=WM_COMMAND then
begin
ShowMessage('OK '+IntToStr(TMsg(Pointer(lParam)^).wParam));
end
end
else
Result := CallNextHookEx(idHook, CODE, WParam, LParam);
end; Вызов SetWindowsHookEx(WH_GETMESSAGE, @PressButtonHook, hInstance, GetWindowThreadProcessId(hFrm,nil)) При этом у меня отлавливаются события, связанные с меню. И в принципе вытащенный wparam соответствует пункту меню. Но все эти сообщения PostMessage. Мне же надо выловить SendMessage, почитав выяснил, что WH_GETMESSAGE их не выдаст, поменял это значение на WH_CALLWNDPROC.... и теперь hook не ловит вообще ничего :( Что еще не так, подскажите пожалуйста?
-
-
Другой вопрос. Я отлавливаю нажатие кнопки в тулбаре, после этого появляется диалоговое окно открытия файла ну и мне надо туда зафигачить свое имя файла и нажатькнопку открыть. Ловлю хуком WH_CALLWNDPROC событие WM_COMMAND с ID этой кнопки. Теперь пока моя функция-фильтр не отработает, программа над которой я "издеваюсь" не работает дальше, так как ей сообщение придет только после рабты моей функции фильтра, соответственно она не создает окно открытия файла, в которое я помещу свои значения. Если использую WH_CALLWNDPROCRET то мой хук начинает работать после того как диалоговое окно в программе закроется... Как мне отловить момент нажатия кнопки и дальше работать "паралелльно" с той программой????
-
> 2Дмитрий Белькевич, я вас понял, спасибо. Кнопка в фокусе > и она нажмется, но сперва надо найти Handle "текстового > окна", чтобы туда имя файла послать или оно тоже без handle > можно, если оно в фокусе стоит?
Если фокус в edit'е, то можно просто keybd_event'ами в нем что-то набрать, без handl'ов, насколько я помню.
-
Программа стоит :) Сообщение к ней не доходит, пока не обработается хууком (функцией фильтром). Если использовать procret то хук стартует полсле закрытия диалогового окна и вводить уже некуда :)
-
чета какаято нездоровая тенденция пошла,писать программы для нажимания кнопок в других программах
-
Учиться то никто не запрещает :) Почему вы считаете что нажимание кнопок в чужих программах "нездорово". Вот с чего то надо начинать, вот начинаю с этого? Или другие сразу со "здоровыми" идеями рождаются? :)
-
> > чета какаято нездоровая тенденция пошла,писать программы > для нажимания кнопок в других программах
ну я, например, для автотестов пользую. благо, что софт свой же, то с ним немного проще договориться. еще как-то из сторонней либы (дллки на билдере) приходилось недостающие данные прямо из формы из TEdit забирать. в саппорт стучали, программисты отказались нужные данные передавать, то сам забрал :)
-
> Сообщение к ней не доходит, пока не обработается хууком > (функцией фильтром).
зачем хук? синхронизация?
-
Это примерно как?? не умею :)
-
Зачем тут хук? Всё проще: var
hW, hEdit, hBtn: HWND;
path: AnsiString;
idBtn: integer;
begin
hW := FindWindow(nil, 'Открыть);
if hW <> 0 then
begin
hEdit := FindWindowEx(hW, 0, 'ComboBoxEx32', '');
if hEdit <> 0 then
begin
path := 'C:\base\MyUserDataBase.udb';
SendMessage(hEdit, WM_SETTEXT, 0, integer(path));
hBtn := FindWindowEx(hW, 0, 'Button', '&Открыть');
if hBtn <> 0 then
begin
IdBtn:=GetDlgCtrlID(hBtn);
SendMessage(hW, WM_COMMAND, MakeWParam(IdBtn, BN_CLICKED), hBtn);
end;
end;
end;
end;
-
> Это примерно как?? не умею :)
В смысле - зачем тебе вообще тут хук?
Пробуй [27]...
-
Подскажите что за прикол: функция обработки EnumWindow function FindDialog(Wd: HWnd; Param: LongInt): Boolean; stdcall;
var
ClassName: array [0..254] of Char;
begin
FindDialog:=True;
GetClassName(Wd, ClassName, SizeOf(ClassName));
if ClassName='#32770' then
if GetWindowThreadProcessId(Wd,nil) = idFrm then
begin
FindDialog:=False;
showmessage('íàøåë');
end;
end; функция вызова EnumWindows(@FindDialog,0); Прикол в том, что через некоторое время (около секунды) переменная hDialog становится равной нулю. hDialog в глобальных переменных. Больше её никто не использует и не меняет
-
блин, hDialog:=Wd; конечно же не закомментирована, просто скопировал так :)
-
ммм.... действительно я туплю, нашел ошибку в другом месте. Вопрос снят :)
|