Что нового

Элементы GUI Создать кнопку на лету с меню на левый клик мыши

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
комбо, конечно, подходит. но на скрине плавающая панель инструментов . а это уже отдельное окно.
по сути задачи это не решение. с другой стороны, если комбо подходит на все сто, то все есть в справке

можно сделать имитацию панели
с картинками и функциями. причем функции менять динамически

Код:
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <WinAPIConstants.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>


Global $iInputTmp, $iButtonCH, $iButtonCH1, $iButtonCH2, $Form1


Global $hSubGUI, $flS
Local $SimpleInput, $SimpleInput1, $SimpleInput2, $SimpleInput3
Local $aParam_Inputs[10]
Local $iOK_Bttn, $iCancel_Bttn
Local $whPos, $aCurInfo, $winpos, $aCurP
$hSubGUI = GUICreate('Sub GUI', 500, 420, -1, -1, $WS_POPUP)
GUISetFont(11)
GUISetBkColor(0x00AACC)
Global $Title = GUICtrlCreateLabel('   Заголовок', 0, 0, 440, 30, BitOR($SS_CENTERIMAGE, $SS_LEFT), $GUI_WS_EX_PARENTDRAG)
GUICtrlSetBkColor(-1, 0x0000FF)
GUICtrlSetColor(-1, 0xFFFFFF)
Global $Mini = GUICtrlCreateLabel('-', 440, 0, 30, 30, $SS_CENTER + $SS_CENTERIMAGE)
GUICtrlSetFont($Mini, 24, 800, 0, "Georgia")
GUICtrlSetBkColor(-1, 0x0000FF)
GUICtrlSetColor(-1, 0xFFFFFF)
Global $Close = GUICtrlCreateLabel('X', 470, 0, 30, 30, $SS_CENTER + $SS_CENTERIMAGE)
GUICtrlSetFont($Close, 10, 800, 0, "Georgia")
GUICtrlSetBkColor(-1, 0x0000FF)
GUICtrlSetColor(-1, 0xFFFFFF)
$SimpleInput = GUICtrlCreateInput('', 20, 35, 300, 22)
$SimpleInput1 = GUICtrlCreateInput('', 170, 102, 60, 22)
$SimpleInput2 = GUICtrlCreateInput('', 170, 132, 60, 22)
$SimpleInput3 = GUICtrlCreateInput('', 300, 132, 60, 22)

GUICtrlCreateLabel('1', 30, 210, 20, 20)
$aParam_Inputs[1] = GUICtrlCreateInput('', 40, 210, 100, 20)
GUICtrlCreateLabel('2', 30, 235, 20, 20)
$aParam_Inputs[2] = GUICtrlCreateInput('', 40, 235, 100, 20)
GUICtrlCreateLabel('3', 30, 260, 20, 20)
$aParam_Inputs[3] = GUICtrlCreateInput('', 40, 260, 100, 20)
GUICtrlCreateLabel('4', 190, 210, 20, 20)
$aParam_Inputs[4] = GUICtrlCreateInput('', 205, 210, 100, 20)
GUICtrlCreateLabel('5', 190, 235, 20, 20)
$aParam_Inputs[5] = GUICtrlCreateInput('', 205, 235, 100, 20)
GUICtrlCreateLabel('6', 190, 260, 20, 20)
$aParam_Inputs[6] = GUICtrlCreateInput('', 205, 260, 100, 20)
GUICtrlCreateLabel('7', 350, 210, 20, 20)
$aParam_Inputs[7] = GUICtrlCreateInput('', 360, 210, 100, 20)
GUICtrlCreateLabel('8', 350, 235, 20, 20)
$aParam_Inputs[8] = GUICtrlCreateInput('', 360, 235, 100, 20)
GUICtrlCreateLabel('9', 350, 260, 20, 20)
$aParam_Inputs[9] = GUICtrlCreateInput('', 360, 260, 100, 20)
$iOK_Bttn = GUICtrlCreateButton('OK', 120, 380, 105, 25)
$iCancel_Bttn = GUICtrlCreateButton('Cancel', 240, 380, 105, 25)
Local $iBF = GUICtrlCreateButton('', 0, 0)
GUICtrlSetState(-1, $GUI_HIDE)
ControlFocus($hSubGUI, '', $iBF)
GUISetState(@SW_SHOW, $hSubGUI)
_GuiB($hSubGUI)
Local $sFolder
While 1
    If $flS = 2 Then
        $sFolder = FileSelectFolder('', '', 0, '', $Form1)
        If Not @error Then GUICtrlSetData($SimpleInput, $sFolder)
        $flS = 1
    EndIf
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $iCancel_Bttn, $iOK_Bttn
            Exit
        Case $GUI_EVENT_PRIMARYUP
            $aCurP = GUIGetCursorInfo($Form1)
            If Not @error And $aCurP[4] > 0 Then ContinueLoop
            $aCurInfo = GUIGetCursorInfo($hSubGUI)
            If @error Or Not $aCurInfo[4] Then
                GUISetState(@SW_HIDE, $Form1)
                $iInputTmp = 0
                ContinueLoop
            EndIf
            If $iInputTmp = $aCurInfo[4] Then ContinueLoop
            $whPos = ControlGetPos($hSubGUI, '', $aCurInfo[4])
            $winpos = WinGetPos($hSubGUI)
            If $aCurInfo[4] = $SimpleInput1 Or $aCurInfo[4] = $SimpleInput2 Or $aCurInfo[4] = $SimpleInput3 Or $aCurInfo[4] = $SimpleInput Then
                If $aCurInfo[4] = $SimpleInput Then
                    GUICtrlSetImage($iButtonCH2, "shell32.dll", 4)
                    $flS = 1
                Else
                    $flS = 0
                    GUICtrlSetImage($iButtonCH2, "shell32.dll", 24)
                EndIf
                WinMove($Form1, '', $whPos[0] + $winpos[0], $whPos[1] - 20 + $winpos[1])
                GUISetState(@SW_SHOW, $Form1)
                ControlFocus($hSubGUI, '', $aCurInfo[4])
                $iInputTmp = $aCurInfo[4]
                ContinueLoop
            Else
                For $i = 1 To 9
                    If $aCurInfo[4] = $aParam_Inputs[$i] Then
                        If $flS Then GUICtrlSetImage($iButtonCH2, "shell32.dll", 24)
                        $flS = 0
                        WinMove($Form1, '', $whPos[0] + $winpos[0], $whPos[1] - 20 + $winpos[1])
                        GUISetState(@SW_SHOW, $Form1)
                        ControlFocus($hSubGUI, '', $aCurInfo[4])
                        $iInputTmp = $aCurInfo[4]
                        ContinueLoop
                    EndIf
                Next
            EndIf
    EndSwitch
WEnd


Func _GuiB($hWND)
    $Form1 = GUICreate("Form1", 85, 20, 0, 0, $WS_POPUP, BitOR($WS_EX_MDICHILD, $WS_EX_TOOLWINDOW), $hWND)
    GUISetBkColor(0xAAAACC)
    $iButtonCH = GUICtrlCreateIcon('', '', 0, 0, 25, 20)
    GUICtrlSetImage(-1, "shell32.dll", 22)
    $iButtonCH1 = GUICtrlCreateIcon('', '', 30, 0, 25, 20)
    GUICtrlSetImage(-1, "shell32.dll", 23)
    $iButtonCH2 = GUICtrlCreateIcon('', '', 60, 0, 25, 20)
    GUISetState(@SW_HIDE, $Form1)
    GUIRegisterMsg($WM_COMMAND, 'WM_COMMAND')
EndFunc   ;==>_GuiB

