|
I am working on a project where I detect HID USB devices, in particular a barcode scanner. I have successfully gotten code the monitors WNDPROC and returns me a value when a particular HID device registers a keypress. I have tried with no success to "handle" events in WNDPROC, but they still make it to the form. The following are a few snippets to show what I have tried
Protected Overloads Overrides Sub WndProc(ByRef message As Message)
If id IsNot Nothing Then
if id.ProcessMessage(message)
End If
If id.Ignore = True Then 'This Is Set To True Only When A Known HID Device Registers A Key Pressed
message.Result = New IntPtr(0)
End If
MyBase.WndProc(message)
End Sub
The following code does work for all controls when I set the KeyPreview on the Form To True
Public Class frmMain
Private Ignore as Boolean = false
Protected Overloads Overrides Sub WndProc(ByRef message As Message)
If id IsNot Nothing Then
if id.ProcessMessage(message)
End If
Ignore = id.ignore
MyBase.WndProc(message)
End Sub
Private Sub frmMain_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress
If Ignore = True Then e.Handled = True
End Sub
end Class
This Method might be the only way, but to me since it occurs in WndProc first, then I should be able to cancel the message at that point rather than wait further down the line. Any help would be greatly appreciated
Ryan
|
|
|
|
|
Ryan Fleming wrote: I am working on a project where I detect HID USB devices, in particular a barcode scanner. I have successfully gotten code the monitors WNDPROC and returns me a value when a particular HID device registers a keypress. I have tried with no success to "handle" events in WNDPROC, but they still make it to the form.
Why?? Wouldn't it just be much easier to add a prefix sequence to the scanned barcode that you can look for in the KeyDown event and either eat or pass the keystrokes appropriately. At least, that's what I was doing about 3 years ago when I did this. If the keypress, and it's successors didn't match the barcode prefix sequence, the keys were passed up the chain. They did match, they got "handled" and the form didn't know anything happened. When the post-fix sequence showed up, I simply assigned the actual barcode to the TextBox that needed to show it.
|
|
|
|
|
I am using multiple HID devices. One a card reader, one a barcode scanner. Multiple textboxes as well. When someone uses the card reader or the barcode scanner I need to know it is different then the keyboard, trap the text and process it appropriately. So unfortunately I can't just monitor text in a single testbox. Otherwise yes it would be easier, and I still use a unique start and end marker for the different HID devices to identify I got a complete message.
So, if anyone knows if I can handle messages in wndProc, like I am doing in the keypress, or has a different solution I am all ears!
Thanks
Ryan
|
|
|
|
|
Ryan Fleming wrote: So unfortunately I can't just monitor text in a single testbox
I didn'y say I monitored test in a textbox. If you turn the Form's KeyPreview property on, you can use the Form's KeyDown event to monitor all keystrokes comming in before they go to any of the forms controls.
|
|
|
|
|
Sorry I read a little more into your answer than you gave, but basically I believe what you suggested is the way I am doing right now. However, unless you know of a way I can identify the actual HID Device sending the text to a keypress, keyup, or keydown event, then I have to use the USB HID class which identifies devices by a handle and unique device name. The HID class determines the device by monitoring a windows forms message which I only now how to get from the wndProc function. If I see that the message in wndProc is from a particular USB device, I set the keyeventargs.handle in the form's keypress event to true, which prevents the text from reaching any controls. Thus my original question is that instead of handling the events in the windows forms keypress, I would like to handle the code in the wndProc. I have posted more complete code below, I always hesitate to post too much because it can confuse the actual question. I added some comments in the code trying to explain what it going on, they are preceded by ***. By the way, I don't want to come across as ranting, I do appreciate your feedback! I'd be happy to post all the code if I am still not getting my question across completely. Lastly I by using the class, I know that no other keypress by another HID device (However unlikely) will not get mixed up in the middle of a transmission. (The card reader takes almost 5 seconds to read all the magnetic strip on a card, plenty of time for a stray keystroke from a keyboard)
Public Class frmMain
Private id As InputDevice '***This Is The Class That Handles USB HID Devices
Private NumberOfKeyboards As Int32
Private HandleText As Boolean = False
Public Overloads Sub Show()
' Create a new InputDevice object, get the number of
' keyboards, and register the method which will handle the
' InputDevice KeyPressed event
id = New InputDevice(handle)
Dim DevicesFound As InputDevice.DeviceInfo() = id.EnumerateDevices()
cmbDevices.Items.Clear()
If DevicesFound Is Nothing Then
cmbDevices.Items.Add("No HID Devices Found!!!")
NumberOfKeyboards = 0
Else
cmbDevices.Items.Add("Handle No Devices")
cmbDevices.Items.AddRange(DevicesFound)
NumberOfKeyboards = DevicesFound.Length
End If
cmbDevices.SelectedIndex = 0
AddHandler id.KeyPressed, AddressOf m_KeyPressed '***Create an Event Handle for the Classes KeyPressed Event
Me.Visible = True
End Sub
' The WndProc is overridden to allow InputDevice to intercept
' messages to the window and thus catch WM_INPUT messages
Protected Overloads Overrides Sub WndProc(ByRef message As Message)
If id IsNot Nothing Then
id.ProcessMessage(message) '***This allows the USB Class To determin if the Message Is From A USB HID Device
'***If it is the m_KeyPressed event is raised
End If
MyBase.WndProc(message)
End Sub
Private Sub m_KeyPressed(ByVal sender As Object, ByVal e As InputDevice.KeyControlEventArgs)
lbHandle.Text = e.Keyboard.deviceHandle.ToString()
lbType.Text = e.Keyboard.deviceType
'**************************************************************************
'Labels Have Trouble Displaying A Single Ampersand So Replace One With two
lbName.Text = e.Keyboard.deviceName.Replace("&", "&&")
'**************************************************************************
lbDescription.Text = e.Keyboard.Name
lbKey.Text = e.Keyboard.key.ToString()
lbNumKeyboards.Text = NumberOfKeyboards.ToString()
lbVKey.Text = e.Keyboard.vKey
If cmbDevices.Text = e.Keyboard.deviceName Then '***If This Device matches a Known Device ID Lets Handle it so it does not show up
'***text on any controls
txtReadOnly.AppendText(e.Keyboard.TextRecieved) '***This is how I would get my text from the USB device and process it
HandleText = True '***This to me is a bit klunky but this flag is the only way in which I
'***can signal the form to handle this text
'***In fact it is possible that if one where banging on the keyboard
'***and using a scanner or card reader, that some text could be blocked
'***from the keyboard as well, but for my application it is highly unlikely
End If
End Sub
'***This event gets fired after the m_KeyPressed event from the USB class via normal windows messaging.
'***If I could handle the message back at the wndProc, I would not need to set a boolean flag in
'***the m_keypressed event, so that I can monitor the boolean flag below and determine whether or
'***not I need to block the keypress from showing up. Instead I could stop it at the wndProc, and get
'***My text from the e.keyboard.textrecieved in the m_KeyPressed
Private Sub frmMain_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress
'You Must Have The Forms KeyPreview protperty set to True for this to work!!!
'This will cause the form to intercept all messsages before individual controls
'on the form do.
If HandleText = True Then
HandleText = False
e.Handled = True
End If
End Sub
End Class
Thanks
Ryan
|
|
|
|
|
Ryan Fleming wrote: id.ProcessMessage(message) '***This allows the USB Class To determin if the Message Is From A USB HID Device
'***If it is the m_KeyPressed event is raised
End If
OK, you need something that keeps track of the input from the individual devices and determines when it has a complete message and when to abandon an incomplete message. THis is where the prefix tags come into play. I'd probably create a class that takes a HID ID and listens for messages from only that HID.
You can call your id.ProcessMessage function, but what does it do?? There's no return information, so it has to raise some kind of message with an identifier and value denoting which device the keystroke value came from. Without that, you've got nothing.
|
|
|
|
|
You can call your id.ProcessMessage function, but what does it do??
In the Form's Show method the following code:
AddHandler id.KeyPressed, AddressOf m_KeyPressed
The code above creates a link to the KeyPressed event of the id class.
When id.ProcessMessage is called, the message is processed and if it comes from a USB HID device a keypressed event is fired which is linked to the m_KeyPressed subroutine in the Form.
The code below shows the information that is passed back to me identifying the device. THIS EVENT GETS FIRED AFTER THE WNDPROC (WITH A USB HID MESSAGE) STARTS, BUT BEFORE THE WNDPROC EVENT IF FINISHED!!!! THIS EVENT ALSO GETS FIRED BEFORE THE FORM'S KEYPRESSED EVENT IS FIRED FOR THE SAME MESSAGE EVALUATED IN WNDPROC.
(I removed the other Information from previous posts and included only that in which I am currently using)
Private Sub m_KeyPressed(ByVal sender As Object, ByVal e As InputDevice.KeyControlEventArgs)
If SavedHIDDeviceName = e.Keyboard.deviceName Then
USBHIDDeviceText = e.Keyboard.TextRecieved)
ProcessHIDText(USBHIDDeviceText)
HandleText = True
End If
End Sub
Private Sub frmMain_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress
If HandleText = True Then
HandleText = False
e.Handled = True
End If
End Sub
From Here I set the HandleText boolean variable to true if it is a recognized device, so when the keypressed event fires I handle the text. It seems cleaner to me to have the processmessage function return a value in wndProc that would signal me to cancel the message before it trickles down to the Form's KeyPressed event, but I can't seem to void the message before it gets returned in the MyBase.WndProc(message) inside the WndProc subroutine. Ideally I could return the text recieved and device information when I call id.Processmessage and void the message before it leaves in the MyBase.WndProc(message), but so far I have not figured out how to void the message like I used to be able to do in callback functions in the VB6 days.
Thanks
Ryan
|
|
|
|
|
Ryan Fleming wrote: THIS EVENT GETS FIRED AFTER THE WNDPROC (WITH A USB HID MESSAGE) STARTS, BUT BEFORE THE WNDPROC EVENT IF FINISHED!!!! THIS EVENT ALSO GETS FIRED BEFORE THE FORM'S KEYPRESSED EVENT IS FIRED FOR THE SAME MESSAGE EVALUATED IN WNDPROC.
OK, so the ProcessMessage call would have to return a value that says if it fired an event or not. If so, then you don't pass the message to the base WndProc method.
|
|
|
|
|
|
dim money as integer
money = 1000000
|
|
|
|
|
prostitution.
Christian Graus
Driven to the arms of OSX by Vista.
|
|
|
|
|
FTW!
Any suggestions, ideas, or 'constructive criticism' are always welcome.
"There's no such thing as a stupid question, only stupid people." - Mr. Garrison
|
|
|
|
|
Volunteer to be a human medical test subject.
|
|
|
|
|
|
Sell your soul
I are troll
|
|
|
|
|
Work for it.
Steve Jowett
-------------------------
Real programmers don't comment their code. If it was hard to write, it should be hard to read.
|
|
|
|
|
He wants to "get" money, not "earn" it
I are troll
|
|
|
|
|
well.. i am still searching for the answer thou..
Audrey
|
|
|
|
|
The government is paying pretty good if you're an executive at a failed US bank or automotive manufacturer.
Any suggestions, ideas, or 'constructive criticism' are always welcome.
"There's no such thing as a stupid question, only stupid people." - Mr. Garrison
|
|
|
|
|
From the bank.
Samir R. Ibrahim
|
|
|
|
|
1) Bid on project X on rentacoder.
2) Come here and ask "HOW TO DO X IN VB. URGENT. CODE PLZ!!"
3) Profit!
|
|
|
|
|
hi,
sorry if this sounds a stupid question but im a beginer so bare with me this is my first non guide based project.
im writing a program that creates a batch file from user entered data.
it then runs and saves the batch file text + result as a text file.
it then displays the text file in a textbox.
this was fine but im trying to develop it further so i now need it to be more simple for the user with more features.
the user can now choose how many times (1-10) the batchfile requests the data.
this works well but the data returned is a complicated unformatted mess.
i would like if possible for the program to read the final text file and return simple formatted results.
eg: instead of "exact returned result for 5x run..
Pinging 192.168.1.1 with 32 bytes of data:Reply from 192.168.1.1: bytes=32 time=24ms TTL=64Reply from 192.168.1.1: bytes=32 time=3ms TTL=64Reply from 192.168.1.1: bytes=32 time=3ms TTL=64Reply from 192.168.1.1: bytes=32 time=3ms TTL=64Reply from 192.168.1.1: bytes=32 time=3ms TTL=64Ping statistics for 192.168.1.1: Packets: Sent = 5, Received = 5, Lost = 0 (0% loss),Approximate round trip times in milli-seconds: Minimum = 3ms, Maximum = 24ms, Average = 7ms
i would prefer just
ping to 192.168.1.1 sucessful 3ms
ping to 192.168.1.1 sucessful 3ms
ping to 192.168.1.1 sucessful 3ms
ping to 192.168.1.1 sucessful 3ms
ping to 192.168.1.1 sucessful 3ms
and to say it failed for eg: "ping to 192.168.1.1 failed"
i know theres more possible results but i'll sort that out later.
i havnt a clue how to do this ive looked high and low but nothing works how i want as the data is completely different everytime.
heres the process code so you can see where im at..
the reason its doubled up is it can ping to IP and name, i just found it easyier that way
Private Sub Button1_Click() Handles Button1.Click
Dim pingamount As Integer
pingamount = NumericUpDown1.Value
If RadioButton1.Checked = True Then
If TextBox1.Text.Length = 0 Or TextBox2.Text.Length = 0 Or TextBox3.Text.Length = 0 Or TextBox4.Text.Length = 0 Then
MsgBox("please enter a valid IP address")
Else : TextBox5.Text = ""
If Form3.TextBox1.TextLength = True Then Form3.Close()
Dim fs As New FileStream("C:\ping.bat", FileMode.Create, FileAccess.Write)
Dim s As New StreamWriter(fs)
s.WriteLine("ping.exe -n " & pingamount & " " & TextBox1.Text & "." & TextBox2.Text & "." & TextBox3.Text & "." & TextBox4.Text & ">C:\ping.txt")
s.Close()
Shell("C:\ping.bat")
Threading.Thread.Sleep(pingamount * 5000)
fs = New FileStream("C:\ping.txt", FileMode.Open, FileAccess.Read)
Dim d As New StreamReader(fs)
d.BaseStream.Seek(0, SeekOrigin.Begin)
While d.Peek() > -1
TextBox5.Text &= d.ReadLine()
End While
d.Close()
Me.Visible = False
Dim f3 As New Form3
f3.Show()
Form3.TextBox1.Text = TextBox5.Text
End If
End If
If RadioButton2.Checked = True Then
If TextBox7.Text.Length = 0 Then
MsgBox("please enter a valid name")
Else : TextBox5.Text = ""
If Form3.Visible = True Then Form3.Close()
Dim fs As New FileStream("C:\ping.bat", FileMode.Create, FileAccess.Write)
Dim s As New StreamWriter(fs)
s.WriteLine("ping.exe -n " & pingamount & " " & TextBox7.Text & ">C:\ping.txt")
s.Close()
Shell("C:\ping.bat")
Threading.Thread.Sleep(pingamount * 5000)
fs = New FileStream("C:\ping.txt", FileMode.Open, FileAccess.Read)
Dim d As New StreamReader(fs)
d.BaseStream.Seek(0, SeekOrigin.Begin)
While d.Peek() > -1
TextBox5.Text &= d.ReadLine()
End While
d.Close()
Me.Visible = False
Dim f3 As New Form3
f3.Show()
Dim fivetext As String
fivetext = TextBox5.Text
Form3.TextBox1.Text = fivetext
End If
End If
End Sub
|
|
|
|
|
Do you need to use an external batch file?
Can you not use the network classes from the framework directly?
|
|
|
|
|
sadly im kinda new to this so its the only way i new
i could try another way.
could you go into more detail
|
|
|
|
|
I use this code
If DataGridView1.RowCount> 0 Then
If DataGridView1.Rows(0).Cells("nadnica").Value <>Nothing Then
CheckBox1.Enabled = True
Else
CheckBox1.Enabled = False
End If
End If
and I want when type first letter in cell DataGridView1.Rows(0).Cells("nadnica") execute
how make this thanks
|
|
|
|
|