-
November 19th, 2006, 07:15 PM
#1
How to make a simple "On screen keyboard".
This example needs a couple buttons.
.NET
Code:
Const HC_ACTION As Int32 = 0
Const HC_GETNEXT As Int32 = 1
Const WM_LBUTTONDOWN As Int32 = 513
Const WM_LBUTTONUP As Int32 = 514
Const WM_RBUTTONDOWN As Int32 = 516
Const WM_RBUTTONUP As Int32 = 517
Const WM_MBUTTONDOWN As Int32 = 519
Const WM_MBUTTONUP As Int32 = 520
Const WM_MOUSEWHEEL As Int32 = 522
Const WM_MOUSEMOVE As Int32 = 512
Const WH_MOUSE_LL As Int32 = 14
Const VK_CONTROL As Int32 = 17
Const VK_MENU As Int32 = 18
Const VK_ESCAPE As Int32 = 27
Const KEYEVENTF_KEYUP As Int32 = 2
Public Structure POINTAPI
Public X, Y As Int32
End Structure
Private Structure MOUSEHOOKSTRUCT
Public pt As POINTAPI
Public hwnd, wHitTestCode, dwExtraInfo As Int32
End Structure
Private Structure MSLLHOOKSTRUCT
Public pt As POINTAPI
Public mouseData, flags, time, dwExtraInfo As Int32
End Structure
Private Declare Function apiSetWindowsMouseHookEx Lib "user32" _
Alias "SetWindowsHookExA" _
(ByVal idHook As Int32, _
ByVal lpfn As MouseHookDelegate, _
ByVal hmod As Int32, _
ByVal dwThreadId As Int32) As Int32
Private Declare Function apiUnhookWindowsHookEx Lib "user32" _
Alias "UnhookWindowsHookEx" _
(ByVal hHook As Int32) As Int32
Private Declare Function apiCallNextMouseHookEx Lib "user32" _
Alias "CallNextHookEx" _
(ByVal hHook As Int32, _
ByVal nCode As Int32, _
ByVal wParam As Int32, _
ByVal lParam As MOUSEHOOKSTRUCT) As Int32
Private Delegate Function MouseHookDelegate _
(ByVal nCode As Int32, _
ByVal wParam As Int32, _
ByRef lParam As MOUSEHOOKSTRUCT) As Int32
Private mCallback As MouseHookDelegate
Private MouseHandle, wfpWnd As Int32
Private Declare Function apikeybd_event Lib "user32" _
Alias "keybd_event" _
(ByVal vKey As Int32, _
ByVal bScan As Byte, _
ByVal dwFlags As Int32, _
ByVal dwExtraInfo As Int32) As Boolean
Private Declare Function apiGetMessageExtraInfo Lib "user32" _
Alias "GetMessageExtraInfo" () As Int32
Private Declare Function apiGetCursorPos Lib "user32" Alias "GetCursorPos" (ByRef lpPoint As POINTAPI) As Boolean
Private Declare Function apiWindowFromPoint Lib "user32" Alias "WindowFromPoint" (ByVal xyPoint As POINTAPI) As Int32
Private Sub Form1_Load _
(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
MouseHook()
End Sub
Private Sub Form1_FormClosed _
(ByVal sender As Object, _
ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
MouseUnHook()
End Sub
Private Function MouseStroke(ByRef hStruct As MOUSEHOOKSTRUCT, ByVal wParam As Int32) As Boolean
On Error Resume Next
If wParam = WM_LBUTTONDOWN Then
wfpWnd = WindowFromPoint()
If wfpWnd = Button1.Handle.ToInt32 Then
apikeybd_event(Keys.A, 0, 0, apiGetMessageExtraInfo)
apikeybd_event(Keys.A, 0, KEYEVENTF_KEYUP, apiGetMessageExtraInfo)
Return True
ElseIf wfpWnd = Button2.Handle.ToInt32 Then
apikeybd_event(Keys.B, 0, 0, apiGetMessageExtraInfo)
apikeybd_event(Keys.B, 0, KEYEVENTF_KEYUP, apiGetMessageExtraInfo)
Return True
End If
ElseIf wParam = WM_LBUTTONUP Then
'
ElseIf wParam = WM_RBUTTONDOWN Then
'
ElseIf wParam = WM_RBUTTONUP Then
'
ElseIf wParam = WM_MOUSEMOVE Then
'
Else
'
End If
End Function
Private Function MouseCallback _
(ByVal Code As Int32, ByVal wParam As Int32, ByRef lParam As MOUSEHOOKSTRUCT) As Int32
On Error Resume Next
If Code = HC_ACTION AndAlso MouseStroke(lParam, wParam) = True Then Return HC_GETNEXT
Return apiCallNextMouseHookEx(MouseHandle, Code, wParam, lParam)
End Function
Private Function MouseHook() As Boolean
On Error Resume Next
mCallback = New MouseHookDelegate(AddressOf MouseCallback)
MouseHandle = apiSetWindowsMouseHookEx _
(WH_MOUSE_LL, mCallback, _
Runtime.InteropServices.Marshal.GetHINSTANCE _
(Reflection.Assembly.GetExecutingAssembly.GetModules()(0)) _
.ToInt32, 0)
Return CBool(MouseHandle)
End Function
Private Function MouseUnHook() As Boolean
On Error Resume Next
MouseHandle = apiUnhookWindowsHookEx(MouseHandle)
Return Not CBool(MouseHandle)
End Function
Public Function WindowFromPoint() As Int32
On Error Resume Next
Dim ret As Int32, p As New POINTAPI
If apiGetCursorPos(p) = False Then Return 0
WindowFromPoint = apiWindowFromPoint(p)
End Function
VB6
Code:
Option Explicit
Const HC_ACTION As Long = 0
Const HC_GETNEXT As Long = 1
Const WH_MOUSE_LL As Long = 14
Const WM_LBUTTONDOWN As Long = 513
Const WM_LBUTTONUP As Long = 514
Const WM_RBUTTONDOWN As Long = 516
Const WM_RBUTTONUP As Long = 517
Const WM_MOUSEMOVE As Long = 512
Const VK_CONTROL As Int32 = 17
Const VK_MENU As Int32 = 18
Const VK_ESCAPE As Int32 = 27
Const KEYEVENTF_KEYUP As Int32 = 2
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Type MOUSEHOOKSTRUCT
pt As POINTAPI
hWnd As Long
wHitTestCode As Long
dwExtraInfo As Long
End Type
Private Declare Function apiCallNextMouseHookEx Lib "user32" Alias "CallNextHookEx" _
(ByVal hHook As Long, _
ByVal nCode As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Private Declare Function apiCopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef pDest As MOUSEHOOKSTRUCT, _
ByVal pSource As Long, _
ByVal cb As Long) As Long
Private Declare Function apiSetWindowsMouseHookEx Lib "user32" Alias "SetWindowsHookExA" _
(ByVal idHook As Long, _
ByVal mHookDel As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
Private Declare Function apiUnhookWindowsHookEx Lib "user32" Alias "UnhookWindowsHookEx" _
(ByVal hHook As Long) As Long
Private phwnd As Long
Private MouseHandle As Long
Private Declare Function apikeybd_event Lib "user32" Alias "keybd_event" _
(ByVal vKey As Long, _
ByVal bScan As Byte, _
ByVal dwFlags As Long, _
ByVal dwExtraInfo As Long) As Boolean
Private Declare Function apiGetMessageExtraInfo Lib "user32" Alias "GetMessageExtraInfo" _
() As Long
Public Function HookIt() As Boolean
On Error Resume Next
MouseHandle = apiSetWindowsMouseHookEx _
(WH_MOUSE_LL, AddressOf MouseCallback, App.hInstance, 0)
End Function
Public Function UnHookIt() As Boolean
On Error Resume Next
MouseHandle = apiUnhookWindowsHookEx(MouseHandle)
End Function
Public Function MouseCallback _
(ByVal Code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
On Error Resume Next
Static hStruct As MOUSEHOOKSTRUCT
Call apiCopyMemory(hStruct, lParam, Len(hStruct))
If Code = HC_ACTION Then
If wParam = WM_LBUTTONDOWN Then
phwnd = WindowFromPoint
If phwnd = frmOSK.Command1.hWnd Then
apikeybd_event(Keys.A, 0, 0, apiGetMessageExtraInfo)
apikeybd_event(Keys.A, 0, KEYEVENTF_KEYUP, apiGetMessageExtraInfo)
MouseCallback = HC_GETNEXT
Exit Function
ElseIf phwnd = frmOSK.Command2.hWnd Then
apikeybd_event(Keys.B, 0, 0, apiGetMessageExtraInfo)
apikeybd_event(Keys.B, 0, KEYEVENTF_KEYUP, apiGetMessageExtraInfo)
MouseCallback = HC_GETNEXT
Exit Function
Else
'
End If
ElseIf wParam = WM_LBUTTONUP Then
'
ElseIf wParam = WM_RBUTTONDOWN Then
'
ElseIf wParam = WM_RBUTTONUP Then
'
End If
End If
MouseCallback = apiCallNextMouseHookEx _
(MouseHandle, Code, wParam, lParam)
End Function
Last edited by TT(n); June 17th, 2010 at 03:45 PM.
Reason: update
-
November 20th, 2006, 03:21 AM
#2
Re: How to make a simple "On screen keyboard".
Do you have a question? Not sure I understand what it is that you're asking but here are some suggestions anyway.
I notice tho that your sub for button 4 is redundant as the event handler for button 3 would do the exact same (you could modify the button 3 MouseDown event handler to read
Code:
Private Sub Button3_MouseDown(ByVal sender As Object, ByVal e As _
System.Windows.Forms.MouseEventArgs) Handles Button3.MouseDown, Button4.MouseDown
Or you could cut your code down to a complete minimum by creating all the button controls programmatically & then processing their events. The code below does pretty much that,
Code:
Option Strict On
Public Class Form1
Dim btn As New Button
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
For Each btn In Me.pnlButtons.Controls
AddHandler btn.Click, AddressOf btn_Click
Next
End Sub
Private Sub btn_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
lblText.Text = lblText.Text & CType(sender, Button).Text
End Sub
End Class
You could include module level boolean variables to flag whether a modifier key was pressed and also add processing to the form KeyUp event (provided the forms KeyPreview property is set to True) instead of using an API call.
Does that help at all?
-
November 20th, 2006, 05:01 PM
#3
Re: How to make a simple "On screen keyboard".
If you didn't notice, the title to the thread is:
"How to...". No question really.
I'm making a list of examples to place in my signature.
There's not much of a need for an elaborate example here, I'm just illustrating the use of key combinations, to return the original foreground window. Clean, simple and pretty reliable.
Not really but thanks anyway.
-
November 21st, 2006, 06:19 AM
#4
Re: How to make a simple "On screen keyboard".
Originally Posted by TT(n)
If you didn't notice, the title to the thread is:
"How to...". No question really.
I did notice but I'm so used to broken English online that I thought there was a question. I'm sure you've seen questions of the type "How to fill a dataset?" or "How to open a Crystal Report?" or "How to consume COM object?" - I thought this was another of those.
I have a few questions for you though (if you don't mind) - why are you using an API call for keyboard events when .NET provides you with this already? Are you trying to trap a specific event?
Why are you posting this in a forum? This could make for good article material. A published article would be far more valuable to you than a few forum threads.
Why are you using redundant code in your example? There are "cleaner" ways of accomplishing the creation of an onscreen keyboard. If you're using this as a base of examples for your signature shouldn't you provide the best possible code that you know how to write? Or have I missed something in your code that doesn't allow you use delegates? I know you write good code which is why this has me so perplexed.
Please - don't misinterpret this, I'm genuinely curious.
-
November 21st, 2006, 07:13 AM
#5
Re: How to make a simple "On screen keyboard".
I hope your not one of those sticklers, when it comes to English.
...always correcting spelling and grammer etc.. lol
Some questions do start with How to... but usually end with a question mark. I see the confusion, although this is a dead give away:
This example uses the Alt + Escape combo to return keyboard focus to the previous application. Meant at face value.
I hadn't seen any good provisions from .NET for keyboard events.
Show me.
Generally I prefer API, because they are true, tried and tested.
That doesn't mean I'm not open to putting up the best, or most elegant example possible, that novice-intermediate readers can still grasp.
I am an intermediate BTW.
I might write up an article, when things are more polished.
Input from others is helpful, so please forgive me If I sounded dismissive.
Hmmm... as I've told you this was an example so it wasn't really redundant to repeat the "L" key. The reader would automatically know(as you should and did) that each button would go to a different key. Actually It was just easier for me to copy and past the whole event, and then change the letter. I spent most of the time working on the return foregroundwindow part. The important part of the example.
Please enlighten me, and post updates to the code here.
My earlier post, looks like I dont appreciate your attempts.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|