Func WM_COMMAND($hWND, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $lParam
    Switch BitAND($wParam, 0x0000FFFF)
        Case $iButtonCH
            GUICtrlSetData($iInputTmp, '1Ex_' & Random(2, 5, 1) + Random(2, 5, 1))
            ControlFocus($hSubGUI, '', $iInputTmp)
        Case $iButtonCH1
            GUICtrlSetData($iInputTmp, '2Ex_' & Random(2, 5, 1) + Random(2, 5, 1))
            ControlFocus($hSubGUI, '', $iInputTmp)
        Case $iButtonCH2
            If $flS = 1 Then
                $flS = 2
            ElseIf Not $flS Then
                GUICtrlSetData($iInputTmp, '3Ex_' & Random(2, 5, 1) + Random(2, 5, 1))
            EndIf
            ControlFocus($hSubGUI, '', $iInputTmp)
        Case $Mini
            GUISetState(@SW_MINIMIZE, $hSubGUI)
        Case $Close
            Exit
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND
 
Последнее редактирование:
Автор
L

liond66

Новичок
Сообщения
117
Репутация
2
Спасибо за ваши примеры.
CreatoR
Это выглядит вполне рабочим.
Но если честно, глаз режут стрелочки на комбо.
Да, я сказал что комбо было бы неплохим решением, но это типа как из двух зол выбираешь меньшее.
Потому что другие элементы или плохо отрисовывались, или была проблема с фокусом.
Но ...
joiner
Вам удалось сделать один в один, как в оригинале!!!
У меня пару дней не будет времени разобраться с кодом, возможно появятся вопросы.
Поэтому тему не закрываю, но пока однозначно лайк!
 

xXx

╚{■_■}╗
Меценат
Сообщения
248
Репутация
95
В догонку
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Global $hPanel, $hSubGUI, $aWinPos, $aControlPos, $a_idInputPos[7] = [6]
Global $idCtrl, $idPrew, $iPanelState, $idButton_Ok, $idButton_1, $idButton_2

$hSubGUI = GUICreate('Sub GUI', 323, 150)
$a_idInputPos[1] = GUICtrlCreateInput('', 40, 10, 100, 20)
$a_idInputPos[2] = GUICtrlCreateInput('', 40, 40, 100, 20)
$a_idInputPos[3] = GUICtrlCreateInput('', 40, 70, 100, 20)
$a_idInputPos[4] = GUICtrlCreateInput('', 200, 10, 100, 20)
$a_idInputPos[5] = GUICtrlCreateInput('', 200, 40, 100, 20)
$a_idInputPos[6] = GUICtrlCreateInput('', 200, 70, 100, 20)

$idButton_Ok = GUICtrlCreateButton('Ok', 120, 110, 100)
GUICtrlSetState(-1, $GUI_FOCUS)

$hPanel = GUICreate('', 36, 18, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_MDICHILD, $hSubGUI)
GUISetBkColor(0xFFFDC7)
$idButton_1 = GUICtrlCreateIcon('shell32.dll', -278, 1, 1, 16, 16)
$idButton_2 = GUICtrlCreateIcon('shell32.dll', -237, 18, 1, 16, 16)

GUISetState(@SW_SHOW, $hSubGUI)

GUIRegisterMsg($WM_COMMAND, '_WM_COMMAND')

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE ;, $idButton_Ok
            Exit
        Case $idButton_1
            MsgBox(262144 + 64, '', '')
        Case $idButton_2
            MsgBox(262144 + 48, '', '')
    EndSwitch

    If $idCtrl And $idCtrl <> $idPrew Then
        For $i = 1 To $a_idInputPos[0]
            If ($idCtrl = $a_idInputPos[$i]) Then
                $aWinPos = WinGetPos($hSubGUI)
                $aControlPos = ControlGetPos($hSubGUI, '', '[ID:' & $a_idInputPos[$i] & ']')
                If Not @error Then
                    WinMove($hPanel, '', $aWinPos[0] + $aControlPos[0], $aWinPos[1] + $aControlPos[1] + 6)
                    If Not $iPanelState Then GUISetState(@SW_SHOW, $hPanel)
                    GUICtrlSetState($idCtrl, $GUI_FOCUS)
                    $iPanelState = 1
                    $idPrew = $a_idInputPos[$i]
                    $idCtrl = 0
                    ExitLoop
                EndIf
            EndIf
        Next
        If $idCtrl Then
            GUISetState(@SW_HIDE, $hPanel)
            $iPanelState = 0
            $idCtrl = 0
        EndIf
    EndIf
WEnd

; === USER FUNCTIONS: =====================================================
Func _WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    If $hWnd = $hSubGUI Then $idCtrl = BitAND($wParam, 0x0000FFFF)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_COMMAND
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,484

Ещё вариант на этой (почти) основе (учитывает все вышесказанные замечания):

Код:
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPIConv.au3>

Global $hSub_GUI, $hOpt_GUI
Global $aInputs[7] = [6]

$hSub_GUI = GUICreate('Sub GUI', 340, 150)

$aInputs[1] = GUICtrlCreateInput('', 40, 10, 100, 20)
$aInputs[2] = GUICtrlCreateInput('', 40, 40, 100, 20)
$aInputs[3] = GUICtrlCreateInput('', 40, 70, 100, 20)
$aInputs[4] = GUICtrlCreateInput('', 200, 10, 100, 20)
$aInputs[5] = GUICtrlCreateInput('', 200, 40, 100, 20)
$aInputs[6] = GUICtrlCreateInput('', 200, 70, 100, 20)

$iOK_Bttn = GUICtrlCreateButton('Ok', 120, 110, 100)
GUICtrlSetState(-1, $GUI_FOCUS)

$hOpt_GUI = GUICreate('', 36, 18, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_MDICHILD, $hSub_GUI)
GUISetBkColor(0xFFFDC7)
$iOpt1_Bttn = GUICtrlCreateIcon('shell32.dll', -278, 1, 1, 16, 16)
$iOpt2_Bttn = GUICtrlCreateIcon('shell32.dll', -237, 18, 1, 16, 16)

$iEnter_Dummy = GUICtrlCreateDummy()
Dim $aAccelKeys[1][2] = [['{ENTER}', $iEnter_Dummy]]
GUISetAccelerators($aAccelKeys, $hSub_GUI)

GUISetState(@SW_SHOW, $hSub_GUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $iOpt1_Bttn
            GUISetState(@SW_HIDE, $hOpt_GUI)
            MsgBox(262144 + 64, '', '', 0, $hSub_GUI)
        Case $iOpt2_Bttn
            GUISetState(@SW_HIDE, $hOpt_GUI)
            MsgBox(262144 + 48, '', '', 0, $hSub_GUI)
        Case $GUI_EVENT_PRIMARYUP
            _CheckFocus()
        Case $iEnter_Dummy
            For $i = 1 To $aInputs[0]
                If _GUICtrlIsFocused($hSub_GUI, $aInputs[$i]) Then
                    If $i = $aInputs[0] Then
                        GUISetState(@SW_HIDE, $hOpt_GUI)
                        GUICtrlSetState($iOK_Bttn, $GUI_FOCUS)
                        ExitLoop
                    EndIf
                    
                    GUICtrlSetState($aInputs[$i + 1], $GUI_FOCUS)
                    _CheckFocus($aInputs[$i + 1])
                    ExitLoop
                EndIf
            Next
    EndSwitch
WEnd

Func _CheckFocus($iID = 0)
    Local $aWinPos, $aCtrlPos, $tPoint
    
    If Not $iID Then
        $iID = GUIGetCursorInfo($hSub_GUI)[4]
    EndIf
    
    If Not _GUICtrlIsFocused($hSub_GUI, $iID) Then
        GUISetState(@SW_HIDE, $hOpt_GUI)
        Return
    EndIf
    
    For $i = 1 To $aInputs[0]
        If $aInputs[$i] = $iID Then
            $aCtrlPos = ControlGetPos($hSub_GUI, '', $aInputs[$i])
            $tPoint = DllStructCreate('int X;int Y')
            
            $tPoint.X = $aCtrlPos[0]
            $tPoint.Y = $aCtrlPos[1]
            
            _WinAPI_ClientToScreen($hSub_GUI, $tPoint)
            
            If Not @error Then
                WinMove($hOpt_GUI, '', $tPoint.X, $tPoint.Y - $aCtrlPos[3])
                GUISetState(@SW_SHOWNOACTIVATE, $hOpt_GUI)
                Return
            EndIf
        EndIf
    Next
    
    GUISetState(@SW_HIDE, $hOpt_GUI)
EndFunc

Func _GUICtrlIsFocused($hGUI, $iCtrlID)
    Return (ControlGetHandle($hGUI, '', ControlGetFocus($hGUI)) = GUICtrlGetHandle($iCtrlID))
EndFunc
 
Последнее редактирование:
Автор
L

liond66

Новичок
Сообщения
117
Репутация
2
Улучшения от CreatoR исправляют пример от xXx тем, что при клике на пустом месте панель инструментов исчезает.
В первом посте я упоминал, что на кнопку будет добавлено меню. В оригинале даже многоуровневое.
Два вопроса. Оба касаются примеров от joiner и совместный от xXx - CreatoR :
1. Будет ли это так же гладко работать при вызове из дочернего меню?
Это не всегда одно и то же, поэтому я в примере именно так показал.
2. Можно ли на некоторые кнопки добавить меню? Опций может быть много.

Можете ли вы добавить эти два пункта в свои примеры?
Спасибо.

menu.png
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
указать меню можно без проблем, и новые дочерние окна можно делать и прочее и прочее. в этой теме есть все примеры. только соединяй)
Безымянный.jpg
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,484
Будет ли это так же гладко работать при вызове из дочернего меню?
Да.
Можно ли на некоторые кнопки добавить меню? Опций может быть много.
Да.
Вопрос в другом (и я уже задавал его), будут ли эти функции глобальными, или меняться от поля к полю?
Также нужно понимать, что на момент вызова меню, ввод невозможен.
 
Автор
L

liond66

Новичок
Сообщения
117
Репутация
2
Вопрос в другом (и я уже задавал его), будут ли эти функции глобальными, или меняться от поля к полю?
Я предполагал, что поля созданные группой через масив будут иметь одинаковые функции.
А другие могут иметь другие вырианты. Зачем ограничиватся.
ув. joiner показал пример с тремя выриантами кнопок.
После этого я считал что вопрос автоматически отпал.

Также нужно понимать, что на момент вызова меню, ввод невозможен.
Невозможно кликнуть одновременно на ввод и на панель инструментов (для вызова меню).
Я не понимаю, в чём может быть проблема.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,484
Невозможно кликнуть одновременно на ввод и на панель инструментов (для вызова меню).
Пока отображается панель ввод возможен, он перестанет быть возможным после появления меню, т.к оно берёт на себя фокус.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,484
Вообщем вот что у меня получилось:

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPIConv.au3>

Global Enum $iPanel_GUI, $iPanel_Bttn, $iPanel_Menu, _
        $iPanel_Total

Global $iLastCtrlID = -1

Global $aInputs1[4] = [3]
Global $aInputs2[4] = [3]

$hSub_GUI = GUICreate('Sub GUI', 340, 150)

$aInputs1[1] = GUICtrlCreateInput('', 40, 10, 100, 20)
$aInputs1[2] = GUICtrlCreateInput('', 40, 40, 100, 20)
$aInputs1[3] = GUICtrlCreateInput('', 40, 70, 100, 20)

$aInputs2[1] = GUICtrlCreateInput('', 200, 10, 100, 20)
$aInputs2[2] = GUICtrlCreateInput('', 200, 40, 100, 20)
$aInputs2[3] = GUICtrlCreateInput('', 200, 70, 100, 20)

$iOK_Bttn = GUICtrlCreateButton('Ok', 120, 110, 100)
GUICtrlSetState(-1, $GUI_FOCUS)

;Must be 8 elements array, where...
;[0][0] - Button icon 1
;[0][1] - Button icon id 1
;[0][2] - Menu option FuncName
;[0][3] - Menu item name 1
;[0][4 + N] - Menu item name N
;[1][1] - Button icon 2
;[1][N] - Button icon id N and so on
Dim $aItems[2][] = _
        [ _
        ['shell32.dll', -278, '_Opt_Proc', 'Opt1', 'Opt2'], _
        ['shell32.dll', -237, '_Opt_Proc', 'Opt3', 'Opt4'] _
        ]
$aPanel1 = _Panel_Create($hSub_GUI, $aItems)

Dim $aItems[2][] = _
        [ _
        ['shell32.dll', -260, '_Opt_Proc', 'Opt5', 'Opt6'], _
        ['shell32.dll', -250, '_Opt_Proc', 'Opt7', 'Opt8'] _
        ]
$aPanel2 = _Panel_Create($hSub_GUI, $aItems)

GUISetState(@SW_SHOW, $hSub_GUI)

While 1
    $aMsg = GUIGetMsg(1)
    
    Switch $aMsg[0]
        Case 0
            ContinueLoop
        Case $GUI_EVENT_CLOSE
            Exit
        Case Else
            _Panel_Events($hSub_GUI, $aPanel1, $aMsg)
            _Panel_Events($hSub_GUI, $aPanel2, $aMsg)
    EndSwitch
WEnd

Func _Opt_Proc($sTextID, $iInputID)
    Local $sData = $sTextID & ' Calc'
    
    ;Can be ommited, just to show how to separate options
    Switch $sTextID
        Case 'Opt1'
            $sData = 'Opt1 Calc'
        Case 'Opt2'
            $sData = 'Opt2 Calc'
        Case 'Opt3'
            $sData = 'Opt3 Calc'
        Case 'Opt4'
            $sData = 'Opt4 Calc'
        Case 'Opt5'
            $sData = 'Opt5 Calc'
        Case 'Opt6'
            $sData = 'Opt6 Calc'
        Case 'Opt7'
            $sData = 'Opt7 Calc'
        Case 'Opt8'
            $sData = 'Opt8 Calc'
    EndSwitch
    
    GUICtrlSetData($iInputID, $sData)
EndFunc

Func _Panel_Create($hParent, $aItems)
    If UBound($aItems, 0) <> 2 Then
        Return SetError(1, 0, 0)
    EndIf
    
    Local $iUbnd = UBound($aItems)
    Local $aRet[$iUbnd][$iPanel_Total]
    Local $aMenu, $iW = 18 * $iUbnd, $iH = 18
    
    $aRet[0][$iPanel_GUI] = GUICreate('', $iW, $iH, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_MDICHILD, $hParent)
    GUISetBkColor(0xFFFDC7)
    
    For $iItem = 0 To $iUbnd - 1
        $aRet[$iItem][$iPanel_Bttn] = GUICtrlCreateIcon($aItems[$iItem][0], $aItems[$iItem][1], 1 + ($iItem * 16), 1, 16, 16)
        
        Dim $aMenu[1][2]
        $aMenu[0][0] = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
        
        For $i = 3 To UBound($aItems, 2) - 1
            If $aItems[$iItem][$i] Then
                $iUbnd = UBound($aMenu)
                ReDim $aMenu[$iUbnd + 1][2]
                
                $aMenu[$iUbnd][0] = GUICtrlCreateMenuItem($aItems[$iItem][$i], $aMenu[0][0])
                $aMenu[$iUbnd][1] = $aItems[$iItem][2] ;FuncName
            EndIf
        Next
        
        $aRet[$iItem][$iPanel_Menu] = $aMenu
        $aMenu = 0
    Next
    
    Return $aRet
EndFunc

Func _Panel_Events($hParent, $aPanel, $aMsg)
    If $aMsg[0] = $GUI_EVENT_PRIMARYUP And $aMsg[1] = $hParent Then
        _Panel_CheckFocus($hParent, $aPanel1, $aInputs1)
        _Panel_CheckFocus($hParent, $aPanel2, $aInputs2)
        Return
    EndIf
    
    For $i = 0 To UBound($aPanel) - 1
        $aMenu = $aPanel[$i][$iPanel_Menu]
        
        If $aMsg[0] = $aPanel[$i][$iPanel_Bttn] Then
            _GUICtrlMenu_Show($aPanel[0][$iPanel_GUI], $aMenu[0][0], $aMsg[0])
            Return 1
        EndIf
        
        For $j = 1 To UBound($aMenu) - 1
            If $aMsg[0] = $aMenu[$j][0] Then
                Call($aMenu[$j][1], GUICtrlRead($aMenu[$j][0], 1), $iLastCtrlID)
                GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
                Return 1
            EndIf
        Next
    Next
    
    Return 0
EndFunc

Func _Panel_CheckFocus($hParent, $aPanel, $aInputs, $iID = 0)
    Local $aCtrlPos, $iX, $iY
    
    If Not $iID Then
        $iID = GUIGetCursorInfo($hParent)[4]
    EndIf
    
    If Not _GUICtrlIsFocused($hParent, $iID) Then
        GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
        Return 0
    EndIf
    
    $iLastCtrlID = $iID
    
    For $i = 1 To $aInputs[0]
        If $aInputs[$i] = $iID Then
            $aCtrlPos = ControlGetPos($hParent, '', $aInputs[$i])
            
            $iX = $aCtrlPos[0]
            $iY = $aCtrlPos[1]
            
            _ClientToScreen($hParent, $iX, $iY)
            
            If Not @error Then
                WinMove($aPanel[0][$iPanel_GUI], '', $iX, $iY - $aCtrlPos[3])
                GUISetState(@SW_SHOWNOACTIVATE, $aPanel[0][$iPanel_GUI])
                Return 1
            EndIf
        EndIf
    Next
    
    GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
    Return 0
EndFunc

Func _GUICtrlMenu_Show($hWnd, $nContextID, $nContextControlID)
    Local $hMenu = GUICtrlGetHandle($nContextID)
    Local $aCtrlPos = ControlGetPos($hWnd, '', $nContextControlID)
    
    Local $iX = $aCtrlPos[0]
    Local $iY = $aCtrlPos[1] + $aCtrlPos[3]
    
    _ClientToScreen($hWnd, $iX, $iY)
    
    DllCall('user32.dll', 'int', 'TrackPopupMenuEx', 'hwnd', $hMenu, 'int', 0, 'int', $iX, 'int', $iY, 'hwnd', $hWnd, 'ptr', 0)
EndFunc

Func _GUICtrlIsFocused($hGUI, $iCtrlID)
    Return(ControlGetHandle($hGUI, '', ControlGetFocus($hGUI)) = GUICtrlGetHandle($iCtrlID))
EndFunc

Func _ClientToScreen($hWnd, ByRef $iX, ByRef $iY)
    Local $tPoint = DllStructCreate('int X;int Y')
    
    $tPoint.X = $iX
    $tPoint.Y = $iY
    
    _WinAPI_ClientToScreen($hWnd, $tPoint)
    
    $iX = $tPoint.X
    $iY = $tPoint.Y
EndFunc


Для вложенных меню нужно будет немного изменить, но в принципе не трудно адаптировать.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,484
Вот версия с вложенными меню (один уровень):

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPIConv.au3>

Global Enum $iPanel_GUI, $iPanel_Func, $iPanel_Bttn, $iPanel_Menu, _
        $iPanel_Total

Global $aInputs1[4] = [3]
Global $aInputs2[4] = [3]

$hSub_GUI = GUICreate('Sub GUI', 340, 150)

$aInputs1[1] = GUICtrlCreateInput('', 40, 10, 100, 20)
$aInputs1[2] = GUICtrlCreateInput('', 40, 40, 100, 20)
$aInputs1[3] = GUICtrlCreateInput('', 40, 70, 100, 20)

$aInputs2[1] = GUICtrlCreateInput('', 200, 10, 100, 20)
$aInputs2[2] = GUICtrlCreateInput('', 200, 40, 100, 20)
$aInputs2[3] = GUICtrlCreateInput('', 200, 70, 100, 20)

$iOK_Bttn = GUICtrlCreateButton('Ok', 120, 110, 100)
GUICtrlSetState(-1, $GUI_FOCUS)

;Must be 8 elements array, where...
;[0][0] - Button icon 1
;[0][1] - Button icon id 1
;[0][2] - Menu option FuncName
;[0][3] - Menu item name 1 (If begins with [MENU], considered as submenu item, and all other strings separated with | considered as subitems).
;[0][4 + N] - Menu item name N
;[1][1] - Button icon 2
;[1][N] - Button icon id N and so on
Dim $aItems[2][] = _
        [ _
        ['shell32.dll', -278, '_Opt_Proc', 'Opt1', '[MENU]Opt2 Menu|Sub Opt1|Sub Opt2'], _
        ['shell32.dll', -237, '_Opt_Proc', 'Opt3', 'Opt4'] _
        ]
$aPanel1 = _Panel_Create($hSub_GUI, $aItems)

Dim $aItems[2][] = _
        [ _
        ['shell32.dll', -260, '_Opt_Proc', 'Opt5', 'Opt6'], _
        ['shell32.dll', -250, '_Opt_Proc', '[MENU]Opt7 Menu|Sub Opt1|Sub Opt2', 'Opt8'] _
        ]
$aPanel2 = _Panel_Create($hSub_GUI, $aItems)

GUISetState(@SW_SHOW, $hSub_GUI)

While 1
    $aMsg = GUIGetMsg(1)
   
    Switch $aMsg[0]
        Case 0
            ContinueLoop
        Case $GUI_EVENT_CLOSE
            Exit
        Case Else
            _Panel_Events($hSub_GUI, $aPanel1, $aMsg)
            _Panel_Events($hSub_GUI, $aPanel2, $aMsg)
    EndSwitch
WEnd

Func _Opt_Proc($sTextID, $iInputID)
    Local $sData = $sTextID & ' Calc'
   
    ;Can be ommited, just to show how to separate options
    Switch $sTextID
        Case 'Opt1'
            $sData = 'Opt1 Calc'
        Case 'Opt2'
            $sData = 'Opt2 Calc'
        Case 'Opt3'
            $sData = 'Opt3 Calc'
        Case 'Opt4'
            $sData = 'Opt4 Calc'
        Case 'Opt5'
            $sData = 'Opt5 Calc'
        Case 'Opt6'
            $sData = 'Opt6 Calc'
        Case 'Opt7'
            $sData = 'Opt7 Calc'
        Case 'Opt8'
            $sData = 'Opt8 Calc'
    EndSwitch
   
    GUICtrlSetData($iInputID, $sData)
EndFunc

Func _Panel_Create($hParent, $aItems)
    If UBound($aItems, 0) <> 2 Then
        Return SetError(1, 0, 0)
    EndIf
   
    Local $iUbnd = UBound($aItems)
    Local $aRet[$iUbnd][$iPanel_Total]
    Local $aMenu, $aSplit, $iSubMenu, $iW = 18 * $iUbnd, $iH = 18
   
    $aRet[0][$iPanel_GUI] = GUICreate('', $iW, $iH, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_MDICHILD, $hParent)
    GUISetBkColor(0xFFFDC7)
   
    For $iItem = 0 To $iUbnd - 1
        $aRet[$iItem][$iPanel_Func] = $aItems[$iItem][2]
        $aRet[$iItem][$iPanel_Bttn] = GUICtrlCreateIcon($aItems[$iItem][0], $aItems[$iItem][1], 1 + ($iItem * 16), 1, 16, 16)
       
        Dim $aMenu[1] = [GUICtrlCreateContextMenu(GUICtrlCreateDummy())]
       
        For $i = 3 To UBound($aItems, 2) - 1
            If $aItems[$iItem][$i] Then
                If StringLeft($aItems[$iItem][$i], 6) == '[MENU]' Then
                    $aSplit = StringSplit(StringTrimLeft($aItems[$iItem][$i], 6), '|')
                    $iSubMenu = GUICtrlCreateMenu($aSplit[1], $aMenu[0])
                   
                    For $iMenu = 2 To $aSplit[0]
                        $iUbnd = UBound($aMenu)
                        ReDim $aMenu[$iUbnd + 1]
                        $aMenu[$iUbnd] = GUICtrlCreateMenuItem($aSplit[$iMenu], $iSubMenu)
                    Next
                   
                    ContinueLoop
                EndIf
               
                $iUbnd = UBound($aMenu)
                ReDim $aMenu[$iUbnd + 1]
                $aMenu[$iUbnd] = GUICtrlCreateMenuItem($aItems[$iItem][$i], $aMenu[0])
            EndIf
        Next
       
        $aRet[$iItem][$iPanel_Menu] = $aMenu
        $aMenu = 0
    Next
   
    Return $aRet
EndFunc

Func _Panel_Events($hParent, $aPanel, $aMsg)
    Local Static $iLastCtrlID = -1
   
    If $aMsg[0] = $GUI_EVENT_PRIMARYUP And $aMsg[1] = $hParent Then
        $iLastCtrlID = _Panel_CheckFocus($hParent, $aPanel1, $aInputs1)
       
        If $iLastCtrlID Then
            Return
        EndIf
       
        $iLastCtrlID = _Panel_CheckFocus($hParent, $aPanel2, $aInputs2)
        Return
    EndIf
   
    Local $aMenu
   
    For $i = 0 To UBound($aPanel) - 1
        $aMenu = $aPanel[$i][$iPanel_Menu]
       
        ;Check panel buttons events
        If $aMsg[0] = $aPanel[$i][$iPanel_Bttn] Then
            _GUICtrlMenu_Show($aPanel[0][$iPanel_GUI], $aMenu[0], $aMsg[0])
            Return 1
        EndIf
       
        ;Check menu items events
        For $j = 1 To UBound($aMenu) - 1
            If $aMsg[0] = $aMenu[$j] Then
                Call($aPanel[$i][$iPanel_Func], GUICtrlRead($aMenu[$j], 1), $iLastCtrlID)
                GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
                Return 1
            EndIf
        Next
    Next
   
    Return 0
EndFunc

Func _Panel_CheckFocus($hParent, $aPanel, $aInputs, $iID = 0)
    Local $aCtrlPos, $iX, $iY
   
    If Not $iID Then
        $iID = GUIGetCursorInfo($hParent)[4]
    EndIf
   
    If Not _GUICtrlIsFocused($hParent, $iID) Then
        GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
        Return 0
    EndIf
   
    For $i = 1 To $aInputs[0]
        If $aInputs[$i] = $iID Then
            $aCtrlPos = ControlGetPos($hParent, '', $aInputs[$i])
           
            $iX = $aCtrlPos[0]
            $iY = $aCtrlPos[1]
           
            _ClientToScreen($hParent, $iX, $iY)
           
            If Not @error Then
                WinMove($aPanel[0][$iPanel_GUI], '', $iX, $iY - $aCtrlPos[3])
                GUISetState(@SW_SHOWNOACTIVATE, $aPanel[0][$iPanel_GUI])
                Return $iID
            EndIf
        EndIf
    Next
   
    GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
    Return 0
EndFunc

Func _GUICtrlMenu_Show($hWnd, $nContextID, $nContextControlID)
    Local $hMenu = GUICtrlGetHandle($nContextID)
    Local $aCtrlPos = ControlGetPos($hWnd, '', $nContextControlID)
   
    Local $iX = $aCtrlPos[0]
    Local $iY = $aCtrlPos[1] + $aCtrlPos[3]
   
    _ClientToScreen($hWnd, $iX, $iY)
   
    DllCall('user32.dll', 'int', 'TrackPopupMenuEx', 'hwnd', $hMenu, 'int', 0, 'int', $iX, 'int', $iY, 'hwnd', $hWnd, 'ptr', 0)
EndFunc

Func _GUICtrlIsFocused($hGUI, $iCtrlID)
    Return(ControlGetHandle($hGUI, '', ControlGetFocus($hGUI)) = GUICtrlGetHandle($iCtrlID))
EndFunc

Func _ClientToScreen($hWnd, ByRef $iX, ByRef $iY)
    Local $tPoint = DllStructCreate('int X;int Y')
   
    $tPoint.X = $iX
    $tPoint.Y = $iY
   
    _WinAPI_ClientToScreen($hWnd, $tPoint)
   
    $iX = $tPoint.X
    $iY = $tPoint.Y
EndFunc


Тут кстати можно указать более чем 2 кнопки и меню для них, всё настраивается из массива $aItems.
 
Последнее редактирование:
  • Like
Реакции: xXx

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,484
Добавил поддержку многоуровнего меню:

Формат задаваемого меню в строке:
[MENU:Имя Меню]{Пункт Меню 1|Пункт Меню 2|[MENU:Имя ПодМеню]{Пункт ПодМеню 1|Пункт ПодМеню 2}}

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPIConv.au3>

Global Enum $iPanel_GUI, $iPanel_Func, $iPanel_Bttn, $iPanel_Menu, _
        $iPanel_Total

Global $aInputs1[4] = [3]
Global $aInputs2[4] = [3]

$hSub_GUI = GUICreate('Sub GUI', 340, 150)

$aInputs1[1] = GUICtrlCreateInput('', 40, 10, 100, 20)
$aInputs1[2] = GUICtrlCreateInput('', 40, 40, 100, 20)
$aInputs1[3] = GUICtrlCreateInput('', 40, 70, 100, 20)

$aInputs2[1] = GUICtrlCreateInput('', 200, 10, 100, 20)
$aInputs2[2] = GUICtrlCreateInput('', 200, 40, 100, 20)
$aInputs2[3] = GUICtrlCreateInput('', 200, 70, 100, 20)

$iOK_Bttn = GUICtrlCreateButton('OK', 120, 110, 100)
GUICtrlSetState(-1, $GUI_FOCUS)

;Array format...
;[0][0] - Button icon 1
;[0][1] - Button icon id 1
;[0][2] - Menu option FuncName
;[0][3] - Menu item 1...
;         A Submenu can be defined using specific format: [MENU:Menu Name]{Menu Item1|Menu Item2|[MENU:SubMenu Name]{SubMenu Item1|SubMenu Item2}}
;[0][3 + N] - Menu item N
;[1][1] - Button icon 2
;[1][N] - Button icon id N and so on
Dim $aItems[2][] = _
    [ _
        ['shell32.dll', -278, '_Opt_Proc', 'Opt1', '[MENU:Opt2 Menu]{Menu Opt1|[MENU:Opt2 SubMenu]{SubMenu Opt1|SubMenu Opt2}}'], _
        ['shell32.dll', -237, '_Opt_Proc', 'Opt3', 'Opt4'] _
    ]
$aPanel1 = _Panel_Create($hSub_GUI, $aItems)

Dim $aItems[2][] = _
    [ _
        ['shell32.dll', -260, '_Opt_Proc', 'Opt5', 'Opt6'], _
        ['shell32.dll', -250, '_Opt_Proc', '[MENU:Opt7 Menu]{SubMenu Opt1|SubMenu Opt2}', 'Opt8'] _
    ]
$aPanel2 = _Panel_Create($hSub_GUI, $aItems)

GUISetState(@SW_SHOW, $hSub_GUI)

While 1
    $aMsg = GUIGetMsg(1)
   
    Switch $aMsg[0]
        Case 0
            ContinueLoop
        Case $GUI_EVENT_CLOSE, $iOK_Bttn
            Exit
        Case Else
            _Panel_Events($hSub_GUI, $aPanel1, $aInputs1, $aMsg)
            _Panel_Events($hSub_GUI, $aPanel2, $aInputs2, $aMsg)
    EndSwitch
WEnd

Func _Opt_Proc($sTextID, $iInputID)
    Local $sData = $sTextID & ' Calc'
   
    ;Can be ommited, just to show how to separate options
    Switch $sTextID
        Case 'Opt1'
            $sData = 'Opt1 Calc'
        Case 'Opt2'
            $sData = 'Opt2 Calc'
        Case 'Opt3'
            $sData = 'Opt3 Calc'
        Case 'Opt4'
            $sData = 'Opt4 Calc'
        Case 'Opt5'
            $sData = 'Opt5 Calc'
        Case 'Opt6'
            $sData = 'Opt6 Calc'
        Case 'Opt7'
            $sData = 'Opt7 Calc'
        Case 'Opt8'
            $sData = 'Opt8 Calc'
    EndSwitch
   
    GUICtrlSetData($iInputID, $sData)
EndFunc

Func _Panel_Create($hParent, $aItems)
    If UBound($aItems, 0) <> 2 Then
        Return SetError(1, 0, 0)
    EndIf
   
    Local $iUbnd = UBound($aItems)
    Local $aRet[$iUbnd][$iPanel_Total]
    Local $aMenu, $iW = 18 * $iUbnd, $iH = 18
   
    $aRet[0][$iPanel_GUI] = GUICreate('', $iW, $iH, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_MDICHILD, $hParent)
    GUISetBkColor(0xFFFDC7)
   
    For $iItem = 0 To $iUbnd - 1
        $aRet[$iItem][$iPanel_Func] = $aItems[$iItem][2]
        $aRet[$iItem][$iPanel_Bttn] = GUICtrlCreateIcon($aItems[$iItem][0], $aItems[$iItem][1], 1 + ($iItem * 16), 1, 16, 16)
       
        Dim $aMenu[1] = [GUICtrlCreateContextMenu(GUICtrlCreateDummy())]
       
        For $i = 3 To UBound($aItems, 2) - 1
            If Not $aItems[$iItem][$i] Then
                ContinueLoop
            EndIf
           
            _Panel_LoadMenuFromString($aItems[$iItem][$i], $aMenu[0], $aMenu)
        Next
       
        $aRet[$iItem][$iPanel_Menu] = $aMenu
        $aMenu = 0
    Next
   
    ;GUISwitch($hParent)
    Return $aRet
EndFunc

Func _Panel_Events($hParent, $aPanel, $aInputs, $aMsg)
    Local Static $iLastCtrlID = -1
   
    If $aMsg[0] = $GUI_EVENT_PRIMARYUP And $aMsg[1] = $hParent Then
        $iID = _Panel_CheckFocus($hParent, $aPanel, $aInputs)
       
        If $iID Then
            $iLastCtrlID = $iID
        EndIf
       
        Return
    EndIf
   
    Local $aMenu
   
    For $i = 0 To UBound($aPanel) - 1
        $aMenu = $aPanel[$i][$iPanel_Menu]
       
        ;Check panel buttons events
        If $aMsg[0] = $aPanel[$i][$iPanel_Bttn] Then
            _GUICtrlMenu_Show($aPanel[0][$iPanel_GUI], $aMenu[0], $aMsg[0])
            Return 1
        EndIf
       
        ;Check menu items events
        For $j = 1 To UBound($aMenu) - 1
            If $aMsg[0] = $aMenu[$j] Then
                Call($aPanel[$i][$iPanel_Func], GUICtrlRead($aMenu[$j], 1), $iLastCtrlID)
                GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
                Return 1
            EndIf
        Next
    Next
   
    Return 0
EndFunc

Func _Panel_CheckFocus($hParent, $aPanel, $aInputs, $iID = 0)
    Local $aCtrlPos, $iX, $iY
   
    If Not $iID Then
        $iID = GUIGetCursorInfo($hParent)[4]
    EndIf
   
    If Not _GUICtrlIsFocused($hParent, $iID) Then
        GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
        Return 0
    EndIf
   
    For $i = 1 To $aInputs[0]
        If $aInputs[$i] = $iID Then
            $aCtrlPos = ControlGetPos($hParent, '', $aInputs[$i])
           
            $iX = $aCtrlPos[0]
            $iY = $aCtrlPos[1]
           
            _ClientToScreen($hParent, $iX, $iY)
           
            If Not @error Then
                WinMove($aPanel[0][$iPanel_GUI], '', $iX, $iY - $aCtrlPos[3])
                GUISetState(@SW_SHOWNOACTIVATE, $aPanel[0][$iPanel_GUI])
                Return $iID
            EndIf
        EndIf
    Next
   
    GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
    Return 0
EndFunc

Func _Panel_LoadMenuFromString($sStr, $hMenu, ByRef $aMenu)
    Local $iUbnd
    Local $aMenuStr = StringRegExp($sStr, '(?U)^\[MENU:(.*)\]{(.*?)}', 3)
   
    If Not StringRegExp($sStr, '^\[MENU:.*\]') Or UBound($aMenuStr) < 2 Then
        $iUbnd = UBound($aMenu)
        ReDim $aMenu[$iUbnd + 1]
       
        $aMenu[$iUbnd] = GUICtrlCreateMenuItem($sStr, $hMenu)
        Return
    EndIf
   
    $iUbnd = UBound($aMenu)
    ReDim $aMenu[$iUbnd + 1]
   
    $aMenu[$iUbnd] = GUICtrlCreateMenu($aMenuStr[0], $hMenu)
    $hMenu = $aMenu[$iUbnd]
   
    Local $sSubMenuSep = '{SUBMENU_SEPARATOR}'
   
    ;Store all submenu data in array to restore later
    Local $aSubMenuSep = StringRegExp($aMenuStr[1], '({[^}]+})', 3)
    $aMenuStr[1] = StringRegExpReplace($aMenuStr[1], '{[^}]+}', $sSubMenuSep)
   
    Local $aItems = StringSplit($aMenuStr[1], '|')
    Local $iC = 0
   
    For $i = 1 To $aItems[0]
        If StringInStr($aItems[$i], $sSubMenuSep) Then
            $aItems[$i] = StringReplace($aItems[$i], $sSubMenuSep, $aSubMenuSep[$iC])
            $iC += 1
        EndIf
       
        If StringRegExp($aItems[$i], '^\[MENU:.*\]') Then
            _Panel_LoadMenuFromString($aItems[$i], $hMenu, $aMenu)
        Else
            $iUbnd = UBound($aMenu)
            ReDim $aMenu[$iUbnd + 1]
            $aMenu[$iUbnd] = GUICtrlCreateMenuItem($aItems[$i], $hMenu)
        EndIf
    Next
EndFunc

Func _GUICtrlMenu_Show($hWnd, $iMenuID, $iCtrlID)
    Local $hMenu = GUICtrlGetHandle($iMenuID)
    Local $aCtrlPos = ControlGetPos($hWnd, '', $iCtrlID)
   
    Local $iX = $aCtrlPos[0]
    Local $iY = $aCtrlPos[1] + $aCtrlPos[3]
   
    _ClientToScreen($hWnd, $iX, $iY)
   
    DllCall('user32.dll', 'int', 'TrackPopupMenuEx', 'hwnd', $hMenu, 'int', 0, 'int', $iX, 'int', $iY, 'hwnd', $hWnd, 'ptr', 0)
EndFunc

Func _GUICtrlIsFocused($hGUI, $iCtrlID)
    Return(ControlGetHandle($hGUI, '', ControlGetFocus($hGUI)) = GUICtrlGetHandle($iCtrlID))
EndFunc

Func _ClientToScreen($hWnd, ByRef $iX, ByRef $iY)
    Local $tPoint = DllStructCreate('int X;int Y')
   
    $tPoint.X = $iX
    $tPoint.Y = $iY
   
    _WinAPI_ClientToScreen($hWnd, $tPoint)
   
    $iX = $tPoint.X
    $iY = $tPoint.Y
EndFunc
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,484
И ещё до кучи (более усовершенствованный вариант, где можно просто указать функцию кнопки, и уже в ней выводить меню, или делать что то ещё):

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPIConv.au3>
#include <WinAPISysWin.au3>
#include <GUIMenu.au3>

Global Enum $iPanel_GUI, $iPanel_Func, $iPanel_Bttn, $iPanel_Menu, _
        $iPanel_Total

Global $aInputs1[4] = [3]
Global $aInputs2[4] = [3]

$hSub_GUI = GUICreate('Sub GUI', 340, 150)

$aInputs1[1] = GUICtrlCreateInput('', 40, 10, 100, 20)
$aInputs1[2] = GUICtrlCreateInput('', 40, 40, 100, 20)
$aInputs1[3] = GUICtrlCreateInput('', 40, 70, 100, 20)

$aInputs2[1] = GUICtrlCreateInput('', 200, 10, 100, 20)
$aInputs2[2] = GUICtrlCreateInput('', 200, 40, 100, 20)
$aInputs2[3] = GUICtrlCreateInput('', 200, 70, 100, 20)

$iOK_Bttn = GUICtrlCreateButton('OK', 120, 110, 100)
GUICtrlSetState(-1, $GUI_FOCUS)

;Array format...
;[0][0] - Button icon 1
;[0][1] - Button icon id 1
;[0][2] - Menu option FuncName
;[0][3] - Menu item 1...
;         A Submenu can be defined using specific format: [MENU:Menu Name]{Menu Item1|Menu Item2|[MENU:SubMenu Name]{SubMenu Item1|SubMenu Item2}}
;[0][3 + N] - Menu item N
;[1][1] - Button icon 2
;[1][N] - Button icon id N and so on
Dim $aItems[2][] = _
    [ _
        ['shell32.dll', -278, '_Opt_Proc', 'Opt1', '[MENU:Opt2 Menu]{Menu Opt1|[MENU:Opt2 SubMenu]{SubMenu Opt1|SubMenu Opt2}}'], _
        ['shell32.dll', -237, '_Opt_Proc', 'Opt3', 'Opt4'] _
    ]
$aPanel1 = _Panel_Create($hSub_GUI, $aItems)

Dim $aItems[2][] = _
    [ _
        ['shell32.dll', -260, '_CustomOpt_Proc'], _
        ['shell32.dll', -250, '_Button_Proc'] _
    ]
$aPanel2 = _Panel_Create($hSub_GUI, $aItems)

GUISetState(@SW_SHOW, $hSub_GUI)

While 1
    $aMsg = GUIGetMsg(1)
    
    Switch $aMsg[0]
        Case 0
            ContinueLoop
        Case $GUI_EVENT_CLOSE, $iOK_Bttn
            Exit
        Case Else
            _Panel_Events($hSub_GUI, $aPanel1, $aInputs1, $aMsg)
            _Panel_Events($hSub_GUI, $aPanel2, $aInputs2, $aMsg)
    EndSwitch
WEnd

Func _Opt_Proc($sTextID, $iInputID)
    Local $sData = $sTextID & ' Calc'
    
    ;Can be omitted, just to show how to separate options
    Switch $sTextID
        Case 'Opt1'
            $sData = 'Opt1 Calc'
        Case 'Opt2'
            ;...
    EndSwitch
    
    GUICtrlSetData($iInputID, $sData)
EndFunc

Func _CustomOpt_Proc($iBttnID, $iInputID)
    Local $iContextMenu = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
    
    Local $iCalc_MItem = GUICtrlCreateMenuItem('Calc', $iContextMenu)
    Local $iMsg_MItem = GUICtrlCreateMenuItem('Message', $iContextMenu)
    
    Local $iItem = _GUICtrlMenu_Show(_WinAPI_GetParent(GUICtrlGetHandle($iBttnID)), $iContextMenu, $iBttnID, True)
    
    Switch $iItem
        Case $iCalc_MItem
            Local $sInput = InputBox('Input', 'Calc:', '5 + 5', '', -1, -1, Default, Default, 0, $hSub_GUI)
            
            If Not @error Then
                GUICtrlSetData($iInputID, Execute($sInput))
            EndIf
        Case $iMsg_MItem
            MsgBox(64, @ScriptName, 'Ok', 0, $hSub_GUI)
    EndSwitch
EndFunc

Func _Button_Proc($iBttnID, $iInputID)
    Local $sInput = InputBox('Input', 'Calc:', '2 + 2', '', -1, -1, Default, Default, 0, $hSub_GUI)
    
    If Not @error Then
        GUICtrlSetData($iInputID, Execute($sInput))
    EndIf
EndFunc

Func _Panel_Create($hParent, $aItems)
    If UBound($aItems, 0) <> 2 Or UBound($aItems, 2) < 3 Then
        Return SetError(1, 0, 0)
    EndIf
    
    Local $iUbnd = UBound($aItems)
    Local $aRet[$iUbnd][$iPanel_Total]
    Local $aMenu, $iW = 18 * $iUbnd, $iH = 18
    
    $aRet[0][$iPanel_GUI] = GUICreate('', $iW, $iH, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_MDICHILD, $hParent)
    GUISetBkColor(0xFFFDC7)
    
    For $iItem = 0 To $iUbnd - 1
        $aRet[$iItem][$iPanel_Func] = $aItems[$iItem][2]
        $aRet[$iItem][$iPanel_Bttn] = GUICtrlCreateIcon($aItems[$iItem][0], $aItems[$iItem][1], 1 + ($iItem * 16), 1, 16, 16)
        
        If UBound($aItems, 2) = 3 Then
            ContinueLoop
        EndIf
        
        Dim $aMenu[1] = [GUICtrlCreateContextMenu(GUICtrlCreateDummy())]
        
        For $i = 3 To UBound($aItems, 2) - 1
            If Not $aItems[$iItem][$i] Then
                ContinueLoop
            EndIf
            
            _Panel_LoadMenuFromString($aItems[$iItem][$i], $aMenu[0], $aMenu)
        Next
        
        $aRet[$iItem][$iPanel_Menu] = (UBound($aMenu) = 1 ? 0 : $aMenu)
        $aMenu = 0
    Next
    
    GUISwitch($hParent)
    Return $aRet
EndFunc

Func _Panel_Events($hParent, $aPanel, $aInputs, $aMsg)
    Local Static $iLastCtrlID = -1
    
    If $aMsg[0] = $GUI_EVENT_PRIMARYUP And $aMsg[1] = $hParent Then
        $iID = _Panel_CheckFocus($hParent, $aPanel, $aInputs)
        
        If $iID Then
            $iLastCtrlID = $iID
        EndIf
        
        Return
    EndIf
    
    Local $aMenu
    
    For $i = 0 To UBound($aPanel) - 1
        $aMenu = $aPanel[$i][$iPanel_Menu]
        
        ;Check panel buttons events
        If $aMsg[0] = $aPanel[$i][$iPanel_Bttn] Then
            If IsArray($aMenu) Then
                _GUICtrlMenu_Show($aPanel[0][$iPanel_GUI], $aMenu[0], $aMsg[0])
            Else
                Call($aPanel[$i][$iPanel_Func], $aMsg[0], $iLastCtrlID)
                GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
            EndIf
            
            Return 1
        EndIf
        
        ;Check menu items events
        For $j = 1 To UBound($aMenu) - 1
            If $aMsg[0] = $aMenu[$j] Then
                Call($aPanel[$i][$iPanel_Func], GUICtrlRead($aMenu[$j], 1), $iLastCtrlID)
                GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
                Return 1
            EndIf
        Next
    Next
    
    Return 0
EndFunc

Func _Panel_CheckFocus($hParent, $aPanel, $aInputs, $iID = 0)
    Local $aCtrlPos, $iX, $iY
    
    If Not $iID Then
        $iID = GUIGetCursorInfo($hParent)[4]
    EndIf
    
    If Not _GUICtrlIsFocused($hParent, $iID) Then
        GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
        Return 0
    EndIf
    
    For $i = 1 To $aInputs[0]
        If $aInputs[$i] = $iID Then
            $aCtrlPos = ControlGetPos($hParent, '', $aInputs[$i])
            
            $iX = $aCtrlPos[0]
            $iY = $aCtrlPos[1]
            
            _ClientToScreen($hParent, $iX, $iY)
            
            If Not @error Then
                WinMove($aPanel[0][$iPanel_GUI], '', $iX, $iY - $aCtrlPos[3])
                GUISetState(@SW_SHOWNOACTIVATE, $aPanel[0][$iPanel_GUI])
                Return $iID
            EndIf
        EndIf
    Next
    
    GUISetState(@SW_HIDE, $aPanel[0][$iPanel_GUI])
    Return 0
EndFunc

Func _Panel_LoadMenuFromString($sStr, $hMenu, ByRef $aMenu)
    Local $iUbnd
    Local $aMenuStr = StringRegExp($sStr, '(?U)^\[MENU:(.*)\]{(.*?)}', 3)
    
    If Not StringRegExp($sStr, '^\[MENU:.*\]') Or UBound($aMenuStr) < 2 Then
        $iUbnd = UBound($aMenu)
        ReDim $aMenu[$iUbnd + 1]
        
        $aMenu[$iUbnd] = GUICtrlCreateMenuItem($sStr, $hMenu)
        Return
    EndIf
    
    $iUbnd = UBound($aMenu)
    ReDim $aMenu[$iUbnd + 1]
    
    $aMenu[$iUbnd] = GUICtrlCreateMenu($aMenuStr[0], $hMenu)
    $hMenu = $aMenu[$iUbnd]
    
    Local $sSubMenuSep = '{SUBMENU_SEPARATOR}'
    
    ;Store all submenu data in array to restore later
    Local $aSubMenuSep = StringRegExp($aMenuStr[1], '({[^}]+})', 3)
    $aMenuStr[1] = StringRegExpReplace($aMenuStr[1], '{[^}]+}', $sSubMenuSep)
    
    Local $aItems = StringSplit($aMenuStr[1], '|')
    Local $iC = 0
    
    For $i = 1 To $aItems[0]
        If StringInStr($aItems[$i], $sSubMenuSep) Then
            $aItems[$i] = StringReplace($aItems[$i], $sSubMenuSep, $aSubMenuSep[$iC])
            $iC += 1
        EndIf
        
        If StringRegExp($aItems[$i], '^\[MENU:.*\]') Then
            _Panel_LoadMenuFromString($aItems[$i], $hMenu, $aMenu)
        Else
            $iUbnd = UBound($aMenu)
            ReDim $aMenu[$iUbnd + 1]
            $aMenu[$iUbnd] = GUICtrlCreateMenuItem($aItems[$i], $hMenu)
        EndIf
    Next
EndFunc

Func _GUICtrlMenu_Show($hWnd, $iMenuID, $iCtrlID, $bNotify = False)
    Local $hMenu = GUICtrlGetHandle($iMenuID)
    Local $aCtrlPos = ControlGetPos($hWnd, '', $iCtrlID)
    
    Local $iX = $aCtrlPos[0]
    Local $iY = $aCtrlPos[1] + $aCtrlPos[3]
    
    _ClientToScreen($hWnd, $iX, $iY)
    
    Return _GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd, $iX, $iY, 1, 1, ($bNotify ? 2 : 0), 1)
