Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Hook, als Componente (https://www.delphipraxis.net/151252-hook-als-componente.html)

4dk2 10. Mai 2010 07:38


Hook, als Componente
 
Hallo,

Wieder mal eine Frage zu Hooks :)

Mein Problem ist das ich eine Komponente machen will die einen Hook beinhaltet.

Problem dabei ist das ich die Hookfunktion nicht übergeben kann:

SetWindowsHookEx bekommt normalerweise so
HandleA := SetWindowsHookEx(WH_KEYBOARD,@Funcktion,HInstance, GetCurrentThreadId());
eine Prodedure mit.

Da es aber ja in eine Componten soll sind es ja keine einfachen procedure sondern
"Methoden" also procedure of object im Prinzip.

Ich habs sogar hinbekommen das die Procedure aufgerufen wird, wenn ich TMethod.Code übergebe,
allerdings mit Zugriffs verletzungen :)

Vielleicht hat einer von euch ja schonmal so was ähnliches gemacht, bzw kennt einer evtl. nen Link zu einer Komponten die Hooks benutzt.



Delphi-Quellcode:
//type TKeyboardHookProc_object=function (Code: Integer;WordParam: Word;LongParam: LongInt): LongInt of object; stdcall;
//type PKeyboardHookProc_object=^TKeyboardHookProc_object;
//type TKeyboardHookProc=function (Code: Integer;WordParam: Word;LongParam: LongInt): LongInt; stdcall;
//type PKeyboardHookProc=^TKeyboardHookProc;

type THook=class (Tcomponent)
  private
    FHooksActive:boolean;
    FHookHandle : HHook;
    function KeyboardHookProc2(Code: Integer;WordParam: Word;LongParam: LongInt): LongInt; stdcall;
  public
    procedure SetActive(const value:boolean);

end;


//.........

procedure THook.SetActive(const value:boolean);
var p:pointer;
begin
  if value=FHooksActive then exit;

  FHooksActive:=value;
  if not FHooksActive then
  begin
    UnHookWindowsHookEx(FHookHandle);
  end
  else
  begin
     p:=@KeyboardHookProc2; //hier das Problem
     FHookHandle:=SetWindowsHookEx(WH_KEYBOARD,
             {callback —>}  p, //hier muss die Funktion/Pointer zur Funktion übergeben werden
                            HInstance,
                            GetCurrentThreadId());
  end;
end;


function THook.KeyboardHookProc2(Code: Integer; WordParam: Word;
  LongParam: Integer): LongInt;
var
  shift : TShiftState;
  key  : Word;
  f:Tform;
  KeyState1: TKeyBoardState;
  s:string;
begin
   result := 0;
   if Code<0 then
   begin
     result:=CallNextHookEx(FHookHandle,Code,WordParam,LongParam);
     exit;
   end;
 
   //Keydown: code=3
   //KeyUp:  code=0;

   //if code<>0 then exit; // alles nur bei keyup verarbeiten...

   if (LongParam and (1 SHL 31) <> 0) then exit;




   GetKeyboardState(KeyState1);
   shift := [];
   if ((KeyState1[vk_Menu] and 128)<>0) then
     shift:=shift+[ssAlt];
   if ((KeyState1[VK_CONTROL] and 128)<>0) then
     shift:=shift+[ssCtrl];
   if ((KeyState1[VK_SHIFT] and 128)<>0) then
     shift:=shift+[ssShift];

   key := WordParam;

   if key=VK_RETURN then
       key:=0;
   if key=VK_TAB then
       key:=0;
 
   if key<>0 then
     result:=CallNextHookEx(FHookHandle,Code,WordParam,LongParam)
   else
   begin
     result:=-1;
     //CallNextHookEx(FHookHandle,Code,0,0)
   end;
end;

4dk2 11. Mai 2010 08:20

Re: Hook, als Componente
 
Hab die Lösung.

scheint sehr kompliziert zu sein unter Delphi das zu instanzieren.

hier noch eine lösung mit csarp, wo es sehr einfach scheint.

Delphi-Quellcode:
public class KeyHook
    {
        private delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

        //Declare hook handle as int.
        static int hHook = 0;

        public static List<Keys> KeyCodes = new List<Keys>();

        //Declare keyboard hook constant.
        //For other hook types, you can obtain these values from Winuser.h in Microsoft SDK.
        const int WH_KEYBOARD_LL = 13;

        HookProc KeyboardHookProcedure;

        [StructLayout(LayoutKind.Sequential)]
        private class keyboardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

        //Import for SetWindowsHookEx function.
        //Use this function to install thread-specific hook.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
        IntPtr hInstance, int threadId);

        //Import for UnhookWindowsHookEx.
        //Call this function to uninstall the hook.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);

        //Import for CallNextHookEx.
        //Use this function to pass the hook information to next hook procedure in chain.
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        private static extern int CallNextHookEx(int idHook, int nCode,
        IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);

        public KeyHook()
        {
            Hook();
        }

        ~KeyHook()
        {
            UnHook();
        }

        public int Hook()
        {
            KeyboardHookProcedure = new HookProc(KeyHook.KeyboardHookProc);

            hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, (IntPtr)LoadLibrary("User32"), 0);
            return hHook;
        }

        public bool UnHook()
        {
            bool ret = UnhookWindowsHookEx(hHook);
            if (ret)
                hHook = 0;
            return ret;
        }

        private static int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode < 0)
            {
                return CallNextHookEx(hHook, nCode, wParam, lParam);
            }
            else
            {

                if (((int)wParam == 256) || ((int)wParam == 260))
                {
                    keyboardHookStruct MyKeyboardHookStruct = (keyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(keyboardHookStruct));
                    KeyCodes.Add((Keys)MyKeyboardHookStruct.vkCode);
                }
                return 1;
            }
        }

    }

jaenicke 11. Mai 2010 08:44

Re: Hook, als Componente
 
Zitat:

Zitat von 4dk2
Ich habs sogar hinbekommen das die Procedure aufgerufen wird, wenn ich TMethod.Code übergebe,
allerdings mit Zugriffs verletzungen :)

Kein Wunder...
Du übergibst eine reine Prozedur. Die hat nun einmal keinen Bezug zu einem Objekt. Dennoch greifst du innerhalb deiner Methode auf Self (z.B. FHookHandle) zu. Das gibt es aber gar nicht.

Es gibt keine Möglichkeit eine Methode inkl. Bezug zum Objekt als Callback anzugeben. Einfach weil dort nur ein Zeiger mit 4 Byte erwartet wird und die zweiten 4 Byte mit dem Zeiger auf die Instanz dort nirgends angegeben werden können.


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