Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Hook / Popupmenu (https://www.delphipraxis.net/97132-hook-popupmenu.html)

golisan 5. Aug 2007 16:49


Hook / Popupmenu
 
Hallo Leute,

ich will in einer Anwendung das Popupmenü "abfangen" und verändern.
Nehmen wir z. Bsp. mal Notepad. Drücke ich die rechte Maustaste, erscheint das Popup mit Ausschneiden, Einfügen etc.
Wie komme ich an dieses Popup?

Ich habe bereits einen Hook, der mir "sagt", daß die rechte Maustaste gedrückt wurde, aber das Popup kommt ja erst danach :roll:
Das bringt als nicht wirklich was :gruebel:
Und die nächste spannende Frage wäre, wenn ich das Popupmenü nun um meine Einträge erweitert habe, wie bekomme ich mit, daß so ein Eintrag ausgwählt wurde?
Es wäre nett, wenn mich jemand in die richte Richtung schubsen würde :tongue:
Danke bye

c113plpbr 5. Aug 2007 17:43

Re: Hook / Popupmenu
 
Zitat:

Zitat von golisan
ich will in einer Anwendung das Popupmenü "abfangen" und verändern.
Nehmen wir z. Bsp. mal Notepad. Drücke ich die rechte Maustaste, erscheint das Popup mit Ausschneiden, Einfügen etc.
Wie komme ich an dieses Popup?

Also, es gibt da zwei praktikable Möglichkeiten (die mir bekannt sind):
Die erste, die ich dir empfehlen würde ist die SetWindowsHookEx-Funktion zu benutzen und damit einen Hook zu "installieren" (welchen typ von hook man dazu braucht steht in der msdn). Dann musst du in der hook-callback-funktion einfach noch auf die WM_CONTEXTMENU-Message warten, dann weißt du, dass ein Kontextmenü aufgerufen wurde. Das kannst du dann nach belieben verändern.

Die andere Methode, die ich mal verwendet hab lief über Function-Hooking. Dazu habe ich auch ein Beispiel gepostet: sit
Allerdings rate ich dir von dieser Methode ab, wenn es nicht unbedingt sein muss, da diese lange nicht so "sauber" ist wie die über SetWindowsHookEx.
Zitat:

Zitat von golisan
Ich habe bereits einen Hook, der mir "sagt", daß die rechte Maustaste gedrückt wurde, aber das Popup kommt ja erst danach :roll:
Das bringt als nicht wirklich was :gruebel:
Und die nächste spannende Frage wäre, wenn ich das Popupmenü nun um meine Einträge erweitert habe, wie bekomme ich mit, daß so ein Eintrag ausgwählt wurde?

Auch dafür lässt sich ein solcher Hook einsetzen, einfach auf die WM_COMMAND-Message (wird gesendet, wenn ein Menü-Eintrag angeklickt wurde) warten und dann schauen ob dein Eintrag ausgewählt wurde.

mfg,
Philipp

LizardKaiser 5. Aug 2007 17:45

Re: Hook / Popupmenu
 
Hey,

also du könntest, nachdem du die Hook Message erhalten hast, versuchen das Fenster des Popups (google mal nach dem Klassennamen, es sind Ziffern, die ich leider nicht mehr im Kopf habe) zu finden. Die Auswahl wird gewöhnlich an das Parent-Fenster (also Notepad) geschickt. Da müsstest du nun auch versuchen, per Hook an die WM_COMMAND Nachricht zu kommen...

Grüße,

Lizard

Edit: zu lahm...

golisan 6. Aug 2007 20:39

Re: Hook / Popupmenu
 
Hallo Leute,
danke erst mal, für die Antworten... aber irgendwie komme ich noch nicht ganz klar.
Mein Msg-Hook sie so aus

Delphi-Quellcode:
function MsgHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM):
 LRESULT; stdcall;
 var
 Scancode : Integer;
 type PMsg = ^TMsg;
  var  msg:           PMsg;

begin
 if ncode = HC_ACTION then
    with Windows.PMsg(lParam)^ do
      if message = WM_INITMENUPOPUP then
      begin
      showmessage('hab dich!');
      end;

  Result := CallNextHookEx(HookHandleMsg, nCode, wParam, lParam);


end;
Gut, ich gebe zu, daß ich den Code mir "zuammengesucht" habe und nicht unbedigt weiß, was da abgeht, aber "optisch" sieht es doch gut aus, oder? :gruebel: (Keyboard-/Maus-Hooks funktionieren)
Nochmal, was ich eigentlich machen will:
Ein Kontext-/Popup-Menu einer anderen Anwendung abfangen und zusätzliche Menüeinträge anhängen.
Das kann doch nicht so schwierig sein.... :coder2:

c113plpbr 6. Aug 2007 22:28

Re: Hook / Popupmenu
 
@golisan:
Ich glaube wir sind alle nicht scharf drauf jetzt den Rest selbst zu schreiben, um auszuprobieren, was an deinem Code nicht funktioniert, daher wäre es besser, wenn du genau sagst, womit du nicht klar kommst, was nicht funktioniert, usw. .

Außerdem, ein erster Blick verrät mir, dass das nur schief gehen kann, da du ShowMessage verwendest. Dies ist eine Funktion aus der VCL, und sollte somit nicht in irgendwelchen Threads in irgendwelchen Programmen außerhalb der VCL aufgerufen werden. Es würde mich also nicht wundern, wenn es da AccessViolations hagelt ...
Benutze doch bitte lieber MessageBox.

mfg,
Philipp

golisan 7. Aug 2007 18:05

Re: Hook / Popupmenu
 
@c113plpbr

Sorry, ich habe nur den Teil gepostet, da der Rest funktioniert. Ich dachte, evtl. ist es nur ein kleiner Bug.

Also die Hooks sind in einer DLL.
Den Tastatur- und Maushook habe ich nur zur Testzwecken, um zu prüfen, ob's überhaupt tut...

Delphi-Quellcode:
library myhook;

uses
  Windows,
  Messages,
  SysUtils;

var
  HookHandleKB  : Cardinal = 0;
  HookHandleM   : Cardinal = 0;
  HookHandleMsg : Cardinal = 0;
  WindowHandle  : Cardinal = 0;

// ------------------------------ Keyboard -------------------------------


function KeyboardHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM):
 LRESULT; stdcall;
 var
 Scancode : Integer;
begin
  Result := CallNextHookEx(HookHandleKB, nCode, wParam, lParam);
  case nCode < 0 of
    TRUE: exit; //wenn code kleiner 0 wird nix gemacht

    FALSE:
      begin
        MessageBox(0,'ok','Info',MB_OK);
      end;
  end;
end;

// ------------------------------ Mouse -------------------------------


function MouseHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM):
 LRESULT; stdcall;
 var
 Scancode : Integer;
begin

  Result := CallNextHookEx(HookHandleM, nCode, wParam, lParam);
  case nCode < 0 of
    TRUE: exit; //wenn code kleiner 0 wird nix gemacht

    FALSE:
      begin

      end;
  end;
end;

// ------------------------------ MSG -------------------------------

function MsgHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM):
 LRESULT; stdcall;
 var
 Scancode : Integer;
 type PMsg = ^TMsg;
  var  msg:           PMsg;

begin
 if ncode = HC_ACTION then
    with Windows.PMsg(lParam)^ do
      begin
        if (message = WM_INITDIALOG) or (message = WM_SETFOCUS) then
        begin
          MessageBox(0,'ok','Info',MB_OK);
        end

      end;

Result := CallNextHookEx(HookHandleMsg, nCode, wParam, lParam);



end;

function InstallHook(Hwnd: Cardinal): Boolean; stdcall;
begin
  Result := False;
  if HookHandleKB = 0 then begin
    HookHandleKB := SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc,
    HInstance, 0);
    WindowHandle := Hwnd;
    Result := TRUE;
  end;
  if HookHandleM = 0 then begin
    HookHandleM := SetWindowsHookEx(WH_MOUSE, @MouseHookProc,
    HInstance, 0);
    WindowHandle := Hwnd;
    Result := TRUE;
  end;
  if HookHandleMSG = 0 then begin
    HookHandleMsg := SetWindowsHookEx(WH_GETMESSAGE, @MsgHookProc,
    HInstance, 0);
    WindowHandle := Hwnd;
    Result := TRUE;
  end;
end;

function UninstallHook: Boolean; stdcall;
begin
//Hook aus der Hookchain entfernen
//Uninstall hook from hook chain
  Result := UnhookWindowsHookEx(HookHandleKB);
  Result := UnhookWindowsHookEx(HookHandleM);
  Result := UnhookWindowsHookEx(HookHandleMsg);
  HookHandleKB := 0;
  HookHandleM  := 0;
  HookHandleMsg := 0;
end;

exports
//Installations- und Deinstallationsroutine exportieren
//Export the installation and deinstallation routine
  InstallHook,
  UninstallHook;
end.
In einer Form lade ich den Hook..
Delphi-Quellcode:
initialization
begin
  lib := LoadLibrary('myhook.dll');
  if lib <> INVALID_HANDLE_VALUE then
  begin
    InstallHook := GetProcAddress(lib, 'InstallHook');
    UnInstallHook := GetProcAddress(lib, 'UninstallHook');
    end else showmessage('myHook.dll wurde nicht gefunden!');
end;
und starte dann den Hook..
Delphi-Quellcode:
installHook(0); // Wozu brauche ich hier ein HWND?? Es geht auch ohne...
Wie gesagt, Maus- und Tastatur-Hook funktionieren! Nur der Message-Hook nicht richtig.
Es kommen Messages an, nur nicht WM_INITPOPUPMENU oder WM_CONTEXTMENU, obwohl die laut Winsight/ Winspector "rumschwirren"
Und DAS verstehe ich nicht. :wall:
Was läuft beim Message-Hook anders als beim Maus- Tastatur-Hook??

Habt ihr eine Idee??

Danke!

PS: ShowMessage tut auch in einer nonVCL, hab's aber trotzdem gegen ein MessageBox getauscht. :wink:

c113plpbr 7. Aug 2007 19:15

Re: Hook / Popupmenu
 
Zitat:

Zitat von golisan
Wie gesagt, Maus- und Tastatur-Hook funktionieren! Nur der Message-Hook nicht richtig.
Es kommen Messages an, nur nicht WM_INITPOPUPMENU oder WM_CONTEXTMENU, obwohl die laut Winsight/ Winspector "rumschwirren"
Und DAS verstehe ich nicht. :wall:

Du solltest nicht vergessen, dass es viele verschiedene arten von SetWindowsHookEx-Hooks gibt, und du nicht unbedingt die richtige für deinen zweck hast.
So steht in der MSDN z.B. bei WH_SYSMSGFILTER, dass hier menü-messages ankommen ... vielleicht sind da ja deine dabei ... ansonsten könnten sie noch in WH_MSGFILTER auftauchen, und wenns da auch ned geht, werden sie in jedem Fall an die WindowProc geschickt, kannste auch abfangen mit nem WH_CALLWNDPROC-Hook.
Zitat:

Zitat von golisan
PS: ShowMessage tut auch in einer nonVCL, hab's aber trotzdem gegen ein MessageBox getauscht. :wink:

Is besser so, auch wenns scheinbar funktioniert, würde ich nicht darauf vertrauen ...

mfg,
Philipp

golisan 12. Aug 2007 16:39

Re: Hook / Popupmenu
 
Hallo,

ich bin jetzt einen (halben?) Schritt weiter! :wink:
Der Tipp, statt WH_GETMESSAGE lieber WH_CALLWNDPROC zu verwenden, war genau der richtige!

Ich habe jetzt das Kontextmenü im Zugriff... aber irgendwie komme ich mit dem AppendMenu nicht zurecht.
Ich möchte folgende Struktur
(bestehendes Menü)
Punkt 1
Punkt 2
Punkt 3
(jetzt sollen "meine" Einträge angehängt werden.
MeinPunkt1 (nur ein Untermenüpukt)
UnterMeinpunkt1 (nur ein Untermenüpunkt)
UnterMeinpunkt1_1 (der erste "echte" Menüpunkt)
UnterMeinpunkt1_2
.
.
UnterMeinpunkt2 (nur ein Untermenüpunkt)
UnterMeinpunkt2_1 (der erste "echte" Menüpunkt)
UnterMeinpunkt2_2
.
.
Die Menüpunkte werden auch erzeugt aber irgendwie "rekursiv".
Hier der Code
Delphi-Quellcode:
          nse  := createPopupMenu;
          subs := createPopupMenu;
          books := createPopupMenu;

          AppendMenu(subs, MF_STRING or MF_ENABLED, 2000, PChar('UnterMeinpunkt1'));
          AppendMenu(books, MF_STRING or MF_ENABLED, 3000, PChar('UnterMeinpunkt2'));
          AppendMenu(nse,  MF_STRING or MF_POPUP,  subs, PChar('UnterMeinpunkt1'));
          AppendMenu(nse,  MF_STRING or MF_POPUP,  books, PChar('UnterMeinpunkt1'));
          AppendMenu(natmenu, MF_STRING or MF_POPUP, nse, PChar('MeinPunkt1'));
und so siehts aus:
(bestehendes Menü)
Punkt 1
Punkt 2
Punkt 3
MeinPunkt1 (nur ein Untermenüpukt) ok soweit
UnterMeinpunkt1 ok soweit
UnterMeinpunkt2 ok soweit
MeinPunkt1(und "darunter" wieder UnterMeinPunkt1/2 usw usw

Was macht "MeinPunkt1" hier?? Habt ihr einen Tipp?
Danke

c113plpbr 13. Aug 2007 18:46

Re: Hook / Popupmenu
 
Naja, dein Resultat klingt logisch, da du vermutlich bei jedem Aufruf deine Menüeinträge hinzufügst, und diese nie wieder löschst. Somit werden es immer mehr ...

Als ich sowas gemacht habe, musste ich außerdem immer nachdem das Menü dann wieder verschwunden war, die Menüeinträge entfernen, sonst gab es verschiedenste Probleme.

mfg,
Philipp

golisan 21. Aug 2007 23:18

Re: Hook / Popupmenu
 
Hallo Philipp,

danke! Genau das war's :thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:03 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