EndFunc

Func _GUICtrlIsFocused($hGUI, $iCtrlID)
    Return(ControlGetHandle($hGUI, '', ControlGetFocus($hGUI)) = GUICtrlGetHandle($iCtrlID))
EndFunc

Func _ClientToScreen($hWnd, ByRef $iX, ByRef $iY)
    Local $tPoint = DllStructCreate('int X;int Y')
    
    $tPoint.X = $iX
    $tPoint.Y = $iY
    
    _WinAPI_ClientToScreen($hWnd, $tPoint)
    
    $iX = $tPoint.X
    $iY = $tPoint.Y
EndFunc
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,484
побороть бы еще мерцание панели заголовка
Можно подробнее? у меня нет мерцания...

пора уже написать библиотеку под это дело
Я вот тоже думал, вопрос только в каком режиме...
Скорее всего нужно присваивать панель указанному элементу ввода, и уже потом обрабатывать.
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
Можно подробнее? у меня нет мерцания...
не так выразился. заголовок основного окна теряет фокус, а значит бледнеет при клике на плавающую панель. в принципе это мелочь

насчет библиотеки
суть в создании плавающей панели и динамическом формировании набора инструментов на ней. а назначить можно на любой элемент.
указать координаты появления панели, ну и замена стиля панели: либо с заголовком(чтобы перемещать панель, вдруг мешает) либо Popup.
набор функций и значков(надписей) скармливать через массив, это если сразу все назначить. либо добавлять функцию и значок(элемент) в панели через отдельную функцию библиотеки. последнее, думаю, будет правильнее. конечно, это влечет за собой корректировку размера панели
 
