Autor Beitrag
zakoon
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 60



BeitragVerfasst: Mi 28.01.09 02:20 
Hallo zusammen,

ich würde gerne herausfinden, ob irgendein Fenster eines bestimmten Prozesses in der Taskleiste "blinkt". Es gibt einige Programm, die das machen um Aufmerksamkeit zu erregen, z.B. Messenger. In der Windows Taskleiste wird der Eintrag des Fensters dann 3 mal kurz "ge-highlighted" :)
Wie ich die Handles der Unterfenster meines Prozesses bekomme weiß ich schon. Aber nicht wie ich dieses "Blink"-Event registrieren kann.

Über sachdienliche Hinweise freut sich:
Zacharias.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 28.01.09 05:45 
Da fällt mir nur ein die entsprechende Funktionen FlashWindow und FlashWindowEx zu hooken. Ich glaube nicht, dass es eine einfachere Lösung gibt.
zakoon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 60



BeitragVerfasst: Mi 28.01.09 11:34 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Da fällt mir nur ein die entsprechende Funktionen FlashWindow und FlashWindowEx zu hooken. Ich glaube nicht, dass es eine einfachere Lösung gibt.


Okay, danke, das deckt sich leider mit den wenigen anderen Hinweisen, die ich gefunden habe :(

Kennt jemand zufällig ein gutes Tutorial zu Hooks? Habe so etwas bisher noch nicht gebraucht.

Habe jetzt ein Beispiel auf Delphi-Treff gefunden und so angepasst, dass es die Messages an die Fenster abfangen sollte

Jetzt frage ich mich, wie ich herausfinde ob die Flashwindow() die Message ausgelößt hat, und an wie ich das Handle des Fensters bekomme, das "flashed". Oder kann ich irgendwie den Hook nur für einen Prozess setzen?

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
library WindowHook;

uses
  Windows,
  Messages;

var
  HookHandle: Cardinal = 0;
  WindowHandle: Cardinal = 0;

function WindowHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM):
LRESULT; stdcall;
begin
//it's possible to call CallNextHookEx conditional only.
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
  case nCode < 0 of
    TRUE: exit; //if code smaller 0 nothing has to be done
    FALSE:
      begin
//Here one can work with the parameters
      end;
  end;
end;

function InstallHook(Hwnd: Cardinal): Boolean; stdcall;
begin
  Result := False;
  if HookHandle = 0 then begin
//First install the hook
    HookHandle := SetWindowsHookEx(WH_CALLWNDPROC, @WindowHookProc,
    HInstance, 0);
//Save the given window handle
    WindowHandle := Hwnd;
    Result := TRUE;
  end;
end;

function UninstallHook: Boolean; stdcall;
begin
//Uninstall hook from hook chain
  Result := UnhookWindowsHookEx(HookHandle);
  HookHandle := 0;
end;

exports
//Export the installation and deinstallation routine
  InstallHook,
  UninstallHook;
end.


Laden tue ich die DLL so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
type
  TInstallHook = function(Hwnd: THandle): Boolean; stdcall;
  TUninstallHook = function: Boolean; stdcall;

var
  InstallHook: TInstallHook;
  UninstallHook: TUninstallHook;
  lib: Cardinal;

procedure TForm1.Button1Click(Sender: TObject);
begin
  lib := LoadLibrary('windowhook.dll');
  if lib <> INVALID_HANDLE_VALUE then begin
    InstallHook := GetProcAddress(lib, 'InstallHook');
    UnInstallHook := GetProcAddress(lib, 'UninstallHook');
  end// else ERROR
end;
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Mi 28.01.09 15:07 
Laut Assarbad's Hook Tutorial ist der von dir genutzte Hooktyp WH_CALLWNDPROC ein lokaler Hooktyp, d.h. du musst beim einhaken ohnehin die ThreadID des Prozesses in den du dich einhaken willst angeben. Ich kenne mich aber mit Hooks nicht aus und habe keine Ahnung, woher "HInstance" kommt :nixweiss:
Ich bin sicher, das Tutorial wird dir aber trotzdem helfen :)

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
zakoon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 60



