AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi WH_CALLWNDPROC-Hook // SystemMenu-Items
Thema durchsuchen
Ansicht
Themen-Optionen

WH_CALLWNDPROC-Hook // SystemMenu-Items

Ein Thema von bepe · begonnen am 12. Apr 2008 · letzter Beitrag vom 12. Apr 2008
Antwort Antwort
bepe

Registriert seit: 17. Okt 2006
118 Beiträge
 
#1

WH_CALLWNDPROC-Hook // SystemMenu-Items

  Alt 12. Apr 2008, 10:29
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:
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;
...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:

Delphi-Quellcode:
...
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 nur mit "Minimieren" aber bei meinen eigenen Items erhalte ich keine Botschaft (zumindest kein WM_SYSCOMMAND).

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..

mfg,
bp
  Mit Zitat antworten Zitat
Macci

Registriert seit: 31. Mai 2007
129 Beiträge
 
#2

Re: WH_CALLWNDPROC-Hook // SystemMenu-Items

  Alt 12. Apr 2008, 13:51
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.
  Mit Zitat antworten Zitat
bepe

Registriert seit: 17. Okt 2006
118 Beiträge
 
#3

Re: WH_CALLWNDPROC-Hook // SystemMenu-Items

  Alt 12. Apr 2008, 15:14
Zitat:
Wie ist im 2. Beispiel von dir denn MeinMenuItem definiert?
Meinst du die Konstante? Wie im Ersten:

Delphi-Quellcode:
const
  MeinMenuItem = 4711;
Und so füge ich ins Menü ein:

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:
Versuch doch mal einen expliziten Aufruf über CallWindowProc mit MeinMenuItem
Das habe ich jetzt ausprobiert und funktioniert wunderbar. (Naja, beim CallNextHookEx kommt eine AV. Aber Ereignis kommt an und wird korrekt verarbeitet.)

Delphi-Quellcode:
var
  cwps: TCWPStruct;
begin
  cwps.message := WM_SYSCOMMAND;
  cwps.wParam := MeinMenuItem;
  WndProc(HC_ACTION, 0, Integer(@cwps));

Zitat:
Wenns dann klappt, weisst du jedenfalls, dass der Fehler nicht an dem gerade eben von dir gepostetem Code liegt.
Da bin ich mir nicht ganz sicher. Wenn in meiner WndProc etwas falsch ist werde ich die Parameter wohl nicht verstanden haben. Somit wäre dann auch mein Aufruf fehlerhaft..

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:
var
  cwps: TCWPStruct;
begin
  cwps.message := WM_SYSCOMMAND;
  cwps.wParam := MeinMenuItem;
  CallWindowProc(@WndProc, Application.MainFormHandle, WM_SYSCOMMAND, 0, Integer(@cwps));
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...

mfg,
bp
  Mit Zitat antworten Zitat
Macci

Registriert seit: 31. Mai 2007
129 Beiträge
 
#4

Re: WH_CALLWNDPROC-Hook // SystemMenu-Items

  Alt 12. Apr 2008, 15:45
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:
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Bei dir sind die Parameter ja etwas anders:
WndProc(nCode : Integer; wParam: longint; lParam : longint): LRESULT Und so würde auf das Systemmenü zugreifen:

Code:
     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) ;
}
(aus dem Buch "Windows Programmierung - 5. Auflage")
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#5

Re: WH_CALLWNDPROC-Hook // SystemMenu-Items

  Alt 12. Apr 2008, 15:55
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 Torry's gerade down, aber dort gibt es die Komponente.
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.482 Beiträge
 
Delphi 10.1 Berlin Professional
 
#6

Re: WH_CALLWNDPROC-Hook // SystemMenu-Items

  Alt 12. Apr 2008, 15:55
Zitat von bepe:
Bisher nur auf einem Vista32 ausprobiert...
Na dann viel Spaß unter einem 64 Bit System.
Warum man kein WH_CALLWNDPROC hook installieren sollte (Engl.)
  Mit Zitat antworten Zitat
bepe

Registriert seit: 17. Okt 2006
118 Beiträge
 
#7

Re: WH_CALLWNDPROC-Hook // SystemMenu-Items

  Alt 12. Apr 2008, 16:13
Danke euch dreien aber leider noch keine Lösung in sicht

@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.

mfg,
bp
  Mit Zitat antworten Zitat
bepe

Registriert seit: 17. Okt 2006
118 Beiträge
 
#8

Re: WH_CALLWNDPROC-Hook // SystemMenu-Items

  Alt 12. Apr 2008, 16:29
Zitat:
Mach dir das Leben doch nicht so schwer !
Gute Idee, habe den Hook entfernt und mache es jetzt doch, mehr oder weniger, wie von Macci gezeigt. Ich überschreibe/tausche einfach die Proc vom MainForm.

Delphi-Quellcode:
...
  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;
So funktioniert es endlich Aber sollte jemand noch eine Idee zu dem Hook haben, ich bin immer noch neugierig.

Und nochmal danke...

mfg,
bp
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:00 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz