Hi everyone,
First of all I want to thank everyone in advance and to apologize because I have very little experience playing with wndproc and messages.
I'm using the code of the following link (converted to Visual Basic and a bit modified) to intercept the keys from a barcode scanner and pass them to the instantiating class when the enter key is received, not letting the keydown be processed using prefiltermessage to don't let the key be processed in the focuseed control/form.
Distinguishing Barcode Scanners from the Keyboard in WinForms
At the moment I don't have a barcode scanner, but for testing purposes, I'm using a second USB keyboard attached to the computer, that should do the trick.
The following subs/functions are the basic core of the barcode scanner intercepter. There is a C++ interop library developed by the author of the previous link for making the GetRawInputInfo and handling the devices, although I think they have nothing to do with the problem.
Public Class BarcodeScannerListener
Private keystrokeBuffer As StringBuilder
Friend Event BarcodeScanned(BarCode As String)
Protected Overrides Sub WndProc(ByRef m As Message)
'Debug.Print(m.Msg)
Select Case m.Msg
Case WM_INPUT
Dim deviceInfo As BarcodeScannerDeviceInfo = Nothing
Dim handled As Boolean = False
Dim keystroke As Boolean = False
Dim localBuffer As String = String.Empty
Dim rawInputDeviceHandle As IntPtr = IntPtr.Zero
Me.interopHelper.GetRawInputInfo(m.LParam, rawInputDeviceHandle, keystroke, localBuffer)
If Me.devices.TryGetValue(rawInputDeviceHandle, deviceInfo) AndAlso keystroke Then
Me.filter.FilterNext = True
If localBuffer.Length = 1 AndAlso Asc(localBuffer(0)) = 13 Then
Dim barcode As String = Me.keystrokeBuffer.ToString()
If barcode IsNot Nothing AndAlso barcode.Length > 0 Then
Me.keystrokeBuffer = New StringBuilder()
RaiseEvent BarcodeScanned(barcode)
End If
Else
Me.keystrokeBuffer.Append(localBuffer)
End If
Else
Me.filter.FilterNext = False
End If
Exit Select
End Select
MyBase.WndProc(m)
End Sub
End Class
Public Class BarcodeScannerKeyDownMessageFilter
Implements IMessageFilter
Public Property FilterNext() As Boolean
Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
Dim filter As Boolean = False
If Me.FilterNext AndAlso m.Msg = WM_KEYDOWN Then
filter = True
Me.FilterNext = False
End If
Return filter
End Function
End Class
Class UsingBarcode
Private WithEvents CodeReaderHandler As New BarcodeScannerListener
Private Sub OnBarcodeScanned(Barcode As String) Handles CodeReaderHandler.BarcodeScanned
MsgBox(barcode)
End Sub
End Class
After receiving the Enter key from the keyboard the barcode string is perfectly sent using the BarcodeScanned event, but the msgbox is not shown, but I can hear the bip os the messagebox in the speakers. If I put a second msgbox just after the first one, the second msgbox works perfectly.
It looks like some message from the Enter key is passing through to the msgbox and the default button is being clicked before the user does, so the first msgbox dissapears and the second works fine. For what I can see, a keydown event is never fired for the Enter key, and a keyup event is being fired and it gets to the instantiating form. I've tried to put an stop in the prefiltermessage with the keyup message and setting the filter to true manually after pressing the Enter key, but still the key gets to the form's keyup event, so I supossed is getting to the messasgebox too.
As a workaround I'm firing 2 msgbox instead of one, but is not an elegant solution.
Anyone knows the answer? I've been trying to look for a solution for myself and in Google, but I couldn't find any, so any help will be really appreciated.