Конференция "WinAPI" » Как получить дескриптор последнего активного окна ? [D7, WinXP]
 
  • delphi_is_cool (30.01.08 20:34) [0]
    Сабж ... т.е мне нужно узнать с какого окна пользователь переключился на окно моего приложения.
  • ketmar © (30.01.08 21:44) [1]
    поставить system-wide хук и внимательно наблюдать.
  • han_malign © (31.01.08 09:57) [2]
    The GetNextWindow function retrieves a handle to the next or previous window in the Z-Order.
  • ketmar © (31.01.08 10:03) [3]
    >[2] han_malign©(31.01.08 09:57)
    только это не обязательно именно то окно, «с которого переключились». а вдруг «то окно» вовсе спрятали, результатом чего и стало переключение, например?
  • han_malign © (31.01.08 10:10) [4]
    оно еще и топовым может быть...
    все зависит от конкретной задачи.
  • ketmar © (31.01.08 10:15) [5]
    >[4] han_malign©(31.01.08 10:10)
    ну да. потому я и сказал сразу универсальный способ. и жду, когда автор изволит пояснить конкретно, чего ему надо-то. %-)
  • delphi_is_cool (31.01.08 10:58) [6]

    > ну да. потому я и сказал сразу универсальный способ. и жду,
    >  когда автор изволит пояснить конкретно, чего ему надо-то.
    >  %-)

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

    > ketmar ©   (30.01.08 21:44) [1]
    >
    > поставить system-wide хук и внимательно наблюдать.
    >

    Ставлю(WH_CBT), наблюдаю ... но что-то не получаеццо, мб не в ту сторону копаю. Выкладываю код:

    const
     CBTHookLib = 'CBTHookLib.dll';

    implementation

    {$R *.dfm}

    procedure TForm1.FormCreate(Sender: TObject);
    begin
     hLib := LoadLibrary(CBTHookLib);
     if hLib = 0 then
       ShowMessage(SysErrorMessage(GetLastError));
    end;

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
     if hLib <> 0 then
       FreeLibrary(hLib);
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
     if hHook <> 0 then
       Exit;

     hHook := SetWindowsHookEx(WH_CBT, GetProcAddress(hLib, 'CBTProc'), hLib, 0);

     if hHook = 0 then
       ShowMessage(SysErrorMessage(GetLastError));
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    begin
     if hHook = 0 then
       Exit;

     if not UnhookWindowsHookEx(hHook) then
       ShowMessage(SysErrorMessage(GetLastError));

     hHook := 0;
    end;


    Код длл:

    const
     LogFileName = 'txt.txt';

    var
     hHook: Windows.HHOOK;

    function CBTProc(nCode: LongInt; wParam: WPARAM; lParam: LPARAM) : LRESULT; stdcall;
    var
     F: TextFile;
     Buffer1, Buffer2: array [0..2047] of Char;
    begin
     if nCode = HCBT_ACTIVATE then
     begin
       ZeroMemory(@Buffer1, SizeOf(Buffer1));
       ZeroMemory(@Buffer2, SizeOf(Buffer2));
       
    // PCBTActivateStruct(lParam)^.hWndActive - наскольно я понимаю тут и должен находится handle активного окна,
       // но имя класса не определяется, - почему ? :)
    GetClassName(PCBTActivateStruct(lParam)^.hWndActive, Buffer1, SizeOf(Buffer1));
       // Здесь handle окна которое будет назначено активным
    GetClassName(HWND(wParam), Buffer2, SizeOf(Buffer2));

       AssignFile(F, LogFileName);
       if not FileExists(LogFileName) then
         Rewrite(F) else Append(F);

       WriteLn(F, String(Buffer1) + ' -> ' + String(Buffer2));
       CloseFile(F);
     end;

     Result := CallNextHookEx(hHook, nCode, wParam, lParam);
    end;

  • clickmaker © (31.01.08 11:19) [7]
    WM_ACTIVATEAPP

    lParam
    Specifies a thread identifier (a DWORD). If the wParam parameter is TRUE, lParam is the identifier of the thread that owns the window being deactivated. If wParam is FALSE, lParam is the identifier of the thread that owns the window being activated.

    WM_SETFOCUS

    wParam
    Handle to the window that has lost the keyboard focus.

    не подойдет?
  • clickmaker © (31.01.08 11:27) [8]
    как вариант, еще WM_ACTIVATE - lParam
  • ketmar © (31.01.08 11:38) [9]
    >Возможно ли сделать это без использования хуков ?
    возможно. но очень напряжно и чревато ошибками.

    >мб не в ту сторону копаю
    может быть. про memory mapping, то, что hHook должна быть одной для всех процессов и ты пы, думаю, пояснять не надо?

    также неплохо бы логить значения hWnd, посмотреть, что дают таки. ну, и LastError до кучи.
  • ketmar © (31.01.08 11:38) [10]
    вдогон: были у меня какие-то проблемы с CBT, но вот от кривых ли рук или от того, что оно «странно работает» — не помню.
  • delphi_is_cool (31.01.08 14:27) [11]
    Похоже CBT хук действительно странно работает - PCBTActivateStruct(lParam)^.hWndActive всегда равен 0, за исключением тех ситуаций, когда переключение между окнами происходит внутри приложения установившего хук(к примеру если вызвать MessageBox или тот же ShowMessage), мб так и должно быть ...

    Вариант с WM_ACTIVATEAPP посредством замены оконной ф-ции Application, я уже пробовал, работает только в тех случаях, когда переключение произошло "не специально", см. [3]
  • Игорь Шевченко © (31.01.08 17:12) [12]
    Запустить WinSight и посмотреть, какие сообщения приходят потоку приложения, не судьба ?
 
Конференция "WinAPI" » Как получить дескриптор последнего активного окна ? [D7, WinXP]
Есть новые Нет новых   [134431   +14][b:0][p:0.002]