Управление меню сторонних приложений с помощью Windows API - PullRequest
0 голосов
/ 11 июля 2019

Я ищу способ автоматизации стороннего производителя и 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 будет работать точно так же для современных приложений, которые требуют передачи дополнительных параметров, но меня это смущает!

...