Автор
L

liond66

Новичок
Сообщения
117
Репутация
2
Посмотрел оба кода: ув. joiner и ув. CreatoR
Переделал "под себя". Добавил запуск в качестве дочернего окна и меню в коде joiner.
Проверяю модульность, т.е. использование функций меню из разных дочерних окон.
Не зря же мой пример построен именно так.

joiner
Есть небольшая проблема.
Я добавил убирание кнопок после того как сделан выбор.
В случае с меню всё хорошо.
Но нажатие одиночной кнопки (знак вопроса), если она над полем ввода, приводит к нажатию на верхнее поле.
Как это можно исправить? Сам не справился.
Вот переделанный код:
Код:
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <WinAPIConstants.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <GuiMenu.au3>

;;;;; for ToolBox
Global Enum $p1, $p2, $p3, $s1, $s2, $s3
Global $iInputTmp, $iButtonCH, $iButtonCH1, $iButtonCH2, $ToolBox, $hSubGUI, $flS
;;;;;;;;;;;;;;;;;;;;;;;;;

Global $Main = GUICreate("Main", 600, 440, 190, 120)
Global $SubWin1 = GUICtrlCreateButton("Sub Window-1", 180, 160, 150, 40)
Global $SubWin2 = GUICtrlCreateButton("Sub Window-2", 180, 210, 150, 40)
GUISetState(@SW_SHOW, $Main)
While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit

        Case $SubWin1
            _SubWin1()
        Case $SubWin2
            _SubWin2()

    EndSwitch
