1

Тема: AHK: Поиск заданного пункта в панели меню

Благодаря пользователю Malcev, использую условие на основе проверки активности заданного пункта меню:


WordWrap := SelectMenu("ahk_class Notepad", 2, 0)

if WordWrap = 8
	MsgBox Word Wrap is Active!
else
	MsgBox Word Wrap is not Active!
return

SelectMenu(program, SubMenuNumber, ItemNumber){
	Hwnd := WinExist(program)
	MainMenu := DllCall("GetMenu", UInt, Hwnd)
	SubMenu := DllCall("GetSubMenu", UInt, MainMenu, Int, SubMenuNumber)
	SendMessage, 0x117, SubMenu, ItemNumber,, ahk_id %Hwnd% ; WM_INITMENUPOPUP
	return DllCall("GetMenuState", UInt, SubMenu, UInt, ItemNumber, UInt, 0x400)
}

В программе, в которой я работаю, такой пункт имеет свойство перемещаться в порядковом расположении.
Необходимо, чтобы при запуске сценария, заданный пункт проверялся на порядковое расположение в подменю. Т.е. на основе данного примера, производился поиск пункта Word Wrap не по всей панели меню, а для ускорения поиска, внутри меню Format, после чего ему присваивался ItemNumber. В сети нашел menu-search.ahk, но не знаю, как его использовать. Помогите, пожалуйста, реализовать такой поиск.

2 (изменено: serzh82saratov, 2017-05-01 19:18:19)

Re: AHK: Поиск заданного пункта в панели меню

Если я понял задачу, то так можно по имени, индексу или вперемешку.


#SingleInstance Force
#NoEnv

; Path := ["3&", "1&"]     ;	разделители тоже в счёт
Path := ["Формат", "Перенос по словам"]
hWnd := WinExist("ahk_class Notepad ahk_exe notepad.exe")
MsgBox % GetItemStateMenu(Path, hWnd)
Return 

GetItemStateMenu(Path, hWnd) {
	Static MF_BYPOSITION := 0x400, States := {"MF_CHECKED":0x00000008, "MF_DISABLED":0x00000002, "MF_GRAYED":0x00000001}
	If !hWnd
		Return "Окно не найдено"
	hMenu := DllCall("GetMenu", Ptr, Hwnd)
	p := GetItemMenu(hMenu, Path)
	If (State := DllCall("GetMenuState", "Ptr", p.hMenu, "UInt", p.idx, "UInt", MF_BYPOSITION)) = -1
		Return "Пункт не найден"
	For k, v in States
		If (State & v)
			Return k
	Return "MF_ENABLED"
}

GetItemMenu(hMenu, Path, Key = 1) {
	Static MF_BYPOSITION := 0x400
	Item := Path[Key]
	Loop, % DllCall("GetMenuItemCount", "Ptr", hMenu)
	{
		If (Item ~= "^\d+&$")
		{
			idx := SubStr(Item, 1, -1) - 1 
			If (Key < Path.MaxIndex())
				Return GetItemMenu(DllCall("GetSubMenu", "Ptr", hMenu, "Uint", idx), Path, Key + 1)
			Return {hMenu:hMenu,idx:idx}
		}
		Else
		{
			idx := A_Index - 1
			idn := DllCall("GetMenuItemID", "Ptr", hMenu, "int", idx)
			nSize++ := DllCall("GetMenuString", "Ptr", hMenu, "Uint", idx, "Uint", 0, "Uint", 0, "Uint", MF_BYPOSITION)
			nSize := (nSize * (A_IsUnicode ? 2 : 1))
			VarSetCapacity(sString, nSize)
			DllCall("GetMenuString", "Ptr", hMenu, "Uint", idx, "Str", sString, "Uint", nSize, "Uint", MF_BYPOSITION)   ; MF_BYPOSITION
			StringReplace, String, sString, &, , 1
			If (Item != String)
				Continue
			If (Key < Path.MaxIndex())
				Return GetItemMenu(DllCall("GetSubMenu", "Ptr", hMenu, "Uint", idx), Path, Key + 1)
			Return {hMenu:hMenu,idx:idx}
		}
	}
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

3 (изменено: becauseim, 2017-05-01 23:11:37)

Re: AHK: Поиск заданного пункта в панели меню

serzh82saratov, спасибо! Но у меня, к соожалению, не получается сделать условие.
Но больше хотелось бы применить результат к уже имеющейся форме из первого поста. Т.е. присвоить полученный порядковый номер значению ItemNumber (последний параметр функции):


Path := ["Формат", "Перенос по словам"]
; ...узнаем, что пункт "Перенос по словам" значится под нулевым порядковым номером
WordWrap := SelectMenu("ahk_class Notepad", 2, 0)

Еще необходима проверка в т.ч. подпунктов меню (в данном случае Timeline):
http://puu.sh/vClAS/e356d9ad18.png

4

Re: AHK: Поиск заданного пункта в панели меню

Так?

msgbox % GetMenuNumber("ahk_class Premiere Pro", 6, 0, "Reset to Saved Layout	Alt+Shift+0")

GetMenuNumber(program, Number1, Number2, Name)
{
   Hwnd := WinExist(program)
   hMenu := DllCall("GetMenu", Ptr, Hwnd)
   loop 2
      hMenu := DllCall("GetSubMenu", Ptr, hMenu, Int, Number%A_Index%)
   count := DllCall("GetMenuItemCount", Ptr, hMenu)
   loop % count
   {
      VarSetCapacity(MENUITEMINFO, size := 4*4 + A_PtrSize*8, 0)
      NumPut(size, MENUITEMINFO)
      NumPut(0x40, &MENUITEMINFO + 4)   ;  MIIM_STRING := 0x40
      DllCall("GetMenuItemInfo", Ptr, hMenu, UInt, A_Index - 1, UInt, true, Ptr, &MENUITEMINFO)
      TextLength := NumGet(&MENUITEMINFO + 4*4 + A_PtrSize*6, "UInt")
      VarSetCapacity(TextBuff, TextLength * (A_IsUnicode ? 2 : 1), 0)
      NumPut(&TextBuff, &MENUITEMINFO + 4*4 + A_PtrSize*5)
      NumPut(++TextLength, &MENUITEMINFO + 4*4 + A_PtrSize*6)
      DllCall("GetMenuItemInfo", Ptr, hMenu, UInt, A_Index - 1, UInt, true, Ptr, &MENUITEMINFO)
      InfoString := StrGet(&TextBuff)
      if (InfoString = name)
         return A_Index - 1
   }
}

5

Re: AHK: Поиск заданного пункта в панели меню

Malcev, да, выдает порядковый номер расположения пункта начиная с нуля. Спасибо! Только я еще не учел то, что и имя пункта меняется в зависимости от его положения в списке, а именно, горячая клавиша. Т.е. необходимо добавить чувствительность к имени пункта, чтобы было достаточно одного слова.

6

Re: AHK: Поиск заданного пункта в панели меню

Уверен, что это вы уже сами сможете сделать.