Конференция "WinAPI" » Подскажите по WinApi
 
  • romsn111 © (05.01.12 13:03) [0]
    Есть некая программа...
    Пишу программу в Delphi Которая может ей управлять (жать на кнопки, заполнять поля и т.д.)
    Определил Handle главного окна, Handle ToolBar'a (с кнопками на нем пока не разобрался, потому жму по координатам (тем более что расположение кнопок изменить невозможно и их мало ... то есть скакать с места на место у них возможности нет)
    Итак, жму на кнопку открыть
    SendMessage(hTBar,WM_LBUTTONDOWN,MK_LBUTTON,MAKELONG(30, 10));
     SendMessage(hTBar,WM_LBUTTONUP,MK_LBUTTON,MAKELONG(30, 10));
    Выскакивает дилоговое окно открытия файла...
    Вот тут вопрос, пытался хоть что-то с ним сделать, но моя программа (которую я пишу) упорно ждет закрытия диалогового окна и ничего не делает до этого момента, как обойти?
  • megavoid © (05.01.12 13:56) [1]
    найти хэндл окна диалога и послать ему нажатия клавиш?
  • Дмитрий Белькевич (05.01.12 14:26) [2]
    попробовать 'нажать' enter (VK_RETURN)
  • romsn111 © (05.01.12 14:27) [3]
    Это понятно, но в том и дело что исполнение программы, которая дальше должна искать 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
       { Private declarations }
     public
       { Public declarations }
     end;

    var
     Form1: TForm1;
     hForm, hTBar, hOpenEdit, hTmp, hOpenOpen, hOpenMain: HWND;
     hFormRect: TRect;
     CurPoint: TPoint;
     xyz: PAnsiChar;
     x: Cardinal;
     a: Integer;

    implementation

    {$R *.dfm}

    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.

  • Дмитрий Белькевич (05.01.12 14:28) [4]
    с помощью keybd_event
  • romsn111 © (05.01.12 14:29) [5]
    2 Дмитрий Белькевич:
    Если я пошлю "нажатие Enter", то он будет пытаться открыть дефолтовый файл, а мне надо туда свой сунуть, чего я сделать не могу ,потмоу как софтина чего-то ждет
  • Дмитрий Белькевич (05.01.12 14:30) [6]
    не нужно искать хэндлы, просто 'нажать' программно кнопку
  • Омлет © (05.01.12 14:30) [7]
    PostMessage вместо SendMessage
  • romsn111 © (05.01.12 14:30) [8]
    На лишние параметры в var не обращайте внимание, это так следды экспериментов :)
  • romsn111 © (05.01.12 14:32) [9]
    Да, PostMessage определенно помог, спасибо, по мере появления вопросов, буду задавать если не найду ответов.
    Спасибо за участие!
  • Дмитрий Белькевич (05.01.12 14:32) [10]
    софтина ждет закрытия окна диалога. свой файл так просто не всунуть, думается, хотя можно попробовать с помощью tab-shift-tab и нажатий кнопок пошаманить, или хэндл диалога таки искать + хэндл эдита для файла
  • romsn111 © (05.01.12 14:33) [11]
    2Дмитрий Белькевич, я вас понял, спасибо. Кнопка в фокусе и она нажмется, но сперва надо найти Handle "текстового окна", чтобы туда имя файла послать или оно тоже без handle можно, если оно в фокусе стоит?
  • Омлет © (05.01.12 14:43) [12]
    Подозреваю, что программа поддерживает открытие файла из параметров запуска:
    ShellExecute(0,nil,'STBLinkEditor_03.00_1.exe ' + MyFileName,....


    Если это так, то нет необходимости управлять диалогом открытия файла.
  • romsn111 © (05.01.12 15:01) [13]
    Я тоже так думал, но она в этом случае выдает Error,
    потому и мудрю :)
  • Омлет © (05.01.12 15:04) [14]
    А не проще будет разобраться с форматом .udb и править файл не этой кривой программой, а своей?
  • romsn111 © (05.01.12 15:06) [15]
    Не, он из 5-ти файлов состоит, резать я их научился, два не используются.
    Оставшиеся три базы данных.
    Один из них еще сжат непойми чем...... Да и базы для меня что-то темное.... проще так.
  • romsn111 © (06.01.12 21:04) [16]
    Правильно ли я пытаюсь поставить 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);
  • romsn111 © (07.01.12 14:31) [17]
    Переправил вот так:
    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 не ловит вообще ничего :( Что еще не так, подскажите пожалуйста?
  • romsn111 © (07.01.12 15:21) [18]
    Пока ждал нашел вон там http://www.delphimaster.net/view/4-84846
    Вместо TMsg использовать CWPSTRUCT
  • romsn111 © (07.01.12 17:40) [19]
    Другой вопрос. Я отлавливаю нажатие кнопки в тулбаре, после этого появляется диалоговое окно открытия файла ну и мне надо туда зафигачить свое имя файла и нажатькнопку открыть.
    Ловлю хуком WH_CALLWNDPROC событие WM_COMMAND с ID этой кнопки. Теперь пока моя функция-фильтр не отработает, программа над которой я "издеваюсь" не работает дальше, так как ей сообщение придет только после рабты моей функции фильтра, соответственно она не создает окно открытия файла, в которое я помещу свои значения.
    Если использую WH_CALLWNDPROCRET то мой хук начинает работать после того как диалоговое окно в программе закроется...
    Как мне отловить момент нажатия кнопки и дальше работать "паралелльно" с той программой????
  • Дмитрий Белькевич (07.01.12 19:01) [20]

    > 2Дмитрий Белькевич, я вас понял, спасибо. Кнопка в фокусе
    > и она нажмется, но сперва надо найти Handle "текстового
    > окна", чтобы туда имя файла послать или оно тоже без handle
    > можно, если оно в фокусе стоит?


    Если фокус в edit'е, то можно просто keybd_event'ами в нем что-то набрать, без handl'ов, насколько я помню.
  • romsn111 © (08.01.12 18:12) [21]
    Программа стоит :) Сообщение к ней не доходит, пока не обработается хууком (функцией фильтром). Если использовать procret то хук стартует полсле закрытия диалогового окна и вводить уже некуда :)
  • QAZ (08.01.12 22:14) [22]
    чета какаято нездоровая тенденция пошла,писать программы для нажимания кнопок в других программах
  • romsn111 © (08.01.12 22:36) [23]
    Учиться то никто не запрещает :) Почему вы считаете что нажимание кнопок в чужих программах "нездорово". Вот с чего то надо начинать, вот начинаю с этого? Или другие сразу со "здоровыми" идеями рождаются? :)
  • Дмитрий Белькевич (08.01.12 23:47) [24]

    >
    > чета какаято нездоровая тенденция пошла,писать программы
    > для нажимания кнопок в других программах


    ну я, например, для автотестов пользую. благо, что софт свой же, то с ним немного проще договориться.
    еще как-то из сторонней либы (дллки на билдере) приходилось недостающие данные прямо из формы из TEdit забирать. в саппорт стучали, программисты отказались нужные данные передавать, то сам забрал :)
  • Дмитрий Белькевич (08.01.12 23:50) [25]

    > Сообщение к ней не доходит, пока не обработается хууком
    > (функцией фильтром).


    зачем хук? синхронизация?
  • romsn111 © (09.01.12 12:13) [26]
    Это примерно как?? не умею :)
  • Омлет © (09.01.12 14:25) [27]
    Зачем тут хук? Всё проще:

    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;

  • Дмитрий Белькевич (09.01.12 17:36) [28]

    > Это примерно как?? не умею :)


    В смысле - зачем тебе вообще тут хук?

    Пробуй [27]...
  • romsn111 © (15.01.12 17:11) [29]
    Подскажите что за прикол:
    функция обработки 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
           //hDialog:=Wd;
           FindDialog:=False;
           showmessage('íàøåë');
         end;
    end;


    функция вызова
    EnumWindows(@FindDialog,0);



    Прикол в том, что через некоторое время (около секунды) переменная hDialog становится равной нулю. hDialog в глобальных переменных. Больше её никто не использует и не меняет
  • romsn111 © (15.01.12 17:12) [30]
    блин, hDialog:=Wd; конечно же не закомментирована, просто скопировал так :)
  • romsn111 © (15.01.12 17:15) [31]
    ммм.... действительно я туплю, нашел ошибку в другом месте.
    Вопрос снят :)
 
Конференция "WinAPI" » Подскажите по WinApi
Есть новые Нет новых   [134430   +4][b:0][p:0.007]