BeitragVerfasst: Mi 28.01.09 15:39 
user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:
Laut Assarbad's Hook Tutorial ist der von dir genutzte Hooktyp WH_CALLWNDPROC ein lokaler Hooktyp, d.h. du musst beim einhaken ohnehin die ThreadID des Prozesses in den du dich einhaken willst angeben. Ich kenne mich aber mit Hooks nicht aus und habe keine Ahnung, woher "HInstance" kommt :nixweiss:
Ich bin sicher, das Tutorial wird dir aber trotzdem helfen :)



Danke für den Hinweis auf das Tutorial. Den gehookten Prozess kann ich jetzt also durch angeben der ID als vierten Parameter in SetWindowsHookEx() festlegen. Einen Schritt weiter :-)

Jetzt fehlt mir also noch, wie ich aus den zurückgegebenen Parametern meiner Function WindowHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM) ermitteln kann, ob FlashWindow() aufgerufen wurde. Hat jemand dazu eine Idee?
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Mi 28.01.09 15:52 
user profile iconzakoon hat folgendes geschrieben Zum zitierten Posting springen:
Jetzt fehlt mir also noch, wie ich aus den zurückgegebenen Parametern meiner Function WindowHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM) ermitteln kann, ob FlashWindow() aufgerufen wurde. Hat jemand dazu eine Idee?
Ich vermute, dass du diese Information aus den Parametern (wParam, lParam) auslesen kannst - wie genau das geht, weiß ich nicht.

Hierzu steht etwas in diesem MSDN-Eintrag (Gute Anlaufstelle für solche Systemnahen Probleme :) Einfach mal dort nach der entsprechenden Konstante suchen.):
Es gibt da diese Struktur CWPRETSTRUCT, in der diverse Informationen darüber stehen, was deinen Hook da angesprochen hat.

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
zakoon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 60



BeitragVerfasst: Mi 28.01.09 16:09 
user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:
Ich vermute, dass du diese Information aus den Parametern (wParam, lParam) auslesen kannst - wie genau das geht, weiß ich nicht.

Hierzu steht etwas in diesem MSDN-Eintrag (Gute Anlaufstelle für solche Systemnahen Probleme :) Einfach mal dort nach der entsprechenden Konstante suchen.):
Es gibt da diese Struktur CWPRETSTRUCT, in der diverse Informationen darüber stehen, was deinen Hook da angesprochen hat.


Ja, die von dir genannten Seiten auf msdn hab ich leider auch schon durchwühlt. Da steht dann immer Parameter XY "Specifies additional information ... " Aber ich habe nicht herausfinden können, was diese "Informationen" im Falle der FlashWindow() sein werden. :(
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Mi 28.01.09 16:51 
Probiers doch mal aus. Schreib dir ein Programm, welches sein Fenster alle 5 sekunden flasht, dann eines, welches einen WH_CALLWNDPROC auf dieses Fenster setzt. In deiner Callback lässt du dir alle interessanten informationen ausgeben, vorallem den message Parameter. Dieser dürfte eine Zahl sein, welche Message das dann ist, musst du selbst rausfinden.
Sobald du weißt, welche Message das ist, kannst du ja in MSDN konkret nach der Bedeutung der w und lParams suchen.

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
zakoon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 60



BeitragVerfasst: Mi 28.01.09 17:45 
user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:
Probiers doch mal aus. Schreib dir ein Programm, welches sein Fenster alle 5 sekunden flasht, dann eines, welches einen WH_CALLWNDPROC auf dieses Fenster setzt. In deiner Callback lässt du dir alle interessanten informationen ausgeben, vorallem den message Parameter. Dieser dürfte eine Zahl sein, welche Message das dann ist, musst du selbst rausfinden.
Sobald du weißt, welche Message das ist, kannst du ja in MSDN konkret nach der Bedeutung der w und lParams suchen.


Gute Idee :D Ich probiers mal aus berichte...
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Mi 28.01.09 17:56 
user profile iconzakoon hat folgendes geschrieben Zum zitierten Posting springen:
Gute Idee :D Ich probiers mal aus berichte...
Das wäre wünschenswert! Wie du vielleicht bemerkt hast, hab ich auch selbst Interesse dran :)

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
zakoon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 60