WEnd

Func _SubWin1()
    #Region Sub-GUI
    $hSubGUI = GUICreate('Sub GUI', 500, 420, -1, -1, $WS_BORDER)
    GUISetFont(11)
    GUICtrlCreateLabel('   ?????????', 0, 0, 440, 30, BitOR($SS_CENTERIMAGE, $SS_LEFT), $GUI_WS_EX_PARENTDRAG)
    Local $iOK_Bttn = GUICtrlCreateButton('OK', 120, 360, 105, 25)
    Local $iCancel_Bttn = GUICtrlCreateButton('Cancel', 240, 360, 105, 25)

    Local $SimpleInput = GUICtrlCreateInput('', 20, 35, 300, 22)
    Local $SimpleInput1 = GUICtrlCreateInput('', 170, 102, 60, 22)
    Local $SimpleInput2 = GUICtrlCreateInput('', 170, 132, 60, 22)
    Local $SimpleInput3 = GUICtrlCreateInput('', 300, 132, 60, 22)
    Local $aParam_Inputs[10]
    GUICtrlCreateLabel('1', 30, 210, 20, 20)
    $aParam_Inputs[1] = GUICtrlCreateInput('', 40, 210, 100, 20)
    GUICtrlCreateLabel('2', 30, 235, 20, 20)
    $aParam_Inputs[2] = GUICtrlCreateInput('', 40, 235, 100, 20)
    GUICtrlCreateLabel('3', 30, 260, 20, 20)
    $aParam_Inputs[3] = GUICtrlCreateInput('', 40, 260, 100, 20)
    GUICtrlCreateLabel('4', 190, 210, 20, 20)
    $aParam_Inputs[4] = GUICtrlCreateInput('', 205, 210, 100, 20)
    GUICtrlCreateLabel('5', 190, 235, 20, 20)
    $aParam_Inputs[5] = GUICtrlCreateInput('', 205, 235, 100, 20)
    GUICtrlCreateLabel('6', 190, 260, 20, 20)
    $aParam_Inputs[6] = GUICtrlCreateInput('', 205, 260, 100, 20)
    GUICtrlCreateLabel('7', 350, 210, 20, 20)
    $aParam_Inputs[7] = GUICtrlCreateInput('', 360, 210, 100, 20)
    GUICtrlCreateLabel('8', 350, 235, 20, 20)
    $aParam_Inputs[8] = GUICtrlCreateInput('', 360, 235, 100, 20)
    GUICtrlCreateLabel('9', 350, 260, 20, 20)
    $aParam_Inputs[9] = GUICtrlCreateInput('', 360, 260, 100, 20)
    #EndRegion Sub-GUI

    ;;;;; for ToolBox
    Local $whPos, $aCurInfo, $winpos, $aCurP
    Local $iBF = GUICtrlCreateButton('', 0, 0)
    GUICtrlSetState(-1, $GUI_HIDE)
    ControlFocus($hSubGUI, '', $iBF)
    GUISetState(@SW_SHOW, $hSubGUI)
    _GuiB($hSubGUI)

    While 1
        $aMsg = GUIGetMsg(1)
        If $flS = 2 Then
            Local $sFolder = FileSelectFolder('', '', 0, '', $ToolBox)
            If Not @error Then GUICtrlSetData($SimpleInput, $sFolder)
            $flS = 1
        EndIf

        Switch $aMsg[0]
            Case $GUI_EVENT_CLOSE
                If $aMsg[1] = $hSubGUI Then
                    GUIDelete($hSubGUI)
                    Return
                EndIf
            Case $iOK_Bttn, $iCancel_Bttn
                GUIDelete($hSubGUI)
                Return
            Case $GUI_EVENT_PRIMARYUP
                $aCurP = GUIGetCursorInfo($ToolBox)
                If Not @error And $aCurP[4] > 0 Then ContinueLoop
                $aCurInfo = GUIGetCursorInfo($hSubGUI)
                If @error Or Not $aCurInfo[4] Then
                    GUISetState(@SW_HIDE, $ToolBox)
                    $iInputTmp = 0
                    ContinueLoop
                EndIf
                If $iInputTmp = $aCurInfo[4] Then ContinueLoop
                $whPos = ControlGetPos($hSubGUI, '', $aCurInfo[4])
                $winpos = WinGetPos($hSubGUI)
                If $aCurInfo[4] = $SimpleInput1 Or $aCurInfo[4] = $SimpleInput2 Or $aCurInfo[4] = $SimpleInput3 Or $aCurInfo[4] = $SimpleInput Then
                    If $aCurInfo[4] = $SimpleInput Then
                        GUICtrlSetImage($iButtonCH2, "shell32.dll", 4)
                        $flS = 1
                    Else
                        $flS = 0
                        GUICtrlSetImage($iButtonCH2, "shell32.dll", 24)
                    EndIf
                    WinMove($ToolBox, '', $whPos[0] + $winpos[0] + 10, $whPos[1] - 2 + $winpos[1])
                    GUISetState(@SW_SHOW, $ToolBox)
                    ControlFocus($hSubGUI, '', $aCurInfo[4])
                    $iInputTmp = $aCurInfo[4]
                    ContinueLoop
                Else
                    For $i = 1 To 9
                        If $aCurInfo[4] = $aParam_Inputs[$i] Then
                            If $flS Then GUICtrlSetImage($iButtonCH2, "shell32.dll", 24)
                            $flS = 0
                            WinMove($ToolBox, '', $whPos[0] + $winpos[0] + 10, $whPos[1] - 2 + $winpos[1])
                            GUISetState(@SW_SHOW, $ToolBox)
                            ControlFocus($hSubGUI, '', $aCurInfo[4])
                            $iInputTmp = $aCurInfo[4]
                            ContinueLoop
                        EndIf
                    Next
                EndIf
        EndSwitch
    WEnd
