Note that for non-relative mouse movement (i.e. if MOUSEEVENTF_ABSOLUTE is not specified as part of dwFlags), negative values for dx and dy are desirable. As such, the "uint" type specification for C# can be safely replaced with Int32.
//Use the values of this enum for the 'dwData' parameter //to specify an X button when using MouseEventFlags.XDOWN or //MouseEventFlags.XUP for the dwFlags parameter. public enum MouseEventDataXButtons : uint { XBUTTON1 = 0x00000001, XBUTTON2 = 0x00000002 }
VB.Net Signature:
This function does indeed return a value, just as the keybd_event API does.
If there is a real error, it will in fact return a value of false, or zero.
The dwExtraInfo appears to be a ULONG_PTR in C++ (IntPtr in VB.NET)
Declare Function apimouse_event Lib "user32.dll" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dX As Int32, ByVal dY As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32) As Boolean
Notes:
FYI, Microsoft tells us for "Windows NT/2000/XP: This function has been superseded. Use SendInput instead."
The C# code below works fine. However you have to keep in mind to add the namespace "System.Runtime.InteropServices" and keep in mind to write the code into a class.
Original contributor tells us:aa
I wanted to emulate the scroll. Searching for this information wasn't easy ... but here is how you do the mouse scroll button
The scroll value can actually be any value larger than 1, if used within a loop.
This allows you to smoothly increment the scrollbar, instead of relying on the inconsistent wheel delta,
which is a variable limited by the user, for mouse wheel. Start-Control Panel-Mouse-Wheel-Scrolling
VB.NET Sample Code:
Const MOUSEEVENTF_WHEEL As Int32 = 2048 Const MOUSEEVENTF_WHEEL_DELTA As Int32 = 120
Private Declare Function apimouse_event Lib "user32" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dX As Int32, ByVal dY As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32) As Boolean Private Declare Function apiGetMessageExtraInfo Lib "user32" Alias "GetMessageExtraInfo" () As Int32
Private Sub PlayScroll(ByVal number As Int32, Optional ByVal increment As Int32 = 2) On Error Resume Next For i As Int32 = 1 To number apimouse_event(MOUSEEVENTF_WHEEL, 0, 0, increment, apiGetMessageExtraInfo) Next End Sub
C# Sample Code:
[DllImport("user32.dll")] static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
This code assumes a form called frmMain with a command button called cmdClick a picture box called picClicker and a text box called txtResults
Note Twips are no more. Also, I stripped the FOR loop of delta moves from the command button click to the middle of the picture box.
Option Explicit On
Friend Class frmMain
Inherits System.Windows.Forms.Form
Declare Auto Sub mouse_event Lib "user32" (ByVal dwFlags As Int32, ByVal dx As Int32, ByVal dy As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As IntPtr)
Const MOUSEEVENTF_MOVE As Int32 = &H1 ' mouse move Const MOUSEEVENTF_LEFTDOWN As Int32 = &H2 ' left button down Const MOUSEEVENTF_LEFTUP As Int32 = &H4 ' left button up Const MOUSEEVENTF_RIGHTDOWN As Int32 = &H8 ' right button down Const MOUSEEVENTF_RIGHTUP As Int32 = &H10 ' right button up Const MOUSEEVENTF_MIDDLEDOWN As Int32 = &H20 ' middle button down Const MOUSEEVENTF_MIDDLEUP As Int32 = &H40 ' middle button up Const MOUSEEVENTF_ABSOLUTE As Int32 = &H8000 ' absolute move Const MOUSEEVENTF_WHEEL As Int32 = &H800 ' wheel button rolled
' Simulate moving the mouse to the center of the ' PictureBox and clicking. Private Sub cmdClick_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdClick.Click Dim cur_x As Single Dim cur_y As Single Dim dest_x As Single Dim dest_y As Single
' mouse_event moves in a coordinate system where ' (0, 0) is in the upper left corner and ' (65535,65535) is in the lower right corner.
' Get the current mouse coordinates and convert ' them into this new system. cur_x = System.Windows.Forms.Cursor.Position.X * 65535 / System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width cur_y = System.Windows.Forms.Cursor.Position.Y * 65535 / System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height
' Convert the coordinates of the center of the ' picClicker PictureBox into this new system. Dim pt As Point = picClicker.PointToScreen(New Point(picClicker.ClientRectangle.Width / 2, picClicker.ClientRectangle.Height / 2))
' Move the mouse to its final destination and click it. mouse_event(MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_MOVE + MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, dest_x, dest_y, 0, 0) End Sub
Private Sub picClicker_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles picClicker.Click txtResults.Text = txtResults.Text & "MouseClick" & vbCrLf End Sub
Private Sub picClicker_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picClicker.MouseDown txtResults.Text = txtResults.Text & "MouseDown (" & e.X & ", " & e.Y & ")" & vbCrLf End Sub
Private Sub picClicker_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picClicker.MouseUp txtResults.Text = txtResults.Text & "MouseUp (" & e.X & ", " & e.Y & ")" & vbCrLf End Sub
Dim eMouse As New System.Windows.Forms.MouseEventArgs(Windows.Forms.MouseButtons.Left, 1, pt.X, pt.Y, 0)
Me.OnMouseDown(eMouse)
Me.OnMouseMove(eMouse)
Me.OnMouseUp(eMouse)
to work as desired. Although it did trigger mouse events in the form showing the movement and click action desired, it didn't move the mouse pointer on the screen nor did it trigger events in the picture box located at pt.X, pt.Y
Thus I have resigned myself to unmanaged code for now. I will post the SendInput version shortly as mouse_event has been deprecated by Bill in favor ofSendInput.
As the original contributor noted:
You can use the System.Windows.Forms.Cursor.Position property to set the position of the mouse, if you would like.
You will note I have replaced the GetCursorPos calls in the original VB source with this as suggested in the MSDN URL I mention above.
<DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, _ CharSet:=CharSet.Unicode, EntryPoint:="keybd_event", _ ExactSpelling:=True, SetLastError:=True)> _ Public Shared Function keybd_event(ByVal bVk As Byte, ByVal bScan As Byte, _ ByVal dwFlags As Int32, ByVal dwExtraInfo As Int32) As Boolean End Function
This sample will generate a 'Scroll Lock' key press event when the user clicks 'Button1'.
Create a new Windows Application project;
Drop a button control in the recently created form;
Add the following code to the form class:
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, _ CharSet:=CharSet.Unicode, EntryPoint:="keybd_event", _ ExactSpelling:=True, SetLastError:=True)> _ Public Shared Sub keybd_event(ByVal bVk As Byte, ByVal bScan As Byte, _ ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer) As Boolean End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Const VK_SCROLL As Byte = &H91 Const KEYEVENTF_KEYUP As Byte = &H2
keybd_event(VK_SCROLL, 0, 0, 0) ' Generates a KEY_DOWN keybd_event(VK_SCROLL, 0, KEYEVENTF_KEYUP, 0) ' Generates a KEY_UP
End Sub
End Class
Please add some more!
Alternative Managed API: System.Windows.Forms.SendKeys
PROBLEM: How do i use combination of shift and tab keys at the same time ?
public const byte VK_LSHIFT= 0xA0; // left shift key public const byte VK_TAB = 0x09; public const int KEYEVENTF_EXTENDEDKEY = 0x01; public const int KEYEVENTF_KEYUP = 0x02;
//press the shift key keybd_event(VK_LSHIFT, 0x45, 0, 0);
//press the tab key keybd_event(VK_TAB, 0x45, 0, 0);
//release the tab key keybd_event(VK_TAB, 0x45, KEYEVENTF_KEYUP, 0);
//release the shift key keybd_event(VK_LSHIFT, 0x45, KEYEVENTF_KEYUP, 0);
I'm using this to create automated UI testing for a custom Textbox control. After a lot of trial and error the following code worked well for me.
public partial class Form2 : Form { [DllImport("user32.dll", SetLastError = true)] static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
void PressKey(Keys key) { const int KEYEVENTF_EXTENDEDKEY = 0x1; const int KEYEVENTF_KEYUP = 0x2; // I had some Compile errors until I Casted the final 0 to UIntPtr like this... keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr)0); keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr)0); }
When you want to set a timer working with GUI, you always come across threading problem. In such scenario, .Net indeed makes programmers life easier. It only matters that you choose the right timer to use.
In Win Form, you need to use System.Windows.Forms.Timer.
In WPF, the one is System.Windows.Threading.DispatcherTimer.