CnRawInput.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2018 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. unit CnRawInput;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:CnPack 组件包不可视组件
  24. * 单元名称:封装了 RawInput 实现键盘捕捉的组件单元
  25. * 单元作者:刘啸(liuxiao@cnpack.org)
  26. * 开发平台:PWinXPPro + Delphi 5.01
  27. * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7/2005 + C++Build 5/6
  28. * 备  注:参考了网上部分 RawInput 的头文件以及其它分析文章
  29. * 单元标识:$Id$
  30. * 修改记录:2008.09.23 V1.0
  31. * LiuXiao 实现键盘捕捉
  32. ================================================================================
  33. |</PRE>}
  34. interface
  35. {$I CnPack.inc}
  36. uses
  37. SysUtils, Windows, Messages, Classes, Forms;
  38. const
  39. WM_INPUT = $00FF;
  40. type
  41. HRAWINPUT = THANDLE;
  42. const
  43. RIM_INPUT = 0;
  44. RIM_INPUTSINK = 1;
  45. type
  46. tagRAWINPUTHEADER = record
  47. dwType: DWORD;
  48. dwSize: DWORD;
  49. hDevice: THANDLE;
  50. wParam: WPARAM;
  51. end;
  52. {$EXTERNALSYM tagRAWINPUTHEADER}
  53. RAWINPUTHEADER = tagRAWINPUTHEADER;
  54. {$EXTERNALSYM RAWINPUTHEADER}
  55. PRAWINPUTHEADER = ^RAWINPUTHEADER;
  56. {$EXTERNALSYM PRAWINPUTHEADER}
  57. LPRAWINPUTHEADER = ^RAWINPUTHEADER;
  58. {$EXTERNALSYM LPRAWINPUTHEADER}
  59. TRawInputHeader = RAWINPUTHEADER;
  60. const
  61. RIM_TYPEMOUSE = 0;
  62. RIM_TYPEKEYBOARD = 1;
  63. RIM_TYPEHID = 2;
  64. type
  65. tagRAWMOUSE = record
  66. usFlags: WORD;
  67. union: record
  68. case Integer of
  69. 0: (
  70. ulButtons: ULONG);
  71. 1: (
  72. usButtonFlags: WORD;
  73. usButtonData: WORD);
  74. end;
  75. ulRawButtons: ULONG;
  76. lLastX: LongInt;
  77. lLastY: LongInt;
  78. ulExtraInformation: ULONG;
  79. end;
  80. {$EXTERNALSYM tagRAWMOUSE}
  81. RAWMOUSE = tagRAWMOUSE;
  82. {$EXTERNALSYM RAWMOUSE}
  83. PRAWMOUSE = ^RAWMOUSE;
  84. {$EXTERNALSYM PRAWMOUSE}
  85. LPRAWMOUSE = ^RAWMOUSE;
  86. {$EXTERNALSYM LPRAWMOUSE}
  87. TRawMouse = RAWMOUSE;
  88. const
  89. RI_MOUSE_LEFT_BUTTON_DOWN = $0001; // Left Button changed to down.
  90. {$EXTERNALSYM RI_MOUSE_LEFT_BUTTON_DOWN}
  91. RI_MOUSE_LEFT_BUTTON_UP = $0002; // Left Button changed to up.
  92. {$EXTERNALSYM RI_MOUSE_LEFT_BUTTON_UP}
  93. RI_MOUSE_RIGHT_BUTTON_DOWN = $0004; // Right Button changed to down.
  94. {$EXTERNALSYM RI_MOUSE_RIGHT_BUTTON_DOWN}
  95. RI_MOUSE_RIGHT_BUTTON_UP = $0008; // Right Button changed to up.
  96. {$EXTERNALSYM RI_MOUSE_RIGHT_BUTTON_UP}
  97. RI_MOUSE_MIDDLE_BUTTON_DOWN = $0010; // Middle Button changed to down.
  98. {$EXTERNALSYM RI_MOUSE_MIDDLE_BUTTON_DOWN}
  99. RI_MOUSE_MIDDLE_BUTTON_UP = $0020; // Middle Button changed to up.
  100. {$EXTERNALSYM RI_MOUSE_MIDDLE_BUTTON_UP}
  101. RI_MOUSE_BUTTON_1_DOWN = RI_MOUSE_LEFT_BUTTON_DOWN;
  102. {$EXTERNALSYM RI_MOUSE_BUTTON_1_DOWN}
  103. RI_MOUSE_BUTTON_1_UP = RI_MOUSE_LEFT_BUTTON_UP;
  104. {$EXTERNALSYM RI_MOUSE_BUTTON_1_UP}
  105. RI_MOUSE_BUTTON_2_DOWN = RI_MOUSE_RIGHT_BUTTON_DOWN;
  106. {$EXTERNALSYM RI_MOUSE_BUTTON_2_DOWN}
  107. RI_MOUSE_BUTTON_2_UP = RI_MOUSE_RIGHT_BUTTON_UP;
  108. {$EXTERNALSYM RI_MOUSE_BUTTON_2_UP}
  109. RI_MOUSE_BUTTON_3_DOWN = RI_MOUSE_MIDDLE_BUTTON_DOWN;
  110. {$EXTERNALSYM RI_MOUSE_BUTTON_3_DOWN}
  111. RI_MOUSE_BUTTON_3_UP = RI_MOUSE_MIDDLE_BUTTON_UP;
  112. {$EXTERNALSYM RI_MOUSE_BUTTON_3_UP}
  113. RI_MOUSE_BUTTON_4_DOWN = $0040;
  114. {$EXTERNALSYM RI_MOUSE_BUTTON_4_DOWN}
  115. RI_MOUSE_BUTTON_4_UP = $0080;
  116. {$EXTERNALSYM RI_MOUSE_BUTTON_4_UP}
  117. RI_MOUSE_BUTTON_5_DOWN = $0100;
  118. {$EXTERNALSYM RI_MOUSE_BUTTON_5_DOWN}
  119. RI_MOUSE_BUTTON_5_UP = $0200;
  120. {$EXTERNALSYM RI_MOUSE_BUTTON_5_UP}
  121. RI_MOUSE_WHEEL = $0400;
  122. {$EXTERNALSYM RI_MOUSE_WHEEL}
  123. MOUSE_MOVE_RELATIVE = 0;
  124. {$EXTERNALSYM MOUSE_MOVE_RELATIVE}
  125. MOUSE_MOVE_ABSOLUTE = 1;
  126. {$EXTERNALSYM MOUSE_MOVE_ABSOLUTE}
  127. MOUSE_VIRTUAL_DESKTOP = $02; // the coordinates are mapped to the virtual desktop
  128. {$EXTERNALSYM MOUSE_VIRTUAL_DESKTOP}
  129. MOUSE_ATTRIBUTES_CHANGED = $04; // requery for mouse attributes
  130. {$EXTERNALSYM MOUSE_ATTRIBUTES_CHANGED}
  131. type
  132. tagRAWKEYBOARD = record
  133. MakeCode: WORD;
  134. Flags: WORD;
  135. Reserved: WORD;
  136. VKey: WORD;
  137. Message: UINT;
  138. ExtraInformation: ULONG;
  139. end;
  140. {$EXTERNALSYM tagRAWKEYBOARD}
  141. RAWKEYBOARD = tagRAWKEYBOARD;
  142. {$EXTERNALSYM RAWKEYBOARD}
  143. PRAWKEYBOARD = ^RAWKEYBOARD;
  144. {$EXTERNALSYM PRAWKEYBOARD}
  145. LPRAWKEYBOARD = ^RAWKEYBOARD;
  146. {$EXTERNALSYM LPRAWKEYBOARD}
  147. TRawKeyBoard = RAWKEYBOARD;
  148. const
  149. KEYBOARD_OVERRUN_MAKE_CODE = $FF;
  150. {$EXTERNALSYM KEYBOARD_OVERRUN_MAKE_CODE}
  151. RI_KEY_MAKE = 0;
  152. {$EXTERNALSYM RI_KEY_MAKE}
  153. RI_KEY_BREAK = 1;
  154. {$EXTERNALSYM RI_KEY_BREAK}
  155. RI_KEY_E0 = 2;
  156. {$EXTERNALSYM RI_KEY_E0}
  157. RI_KEY_E1 = 4;
  158. {$EXTERNALSYM RI_KEY_E1}
  159. RI_KEY_TERMSRV_SET_LED = 8;
  160. {$EXTERNALSYM RI_KEY_TERMSRV_SET_LED}
  161. RI_KEY_TERMSRV_SHADOW = $10;
  162. {$EXTERNALSYM RI_KEY_TERMSRV_SHADOW}
  163. type
  164. tagRAWHID = record
  165. dwSizeHid: DWORD; // byte size of each report
  166. dwCount: DWORD; // number of input packed
  167. bRawData: array [0..0] of BYTE;
  168. end;
  169. {$EXTERNALSYM tagRAWHID}
  170. RAWHID = tagRAWHID;
  171. {$EXTERNALSYM RAWHID}
  172. PRAWHID = ^RAWHID;
  173. {$EXTERNALSYM PRAWHID}
  174. LPRAWHID = ^RAWHID;
  175. {$EXTERNALSYM LPRAWHID}
  176. TRawHid = RAWHID;
  177. tagRAWINPUT = record
  178. header: RAWINPUTHEADER;
  179. case Integer of
  180. 0: (mouse: RAWMOUSE);
  181. 1: (keyboard: RAWKEYBOARD);
  182. 2: (hid: RAWHID);
  183. end;
  184. {$EXTERNALSYM tagRAWINPUT}
  185. RAWINPUT = tagRAWINPUT;
  186. {$EXTERNALSYM RAWINPUT}
  187. PRAWINPUT = ^RAWINPUT;
  188. {$EXTERNALSYM PRAWINPUT}
  189. LPRAWINPUT = ^RAWINPUT;
  190. {$EXTERNALSYM LPRAWINPUT}
  191. TRawInput = RAWINPUT;
  192. const
  193. RID_INPUT = $10000003;
  194. {$EXTERNALSYM RID_INPUT}
  195. RID_HEADER = $10000005;
  196. {$EXTERNALSYM RID_HEADER}
  197. RIDI_PREPARSEDDATA = $20000005;
  198. {$EXTERNALSYM RIDI_PREPARSEDDATA}
  199. RIDI_DEVICENAME = $20000007; // the return valus is the character length, not the byte size
  200. {$EXTERNALSYM RIDI_DEVICENAME}
  201. RIDI_DEVICEINFO = $2000000b;
  202. {$EXTERNALSYM RIDI_DEVICEINFO}
  203. type
  204. PRID_DEVICE_INFO_MOUSE = ^RID_DEVICE_INFO_MOUSE;
  205. {$EXTERNALSYM PRID_DEVICE_INFO_MOUSE}
  206. tagRID_DEVICE_INFO_MOUSE = record
  207. dwId: DWORD;
  208. dwNumberOfButtons: DWORD;
  209. dwSampleRate: DWORD;
  210. end;
  211. {$EXTERNALSYM tagRID_DEVICE_INFO_MOUSE}
  212. RID_DEVICE_INFO_MOUSE = tagRID_DEVICE_INFO_MOUSE;
  213. {$EXTERNALSYM RID_DEVICE_INFO_MOUSE}
  214. TRidDeviceInfoMouse = RID_DEVICE_INFO_MOUSE;
  215. PRidDeviceInfoMouse = PRID_DEVICE_INFO_MOUSE;
  216. PRID_DEVICE_INFO_KEYBOARD = ^RID_DEVICE_INFO_KEYBOARD;
  217. {$EXTERNALSYM PRID_DEVICE_INFO_KEYBOARD}
  218. tagRID_DEVICE_INFO_KEYBOARD = record
  219. dwType: DWORD;
  220. dwSubType: DWORD;
  221. dwKeyboardMode: DWORD;
  222. dwNumberOfFunctionKeys: DWORD;
  223. dwNumberOfIndicators: DWORD;
  224. dwNumberOfKeysTotal: DWORD;
  225. end;
  226. {$EXTERNALSYM tagRID_DEVICE_INFO_KEYBOARD}
  227. RID_DEVICE_INFO_KEYBOARD = tagRID_DEVICE_INFO_KEYBOARD;
  228. {$EXTERNALSYM RID_DEVICE_INFO_KEYBOARD}
  229. TRidDeviceInfoKeyboard = RID_DEVICE_INFO_KEYBOARD;
  230. PRidDeviceInfoKeyboard = PRID_DEVICE_INFO_KEYBOARD;
  231. PRID_DEVICE_INFO_HID = ^RID_DEVICE_INFO_HID;
  232. {$EXTERNALSYM PRID_DEVICE_INFO_HID}
  233. tagRID_DEVICE_INFO_HID = record
  234. dwVendorId: DWORD;
  235. dwProductId: DWORD;
  236. dwVersionNumber: DWORD;
  237. usUsagePage: WORD;
  238. usUsage: WORD;
  239. end;
  240. {$EXTERNALSYM tagRID_DEVICE_INFO_HID}
  241. RID_DEVICE_INFO_HID = tagRID_DEVICE_INFO_HID;
  242. {$EXTERNALSYM RID_DEVICE_INFO_HID}
  243. TRidDeviceInfoHid = RID_DEVICE_INFO_HID;
  244. PRidDeviceInfoHid = PRID_DEVICE_INFO_HID;
  245. tagRID_DEVICE_INFO = record
  246. cbSize: DWORD;
  247. dwType: DWORD;
  248. case Integer of
  249. 0: (mouse: RID_DEVICE_INFO_MOUSE);
  250. 1: (keyboard: RID_DEVICE_INFO_KEYBOARD);
  251. 2: (hid: RID_DEVICE_INFO_HID);
  252. end;
  253. {$EXTERNALSYM tagRID_DEVICE_INFO}
  254. RID_DEVICE_INFO = tagRID_DEVICE_INFO;
  255. {$EXTERNALSYM RID_DEVICE_INFO}
  256. PRID_DEVICE_INFO = ^RID_DEVICE_INFO;
  257. {$EXTERNALSYM PRID_DEVICE_INFO}
  258. LPRID_DEVICE_INFO = ^RID_DEVICE_INFO;
  259. {$EXTERNALSYM LPRID_DEVICE_INFO}
  260. TRidDeviceInfo = RID_DEVICE_INFO;
  261. PRidDeviceInfo = PRID_DEVICE_INFO;
  262. TGetRawInputDeviceInfo = function (hDevice: THANDLE; uiCommand: UINT; pData: POINTER;
  263. var pcbSize: UINT): UINT; stdcall;
  264. TGetRawInputBuffer = function (pData: PRAWINPUT; var pcbSize: UINT;
  265. cbSizeHeader: UINT): UINT; stdcall;
  266. TGetRawInputData = function (hRawInput: HRAWINPUT; uiCommand: UINT; pData: POINTER;
  267. var pcbSize: UINT; cbSizeHeader: UINT): UINT; stdcall;
  268. LPRAWINPUTDEVICE = ^RAWINPUTDEVICE;
  269. {$EXTERNALSYM LPRAWINPUTDEVICE}
  270. PRAWINPUTDEVICE = ^RAWINPUTDEVICE;
  271. {$EXTERNALSYM PRAWINPUTDEVICE}
  272. tagRAWINPUTDEVICE = record
  273. usUsagePage: WORD; // Toplevel collection UsagePage
  274. usUsage: WORD; // Toplevel collection Usage
  275. dwFlags: DWORD;
  276. hwndTarget: HWND; // Target hwnd. NULL = follows keyboard focus
  277. end;
  278. {$EXTERNALSYM tagRAWINPUTDEVICE}
  279. RAWINPUTDEVICE = tagRAWINPUTDEVICE;
  280. {$EXTERNALSYM RAWINPUTDEVICE}
  281. TRawInputDevice = RAWINPUTDEVICE;
  282. const
  283. RIDEV_REMOVE = $00000001;
  284. {$EXTERNALSYM RIDEV_REMOVE}
  285. RIDEV_EXCLUDE = $00000010;
  286. {$EXTERNALSYM RIDEV_EXCLUDE}
  287. RIDEV_PAGEONLY = $00000020;
  288. {$EXTERNALSYM RIDEV_PAGEONLY}
  289. RIDEV_NOLEGACY = $00000030;
  290. {$EXTERNALSYM RIDEV_NOLEGACY}
  291. RIDEV_INPUTSINK = $00000100;
  292. {$EXTERNALSYM RIDEV_INPUTSINK}
  293. RIDEV_CAPTUREMOUSE = $00000200; // effective when mouse nolegacy is specified, otherwise it would be an error
  294. {$EXTERNALSYM RIDEV_CAPTUREMOUSE}
  295. RIDEV_NOHOTKEYS = $00000200; // effective for keyboard.
  296. {$EXTERNALSYM RIDEV_NOHOTKEYS}
  297. RIDEV_APPKEYS = $00000400; // effective for keyboard.
  298. {$EXTERNALSYM RIDEV_APPKEYS}
  299. RIDEV_EXMODEMASK = $000000F0;
  300. {$EXTERNALSYM RIDEV_EXMODEMASK}
  301. type
  302. PRAWINPUTDEVICELIST = ^RAWINPUTDEVICELIST;
  303. {$EXTERNALSYM PRAWINPUTDEVICELIST}
  304. tagRAWINPUTDEVICELIST = record
  305. hDevice: THANDLE;
  306. dwType: DWORD;
  307. end;
  308. {$EXTERNALSYM tagRAWINPUTDEVICELIST}
  309. RAWINPUTDEVICELIST = tagRAWINPUTDEVICELIST;
  310. {$EXTERNALSYM RAWINPUTDEVICELIST}
  311. TRawInputDeviceList = RAWINPUTDEVICELIST;
  312. TGetRawInputDeviceList = function (pRawInputDeviceList: PRAWINPUTDEVICELIST;
  313. var puiNumDevices: UINT; cbSize: UINT): UINT; stdcall;
  314. TRegisterRawInputDevices = function (pRawInputDevices: PRAWINPUTDEVICE;
  315. uiNumDevices: UINT; cbSize: UINT): BOOL; stdcall;
  316. TGetRegisteredRawInputDevices = function (pRawInputDevices: PRAWINPUTDEVICE;
  317. var puiNumDevices: UINT; cbSize: UINT): UINT; stdcall;
  318. type
  319. TOnRawKeyDown = procedure (Sender: TObject; Key: Word; FromKeyBoard: THandle) of object;
  320. TOnRawKeyUp = procedure (Sender: TObject; Key: Word; FromKeyBoard: THandle) of object;
  321. TCnRawKeyBoard = class(TComponent)
  322. private
  323. FHandle: THandle;
  324. FEnabled: Boolean;
  325. FDevices: array of RAWINPUTDEVICELIST;
  326. FKeyBoardNames: TStrings;
  327. FRegistered: Boolean;
  328. FOnRawKeyDown: TOnRawKeyDown;
  329. FOnRawKeyUp: TOnRawKeyUp;
  330. FBackground: Boolean;
  331. FKeyBoardCount: Integer;
  332. procedure RegisterRawInput;
  333. function GetKeyBoardCount: Integer;
  334. procedure SetEnabled(const Value: Boolean);
  335. procedure SetBackground(const Value: Boolean);
  336. function GetKeyBoardName(Index: Integer): string;
  337. protected
  338. procedure WinProc(var Message: TMessage);
  339. procedure Loaded; override;
  340. procedure DoRawKeyDown(Key: Word; FromKeyBoard: THandle); virtual;
  341. procedure DoRawKeyUp(Key: Word; FromKeyBoard: THandle); virtual;
  342. public
  343. constructor Create(AOwner: TComponent); override;
  344. destructor Destroy; override;
  345. procedure UpdateKeyBoardsInfo;
  346. function KeyBoardNameFromHandle(KeyHandle: THandle): string;
  347. property KeyBoardCount: Integer read GetKeyBoardCount;
  348. property KeyBoardName[Index: Integer]: string read GetKeyBoardName;
  349. published
  350. property Enabled: Boolean read FEnabled write SetEnabled;
  351. property Background: Boolean read FBackground write SetBackground;
  352. property OnRawKeyDown: TOnRawKeyDown read FOnRawKeyDown write FOnRawKeyDown;
  353. property OnRawKeyUp: TOnRawKeyUp read FOnRawKeyUp write FOnRawKeyUp;
  354. end;
  355. implementation
  356. var
  357. User32DllHandle: THandle = 0;
  358. User32NeedFree: Boolean = False;
  359. GetRawInputDeviceInfo : TGetRawInputDeviceInfo = nil;
  360. GetRawInputBuffer : TGetRawInputBuffer = nil;
  361. GetRawInputData : TGetRawInputData = nil;
  362. GetRawInputDeviceList : TGetRawInputDeviceList = nil;
  363. RegisterRawInputDevices : TRegisterRawInputDevices = nil;
  364. GetRegisteredRawInputDevices : TGetRegisteredRawInputDevices = nil;
  365. { TCnRawKeyBoard }
  366. constructor TCnRawKeyBoard.Create(AOwner: TComponent);
  367. begin
  368. inherited;
  369. if @GetRawInputDeviceInfo = nil then
  370. raise Exception.Create('Only Windows XP/2003 or Later can be Supported.');
  371. FEnabled := False;
  372. FBackground := True;
  373. FKeyBoardNames := TStringList.Create;
  374. FHandle := AllocateHWnd(WinProc);
  375. UpdateKeyBoardsInfo;
  376. end;
  377. destructor TCnRawKeyBoard.Destroy;
  378. begin
  379. if FHandle <> 0 then
  380. begin
  381. DeallocateHWnd(FHandle);
  382. FHandle := 0;
  383. end;
  384. FKeyBoardNames.Free;
  385. SetLength(FDevices, 0);
  386. inherited;
  387. end;
  388. procedure TCnRawKeyBoard.DoRawKeyDown(Key: Word; FromKeyBoard: THandle);
  389. begin
  390. if Assigned(FOnRawKeyDown) then
  391. FOnRawKeyDown(Self, Key, FromKeyBoard);
  392. end;
  393. procedure TCnRawKeyBoard.DoRawKeyUp(Key: Word; FromKeyBoard: THandle);
  394. begin
  395. if Assigned(FOnRawKeyUp) then
  396. FOnRawKeyUp(Self, Key, FromKeyBoard);
  397. end;
  398. function TCnRawKeyBoard.GetKeyBoardCount: Integer;
  399. begin
  400. Result := FKeyBoardCount;
  401. end;
  402. procedure TCnRawKeyBoard.Loaded;
  403. begin
  404. inherited;
  405. end;
  406. procedure TCnRawKeyBoard.RegisterRawInput;
  407. var
  408. Device: array[0..0] of RAWINPUTDEVICE;
  409. begin
  410. Device[0].usUsagePage := RIM_TYPEKEYBOARD;
  411. Device[0].usUsage := 6; //6 表示键盘子类
  412. Device[0].hwndTarget := FHandle;
  413. if FBackground then
  414. Device[0].dwFlags := RIDEV_INPUTSINK
  415. else
  416. Device[0].dwFlags := RIDEV_CAPTUREMOUSE;
  417. // 注册一个 RawInputDevice
  418. if not (RegisterRawInputDevices(@Device, 1, SizeOf(RAWINPUTDEVICE))) then
  419. raise Exception.Create('RegisterRawInputDevices error!');
  420. end;
  421. procedure TCnRawKeyBoard.SetEnabled(const Value: Boolean);
  422. begin
  423. if FEnabled <> Value then
  424. begin
  425. FEnabled := Value;
  426. if FEnabled and not FRegistered then
  427. begin
  428. if not (csDesigning in ComponentState) then
  429. begin
  430. RegisterRawInput;
  431. FRegistered := True;
  432. end;
  433. end;
  434. end;
  435. end;
  436. procedure TCnRawKeyBoard.SetBackground(const Value: Boolean);
  437. begin
  438. if FBackground <> Value then
  439. begin
  440. if not (csDesigning in ComponentState) and not (csLoading in ComponentState) then
  441. raise Exception.Create('Can NOT Change Background Mode when Running.');
  442. FBackground := Value;
  443. end;
  444. end;
  445. procedure TCnRawKeyBoard.WinProc(var Message: TMessage);
  446. var
  447. Ri: tagRAWINPUT;
  448. Size: Cardinal;
  449. begin
  450. if FEnabled and (Message.Msg = WM_INPUT) then
  451. begin
  452. Ri.header.dwSize := SizeOf(RAWINPUTHEADER);
  453. Size := SizeOf(RAWINPUTHEADER);
  454. GetRawInputData(HRAWINPUT(Message.LParam), RID_INPUT, nil,
  455. Size, SizeOf(RAWINPUTHEADER));
  456. if GetRawInputData(HRAWINPUT(Message.LParam), RID_INPUT, @Ri,
  457. Size, SizeOf(RAWINPUTHEADER)) = Size then
  458. begin
  459. if (Ri.header.dwType = RIM_TYPEKEYBOARD) then
  460. begin
  461. if Ri.keyboard.Message = WM_KEYDOWN then
  462. DoRawKeyDown(Ri.keyboard.VKey, Ri.header.hDevice)
  463. else if Ri.keyboard.Message = WM_KEYUP then
  464. DoRawKeyUp(Ri.keyboard.VKey, Ri.header.hDevice);
  465. end;
  466. end;
  467. end
  468. else if Message.Msg = WM_ENDSESSION then
  469. begin
  470. Application.Terminate;
  471. end
  472. else
  473. inherited;
  474. end;
  475. procedure GetRawInputAPIs;
  476. begin
  477. if Win32Platform = VER_PLATFORM_WIN32_NT then
  478. begin
  479. User32DllHandle := GetModuleHandle('User32.DLL');
  480. if User32DllHandle = 0 then
  481. begin
  482. User32DllHandle := LoadLibrary('User32.DLL');
  483. User32NeedFree := User32DllHandle <> 0;
  484. end;
  485. if User32DllHandle <> 0 then
  486. begin
  487. @GetRawInputDeviceInfo := GetProcAddress(User32DllHandle, 'GetRawInputDeviceInfoA');
  488. @GetRawInputBuffer := GetProcAddress(User32DllHandle, 'GetRawInputBuffer');
  489. @GetRawInputData := GetProcAddress(User32DllHandle, 'GetRawInputData');
  490. @GetRawInputDeviceList := GetProcAddress(User32DllHandle, 'GetRawInputDeviceList');
  491. @RegisterRawInputDevices := GetProcAddress(User32DllHandle, 'RegisterRawInputDevices');
  492. @GetRegisteredRawInputDevices := GetProcAddress(User32DllHandle, 'GetRegisteredRawInputDevices');
  493. end;
  494. end;
  495. end;
  496. procedure FreeRawInputAPIs;
  497. begin
  498. if User32NeedFree and (User32DllHandle <> 0) then
  499. begin
  500. FreeLibrary(User32DllHandle);
  501. User32DllHandle := 0;
  502. end;
  503. end;
  504. procedure TCnRawKeyBoard.UpdateKeyBoardsInfo;
  505. var
  506. C, Sl: Cardinal;
  507. KBName: array[0..1023] of AnsiChar;
  508. I: Integer;
  509. // DevInfo: RID_DEVICE_INFO;
  510. begin
  511. FKeyBoardCount := 0;
  512. FKeyBoardNames.Clear;
  513. Sl := SizeOf(KBName);
  514. if GetRawInputDeviceList(nil, C, SizeOf(RAWINPUTDEVICELIST)) = 0 then
  515. begin
  516. if C > 0 then
  517. begin
  518. SetLength(FDevices, C);
  519. if GetRawInputDeviceList(@FDevices[0], C, SizeOf(RAWINPUTDEVICELIST)) <> $FFFFFFFF then
  520. begin
  521. for I := 0 to C - 1 do
  522. begin
  523. if FDevices[I].dwType = RIM_TYPEKEYBOARD then
  524. begin
  525. // DevInfo.cbSize := SizeOf(RID_DEVICE_INFO);
  526. // C := DevInfo.cbSize;
  527. // GetRawInputDeviceInfo(FDevices[I].hDevice, RIDI_DEVICEINFO, @DevInfo, C);
  528. Inc(FKeyBoardCount);
  529. GetRawInputDeviceInfo(FDevices[I].hDevice, RIDI_DEVICENAME, @KBName, Sl);
  530. FKeyBoardNames.AddObject({$IFDEF UNICODE}String{$ENDIF}(KBName), TObject(FDevices[I].hDevice));
  531. end;
  532. end;
  533. end;
  534. end;
  535. end;
  536. end;
  537. function TCnRawKeyBoard.GetKeyBoardName(Index: Integer): string;
  538. begin
  539. if (Index >= 0) and (Index < FKeyBoardNames.Count) then
  540. Result := FKeyBoardNames[Index];
  541. end;
  542. function TCnRawKeyBoard.KeyBoardNameFromHandle(KeyHandle: THandle): string;
  543. var
  544. I: Integer;
  545. begin
  546. I := FKeyBoardNames.IndexOfObject(TObject(KeyHandle));
  547. if I >= 0 then
  548. Result := FKeyBoardNames[I]
  549. else
  550. Result := '';
  551. end;
  552. initialization
  553. GetRawInputAPIs;
  554. finalization
  555. FreeRawInputAPIs;
  556. end.