EndFunc   ;==>_SubWin1

Func _SubWin2()
    #Region Sub-GUI
    $hSubGUI = GUICreate('Sub GUI', 500, 420, -1, -1, $WS_BORDER)
    GUISetFont(11)
    GUICtrlCreateLabel('   ?????????', 0, 0, 440, 30, BitOR($SS_CENTERIMAGE, $SS_LEFT), $GUI_WS_EX_PARENTDRAG)
    Local $iOK_Bttn = GUICtrlCreateButton('OK', 120, 360, 105, 25)
    Local $iCancel_Bttn = GUICtrlCreateButton('Cancel', 240, 360, 105, 25)

    Local $SecondInput1 = GUICtrlCreateInput('', 170, 102, 60, 22)
    Local $SecondInput2 = GUICtrlCreateInput('', 170, 132, 60, 22)
    Local $aParam_Inputs[10]
    GUICtrlCreateLabel('1', 30, 210, 20, 20)
    $aParam_Inputs[1] = GUICtrlCreateInput('', 40, 210, 100, 20)
    GUICtrlCreateLabel('2', 30, 235, 20, 20)
    $aParam_Inputs[2] = GUICtrlCreateInput('', 40, 235, 100, 20)
    GUICtrlCreateLabel('3', 30, 260, 20, 20)
    $aParam_Inputs[3] = GUICtrlCreateInput('', 40, 260, 100, 20)
    GUICtrlCreateLabel('4', 190, 210, 20, 20)
    $aParam_Inputs[4] = GUICtrlCreateInput('', 205, 210, 100, 20)
    GUICtrlCreateLabel('5', 190, 235, 20, 20)
    $aParam_Inputs[5] = GUICtrlCreateInput('', 205, 235, 100, 20)
    GUICtrlCreateLabel('6', 190, 260, 20, 20)
    $aParam_Inputs[6] = GUICtrlCreateInput('', 205, 260, 100, 20)
    GUICtrlCreateLabel('7', 350, 210, 20, 20)
    $aParam_Inputs[7] = GUICtrlCreateInput('', 360, 210, 100, 20)
    GUICtrlCreateLabel('8', 350, 235, 20, 20)
    $aParam_Inputs[8] = GUICtrlCreateInput('', 360, 235, 100, 20)
    GUICtrlCreateLabel('9', 350, 260, 20, 20)
    $aParam_Inputs[9] = GUICtrlCreateInput('', 360, 260, 100, 20)
    #EndRegion Sub-GUI

    ;;;;; for ToolBox
    Local $whPos, $aCurInfo, $winpos, $aCurP
    Local $iBF = GUICtrlCreateButton('', 0, 0)
    GUICtrlSetState(-1, $GUI_HIDE)
    ControlFocus($hSubGUI, '', $iBF)
    GUISetState(@SW_SHOW, $hSubGUI)
    _GuiB($hSubGUI)

    While 1
        $aMsg = GUIGetMsg(1)

        Switch $aMsg[0]
            Case $GUI_EVENT_CLOSE
                If $aMsg[1] = $hSubGUI Then
                    GUIDelete($hSubGUI)
                    Return
                EndIf
            Case $iOK_Bttn, $iCancel_Bttn
                GUIDelete($hSubGUI)
                Return
            Case $GUI_EVENT_PRIMARYUP
                $aCurP = GUIGetCursorInfo($ToolBox)
                If Not @error And $aCurP[4] > 0 Then ContinueLoop
                $aCurInfo = GUIGetCursorInfo($hSubGUI)
                If @error Or Not $aCurInfo[4] Then
                    GUISetState(@SW_HIDE, $ToolBox)
                    $iInputTmp = 0
                    ContinueLoop
                EndIf
                If $iInputTmp = $aCurInfo[4] Then ContinueLoop
                $whPos = ControlGetPos($hSubGUI, '', $aCurInfo[4])
                $winpos = WinGetPos($hSubGUI)
                If $aCurInfo[4] = $SecondInput1 Or $aCurInfo[4] = $SecondInput2 Then
                    $flS = 0
                    GUICtrlSetImage($iButtonCH2, "shell32.dll", 24)
                    WinMove($ToolBox, '', $whPos[0] + $winpos[0] + 10, $whPos[1] - 2 + $winpos[1])
                    GUISetState(@SW_SHOW, $ToolBox)
                    ControlFocus($hSubGUI, '', $aCurInfo[4])
                    $iInputTmp = $aCurInfo[4]
                    ContinueLoop
                Else
                    For $i = 1 To 9
                        If $aCurInfo[4] = $aParam_Inputs[$i] Then
                            If $flS Then GUICtrlSetImage($iButtonCH2, "shell32.dll", 24)
                            $flS = 0
                            WinMove($ToolBox, '', $whPos[0] + $winpos[0] + 10, $whPos[1] - 2 + $winpos[1])
                            GUISetState(@SW_SHOW, $ToolBox)
                            ControlFocus($hSubGUI, '', $aCurInfo[4])
                            $iInputTmp = $aCurInfo[4]
                            ContinueLoop
                        EndIf
                    Next
                EndIf
        EndSwitch
    WEnd
