Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   [решено] Создание меню кнопки (http://forum.oszone.net/showthread.php?t=150148)

malev 10-09-2009 08:26 1215348

Создание меню кнопки
 
Подскажите как создать меню кнопки, только не контекстное по правой кнопке мыши а обычное через левую. В справке по контекстному меню есть пример и с обычным для собственной кнопки, но как то слишком мудрено через вызовы dll. Есть ли вариант попроще.

Creat0R 10-09-2009 12:35 1215534

Цитата:

Цитата malev
В справке по контекстному меню есть пример и с обычным для собственной кнопки, но как то слишком мудрено через вызовы dll. Есть ли вариант попроще. »

Нет, для показа меню (тем более в определённом месте) вызов Dll необходим.

beve 10-09-2009 12:38 1215544

Цитата:

Цитата malev
но как то слишком мудрено через вызовы 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
;----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


malev 10-09-2009 19:50 1215997

Ну раз нельзя так нельзя, все равно спасибо

malev 10-09-2009 21:16 1216063

Может объясните еще как сделать меню с элементами цикле (ПунктМеню1, ПунктМеню2, ПунктМеню3) и чтобы для каждого была своя обработка (ПриВыбореПунктаМеню1,ПриВыбореПунктаМеню2,ПриВыбореПунктаМеню3) ну или общая с индексом ПриВыбореПунктаМеню(индекс пункта меню)

Creat0R 10-09-2009 23:34 1216166

Цитата:

Цитата malev
как сделать меню с элементами цикле (ПунктМеню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


malev 11-09-2009 10:49 1216420

Это не то, во-первых создание пунктов меню должно идти в цикле, во вторых заранее неизвестно количество пунктов меню. Вот обрывки кода, с первым вроде разобрался, а вот со вторым нет
Код:

$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) вызывать??? Если да то что искать...

Creat0R 11-09-2009 15:44 1216611

Цитата:

Цитата malev
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, и тогда скрипт вывалится с фатальной ошибкой (определение размерности массива). Нужно делать проверку таких переменных.

Цитата:

Цитата malev
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


malev 11-09-2009 16:26 1216648

MsgBox (0,"", GUICtrlRead($nMsg)) - возвращает почему-то одно и тоже у меня к примеру 68. А мне надо например 68, 69 или 70 для 3-х пунктов меню

Creat0R 11-09-2009 17:03 1216676

Цитата:

Цитата malev
возвращает почему-то одно и тоже у меня к примеру 68 »

Это состояние (State) элемента. Я забыл, для получения текста нужно так - GUICtrlRead($nMsg, 1).

Цитата:

Цитата malev
А мне надо например 68, 69 или 70 для 3-х пунктов меню »

Т.е идентификаторы? Ну так я же написал, $nMsg это и есть ID.

malev 11-09-2009 20:24 1216823

Спасибо 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



Время: 15:47.

Время: 15:47.
© OSzone.net 2001-