Я ищу способ автоматизации стороннего производителя и VBA с использованием Windows API. Мне уже удалось автоматизировать другие элементы управления, такие как командные кнопки, текстовые поля, списки (почти), вкладки и т. Д. Я действительно уверен, что это не будет иметь большого значения в отношении того, что мне уже удалось достижения, но по некоторым причинам это не удается для элементов управления меню.
Мне уже удалось управлять пунктами меню в «базовых» приложениях, таких как «Блокнот», «Блокнот ++» и т. Д. Я думаю, что не все меню управляются одинаково (идентификатор и позиция), но мне не удалось чтобы проверить, какой случай относится к моему целевому приложению.
Option explicit
FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
Declare PtrSafe Function GetMenu Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Declare PtrSafe Function GetSubMenu Lib "user32" (ByVal hMenu As LongPtr, ByVal nPos As Long) As LongPtr
Declare PtrSafe Function GetMenuItemID Lib "user32" (ByVal hMenu As LongPtr, ByVal nPos As Long) As Long
Declare PtrSafe Function GetMenuString Lib "user32" Alias "GetMenuStringA" (ByVal hMenu As LongPtr, ByVal wIDItem As Long, ByVal lpString As String, ByVal nMaxCount As Long, ByVal wFlag As Long) As Long
Declare PtrSafe Function GetMenuInfo Lib "user32" (ByVal hMenu As LongPtr, ByRef lpcmi As MENUINFO) As Long 'not sure it really exists
Public Type MENUINFO
cbSize As Long
fMask As Long
dwStyle As Long 'MNS_NOTIFYBYPOS
cyMax As Long
hbrBack As Long
dwContextHelpID As Long
dwMenuData As Long
End Type
Public Const MNS_NOTIFYBYPOS As Long = &H8000000
Public Const WM_COMMAND As Long = &H111
Public Const WM_MENUCOMMAND As Long = &H126
Public Const MF_BYCOMMAND As Long = &H0&
Public Const MF_BYPOSITION As Long = &H400
'---------------------------------
'
Sub test()
Dim hwnd As LongPtr: hwnd = FindWindow(lpClassName:="Notepad", lpWindowText:="Untitled - Notepad")
'Overall menu
Dim hMenu As LongPtr: hMenu = GetMenu(hwnd:=hwnd)
'File sub-menu
Dim hSubMenu As LongPtr: hSubMenu = GetSubMenu(hMenu:=hMenu, nPos:=0)
'Open... command ID
Dim menuItem As Long: menuItem = GetMenuItemID(hMenu:=hSubMenu, nPos:=1)
Dim infoMenu As MENUINFO
infoMenu.cbSize = Len(infoMenu)
Dim lRet As Long: lRet = GetMenuInfo(hMenu:=hMenu, lpcmi:=infoMenu) 'returns 0 - not sure it really exists as I only found examples on Russian-spoken websites...
'infoMenu.dwStyle ---> MNS_NOTIFYBYPOS to check, but infoMenu fails
Debug.Print Err.LastDllError 'returns 87, ie. Invalid parameter I believe
'Debug.Print menuString(hMenu:=hMenu, wIDItem:=1, wFlag:=MF_BYPOSITION)
'wParam:
' Menu: 0 ~ Menu identifier (IDM_*)
' Accelerator: 1 ~ Menu identifier (IDM_*)
'lParam: 0&
PostMessage hwnd:=hwnd, wMsg:=WM_COMMAND, wParam:=GetMenuItemID(hMenu:=hSubMenu, nPos:=3), lParam:=ByVal 0& ' OK open the Notepad Open dialog (asynchronously)
'wParam: The zero-based index of the item selected.
'lParam: A handle to the menu for the item selected.
'PostMessage(hwnd:=hwnd, wMsg:=WM_MENUCOMMAND, wParam:=1, lParam:=hwndSubMenu) 'not tested with the targeted app yet
End Sub
Подскажите, пожалуйста, в чем разница между WM_COMMAND и WM_NOTIFY ? Я уже где-то читал, что WM_NOTIFY будет работать точно так же для современных приложений, которые требуют передачи дополнительных параметров, но меня это смущает!