Показать полную графическую версию : [решено] Создание меню кнопки
Подскажите как создать меню кнопки, только не контекстное по правой кнопке мыши а обычное через левую. В справке по контекстному меню есть пример и с обычным для собственной кнопки, но как то слишком мудрено через вызовы dll. Есть ли вариант попроще.
В справке по контекстному меню есть пример и с обычным для собственной кнопки, но как то слишком мудрено через вызовы dll. Есть ли вариант попроще. »
Нет, для показа меню (тем более в определённом месте) вызов Dll необходим.
но как то слишком мудрено через вызовы dll »
Проще врятли есть... Просто не обращай внимания на те функции, работа которых непонятна и все.#include <GUIConstantsEx.au3>
Opt("GUIOnEventMode", 1)
$hMainWin= GUICreate("Form1", 408, 229, 192, 193)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Pro_Exit")
$hMainBut = GUICtrlCreateButton("Кнопка", 104, 56, 201, 97, 0)
GUICtrlSetOnEvent(-1, '_ButtonPressed')
$hMenu = GUICtrlCreateContextMenu($hMainBut)
GUICtrlCreateMenuItem('1', $hMenu)
GUICtrlSetOnEvent(-1, '_1')
GUICtrlCreateMenuItem('2', $hMenu)
GUICtrlSetOnEvent(-1, '_2')
GUISetState(@SW_SHOW)
While 1
Sleep(50)
WEnd
Func _1()
MsgBox(0,"","вызвана функция 1",2)
EndFunc
Func _2()
MsgBox(0,"","вызвана функция 2",2)
EndFunc
Func _Pro_Exit()
Exit
EndFunc
Func _ButtonPressed()
_ShowMenu($hMainWin, $hMainBut, $hMenu )
EndFunc
;----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Func _ShowMenu($hWnd, $CtrlID, $nContextID)
Local $arPos, $x, $y
Local $hMenu = GUICtrlGetHandle($nContextID)
$arPos = ControlGetPos($hWnd, "", $CtrlID)
$x = $arPos[0]
$y = $arPos[1] + $arPos[3]
_ClientToScreen($hWnd, $x, $y)
_TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc ;==>ShowMenu
; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func _ClientToScreen($hWnd, ByRef $x, ByRef $y)
Local $stPoint = DllStructCreate("int;int")
DllStructSetData($stPoint, 1, $x)
DllStructSetData($stPoint, 2, $y)
DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint))
$x = DllStructGetData($stPoint, 1)
$y = DllStructGetData($stPoint, 2)
; release Struct not really needed as it is a local
$stPoint = 0
EndFunc ;==>ClientToScreen
; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd)
Func _TrackPopupMenu($hWnd, $hMenu, $x, $y)
DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc ;==>TrackPopupMenu
;----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Ну раз нельзя так нельзя, все равно спасибо
Может объясните еще как сделать меню с элементами цикле (ПунктМеню1, ПунктМеню2, ПунктМеню3) и чтобы для каждого была своя обработка (ПриВыбореПунктаМеню1,ПриВыбореПунктаМеню2,ПриВыбореПунктаМеню3) ну или общая с индексом ПриВыбореПунктаМеню(индекс пункта меню)
как сделать меню с элементами цикле (ПунктМеню1, ПунктМеню2, ПунктМеню3) и чтобы для каждого была своя обработка »
Изменённый пример из справки:
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
;
$hGUI = GUICreate("My GUI", 170, 40)
$OptionsBtn = GUICtrlCreateButton("&Options", 10, 10, 70, 20, $BS_FLAT)
; At first create a dummy control for the options and a contextmenu for it
$OptionsDummy = GUICtrlCreateDummy()
$OptionsContext = GUICtrlCreateContextMenu($OptionsDummy)
$OptionsCommon = GUICtrlCreateMenuItem("Common", $OptionsContext)
$OptionsFile = GUICtrlCreateMenuItem("File", $OptionsContext)
GUICtrlCreateMenuItem("", $OptionsContext)
$OptionsExit = GUICtrlCreateMenuItem("Exit", $OptionsContext)
$HelpBtn = GUICtrlCreateButton("&Help", 90, 10, 70, 20, $BS_FLAT)
; Create a dummy control and a contextmenu for the help too
$HelpDummy = GUICtrlCreateDummy()
$HelpContext = GUICtrlCreateContextMenu($HelpDummy)
$HelpWWW = GUICtrlCreateMenuItem("Website", $HelpContext)
GUICtrlCreateMenuItem("", $HelpContext)
$HelpAbout = GUICtrlCreateMenuItem("About...", $HelpContext)
GUISetState()
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $OptionsExit, $GUI_EVENT_CLOSE
If $nMsg = $OptionsExit Then MsgBox(64, 'Title', "[Exit] item selected.", 0, $hGUI)
ExitLoop
Case $OptionsCommon
MsgBox(64, 'Common...', "[Common] item selected.", 0, $hGUI)
Case $OptionsFile
MsgBox(64, 'File...', "[File] item selected.", 0, $hGUI)
Case $OptionsBtn
ShowMenu($hGUI, $nMsg, $OptionsContext)
Case $HelpBtn
ShowMenu($hGUI, $nMsg, $HelpContext)
Case $HelpWWW
MsgBox(64, "WWW...", "www.autoitscript.com", 0, $hGUI)
ShellExecute("www.autoitscript.com")
Case $HelpAbout
MsgBox(64, "About...", "GUICtrlGetHandle-Sample", 0, $hGUI)
EndSwitch
WEnd
; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func ShowMenu($hWnd, $CtrlID, $nContextID)
Local $arPos, $x, $y
Local $hMenu = GUICtrlGetHandle($nContextID)
$arPos = ControlGetPos($hWnd, "", $CtrlID)
$x = $arPos[0]
$y = $arPos[1] + $arPos[3]
ClientToScreen($hWnd, $x, $y)
TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc ;==>ShowMenu
; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
Local $stPoint = DllStructCreate("int;int")
DllStructSetData($stPoint, 1, $x)
DllStructSetData($stPoint, 2, $y)
DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint))
$x = DllStructGetData($stPoint, 1)
$y = DllStructGetData($stPoint, 2)
; release Struct not really needed as it is a local
$stPoint = 0
EndFunc ;==>ClientToScreen
; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd)
Func TrackPopupMenu($hWnd, $hMenu, $x, $y)
DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc ;==>TrackPopupMenu
Это не то, во-первых создание пунктов меню должно идти в цикле, во вторых заранее неизвестно количество пунктов меню. Вот обрывки кода, с первым вроде разобрался, а вот со вторым нет
$max=IniRead("my.ini","Main","Max","1")
Dim $conMenu[$max]
For $men=1 to $max
$conMenu[$men-1]=GUICtrlCreateMenuItem(IniRead("my.ini","CAP" & $men,"Caption","xxx"), $cmdUpd_submenu)
GUICtrlSetOnEvent(-1, ?????)
Next
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $conMenu[0]
MsgBox (0,"","000")
Case $conMenu[1]
MsgBox (0,"","111")
................................
Case $conMenu[???]
MsgBox (0,"","???")
GUICtrlSetOnEvent можно конечно не вызывать если напрямую использую или если вызывать то какую функцию ставить в параметрах, просто Menu не подойдет.
Может GUIGetMsg (1) вызывать??? Если да то что искать...
GUICtrlSetOnEvent можно конечно не вызывать »
Оно вообще не нужно если обработка не происходит в режиме событии.
То что вам нужно так это использование возможностей Case:
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $conMenu[0] To $conMenu[$max]
MsgBox (0,"", GUICtrlRead($nMsg)) ;Тут используем $nMsg, это и есть идентификатор вызванного контроля (пункт меню)
$conMenu[$men-1]
Вообще то лучше убрать -1, а в начале при объявлении массива добвавить (Dim $conMenu[$max+1]).
И ещё, это может быть опасно вот так задавать размерность массива используя переменную возвращаемую от IniRead ($max). Юзер ведь может там написать -1, и тогда скрипт вывалится с фатальной ошибкой (определение размерности массива). Нужно делать проверку таких переменных.
GUICtrlSetOnEvent(-1, ?????) »
Нужно задать в начале Opt("GUIOnEventMode", 1), и тогда обрабатывать не в цикле, а в функции:
Opt("GUIOnEventMode", 1)
.....
For $men=1 to $max
$conMenu[$men-1]=GUICtrlCreateMenuItem(IniRead("my.ini","CAP" & $men,"Caption","xxx"), $cmdUpd_submenu)
GUICtrlSetOnEvent(-1, "_MenuEvents")
Next
.....
Func _MenuEvents()
MsgBox(0,"", GUICtrlRead(@GUI_CtrlId)) ;Тут используем @GUI_CtrlId, это и есть идентификатор вызванного контроля (пункт меню)
EndFunc
MsgBox (0,"", GUICtrlRead($nMsg)) - возвращает почему-то одно и тоже у меня к примеру 68. А мне надо например 68, 69 или 70 для 3-х пунктов меню
возвращает почему-то одно и тоже у меня к примеру 68 »
Это состояние (State) элемента. Я забыл, для получения текста нужно так - GUICtrlRead($nMsg, 1).
А мне надо например 68, 69 или 70 для 3-х пунктов меню »
Т.е идентификаторы? Ну так я же написал, $nMsg это и есть ID.
Спасибо Creat0R, все узнал что хотел, вот мой пример, вдруг кому понадобится,меню через левую кнопку мыши смотреть выше.
#include <GuiConstants.au3>
;~ Создаем форму
$Form1 = GUICreate("Zzz", 100, 100, @DesktopWidth/2-50, @DesktopHeight/2-50,-1)
;~ создали кнопку
$cmdUpd = GUICtrlCreateButton("Кнопочка", 10, 20, 73, 22, 0)
GUICtrlSetTip(-1, "Нажми правой кнопкой мыши на кнопке")
;~ создаем контекстное меню
$cmdUpd_con = GUICtrlCreateContextMenu($cmdUpd)
;~ создаем для контекстного меню, субменю со списком
$cmdUpd_submenu = GUICtrlCreateMenu("Основное >>", $cmdUpd_con)
;~ задаем макс. количество пунктв меню (у меня будет считываться из ини-файла)
$max=3
;~ создаем массив пунктов меню
Dim $conMenu[$max]
;~ формируем пункты меню в цикле
;~ названия у меня опять же будут считываться из ини-файла
For $men=1 to $max
$conMenu[$men-1]=GUICtrlCreateMenuItem("ПунктМеню" & $men, $cmdUpd_submenu)
Next
GUISetState(@SW_SHOW)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
;~ здесь обрабатываются все созданные пункты меню
Case $conMenu[0] To $conMenu[$max-1]
MsgBox (0,"ID пункта меню- " & $nMsg,GUICtrlRead($nMsg,1))
EndSwitch
WEnd
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.
Available in ZeroNet 1osznRoVratMCN3bFoFpR2pSV5c9z6sTC