2009-10-19 96 views
1

我被要求開發一個新的應用程序,它將與現有的應用程序一起工作。這兩個應用程序將等待條形碼閱讀器輸入。我不希望我們的操作員掃描兩次條形碼:一次用於現有應用程序(16位剪輯,無源),一次用於新應用程序。爲了解決這個問題,我決定使用低級別的鍵盤鉤子(用Delphi編寫)。它看起來很完美,因爲2個應用程序需要條形碼閱讀器輸入,而且大多數時候我的應用程序都不會集中。低級鍵盤掛鉤問題:應用程序不集中時鍵盤狀態丟失(德爾福)

我的低級別鍵盤掛鉤在我的應用程序專注時工作良好。例如,如果我進入一個TEdit控件,然後如果我掃描我的條碼:

  • 的期待已久的人物將在TEdit控件 顯示 (#02; 90BDIJ#)。
  • 低級鉤子將獲得所有字符(#,然後0,然後2等等 )。

事情變得當我的應用程序是沒有更集中更差:如果我打開記事本,然後,如果我掃描我的條碼:

  • 了期待已久的人物將在記事本中顯示 (#02; 90BDIJ #)。
  • 低級別掛鉤會得到冤屈字符:「AE;çàbdij」

它看起來像鍵盤狀態在帳戶中沒有上當受騙!它看起來像Shift,Ctrl或Alt鍵連鍵沒有在account.On更多的把我的法語鍵盤:

  • '#'= = CTRL + ALT「
  • '0'= Shift + A鍵
  • 「2」 = SHIFT + E
  • ...

現在有沒有人如何解決這個問題呢? 我做了錯誤的方式(我應該使用Windows的消息呢?)。謝謝你前進。

FWIW這裏是我的源代碼:

unit Unit5; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls, Math; 

const 
    LLKHF_UP    = $0080; 

type 
    tagKBDLLHOOKSTRUCT = packed record 
    vkCode :   DWORD; 
    scanCode :   DWORD; 
    flags :    DWORD; 
    time :    DWORD; 
    dwExtraInfo :  Integer; 
    end; 
    KBDLLHOOKSTRUCT  = tagKBDLLHOOKSTRUCT; 
    PKBDLLHOOKSTRUCT  = ^KBDLLHOOKSTRUCT; 

var 
    hkHook : HHook; 
    function LowLevelKeyboardProc(Code, wParam, lParam: Integer): Integer; stdcall; 
    procedure HookIt; 
    procedure UnHookIt; 

implementation 

uses Unit1; 

procedure HookIt; 
begin 
    hkHook := SetWindowsHookEx(WH_KEYBOARD_LL,@LowLevelKeyboardProc,hInstance,0); 
end; 

procedure UnHookIt; 
begin 
    UnHookWindowsHookEx(hkHook); 
end; 

function LowLevelKeyboardProc(Code, wParam, lParam: Integer): Integer; 
var 
    KeyState : TKeyboardState; 
    NewChar: array[0..1] of Char; 
    Hook : PKBDLLHOOKSTRUCT; 
    bControlKeyDown : Boolean; 
begin 
    Try 
    Hook := Pointer(lParam); 
    Case Code Of 
     HC_ACTION: 
     begin 
      If (Hook^.flags And LLKHF_UP) <> 0 Then 
      begin 
       FillChar(NewChar,2,#0); 
       GetKeyboardState(KeyState); 
       If ToAscii(Hook^.vkCode,Hook^.scanCode,KeyState,NewChar,0) = 1 Then 
        Form1.ListBox1.Items.Add(NewChar[0]); 
      end; 
     end;boar 
     end; 
    Finally 
    Result := CallNextHookEx(hkHook,Code,wParam,lParam); 
    end; 
end; 

end. 
+0

我用的條形碼閱讀器模擬鍵盤,所以不需要編寫任何代碼。您是否在使用不具備此功能的閱讀器? – jdigital 2009-10-19 20:47:15

+0

我的條形碼閱讀器也模擬鍵盤。條形碼讀取器輸入當前由一個現有的(16位/削波器)軟件處理。我被要求開發一種新的應用程序,它將與舊版本一起工作。我想使用低級鍵盤鉤,以便我們的操作員不必掃描條形碼兩次(一個用於裁剪軟件,另一個用於我們未來的室內軟件) – 2009-10-19 20:51:42

+0

打包此記錄是錯誤的。不要這樣做。 – 2014-12-01 07:49:26

回答

2

這是一個本地鍵盤鉤子。您需要創建一個global hook,以便它可以在任何地方工作。全局鍵盤(和鼠標)鉤子需要在單獨的.dll中實現。

更新:

我已得到糾正。顯然這不需要在dll中實現。

+0

謝謝你的回答布魯斯,但我無法使它在Windows 7和德爾福(unicode世界;)下工作。 – 2009-10-19 22:27:58

+0

我已經在Vista中完成了這一工作,取得了巨大成功 - 但是unicode可能會阻礙你。我認爲布魯斯是正確的,一個全球性的鉤子是你唯一的選擇。 – Alister 2009-10-19 23:14:00

+0

Alister,我正試圖將這段代碼改編成一個DLL ......到目前爲止沒有運氣,我甚至無法得到一個關鍵行程:( 你願意幫我嗎? – 2009-10-20 16:17:51

3

我今天遇到這個問題,並通過在GetKeyboardState(KeyState)後添加這些行來解決;

KeyState[VK_CAPITAL] := GetKeyState(VK_CAPITAL); 
KeyState[VK_SHIFT] := GetKeyState(VK_SHIFT); 
KeyState[VK_CONTROL] := GetKeyState(VK_CONTROL); 
KeyState[VK_MENU] := GetKeyState(VK_MENU); 
+0

令人難以置信的是,這對我很有用我剛纔假設GetKeyState只是一種看起來很簡單的方法在由GetKeyboardState返回的數組的特定索引處,然而,這似乎並非基於您的答案,您是否會知道爲什麼這種方法有效? – Anthony 2017-08-16 16:25:18