BeitragVerfasst: Mi 28.01.09 19:04 
user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconzakoon hat folgendes geschrieben Zum zitierten Posting springen:
Gute Idee :D Ich probiers mal aus berichte...
Das wäre wünschenswert! Wie du vielleicht bemerkt hast, hab ich auch selbst Interesse dran :)


Ok, here mal ein Dump. Mein Testprogramm flasht alle 5 sekunden einmal.
Kannst du daraus etwas erkennen?

EDIT: PS: 134 ist WM_NCACTIVATE und 127 WM_GETICON. Kann man aus einer der Messages auf das Flashen schliessen?

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
Zeit: CWPRETSTRUCT.Message - nCode - wParam - lParam 
17:59:14: 134 - 0 - 0 - 1244532
17:59:14: 127 - 0 - 1 - 1244792
17:59:15: 134 - 0 - 0 - 1244808
17:59:15: 127 - 0 - 1 - 1244792
17:59:15: 134 - 0 - 0 - 1244808
17:59:15: 127 - 0 - 1 - 1244792
17:59:19: 134 - 0 - 0 - 1244532
17:59:19: 127 - 0 - 1 - 1244792
17:59:20: 134 - 0 - 0 - 1244808
17:59:20: 127 - 0 - 1 - 1244792
17:59:20: 134 - 0 - 0 - 1244808
17:59:20: 127 - 0 - 1 - 1244792
17:59:24: 134 - 0 - 0 - 1244532
17:59:24: 127 - 0 - 1 - 1244792
17:59:25: 134 - 0 - 0 - 1244808
17:59:25: 127 - 0 - 1 - 1244792
17:59:25: 134 - 0 - 0 - 1244808
17:59:25: 127 - 0 - 1 - 1244792



PS: Den Dump habe ich mit folgenden Änderungen erstellt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
function WindowHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM):
LRESULT; stdcall;
var
 cwps: TCWPStruct;
begin
//it's possible to call CallNextHookEx conditional only.
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
  case nCode < 0 of
    TRUE:  exit;
    FALSE:
      begin
        CopyMemory(@cwps, Pointer(lParam), SizeOf(CWPSTRUCT));

        outStr:= TimeToStr(now)+': '+IntToStr(cwps.message)+' - '+ IntToStr(nCode)+' - '+IntToStr(wParam)+' - '+IntToStr(lParam);
        assignfile(datei, 'dump.txt');  // <-- File name of the dump
        if FileExists('dump.txt'then  // if File exists, append the line, if not, create the File
          Append (datei)
        else
          rewrite(datei);
        writeln(datei, outStr); // write your Line
        closefile(datei);
      end;
  end;
end;
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Mi 28.01.09 23:58 
OK das war nicht hilfreich :( Reichlich enttäuschend. Ich vermute, da muss man noch mehr tun...

OK neuer Ansatz: Nutze die uallCollection, im speziellen die uallHook. Meine Callback-Funktion wird aufgerufen aber ich hab einen Fehler drin: danach kommt eine AV:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
  
var
  NextFunc: FlashFunc;

function myCallBack(hWnd : HWND; bInvert : LongBool) : LongBool;
begin
  showmessage('flashed' + IntToStr(hWnd));
  result := NextFunc(hWnd, bInvert);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  HookCode(@FlashWindow, @myCallBack, @NextFunc);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  UnHookCode(@NextFunc);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  FlashWindow(self.Handle, false);
end;

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.