![]() |
WH_CALLWNDPROC-Hook // SystemMenu-Items
Hallo,
ich habe mir mittels Hooks eine kleine Hilfskomponente gebastelt, welche mir zur Laufzeit ein par Eigenschaften zu meinen Controls anzeigt und ggf. ändert. Einige Funktionen habe ich in das Systemmenü meines Programms eingebunden. Nun wüsste ich gerne wann diese ausgewählt/angeklickt werden. So:
Delphi-Quellcode:
...funktioniert alles, immer wunderbar. Auch mit meinen eigenen MenuItems. Ich möchte aber meine Programme nicht anpassen müssen und habe deshalb in meiner Komponente ein WH_CALLWNDPROC-Hook eingebaut:
const
MeinMenuItem = 4711; procedure WMSysCommand(var Msg: TMessage); message WM_SYSCOMMAND; ... procedure TForm1.WMSysCommand(var Msg: TMessage); begin inherited; if (Msg.wParam shr 16) = 0 then begin case Word(Msg.wParam) of MeinMenuItem: MessageBox(0, 'MeinItem', '', 0); SC_MINIMIZE: MessageBox(0, 'Minimize', '', 0); end; end; end;
Delphi-Quellcode:
Das funktioniert nur mit "Minimieren" aber bei meinen eigenen Items erhalte ich keine Botschaft (zumindest kein WM_SYSCOMMAND).
...
wndHook := SetWindowsHookEx(WH_CALLWNDPROC, @WndProc, 0, GetCurrentThreadId); ... function WndProc(nCode : Integer; wParam: longint; lParam : longint): LRESULT; stdcall; var cwps: TCWPStruct; begin if (nCode = HC_ACTION) then begin CopyMemory(@cwps, Pointer(lParam), SizeOf(CWPSTRUCT)); case cwps.message of WM_SYSCOMMAND: begin if (cwps.wParam shr 16) = 0 then begin case Word(cwps.wParam) of MeinMenuItem: MessageBox(0, 'MeinItem', '', 0); SC_MINIMIZE: MessageBox(0, 'Minimize', '', 0); end; end; end; end; end; Result := CallNextHookEx(wndHook, nCode, wParam, lParam); end; Das funktioniert nicht immer. Wähle ich jetzt im Menü "Minimieren" wird das Programm minimiert aber ich erhalte keine Botschaft (zumindest kein WM_SYSCOMMAND). Klicke ich im Titel auf den entsprechenden Button, greift mein Hook. Hat jemand eine Idee woran das liegen könnte oder ob es Alternativen für mich gibt? Bisher nur auf einem Vista32 ausprobiert... Im Netz findet man ja einige unterschiedliche Ansätze um den Hook zu implementieren. Bei allen hatte ich das gleiche Verhalten. EDIT: Hatte Unsinn im Quelltext, daher habe ich die Problemschilderung korrigiert.. |
Re: WH_CALLWNDPROC-Hook // SystemMenu-Items
Wie ist im 2. Beispiel von dir denn MeinMenuItem definiert? Versuch doch mal einen expliziten Aufruf über CallWindowProc mit MeinMenuItem als entsprechendem Parameter. Wenns dann klappt, weisst du jedenfalls, dass der Fehler nicht an dem gerade eben von dir gepostetem Code liegt. :-)
|
Re: WH_CALLWNDPROC-Hook // SystemMenu-Items
Zitat:
Delphi-Quellcode:
Und so füge ich ins Menü ein:
const
MeinMenuItem = 4711;
Delphi-Quellcode:
var
hMenu: THandle; begin hMenu := GetSystemMenu(Application.MainFormHandle, False); if hMenu <> 0 then begin InsertMenu(hMenu, 0, MF_BYPOSITION, MeinMenuItem, 'MeinItem'); DrawMenuBar(hMenu); end; Zitat:
Delphi-Quellcode:
var
cwps: TCWPStruct; begin cwps.message := WM_SYSCOMMAND; cwps.wParam := MeinMenuItem; WndProc(HC_ACTION, 0, Integer(@cwps)); Zitat:
Aber danke.. EDIT: OK, wer beim Lesen die Augen öffnet ist klar im Vorteil. Du hast CallWindowProc gesagt und nicht direkter Aufruf, also:
Delphi-Quellcode:
Er geht wieder in meine WndProc, ich bekomme wieder eine AV beim CallNextHookEx. Aber er ich habe keine Ahnung wie ich HC_ACTION übergeben könnte. Daher greift meine Behandlung nicht...
var
cwps: TCWPStruct; begin cwps.message := WM_SYSCOMMAND; cwps.wParam := MeinMenuItem; CallWindowProc(@WndProc, Application.MainFormHandle, WM_SYSCOMMAND, 0, Integer(@cwps)); |
Re: WH_CALLWNDPROC-Hook // SystemMenu-Items
Hi,
bist du dir schon sicher, dass dein WndProc richtig definiert ist? Hooks habe ich ehrlichgesagt erst einmal gebraucht (um TerminateProcess zu hooken), ist aber schon lange her, deswegen weiss ich da nicht mehr so gut bescheid. In Delphi habe ich das WndProc auch noch nie wirklich gebraucht, in C++ geht es aber soo:
Code:
Bei dir sind die Parameter ja etwas anders:
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Delphi-Quellcode:
Und so würde auf das Systemmenü zugreifen:
WndProc(nCode : Integer; wParam: longint; lParam : longint): LRESULT
Code:
(aus dem Buch "Windows Programmierung - 5. Auflage")
hMenu = GetSystemMenu (hwnd, FALSE) ;
AppendMenu (hMenu, MF_SEPARATOR, 0, NULL) ; AppendMenu (hMenu, MF_STRING, IDM_SYS_ABOUT, TEXT ("Info über...")) ; AppendMenu (hMenu, MF_STRING, IDM_SYS_HELP, TEXT ("Hilfe...")) ; AppendMenu (hMenu, MF_STRING, IDM_SYS_REMOVE, TEXT ("Erweiterungen recyceln")) ; .... LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_SYSCOMMAND: switch (LOWORD (wParam)) { case IDM_SYS_ABOUT: MessageBox (hwnd, TEXT ("Ein Menü für arme Leute\n") TEXT ("(c) Charles Petzold, 1998"), szAppName, MB_OK | MB_ICONINFORMATION) ; return 0 ; case IDM_SYS_HELP: MessageBox (hwnd, TEXT ("Hilfestellung noch nicht implementiert!"), szAppName, MB_OK | MB_ICONEXCLAMATION) ; return 0 ; case IDM_SYS_REMOVE: GetSystemMenu (hwnd, TRUE) ; // zurück zum Original return 0 ; } break ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } |
Re: WH_CALLWNDPROC-Hook // SystemMenu-Items
Mach dir das Leben doch nicht so schwer !
Es gibt eine Komponente, der gibt man einfach ein PopupMenu mit, und sie zeigt alle Items als System-Menu an. Natürlich braucht man sich selbst nicht um Windows Messages kümmern, sondern bekommt einen Klick im Menu als Event geliefert. Leider ist ![]() |
Re: WH_CALLWNDPROC-Hook // SystemMenu-Items
Zitat:
![]() |
Re: WH_CALLWNDPROC-Hook // SystemMenu-Items
Danke euch dreien aber leider noch keine Lösung in sicht :-D
@jbg: Von dem Problem habe ich bei meiner Suche auch schon gelesen. Aber das ist für mich irrelevant. Die Komponente wird ja nur während der Entwicklung benötigt, danach wird sie wieder entfernt. Daher ja auch der Umweg über ein Hook. @sx2008: Cool, das wäre natürlich auch eine Alternative. Sobald Torry wieder da ist :( Aber mich würde dennoch intressieren was mein Problem ist. @Macci: Danke für deine Mühen. Die Unterschiede sind Hook bedingt. Der nCode gibt an ob ich auf die Nachricht reagieren darf/sollte. Dein Source scheint eine Hook freie Variante zu sein. Also doch das mein MainForm bearbeiten. |
Re: WH_CALLWNDPROC-Hook // SystemMenu-Items
Zitat:
Delphi-Quellcode:
So funktioniert es endlich :party: Aber sollte jemand noch eine Idee zu dem Hook haben, ich bin immer noch neugierig.
...
FWndBackup := Pointer(GetWindowLong(Application.MainFormHandle, GWL_WNDPROC)); SetWindowLong(Application.MainFormHandle, GWL_WNDPROC, Integer(@WndProc2)); ... function WndProc2(WND: hwnd; Msg: LongInt; wParam: longint; lParam : longint): LRESULT; stdcall; begin Result := CallWindowProc(FWndBackup, Wnd, Msg, wParam, lParam); case Msg of WM_SYSCOMMAND: begin case Word(wParam) of MeinMenutItem: MessageBox(0, 'Es klappt endlich!', '', 0); end; end; end; end; Und nochmal danke... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:38 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz