Recent

Author Topic: [SOLVED]WM_INPUT never arrived [Win10 b4bit + Lazarus1.8.4 + FPC3.0.4]  (Read 2882 times)

kinlion

  • New member
  • *
  • Posts: 44
  • I Love Lazarus
Hi all,

I'm trying to use windows raw input to get a IC card reader input, the IC card reader is kown by windows as a HID keyboard.

as described in the post:https://forum.lazarus.freepascal.org/index.php/topic,34797.msg228966.html#msg228966

Firstly, I overide form.InitializeWnd, in which to register the raw device.

Then I add the WM_INPUT message handler to my form, but the handler never executed.

At last I override the WndProc of my form,but still no WM_INPUT comes.

Can anyone tell me how to do?

Thanks in advance.

Bellow is some of my code:
----------------------------

procedure registerHIDDevice(targetHandle: HWND);
var
  Rid: array[0..0] of RAWINPUTDEVICE;
begin
  with Rid[0] do
  begin
    usUsagePage := $01;
    usUsage := $06;
    dwFlags := RIDEV_NOLEGACY or RIDEV_INPUTSINK;   // adds HID keyboard and also ignores legacy keyboard messages
    hwndTarget := targetHandle;
  end;

  if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) = FALSE) then
    raise Exception.Create('Failed to register');
end;


procedure TfmMain.InitializeWnd; override;
begin
  inherited InitializeWnd;
  registerHIDDevice(Self.Handle);
end;

procedure TfmMain.getHIDInput(var msg: TMessage);
{
https://docs.microsoft.com/zh-cn/windows/desktop/inputdev/using-raw-input
}
var
  dwSize: UINT;
  lpb: LPBYTE;
  raw: PRAWINPUT;
begin
  GetRawInputData(HRAWINPUT(msg.lParam), RID_INPUT, nil, @dwSize,
                  sizeof(RAWINPUTHEADER));
  GetMem(lpb, dwSize);
  if (lpb = nil) then Exit;

  if (GetRawInputData(HRAWINPUT(msg.lParam), RID_INPUT, lpb, @dwSize,
      sizeof(RAWINPUTHEADER)) <> dwSize ) then
  begin
    ShowMessage('Bad data size');
    Freemem(lpb);
    Exit;
  end;

  raw := PRAWINPUT(lpb);
  if (raw^.header.dwType = RIM_TYPEKEYBOARD) then
  begin
    ShowMessage(Format('Kbd:'
                + '\n\tmake=%04x'
                + '\n\tFlags:%04x'
                + '\n\tReserved:%04x'
                + '\n\tExtraInformation:%08x'
                + '\n\tmsg=%04x'
                + '\n\tVK=%04x',
              [
                raw^.data.keyboard.MakeCode,
                raw^.data.keyboard.Flags,
                raw^.data.keyboard.Reserved,
                raw^.Data.keyboard.ExtraInformation,
                raw^.data.keyboard.Message,
                raw^.data.keyboard.VKey
              ])
              );
  end;
  DefRawInputProc(@lpb, 1, sizeof(RAWINPUTHEADER));
  Freemem(lpb);
end;

procedure TfmMain.WndProc(var TheMessage: TLMessage); override;
begin
  if TheMessage.msg = WM_INPUT then
    getHIDInput(TheMessage);
  inherited WndProc(TheMessage);
end;

« Last Edit: December 14, 2018, 10:32:57 am by kinlion »
Lazarus 1.8.4 / FPC 3.0.4 / SVN 57972
On Win10 X64, have to compile for Win32

kinlion

  • New member
  • *
  • Posts: 44
  • I Love Lazarus
Re: WM_INPUT never arrived [Win10 b4bit + Lazarus1.8.4 + FPC3.0.4]
« Reply #1 on: October 17, 2018, 08:59:57 am »
I'm sure the card reader is OK because when I remove RIDEV_NOLEGACY  flag from dwFlags during register raw input device,  card id can be read in to a text edit.
Lazarus 1.8.4 / FPC 3.0.4 / SVN 57972
On Win10 X64, have to compile for Win32

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7071
Re: WM_INPUT never arrived [Win10 b4bit + Lazarus1.8.4 + FPC3.0.4]
« Reply #2 on: October 17, 2018, 09:57:15 am »

kinlion

  • New member
  • *
  • Posts: 44
  • I Love Lazarus
Re: WM_INPUT never arrived [Win10 b4bit + Lazarus1.8.4 + FPC3.0.4]
« Reply #3 on: October 17, 2018, 10:32:22 am »
YES, IT WORKS :D
THANK YOU MARCOV!

But, I found the traditional PS/2 keyboard also gernates WM_INPUT message. I can't distinguish the messages from card reader and PS/2 keyboard.
However, it's anothor problem.

I'm no expert on the matter, but did you read through this:

http://wiki.lazarus.freepascal.org/Win32/64_Interface#Processing_non-user_messages_in_your_window

?
Lazarus 1.8.4 / FPC 3.0.4 / SVN 57972
On Win10 X64, have to compile for Win32

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 616
    • Lebeau Software
Re: WM_INPUT never arrived [Win10 b4bit + Lazarus1.8.4 + FPC3.0.4]
« Reply #4 on: October 22, 2018, 11:54:56 pm »
I'm no expert on the matter, but did you read through this:

http://wiki.lazarus.freepascal.org/Win32/64_Interface#Processing_non-user_messages_in_your_window

?

Note that SetWindowSubclass() is preferred over SendWindowLong/Ptr().  See Subclassing Controls and Safer subclassing on MSDN.

But, I found the traditional PS/2 keyboard also gernates WM_INPUT message.

In fact, ANY type of input device can, whether it is PS/2, USB, etc.

I can't distinguish the messages from card reader and PS/2 keyboard.

Yes, you can.  One of the defining features of the Raw Input API is the ability to distinguish between specific devices.  The WM_INPUT message gives you a handle to the specific device that is generating the message.  You can use GetRawInputDeviceInfo() if you need to retrieve specific details about that device.  On the other hand, you are not going to get WM_INPUT messages from devices that you have not registered with RegisterRawInputDevices().  So, if you register only the card reader, then you will get messages only from the card reader and not the PS/2 keyboard.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

kinlion

  • New member
  • *
  • Posts: 44
  • I Love Lazarus
Re: WM_INPUT never arrived [Win10 b4bit + Lazarus1.8.4 + FPC3.0.4]
« Reply #5 on: December 08, 2018, 08:09:06 am »
Yes, you can.  One of the defining features of the Raw Input API is the ability to distinguish between specific devices.  The WM_INPUT message gives you a handle to the specific device that is generating the message.  You can use GetRawInputDeviceInfo() if you need to retrieve specific details about that device.  On the other hand, you are not going to get WM_INPUT messages from devices that you have not registered with RegisterRawInputDevices().  So, if you register only the card reader, then you will get messages only from the card reader and not the PS/2 keyboard.

Yes, finally I can filter the messages by checking device info.
But I still don't know how to register ONLY the card-reader.
The problem is:
The card-reader makes itself as a HID keyboard.
To register raw input device, one must specify usUsagePage and/or usUsage of the record RAWINPUTDEVICE, and meanwhile the card-reader and PS/2 keyboard share the same values.
So, how can I register only the card-reader?  :(
That would be great if can.
Lazarus 1.8.4 / FPC 3.0.4 / SVN 57972
On Win10 X64, have to compile for Win32

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 616
    • Lebeau Software
Re: WM_INPUT never arrived [Win10 b4bit + Lazarus1.8.4 + FPC3.0.4]
« Reply #6 on: December 10, 2018, 09:12:07 pm »
But I still don't know how to register ONLY the card-reader.
The problem is:
The card-reader makes itself as a HID keyboard.
To register raw input device, one must specify usUsagePage and/or usUsage of the record RAWINPUTDEVICE, and meanwhile the card-reader and PS/2 keyboard share the same values.

Which values exactly?
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

kinlion

  • New member
  • *
  • Posts: 44
  • I Love Lazarus
Re: WM_INPUT never arrived [Win10 b4bit + Lazarus1.8.4 + FPC3.0.4]
« Reply #7 on: December 13, 2018, 07:07:26 am »
Which values exactly?

When register raw input device, I used:
Code: Pascal  [Select]
  1.     usUsagePage := $01;
  2.     usUsage := $06;
  3.  

And the start of the file name of my card-reader is: '\\?\HID#VID_FFFF&PID_0035&MI_00#'
Lazarus 1.8.4 / FPC 3.0.4 / SVN 57972
On Win10 X64, have to compile for Win32

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 616
    • Lebeau Software
Re: WM_INPUT never arrived [Win10 b4bit + Lazarus1.8.4 + FPC3.0.4]
« Reply #8 on: December 13, 2018, 08:33:29 pm »
When register raw input device, I used:
Code: Pascal  [Select]
  1.     usUsagePage := $01;
  2.     usUsage := $06;
  3.  

OK, that pair is generic for keyboards, so it will register all available keyboards.  In which case, to handle messages only from the card reader, you will have to use GetRawInputDeviceList() and GetRawInputDeviceInfo() to discover the HANDLE of the card reader specifically, and then you can ignore any WM_INPUT messages that do not carry that same HANDLE in their RAWINPUT.header info.  No need to call GetRawInputDeviceInfo() on every message.

Otherwise, contact the card reader manufacturer and see if there is an alternative UsagePage+Usage pair available for their card reader that does not identify it as a keyboard.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

kinlion

  • New member
  • *
  • Posts: 44
  • I Love Lazarus
Re: WM_INPUT never arrived [Win10 b4bit + Lazarus1.8.4 + FPC3.0.4]
« Reply #9 on: December 14, 2018, 10:34:35 am »
Otherwise, contact the card reader manufacturer and see if there is an alternative UsagePage+Usage pair available for their card reader that does not identify it as a keyboard.

I hope there is.  :)
Lazarus 1.8.4 / FPC 3.0.4 / SVN 57972
On Win10 X64, have to compile for Win32