This code is a combo of two great piece of code. From this example you will learn the following items
- How to generate various mouse events using mouse_event API - How display shortcut menu created at runtime using CreatePopupMenu and TrackPopupMenu APIs - How to use MF_MENUBARBREAK flag to split Menu into several columns if total height of menu exceeds than user defined limit.
The whole example is well documeted so I think you wont have any problem to understand it.
Step-By-Step Example
- Create a standard exe project - Add one command button, one textbox (MultiLine=True and ScroolBar=Both) and one timer control on the form1 - Add the following code in form1 |
Click here to copy the following block | Option Explicit
Const MF_UNCHECKED = &H0& Const MF_CHECKED = &H8& Const MF_DISABLED = &H2& Const MF_GRAYED = &H1& Const MF_SEPARATOR = &H800& Const MF_STRING = &H0& Const MF_POPUP = &H10& Const MF_BYCOMMAND = &H0& Const MF_MENUBARBREAK = &H20& Const MF_BYPOSITION = &H400&
Const TPM_LEFTALIGN = &H0& Const TPM_RETURNCMD = &H100& Const TPM_NONOTIFY = &H80&
Private Declare Function GetCursorPos Lib "user32" ( _ lpPoint As POINTAPI) As Long
Private Declare Function ClientToScreen Lib "user32" ( _ ByVal hwnd As Long, _ lpPoint As POINTAPI) As Long
Private Declare Sub mouse_event Lib "user32" ( _ ByVal dwFlags As Long, _ ByVal dx As Long, _ ByVal dy As Long, _ ByVal cButtons As Long, _ ByVal dwExtraInfo As Long)
Private Declare Function CreatePopupMenu Lib "user32" () As Long
Private Declare Function TrackPopupMenu Lib "user32" ( _ ByVal hMenu As Long, _ ByVal wFlags As Long, _ ByVal x As Long, _ ByVal y As Long, _ ByVal nReserved As Long, _ ByVal hwnd As Long, _ ByVal lprc As Any) As Long
Private Declare Function AppendMenu Lib "user32" Alias "AppendMenuA" ( _ ByVal hMenu As Long, _ ByVal wFlags As Long, _ ByVal wIDNewItem As Long, _ ByVal lpNewItem As Any) As Long
Private Declare Function DestroyMenu Lib "user32" ( _ ByVal hMenu As Long) As Long
Private Declare Function GetMenuItemRect Lib "user32" ( _ ByVal hwnd As Long, _ ByVal hMenu As Long, _ ByVal uItem As Long, _ lprcItem As RECT) As Long
Private Declare Function GetSystemMetrics Lib "user32" ( _ ByVal nIndex As Long) As Long
Const SM_CYMENU = 15
Enum enumMouseEvents MOUSEEVENTF_MOVE = &H1 MOUSEEVENTF_LEFTDOWN = &H2 MOUSEEVENTF_LEFTUP = &H4 MOUSEEVENTF_RIGHTDOWN = &H8 MOUSEEVENTF_RIGHTUP = &H10 MOUSEEVENTF_MIDDLEDOWN = &H20 MOUSEEVENTF_MIDDLEUP = &H40 MOUSEEVENTF_WHEEL = &H800 MOUSEEVENTF_ABSOLUTE = &H8000 End Enum
Private Type POINTAPI x As Long y As Long End Type
Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type
Const MAX_MENU_ITEMS = 50
Dim hMenu As Long, iCnt As Long
Sub FireMouseEvent(Optional EventFlag As enumMouseEvents = MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_MOVE, _ Optional destX = 0, Optional destY = 0, _ Optional NumMoves = 200, Optional hWndClient As Long = 0)
Dim pt As POINTAPI Dim cur_x As Single Dim cur_y As Single Dim dest_x As Single Dim dest_y As Single Dim dx As Single Dim dy As Single Dim i As Integer
GetCursorPos pt
cur_x = pt.x * 65535 / (Screen.Width / Screen.TwipsPerPixelX) cur_y = pt.y * 65535 / (Screen.Height / Screen.TwipsPerPixelY)
pt.x = destX pt.y = destY
If hWndClient <> 0 Then ClientToScreen hWndClient, pt
dest_x = pt.x * 65535 / (Screen.Width / Screen.TwipsPerPixelX) dest_y = pt.y * 65535 / (Screen.Height / Screen.TwipsPerPixelY)
dx = (dest_x - cur_x) / NumMoves dy = (dest_y - cur_y) / NumMoves
If (dest_x = cur_x And dest_y = cur_y) = False And (EventFlag And MOUSEEVENTF_MOVE) = MOUSEEVENTF_MOVE Then For i = 1 To NumMoves - 1 cur_x = cur_x + dx cur_y = cur_y + dy mouse_event MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_MOVE, cur_x, cur_y, 0, 0 DoEvents Next i End If
mouse_event EventFlag, dest_x, dest_y, 0, 0 End Sub
Sub CreateTestPopup() Dim i, mHeight As Long, fHeight As Long, sM As Long Dim R As RECT
hMenu = CreatePopupMenu()
Me.ScaleMode = vbPixels
mHeight = 0 fHeight = Me.ScaleHeight
sM = GetSystemMetrics(SM_CYMENU)
For i = 0 To MAX_MENU_ITEMS - 1 If (mHeight > fHeight) Then mHeight = 0 AppendMenu hMenu, MF_STRING Or MF_MENUBARBREAK Or MF_BYCOMMAND, ByVal i, "Item-" & CStr(i) Else AppendMenu hMenu, MF_STRING Or MF_BYCOMMAND, ByVal i, "Item-" & CStr(i) End If mHeight = mHeight + sM Next
End Sub
Private Sub Command1_Click() Dim pt As POINTAPI, ClickedItem
Me.ScaleMode = vbPixels pt.x = Command1.Left pt.y = Command1.Top + Command1.Height
ClientToScreen Me.hwnd, pt
CreateTestPopup
Timer1.Interval = 300 Timer1.Enabled = True iCnt = 0 ClickedItem = TrackPopupMenu(hMenu, TPM_RETURNCMD Or TPM_LEFTALIGN, pt.x, pt.y, 0, Me.hwnd, ByVal 0&) If ClickedItem > 0 Then MsgBox "Clicked : Item #" & ClickedItem Timer1.Enabled = False End Sub
Sub AutoMouseDemo(Optional PickMouseItem = 0, Optional DoClick As Boolean = False) Dim R As RECT, pt As POINTAPI, i As Integer
If (GetMenuItemRect(0, hMenu, PickMouseItem, R)) = 0 Then Exit Sub
pt.x = R.Left + (R.Right - R.Left) / 2 pt.y = R.Top + (R.Bottom - R.Top) / 2
Dim EventFlag As enumMouseEvents
If DoClick = True Then EventFlag = MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_MOVE + MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP Else EventFlag = MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_MOVE End If
FireMouseEvent EventFlag, pt.x, pt.y, 1 If DoClick = False Then LogEvent "Mouse Move >> Item-" & PickMouseItem & " (" & pt.x & "," & pt.y & ")" Else LogEvent "Mouse Click >> Item-" & PickMouseItem & " (" & pt.x & "," & pt.y & ")" End If End Sub
Sub LogEvent(strMsg As String) Text1 = strMsg & vbCrLf & Text1 End Sub
Private Sub Form_Unload(Cancel As Integer) DestroyMenu hMenu End Sub
Private Sub Timer1_Timer() If iCnt >= MAX_MENU_ITEMS Then Timer1.Enabled = False: iCnt = 0 If iCnt = 10 Then AutoMouseDemo iCnt, True Else AutoMouseDemo iCnt End If iCnt = iCnt + 1 End Sub |
- Press F5 to run the project - Click on the command1 and watch the automatic movement of mouse cursor. |
|