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 Keyboardhook + D7 & BDS2006 (https://www.delphipraxis.net/90758-keyboardhook-d7-bds2006.html)

Schubi 23. Apr 2007 12:50


Keyboardhook + D7 & BDS2006
 
Hallo!

Habe in meinem Projekt den Keyboardhook von William Egge in Gebrauch.

Hier der Quellcode dazu:
Delphi-Quellcode:
unit keyboardhook;

  By William Egge
  Sep 20, 2002 
  [email]egge@eggcentric.com[/email]
  [url]http://www.eggcentric.com[/url]

  This code may be used/modified however you wish.


interface

uses
  Windows, Classes;

type
  TCallbackThunk = packed record
    POPEDX: Byte;
    MOVEAX: Byte;
    SelfPtr: Pointer;
    PUSHEAX: Byte;
    PUSHEDX: Byte;
    JMP: Byte;
    JmpOffset: Integer;
  end;

  // See windows help on KeyboardProc
  // Or press F1 while your cursor is on "KeyboardProc"
  TKeyboardCallback =
      procedure(code: Integer; wparam: WPARAM; lparam: LPARAM) of object;

  TKeyboardHook = class(TComponent)
  private
    { Private declarations } 
    FHook: HHook;
    FThunk: TCallbackThunk;
    FOnCallback: TKeyboardCallBack;
    function CallBack(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT
        stdcall;
    procedure SetOnCallback(const Value: TKeyboardCallBack);
  protected
    { Protected declarations } 
  public
    { Public declarations } 
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published declarations } 
    property OnCallback: TKeyboardCallBack read FOnCallback write SetOnCallback;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('EggMisc', [TKeyboardHook]);
end;

{ TKeyboardHook } 

function TKeyboardHook.CallBack(code: Integer; wparam: WPARAM;
  lparam: LPARAM): LRESULT;
begin
  if Code < 0 then
    Result:= CallNextHookEx(FHook, Code, wparam, lparam)
  else
  begin
    if Assigned(FOnCallback) then
      FOnCallback(Code, wParam, lParam);
    Result:= 0;
  end;
end;

constructor TKeyboardHook.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FThunk.POPEDX:= $5A;
  FThunk.MOVEAX:= $B8;
  FThunk.SelfPtr:= Self;
  FThunk.PUSHEAX:= $50;
  FThunk.PUSHEDX:= $52;
  FThunk.JMP:= $E9;
  FThunk.JmpOffset:= Integer(@TKeyboardHook.Callback)-Integer(@FThunk.JMP)-5;
  FHook:= SetWindowsHookEx(WH_KEYBOARD, TFNHookProc(@FThunk), 0, MainThreadID);
end;

destructor TKeyboardHook.Destroy;
begin
  UnhookWindowsHookEx(FHook);
  inherited;
end;

procedure TKeyboardHook.SetOnCallback(const Value: TKeyboardCallBack);
begin
  FOnCallback := Value;
end;

end.
Zu meinem Problem:
Ich bin kürzlich von Delphi 7 auf BDS 2006 umgestiegen.
Seit dem kommen alle Ereignisse doppelt.
Sprich also:
"Key down", "Key down", "Key up", "Key up".

Habe schon ein leeres Projekt erstellt, und die Komponente reingezogen. Dort ist das gleiche Verhalten. Sobald ich das Projekt mit D7 öffne geht es wieder.

Kann mir jemand weiterhelfen?

SirThornberry 23. Apr 2007 14:54

Re: Keyboardhook + D7 & BDS2006
 
ist das nur so wenn du es innerhalb von Delphi ausführst?

zu dem schreibst du etwas von: "Key down", "Key down", "Key up", "Key up".
Innerhalb des geposteten Codes wird dies aber gar nicht ausgewertet. Könntest du den Teil noch posten in dem du auswertest ob "Key down", "Key up" etc. ausgelöst wird?
Genrell wird bei Hooks "Key down" etc. tatsächlich mehrfach empfangen wenn zum Beispiel die Taste gedrückt gehalten wird

Schubi 23. Apr 2007 14:59

Re: Keyboardhook + D7 & BDS2006
 
Ist auch bei der fertig Compilierten EXE so :-(

Die Auswertung ist einfach.
Die Komponente (siehe Quelltext oben) befeuert ein Ereignis:
Delphi-Quellcode:
procedure TForm1.KeyboardHook1Callback(code, wparam, lparam: Integer);
begin
  memo1.lines.add(inttostr(lparam));
end;
Und dieses Ereignis kommt bei BDS 2006 doppelt.

Also:
Zitat:

1966081
1966081
-1071775743
-1071775743
statt
Zitat:

1966081
-1071775743

SirThornberry 23. Apr 2007 15:17

Re: Keyboardhook + D7 & BDS2006
 
Du solltest dich nicht darauf verlassen wie oft es ausgelöst wird. Bei mir wurde es teilweise sogar 3 mal ausgelöst. Schau dir am besten die Hilfe zu SetWindowsHookEx und wh_keyboard an damit du weißt worauf du dich verlassen kannst und was nur glück/zufall ist.

Der Grund für das von dir unerwartete Verhalten sollte der sein:
Zitat:

The KeyboardProc hook procedure is an application-defined or library-defined callback function used with the SetWindowsHookEx function. The system calls this function whenever an application calls the GetMessage or PeekMessage function and there is a keyboard message (WM_KEYUP or WM_KEYDOWN) to be processed.
[Edit]
Habs auch so eben probiert: Durch mehrere Aufrufe von PeekMessage mit PM_NOREMOVE wird die Hookprocedure immer wieder aufgerufen (so wie in der Hilfe beschrieben
[/Edit]

Schubi 23. Apr 2007 15:36

Re: Keyboardhook + D7 & BDS2006
 
Muss doch aber irgendwie auch an Delphi liegen.
Unter Delphi 7 habe ich die Komponente schon seit 3 Jahren im Einsatz. Ohne ein einziges Problem, geschweige denn dass da jemals was doppelt gekommen wäre.
Hat sich an der Nachrichten-Kette in Delphi irgendwas geändert?

SirThornberry 23. Apr 2007 15:47

Re: Keyboardhook + D7 & BDS2006
 
scheint so, vermutlich wird jetzt PeekMessage verwendet, eventuell für Application-Events etc.
Auf jeden Fall muss irgendwo ein PeekMessage oder GetMessage hinzugekommen sein. Wobei GetMessage fast ausgeschlossen ist da nach einem Aufruf von GetMessage die Nachricht erstmal weg wäre sofern sie nicht zwischenbespeichert wird.

Schubi 23. Apr 2007 21:39

Re: Keyboardhook + D7 & BDS2006
 
hm. Irgendeine Idee, wie ich das Verhalten weg bekomme?
Filtern wäre halt die unelegante Lösung.

Ansonsten danke schonmal!

Flocke 23. Apr 2007 22:24

Re: Keyboardhook + D7 & BDS2006
 
Zitat:

Zitat von Schubi
hm. Irgendeine Idee, wie ich das Verhalten weg bekomme?

Lass dir beim Debuggen auch mal den Wert von "Code" ausgeben. Der sollte bei PeekMessage mit PM_NOREMOVE den Wert HC_NOREMOVE haben (laut MSDN). Ggf. kannst du das dann einfach in die If-Abfrage einbauen.

Schubi 24. Apr 2007 08:11

Re: Keyboardhook + D7 & BDS2006
 
Blind muss der Mensch sein. :oops:

Zitat:

3 65 1966081
0 65 1966081
3 65 -1071775743
0 65 -1071775743
War die ganze Zeit schon da, hatte hier nur die vereinfachte form ohne code gepostet.
das isses dann wohl so weit.

Vielen dank fürs entfernen der Tomaten :-D


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