EndFunc   ;==>_SubWin2

Func _GuiB($hWND)
    $ToolBox = GUICreate("Form1", 85, 20, 0, 0, $WS_POPUP, BitOR($WS_EX_MDICHILD, $WS_EX_TOOLWINDOW), $hWND)
    GUISetBkColor(0xAAAACC)
    $iButtonCH = GUICtrlCreateIcon('', '', 0, 0, 25, 20)
    GUICtrlSetImage(-1, "shell32.dll", 22)
    $iButtonCH1 = GUICtrlCreateIcon('', '', 30, 0, 25, 20)
    GUICtrlSetImage(-1, "shell32.dll", 23)
    $iButtonCH2 = GUICtrlCreateIcon('', '', 60, 0, 25, 20)
    GUICtrlSetImage(-1, "shell32.dll", 24)
    GUISetState(@SW_HIDE, $ToolBox)
    GUIRegisterMsg($WM_COMMAND, 'WM_COMMAND_TOOLBOX')
EndFunc   ;==>_GuiB

Func _MenuItem1($HW)
    Local $hMenu1 = _GUICtrlMenu_CreatePopup(1)
    _GUICtrlMenu_InsertMenuItem($hMenu1, 0, "item 1", $p1)
    _GUICtrlMenu_InsertMenuItem($hMenu1, 1, "item 2", $p2)
    _GUICtrlMenu_InsertMenuItem($hMenu1, 2, "item 3", $p3)
    _GUICtrlMenu_TrackPopupMenu($hMenu1, $HW)
    _GUICtrlMenu_DestroyMenu($hMenu1)
EndFunc   ;==>_MenuItem1

Func _MenuItem2($HW)
    Local $hMenu2 = _GUICtrlMenu_CreatePopup(1)
    _GUICtrlMenu_InsertMenuItem($hMenu2, 0, "sub-item 1", $s1)
    _GUICtrlMenu_InsertMenuItem($hMenu2, 1, "sub-item 2", $s2)
    _GUICtrlMenu_TrackPopupMenu($hMenu2, $HW)
    _GUICtrlMenu_DestroyMenu($hMenu2)
EndFunc   ;==>_MenuItem2

Func WM_COMMAND_TOOLBOX($hWND, $iMsg, $wParam, $lParam)
    #forceref $hWND, $iMsg, $lParam
    Switch BitAND($wParam, 0x0000FFFF)
        Case $iButtonCH
            _MenuItem1($hWND)
            GUISetState(@SW_HIDE, $ToolBox)
            ControlFocus($hSubGUI, '', $iInputTmp)
        Case $iButtonCH1
            _MenuItem2($hWND)
            GUISetState(@SW_HIDE, $ToolBox)
            ControlFocus($hSubGUI, '', $iInputTmp)
        Case $iButtonCH2
            If $flS = 1 Then
                $flS = 2
            ElseIf Not $flS Then
                GUICtrlSetData($iInputTmp, '3Ex_' & Random(2, 5, 1) + Random(2, 5, 1))
            EndIf
            GUISetState(@SW_HIDE, $ToolBox)
            ControlFocus($hSubGUI, '', $iInputTmp)
        Case $p1
            GUICtrlSetData($iInputTmp, 'p1')
            ControlFocus($hSubGUI, '', $iInputTmp)
            GUISetState(@SW_HIDE, $ToolBox)
        Case $p2
            GUICtrlSetData($iInputTmp, 'p2')
            ControlFocus($hSubGUI, '', $iInputTmp)
            GUISetState(@SW_HIDE, $ToolBox)
        Case $p3
            GUICtrlSetData($iInputTmp, 'p3')
            ControlFocus($hSubGUI, '', $iInputTmp)
            GUISetState(@SW_HIDE, $ToolBox)
        Case $s1
            GUICtrlSetData($iInputTmp, 's1')
            ControlFocus($hSubGUI, '', $iInputTmp)
            GUISetState(@SW_HIDE, $ToolBox)
        Case $s2
            GUICtrlSetData($iInputTmp, 's2')
            ControlFocus($hSubGUI, '', $iInputTmp)
            GUISetState(@SW_HIDE, $ToolBox)


    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND_TOOLBOX
Сообщение автоматически объединено:

CreatoR
Красиво работает код. С меня лайк.
Но возникает проблема с модульностью:
Переменная поля ввода глобальная и, кроме цикла в дочернем окне, прописывается жёстко в функции _Panel_Events.
На каждое новое имя переменной нужно создавать дополнительную функцию _Panel_Events.
Я не стал дальше вносить изменения, так как только испорчу.
Хотел вставить переделанный код, но пишет об ограничении 20000 знаков.
Возможно он соединяет два поста.
Если кто то ответит, я попробую вставить свой код, если нужно.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,484
На каждое новое имя переменной нужно создавать дополнительную функцию _Panel_Events.
Нет, только на каждую группу элементов ($aInputs).

Хотел вставить переделанный код, но пишет об ограничении 20000 знаков.
Для этого есть вложения.

проблема с модульностью
Решаю в виде библиотеки, терпение.
 
Верх