Конференция "WinAPI" » окно рядом с другим приложением [D7]
 
  • SKIPtr © (05.01.13 05:56) [0]
    драсте
    не могу получить чтоб мое окно распологалось рядом с другим окном

    моя программа запустила хук WH_CBT
    хук сформировав строку где есть код комады и хендл окна получившего сообщения
    передаю эту строку своей програме через
    SendMessage(...WM_COPYDATA,
    на принемающей программе
    расшифровав и когда код HCBT_MOVESIZE я выполняю чтение кординат через GetWindowRect и установку кординат у своего окна чтоб было рядом с тем окном

    то появилась проблема
    моя пробрамма устанавливает кординаты относительно кординат  которые были до перемещени

    как мне сделать чтоб программа ставила относительно новых кординат
  • Dimka Maslov © (06.01.13 11:19) [1]
    Событие WM_WINDOWPOSCHANGING возникает тогда, когда окно только собирается сменить положение, когда у него ещё старые координаты. А вот WM_WINDOWPOSCHANGED - когда координаты уже сменились.

    Следовательно, можно попытаться сделать хук WH_GETMESSAGE и перехватывать WM_WINDOWPOSCHANGED для нужного окна.
  • Dimka Maslov © (06.01.13 11:21) [2]
    А в MSDNe про HCBT_MOVESIZE сказано, что "A window is about to be moved or sized". Другими словами, это как раз реакция на WM_WINDOWPOSCHANGING, когда координаты ещё старые.
  • SKIPtr © (06.01.13 19:51) [3]
    ой как плохо
    в  WH_CBT просто  есть команда HCBT_MOVESIZE ее и отлавливать
    а в WH_GETMESSAGE прийдет только HC_ACTION

    это что получаеться если прийдет HCBT_MOVESIZE нужно будет дождаться HC_ACTION и тогда выполнять чтение кординат
  • Styx (06.01.13 20:11) [4]

    > прийдет только HC_ACTION

    Главное, что прийдёт само сообщение WM_WINDOWPOSCHANGED - его и ловите/обрабатывайте.
    А HCBT_MOVESIZE вообще не нужен.
  • DVM © (06.01.13 20:27) [5]
    Я думаю одним WM_WINDOWPOSCHANGED не обойтись. Вероятно еще видимость окна надо отслеживать и скрывать свою прилипалу вместе с родительским окном. Возможно еще какие сообщения надо.
  • SKIPtr © (06.01.13 21:50) [6]

    > Возможно еще какие сообщения надо.

    так вот у меня было  HCBT_MOVESIZE
    после получания этого сообщения получаю кординаты окна и выставляю кординаты у себя


    > Главное, что прийдёт само сообщение WM_WINDOWPOSCHANGED

    но это сообщение не несет что сделали с окном
    нужно следить что окно создано разрушено свернуто или перемещено
  • Styx (06.01.13 22:12) [7]

    > но это сообщение не несет что сделали с окном

    Как это не несёт?
    http://msdn.microsoft.com/ru-ru/library/windows/desktop/ms632652(v=vs.85).aspx
  • DVM © (07.01.13 00:41) [8]

    > SKIPtr ©   (06.01.13 21:50) [6]


    > нужно следить что окно создано разрушено свернуто или перемещено

    касательно перемещения и изменения z-order WM_WINDOWPOSCHANGED как раз подходит, хотя имхо правильнее WM_MOVE, а для размера WM_SIZE, но это не принципиально. А для разрушения, сворачивания и пр есть другие сообщения, как я уже сказал.
  • Styx (07.01.13 00:53) [9]
    2DVM
    А чем для размера WM_WINDOWPOSCHANGED плох?
  • DVM © (07.01.13 11:24) [10]

    > Styx   (07.01.13 00:53) [9]


    > А чем для размера WM_WINDOWPOSCHANGED плох?

    Почему плох? Совсем не плох.
  • Styx (07.01.13 14:08) [11]
    А, значит, я неправильно запятые понял :)
  • SKIPtr © (10.01.13 21:14) [12]
    прошу прощения но что то у меня не получаеться
    я в хуке написал

    Function hokm(Code:Integer; WParam:LongInt; LParam:LongInt):LongInt; stdcall;
       begin
         wnd := TPMsg(lParam)^.hwnd;
         b := TPMsg(lParam)^.message;
         l := '';
         case b of  
           WM_WindowPosChanging : l := 'Changing';
           WM_WindowPosChanged  : l := 'Changed';
           WM_SIZE : l := 'SIZE';
           WM_MOVE : l := 'MOVE';
           WM_CHAR : l := 'char';
           WM_SYSCOMMAND : l := 'COMMAND';
           {else l := '' }
         end;
         s :=  IntToStr(wnd);
         s :=  s + ' ' + l;  
         cd.cbData := Length(s);
         cd.lpData := PChar(s);
         SendMessage (hd, WM_COPYDATA, 0, LongInt(@cd));
         result:= CallNextHookEx(km, Code, WParam, LParam);



    wnd передаеться нормально
    а вот тип сообщения не передаеться
    что я сделал не так
  • DVM © (10.01.13 23:30) [13]

    > SKIPtr ©   (10.01.13 21:14) [12]

    во-первых исправь (обрати внимание на типы параметров), сейчвс это ошибки не вызывает но вызовет потом.

    Function hokm(Code:Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;

    во-вторых, ты тип сообщения нигде и не передаешь

    в-третьих, что такое TPMsg? Есть же

    PMsg = ^TMsg;
     tagMSG = record
       hwnd: HWND;
       message: UINT;
       wParam: WPARAM;
       lParam: LPARAM;
       time: DWORD;
       pt: TPoint;
     end;
     {$EXTERNALSYM tagMSG}
     TMsg = tagMSG;
     MSG = tagMSG;



    в Windows.pas

    В-четвертых, зачем все эти выкрутасы со строкой в WM_COPYDATA?
  • SKIPtr © (11.01.13 18:10) [14]

    > во-первых исправь (обрати внимание на типы параметров),
    > сейчвс это ошибки не вызывает но вызовет потом.Function
    > hokm(Code:Integer; WParam: WPARAM; LParam: LPARAM): LRESULT;
    >  stdcall;

    этот вариант я делал не пошло
    потом заметил что имя переменой совпадает с именем типа
    подумал это ошибка и исправил


    > во-вторых, ты тип сообщения нигде и не передаешь

    вот как передаю
       
    b := TPMsg(lParam)^.message;
        case b of  
           WM_WindowPosChanging : l := 'Changing';
           WM_WindowPosChanged  : l := 'Changed';
           WM_SIZE : l := 'SIZE';
           WM_MOVE : l := 'MOVE';
           WM_CHAR : l := 'char';
           WM_SYSCOMMAND : l := 'COMMAND';
           {else l := '' }
         end;
         s :=  s + ' ' + l;


    а дальше строку через сообщение WM_COPYDATA


    > что такое TPMsg

    среди примеров нашел
    а до этого обьявил TPMsg = ^TMsg


    > зачем все эти выкрутасы со строкой в WM_COPYDATA?

    передаю даные полученые хуком моей програме через текстовую строку

    но самое главное из поле message
    не получаеться получить переменые
    WM_WindowPosChanging ; WM_WindowPosChanged ;
    WM_SIZE ; WM_MOVE ; WM_CHAR ; WM_SYSCOMMAND ;
    а ведь это мне нужно получить
  • DVM © (11.01.13 22:03) [15]

    > SKIPtr ©   (11.01.13 18:10) [14]


    >
    > этот вариант я делал не пошло
    > потом заметил что имя переменой совпадает с именем типа
    > подумал это ошибка и исправил
    >

    что значит не пошло? То, что имя параметра совпадает с именем типа - ничего страшного, если совпадение смущает можно параметр переименовать, но типы надо именно такие иначе под 64 бит будут проблемы.


    > вот как передаю

    способ конечно оригинальный, но зачем это все? И это и дальше все выкрутасы со строками? Можно прекрасно обойтись без строк, просто передавая структуру с WM_COPYDATA со всеми необходимыми полями. Вот прямо PMsg и передавал бы.

    Ты не показал весь код ловушки, поэтому сложно судить где у тебя ошибка, судя по всему в hokm() у тебя управление передается? Посмотри отладчиком, что содержится в PMsg(lParam)^.message, есть ли там корректные коды сообщений.

    Еще замечание такое:
    SendMessage (hd, WM_COPYDATA, 0, LongInt(@cd));
    LongInt на LPARAM замени
  • SKIPtr © (12.01.13 02:25) [16]

    > Ты не показал весь код ловушки, поэтому сложно судить где
    > у тебя ошибка,

    вот как текст с моими черновыми вариантами

    uses
     SysUtils, Windows, Classes, Messages;

    {$R *.res}

    type
     TPMsg = ^TMsg;

    var
    { h,} kc, km : thandle;
     hd : hwnd;

    function hokc(Code: integer; WParam: WPARAM; LParam: LPARAM):LRESULT stdcall;
    var
     {capt:array[0..255] of char;}
     s : string;
     cd : TCopyDataStruct;
     Wnd: hwnd;

    begin
     result:= CallNextHookEx(kc, Code, WParam, LParam);
     if (code >= 0) and (Code <> 6) then
       begin
         s := 'CBT ' + IntToStr(Code);
         s :=  s + ' ' + IntToStr(WParam)  + ' a';
         cd.cbData := Length(s);
         cd.lpData := PChar(s);
         SendMessage ( hd, WM_COPYDATA, 0, LongInt(@cd));
       end
    end;

    Function hokm(Code:Integer; WParam:LongInt; LParam:LongInt):LongInt; stdcall;
    {function hokm(Code: integer; WParam: WPARAM; LParam: LPARAM):DWORD stdcall;}
    var
     s, l : string;
     cd : TCopyDataStruct;
     Wnd: hwnd;
     b : integer;
     msg:^TMessage;
     m:cardinal;
    begin
      {if code =  HCBT_ACTIVATE then }
       begin
         s := 'MSG ' + IntToStr(Code);
         wnd := TPMsg(lParam)^.hwnd;
         b := TPMsg(lParam)^.message;
         l := '';
         case b of  // получаем   команду
          WM_WindowPosChanging : l := 'Changing';
           WM_WindowPosChanged  : l := 'Changed';
           WM_SIZE : l := 'SIZE';
           WM_MOVE : l := 'MOVE';
           WM_CHAR : l := 'char';
           WM_SYSCOMMAND : l := 'COMMAND';
           {else l := '' }
         end;
         s :=  s + ' ' + IntToStr(wnd);
         s :=  s + ' ' + l + ' '  + IntToStr(b)  +  ' a';  
         cd.cbData := Length(s);
         cd.lpData := PChar(s);
         SendMessage (hd, WM_COPYDATA, 0, LongInt(@cd));
         result:= CallNextHookEx(km, Code, WParam, LParam);
       end  
    end;

    procedure StarH;
    begin

    {kc := SetWindowsHookEx(WH_CBT, @hokc, hInstance, 0); {включаем ловушку}
    km := SetWindowsHookEx(WH_GETMESSAGE, @hokm, hInstance, 0); {включаем ловушку}

    end;

    procedure StpH;
    begin

    {UnhookWindowsHookEx(kc); }
    UnhookWindowsHookEx(km);

    end;

    exports StarH index 1;
    exports StpH index 2;

    begin
      hd := FindWindow('Tmesag', nil)

    end.




    > Посмотри отладчиком, что содержится в PMsg(lParam)^.message,

    я ставил раньше ставил останов программы
    но возникала какая то ошибка во время выполнения
    поэтому я воставил преобразование переменной b в строку
    значение переменой разные
    когда hokm работала вместе с hokc дистребьюторы двух сообщений рядом совпадают
  • DVM © (12.01.13 11:46) [17]

    > SKIPtr ©   (12.01.13 02:25) [16]

    вот сюда посмотри http://www.delphimaster.ru/articles/hooks/ там как раз в примере 2 есть передача параметров из dll с ловушкой в основное приложение
  • SKIPtr © (12.01.13 16:24) [18]

    > в примере 2 есть передача параметров из dll с ловушкой в
    > основное приложение

    передавать параметры с хука програме мне больше нравиться через сообщения а не через файл
    меня интересует почему у меня хук не ловит сообщения WM_WINDOWPOSCHANGED и WM_MOVE
    они мне нужны
  • Styx (12.01.13 17:22) [19]
    Попробуйте WH_CALLWNDPROC
  • SKIPtr © (12.01.13 18:49) [20]

    > Styx   (12.01.13 17:22) [19]

    вот в интернете нашел
    WH_GETMESSAGE возникает когда сообщение в очереди
    а действие мышы похоже в очередь не ставиться
    и пишут что поможет WH_CALLWNDPROC но он не может поменять сообщения
    но мне этого и не надо
    спасибо пойду пробывать
  • Игорь Шевченко © (12.01.13 19:42) [21]

    > а действие мышы похоже в очередь не ставиться


    Ставится. Действия мыши и клавиатуры кроме как в очередь поставлены быть не могут
  • DVM © (12.01.13 20:06) [22]

    > SKIPtr ©   (12.01.13 16:24) [18]


    > передавать параметры с хука програме мне больше нравиться
    > через сообщения а не через файл

    ты своим кодом кстати удваиваешь количество сообщений в системе в 2 раза. Отделял бы нужные тебе окна от остальных, а то на каждое сообщение любого окна генерируется еще одно твоему окну, а потом все лавинообразно растет.
  • SKIPtr © (12.01.13 20:34) [23]

    > ты своим кодом кстати удваиваешь количество сообщений в
    > системе в 2 раза.

    по логике так и должно быть
    но я смотрю на отщет о том что передано
    я не вижу дестрибьютор окна в котором выводятся сообщения
    получаеться окно само себе не передает
  • DVM © (12.01.13 21:02) [24]

    > SKIPtr ©

    я кстати посмотрел WM_WINDOWPOSCHANGED, WM_DESTROY, WM_SIZE, WM_CLOSE, WM_MOVE с помощью WH_GETMESSAGE не перехватываются, но перехватываются с помощью WH_CALLWNDPROC
  • DVM © (12.01.13 21:10) [25]

    > SKIPtr ©   (12.01.13 20:34) [23]


    > получаеться окно само себе не передает

    если бы тебе сообщения не посылались, то ты бы вообще ничего не получал из функции hokm(), сообщений в 2 раза больше и становится в общем и всё еще замедляется так как фактически синхронизируется с твоим окном функцией SendMessage(), которая блокирует поток в котором выполняется hokm()
  • SKIPtr © (13.01.13 09:36) [26]
    это пока программа для просмотра
    конечная программа будет проверять дистребьютор сообщения на соответствие окна по его названию
    это даст возможность что ответ будет посылать только та программа для которой писалась ловушка
  • SKIPtr © (14.01.13 04:45) [27]

    > сообщений в 2 раза больше и становится в общем и всё еще
    > замедляется так как фактически синхронизируется с твоим
    > окном функцией SendMessage()

    вот с хуком WH_CALLWNDPROC окажываеться возникает эта проблема
    в хуке сделал проверку на соответствие дистребьютора в сообщении с дистребьютором окна моей програмы и если они разные то отсылаю сообщение
    но обнаружил в коде

         
    wnd := PMsg(lParam)^.hwnd;
         b := PMsg(lParam)^.message;



    дистребьютор и сообщение поменялись местами


    > WM_WINDOWPOSCHANGED, WM_DESTROY, WM_SIZE, WM_CLOSE, WM_MOVE
    > с помощью WH_GETMESSAGE не перехватываются, но перехватываются
    > с помощью WH_CALLWNDPROC

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