Что нового

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

liond66

Новичок
Сообщения
94
Репутация
1
Подсмотрел в одной программе и хочу попробовать повторить на Autoit.
При клике на поле ввода (Input) кроме свободного ввода всплывает элемент (кнопка) с меню выбора функции, результат которой отображается в поле ввода.
Пока что сделал, что сделал. Может не самый правильный алгоритм, тогда предложите другой.
Сейчас застрял на том, что не срабатывает нажатие на кнопку.
Вот код. Кто может помочь? Спасибо.
Код:
#include <Array.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>
#include <GUIConstantsEx.au3>
#include <GuiMenu.au3>
#include <GuiToolbar.au3>
#include <WinAPIConstants.au3>
#include <WindowsConstants.au3>

Local $Main = GUICreate("Main", 600, 440, 190, 120)
Local $SubWin = GUICtrlCreateButton("Sub Window", 180, 160, 150, 40)
Global $SubGUI

; Create OptGUI for future use
Global $OptGUI = _OptGUI($SubGUI)
Global $OptButton = -1, $OptComboBox = -1

GUISetState(@SW_SHOW, $Main)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit

        Case $SubWin
            _SubWin()

    EndSwitch
WEnd

Func _SubWin()
    Local $ParamInput[10]
    $SubGUI = GUICreate("Sub GUI", 523, 420, 192, 124, -1, -1, $Main)
    GUISetFont(11)
    #Region Inputs
    Local $SimpleInput1 = GUICtrlCreateInput("", 170, 102, 60, 22)
    Local $SimpleInput2 = GUICtrlCreateInput("", 170, 132, 60, 22)
    Local $SimpleInput3 = GUICtrlCreateInput("", 300, 132, 60, 22)

    GUICtrlCreateLabel("1", 30, 210, 20, 20)
    $ParamInput[1] = GUICtrlCreateInput("", 40, 210, 100, 20)
    GUICtrlCreateLabel("2", 30, 235, 20, 20)
    $ParamInput[2] = GUICtrlCreateInput("", 40, 235, 100, 20)
    GUICtrlCreateLabel("3", 30, 260, 20, 20)
    $ParamInput[3] = GUICtrlCreateInput("", 40, 260, 100, 20)
    GUICtrlCreateLabel("4", 190, 210, 20, 20)
    $ParamInput[4] = GUICtrlCreateInput("", 205, 210, 100, 20)
    GUICtrlCreateLabel("5", 190, 235, 20, 20)
    $ParamInput[5] = GUICtrlCreateInput("", 205, 235, 100, 20)
    GUICtrlCreateLabel("6", 190, 260, 20, 20)
    $ParamInput[6] = GUICtrlCreateInput("", 205, 260, 100, 20)
    GUICtrlCreateLabel("7", 350, 210, 20, 20)
    $ParamInput[7] = GUICtrlCreateInput("", 360, 210, 100, 20)
    GUICtrlCreateLabel("8", 350, 235, 20, 20)
    $ParamInput[8] = GUICtrlCreateInput("", 360, 235, 100, 20)
    GUICtrlCreateLabel("9", 350, 260, 20, 20)
    $ParamInput[9] = GUICtrlCreateInput("", 360, 260, 100, 20)
    #EndRegion Inputs
    Local $OK = GUICtrlCreateButton("OK", 120, 380, 105, 25)
    Local $Cancel = GUICtrlCreateButton("Cancel", 240, 380, 105, 25)

    GUISetState(@SW_SHOW, $SubGUI)

    While 1
        $aMsg = GUIGetMsg(1)
        Switch $aMsg[0]
            Case $GUI_EVENT_CLOSE
                If $aMsg[1] = $SubGUI Then
                    GUIDelete($SubGUI)
                    If WinExists($OptGUI) Then GUISetState(@SW_HIDE, $OptGUI)
                    Return
                EndIf
            Case $Cancel, $OK
                GUIDelete($SubGUI)
                If WinExists($OptGUI) Then GUISetState(@SW_HIDE, $OptGUI)
                Return
            Case $GUI_EVENT_PRIMARYUP
                $ci = GUIGetCursorInfo()
                For $i = 1 To 9
                    If IsArray($ci) Then
                        If $ci[4] = $SimpleInput1 Or $ci[4] = $SimpleInput2 Or $ci[4] = $SimpleInput3 Or $ci[4] = $ParamInput[$i] Then
                            Local $WinPos = WinGetPos($SubGUI)
                            Local $ControlPos = ControlGetPos($SubGUI, '', $ci[4])
                            GUISetState(@SW_SHOW, $OptGUI)
                            WinMove($OptGUI, "", $WinPos[0] + $ControlPos[0] + 20, $WinPos[1] + $ControlPos[1] - 2)
                            WinActivate($OptGUI)
                            GUISwitch($SubGUI)
                        EndIf
                    EndIf
                Next

            Case $OptButton
                WinActivate($OptGUI)
                MsgBox(0, "", "Opt button")
                GUISetState(@SW_HIDE, $OptGUI)

        EndSwitch
    WEnd
EndFunc   ;==>_SubWin

Func _OptGUI($ParentGUI)
    Local $WinPos = WinGetPos($ParentGUI)
    $OptGUI = GUICreate("", 90, 20, $WinPos[0], $WinPos[1], $WS_POPUPWINDOW, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST, $ParentGUI)
    $OptButton = GUICtrlCreateButton('Button', 0, 0, 90, 20)
    Return $OptGUI
EndFunc   ;==>_OptGUI
 

ra4o

AutoIT Гуру
Сообщения
1 066
Репутация
206
Может кнопку создавать не в новом окне , а в окне "Sub GUI", только невидимой и в нужный момент её показывать и перемещать в нужные координаты (примерно так же , как Вы поступали с окном в "_OptGUI")
Например так :
Код:
#include <Array.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>
#include <GUIConstantsEx.au3>
#include <GuiMenu.au3>
#include <GuiToolbar.au3>
#include <WinAPIConstants.au3>
#include <WindowsConstants.au3>

Local $Main = GUICreate("Main", 600, 440, 190, 120)
Local $SubWin = GUICtrlCreateButton("Sub Window", 180, 160, 150, 40)
Global $SubGUI

; Create OptGUI for future use
;Global $OptGUI = _OptGUI($SubGUI)
Global $OptButton = -1, $OptComboBox = -1

GUISetState(@SW_SHOW, $Main)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit

        Case $SubWin
            _SubWin()

    EndSwitch
WEnd

Func _SubWin()
    Local $ParamInput[10]
    $SubGUI = GUICreate("Sub GUI", 523, 420, 192, 124, -1, -1, $Main)
    GUISetFont(11)
    #Region Inputs
    Local $SimpleInput1 = GUICtrlCreateInput("", 170, 102, 60, 22)
    Local $SimpleInput2 = GUICtrlCreateInput("", 170, 132, 60, 22)
    Local $SimpleInput3 = GUICtrlCreateInput("", 300, 132, 60, 22)

    GUICtrlCreateLabel("1", 30, 210, 20, 20)
    $ParamInput[1] = GUICtrlCreateInput("", 40, 210, 100, 20)
    GUICtrlCreateLabel("2", 30, 235, 20, 20)
    $ParamInput[2] = GUICtrlCreateInput("", 40, 235, 100, 20)
    GUICtrlCreateLabel("3", 30, 260, 20, 20)
    $ParamInput[3] = GUICtrlCreateInput("", 40, 260, 100, 20)
    GUICtrlCreateLabel("4", 190, 210, 20, 20)
    $ParamInput[4] = GUICtrlCreateInput("", 205, 210, 100, 20)
    GUICtrlCreateLabel("5", 190, 235, 20, 20)
    $ParamInput[5] = GUICtrlCreateInput("", 205, 235, 100, 20)
    GUICtrlCreateLabel("6", 190, 260, 20, 20)
    $ParamInput[6] = GUICtrlCreateInput("", 205, 260, 100, 20)
    GUICtrlCreateLabel("7", 350, 210, 20, 20)
    $ParamInput[7] = GUICtrlCreateInput("", 360, 210, 100, 20)
    GUICtrlCreateLabel("8", 350, 235, 20, 20)
    $ParamInput[8] = GUICtrlCreateInput("", 360, 235, 100, 20)
    GUICtrlCreateLabel("9", 350, 260, 20, 20)
    $ParamInput[9] = GUICtrlCreateInput("", 360, 260, 100, 20)
    #EndRegion Inputs
    Local $OK = GUICtrlCreateButton("OK", 120, 380, 105, 25)
    Local $Cancel = GUICtrlCreateButton("Cancel", 240, 380, 105, 25)

    $OptButton = GUICtrlCreateButton('Button', 0, 0, 90, 20)
    GuiCtrlSetState($OptButton,$GUI_ONTOP)
    GuiCtrlSetState($OptButton,$GUI_HIDE)

    GUISetState(@SW_SHOW, $SubGUI)

    While 1
        $aMsg = GUIGetMsg(1)
        Switch $aMsg[0]
            Case $GUI_EVENT_CLOSE
                If $aMsg[1] = $SubGUI Then
                    GUIDelete($SubGUI)
                    Return
                EndIf
            Case $Cancel, $OK
                GUIDelete($SubGUI)
                Return
            Case $GUI_EVENT_PRIMARYUP
                $ci = GUIGetCursorInfo()
                For $i = 1 To 9
                    If IsArray($ci) Then
                        If $ci[4] = $SimpleInput1 Or $ci[4] = $SimpleInput2 Or $ci[4] = $SimpleInput3 Or $ci[4] = $ParamInput[$i] Then
                            Local $WinPos = WinGetPos($SubGUI)
                            Local $ControlPos = ControlGetPos($SubGUI, '', $ci[4])
                            GUICtrlSetPos($OptButton,$ci[0], $ci[1]- 35)
                            GuiCtrlSetState($OptButton,$GUI_SHOW)

                        EndIf
                    EndIf
                Next

            Case $OptButton

                GuiCtrlSetState($OptButton,$GUI_HIDE)
                MsgBox(0, "", "Opt button")

        EndSwitch
    WEnd
EndFunc   ;==>_SubWin
 
Сообщения
29
Репутация
0
Try this
Код:
#include <GUIConstants.au3>

Global $isToolbox = False
Global $TimeOut

$Form1 = GUICreate("by Se7enstars", 309, 117, 192, 124)
GUISetBkColor(0xBB88F3, $Form1)
$Input1 = GUICtrlCreateInput("Enter Text", 24, 32, 265, 21)
$Button1 = GUICtrlCreateButton("Submit", 120, 72, 75, 25)

Global $bold, $italic, $under
$toolbox = GUICreate("", 208, 23, Default, Default, $WS_POPUP, $WS_EX_TOOLWINDOW+$WS_EX_TOPMOST)
GUISetBkColor(0x0, $toolbox)
$bold = GUICtrlCreateButton("B", 1, 1, 20, 20)
$italic = GUICtrlCreateButton("I", 22, 1, 20, 20)
$under = GUICtrlCreateButton("U", 44, 1, 20, 20)
$font = GUICtrlCreateCombo("Font", 66, 1, 140, 20)
GUICtrlSetData(-1, "Consolas|Segoe UI|Times New Roman")

GUISetState(@SW_SHOW, $Form1)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $bold
            GUICtrlSetFont($Input1, Default, 700)
        Case $italic
            GUICtrlSetFont($Input1, Default, Default, 2)
        Case $under
            GUICtrlSetFont($Input1, Default, Default, 4)
    EndSwitch

    $GetFocusedCtrl = GUIGetCursorInfo($Form1)
    If Not @error Then
        If $GetFocusedCtrl[4] = $Input1 Then
            If $isToolbox = False Then

                WinMove($toolbox, '', MouseGetPos(0), MouseGetPos(1)-40)
                GUISetState(@SW_SHOW, $toolbox)
                $isToolbox = True
            EndIf
        Else
            If $isToolbox = True Then
                If Not WinActive($toolbox) Then
                    If Not $TimeOut Then
                        $TimeOut = TimerInit()
                    EndIf
;~                     ConsoleWrite(TimerDiff($TimeOut) & @LF)
                    If TimerDiff($TimeOut) > 2000 Then
                        GUISetState(@SW_HIDE, $toolbox)
                        $isToolbox = False
                        $TimeOut = 0
                    EndIf
                EndIf
            EndIf
        EndIf
    EndIf
WEnd
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 397
Репутация
2 384
Как вариант:

Код:
#include <Array.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>
#include <GUIConstantsEx.au3>
#include <GuiMenu.au3>
#include <GuiToolbar.au3>
#include <WinAPIConstants.au3>
#include <WindowsConstants.au3>

Local $Main = GUICreate("Main", 600, 440, 190, 120)
Local $SubWin = GUICtrlCreateButton("Sub Window", 180, 160, 150, 40)
Global $SubGUI

; Create OptGUI for future use
Global $OptGUI, $OptButton = -1, $OptComboBox = -1
Global $iContext_Menu, $iFunc1_Item, $iFunc2_Item

_OptGUI($SubGUI)
_OptMenu()

GUISetState(@SW_SHOW, $Main)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $SubWin
            _SubWin()
    EndSwitch
WEnd

Func _SubWin()
    Local $ParamInput[10]
    Local $iFlag = 0
    
    $SubGUI = GUICreate("Sub GUI", 523, 420, 192, 124, -1, -1, $Main)
    GUISetFont(11)
    
    #Region Inputs
    Local $SimpleInput1 = GUICtrlCreateInput("", 170, 102, 60, 22)
    Local $SimpleInput2 = GUICtrlCreateInput("", 170, 132, 60, 22)
    Local $SimpleInput3 = GUICtrlCreateInput("", 300, 132, 60, 22)

    GUICtrlCreateLabel("1", 30, 210, 20, 20)
    $ParamInput[1] = GUICtrlCreateInput("", 40, 210, 100, 20)
    GUICtrlCreateLabel("2", 30, 235, 20, 20)
    $ParamInput[2] = GUICtrlCreateInput("", 40, 235, 100, 20)
    GUICtrlCreateLabel("3", 30, 260, 20, 20)
    $ParamInput[3] = GUICtrlCreateInput("", 40, 260, 100, 20)
    GUICtrlCreateLabel("4", 190, 210, 20, 20)
    $ParamInput[4] = GUICtrlCreateInput("", 205, 210, 100, 20)
    GUICtrlCreateLabel("5", 190, 235, 20, 20)
    $ParamInput[5] = GUICtrlCreateInput("", 205, 235, 100, 20)
    GUICtrlCreateLabel("6", 190, 260, 20, 20)
    $ParamInput[6] = GUICtrlCreateInput("", 205, 260, 100, 20)
    GUICtrlCreateLabel("7", 350, 210, 20, 20)
    $ParamInput[7] = GUICtrlCreateInput("", 360, 210, 100, 20)
    GUICtrlCreateLabel("8", 350, 235, 20, 20)
    $ParamInput[8] = GUICtrlCreateInput("", 360, 235, 100, 20)
    GUICtrlCreateLabel("9", 350, 260, 20, 20)
    $ParamInput[9] = GUICtrlCreateInput("", 360, 260, 100, 20)
    #EndRegion Inputs
    Local $OK = GUICtrlCreateButton("OK", 120, 380, 105, 25)
    Local $Cancel = GUICtrlCreateButton("Cancel", 240, 380, 105, 25)

    GUISetState(@SW_SHOW, $SubGUI)

    While 1
        $aMsg = GUIGetMsg(1)
        
        Switch $aMsg[0]
            Case $GUI_EVENT_CLOSE
                If $aMsg[1] = $SubGUI Then
                    GUIDelete($SubGUI)
                    If WinExists($OptGUI) Then GUISetState(@SW_HIDE, $OptGUI)
                    Return
                EndIf
            Case $Cancel, $OK
                GUIDelete($SubGUI)
                If WinExists($OptGUI) Then GUISetState(@SW_HIDE, $OptGUI)
                Return
            Case $GUI_EVENT_PRIMARYUP
                If $iFlag Then
                    $iFlag = 0
                    ContinueLoop
                EndIf
                
                $aCurInfo = GUIGetCursorInfo($SubGUI)
                
                If @error Then
                    ContinueLoop
                EndIf
                
                Local $iID = $aCurInfo[4]
                Local $bOK = False
                
                If $iID = $SimpleInput1 Or $iID = $SimpleInput2 Or $iID = $SimpleInput3 Then
                    $bOK = True
                Else
                    For $i = 1 To 9
                        If $iID = $ParamInput[$i] Then
                            $bOK = True
                            ExitLoop
                        EndIf
                    Next
                EndIf
                
                If $bOK Then
                    Local $aWinPos = WinGetPos($SubGUI)
                    Local $aCtrlPos = ControlGetPos($SubGUI, '', $iID)
                    GUISetState(@SW_SHOW, $OptGUI)
                    WinMove($OptGUI, "", $aWinPos[0] + $aCtrlPos[0] + 20, $aWinPos[1] + $aCtrlPos[1] - 2)
                    WinActivate($OptGUI)
                    GUISwitch($SubGUI)
                EndIf
            Case $OptButton
                $iFlag = 1
                _GUICtrlMenu_Show($OptGUI, $iContext_Menu, $OptButton)
                GUISetState(@SW_HIDE, $OptGUI)
            Case $iFunc1_Item
                ControlSetText($SubGUI, '', ControlGetFocus($SubGUI), 'Func1')
            Case $iFunc2_Item
                ControlSetText($SubGUI, '', ControlGetFocus($SubGUI), 'Func2')
        EndSwitch
    WEnd
EndFunc   ;==>_SubWin

Func _OptGUI($ParentGUI)
    Local $WinPos = WinGetPos($ParentGUI)
    $OptGUI = GUICreate("", 90, 20, $WinPos[0], $WinPos[1], $WS_POPUPWINDOW, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST, $ParentGUI)
    $OptButton = GUICtrlCreateButton('Button', 0, 0, 90, 20)
EndFunc   ;==>_OptGUI

Func _OptMenu()
    Local $iDummyMenu = GUICtrlCreateDummy()
    $iContext_Menu = GUICtrlCreateContextMenu($iDummyMenu)
    $iFunc1_Item = GUICtrlCreateMenuItem('Func1', $iContext_Menu)
    $iFunc2_Item = GUICtrlCreateMenuItem('Func 2', $iContext_Menu)
EndFunc

Func _GUICtrlMenu_Show($hWnd, $nContextID, $nContextControlID, $iMouse = 0)
    Local $hMenu = GUICtrlGetHandle($nContextID)
    Local $iCtrlPos = ControlGetPos($hWnd, "", $nContextControlID)
    
    Local $iX = $iCtrlPos[0]
    Local $iY = $iCtrlPos[1] + $iCtrlPos[3]
    
    ; Convert the client (GUI) coordinates to screen (desktop) coordinates
    ;ClientToScreen
    Local $stPoint = DllStructCreate("int;int")
    
    DllStructSetData($stPoint, 1, $iX)
    DllStructSetData($stPoint, 2, $iY)
    
    DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint))
    
    $iX = DllStructGetData($stPoint, 1)
    $iY = DllStructGetData($stPoint, 2)
    ;ClientToScreen
    
    If $iMouse Then
        $iX = MouseGetPos(0)
        $iY = MouseGetPos(1)
    EndIf
    
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $iX, "int", $iY, "hwnd", $hWnd, "ptr", 0)
EndFunc
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 397
Репутация
2 384
А вообще я бы делал так (без кнопки, сразу меню выбора):

Код:
#include <GUIConstantsEx.au3>

$hMainGUI = GUICreate('Main', 600, 440, 190, 120)
$iSubWin_Bttn = GUICtrlCreateButton('Sub Window', 180, 160, 150, 40)

GUISetState(@SW_SHOW, $hMainGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $iSubWin_Bttn
            _SubWin()
    EndSwitch
WEnd

Func _SubWin()
    Local $hSubGUI, $iDummy, $iContext_Menu, $iOpt1_Item, $iOpt2_Item
    Local $SimpleInput1, $SimpleInput2, $SimpleInput3
    Local $aParam_Inputs[10]
    Local $iOK_Bttn, $iCancel_Bttn
 
    $hSubGUI = GUICreate('Sub GUI', 523, 420, 192, 124, -1, -1, $hMainGUI)
    GUISetFont(11)
 
    $iDummy = GUICtrlCreateLabel('', -999, -999)
 
    $iContext_Menu = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
    $iOpt1_Item = GUICtrlCreateMenuItem('Opt1', $iContext_Menu)
    $iOpt2_Item = GUICtrlCreateMenuItem('Opt2', $iContext_Menu)
 
    #Region Inputs
    $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)
    #EndRegion Inputs
 
    $iOK_Bttn = GUICtrlCreateButton('OK', 120, 380, 105, 25)
    $iCancel_Bttn = GUICtrlCreateButton('Cancel', 240, 380, 105, 25)
 
    GUISetState(@SW_SHOW, $hSubGUI)
    GUICtrlSetState($iDummy, $GUI_FOCUS)
 
    While 1
        $aMsg = GUIGetMsg(1)
     
        Switch $aMsg[0]
            Case $GUI_EVENT_CLOSE
                If $aMsg[1] = $hSubGUI Then
                    GUIDelete($hSubGUI)
                    Return
                ElseIf $aMsg[1] = $hMainGUI Then
                    Exit
                EndIf
            Case $iCancel_Bttn, $iOK_Bttn
                GUIDelete($hSubGUI)
                Return
            Case $GUI_EVENT_PRIMARYUP
                Local $aCurInfo = GUIGetCursorInfo($hSubGUI)
             
                If @error Or ControlGetHandle($hSubGUI, '', ControlGetFocus($hSubGUI)) <> GUICtrlGetHandle($aCurInfo[4]) Then
                    ContinueLoop
                EndIf
              
                Local $iID = $aCurInfo[4]
             
                If $iID = $SimpleInput1 Or $iID = $SimpleInput2 Or $iID = $SimpleInput3 Then
                    _GUICtrlMenu_Show($hSubGUI, $iContext_Menu, $iID)
                    ContinueLoop
                EndIf
             
                For $i = 1 To 9
                    If $iID = $aParam_Inputs[$i] Then
                        _GUICtrlMenu_Show($hSubGUI, $iContext_Menu, $iID)
                        ExitLoop
                    EndIf
                Next
            Case $iOpt1_Item
                ControlSetText($hSubGUI, '', ControlGetFocus($hSubGUI), 'Opt1')
                GUICtrlSetState($iDummy, $GUI_FOCUS)
            Case $iOpt2_Item
                ControlSetText($hSubGUI, '', ControlGetFocus($hSubGUI), 'Opt2')
                GUICtrlSetState($iDummy, $GUI_FOCUS)
        EndSwitch
    WEnd
EndFunc

Func _GUICtrlMenu_Show($hWnd, $nContextID, $nContextControlID, $iMouse = 0)
    Local $hMenu = GUICtrlGetHandle($nContextID)
    Local $iCtrlPos = ControlGetPos($hWnd, '', $nContextControlID)
    Local $iX = $iCtrlPos[0]
    Local $iY = $iCtrlPos[1] + $iCtrlPos[3]
 
    Local $tPoint = DllStructCreate('int X;int Y')
    DllStructSetData($tPoint, 'X', $iX)
    DllStructSetData($tPoint, 'Y', $iY)
 
    DllCall('user32.dll', 'bool', 'ClientToScreen', 'hwnd', $hWnd, 'struct*', $tPoint)
 
    $iX = DllStructGetData($tPoint, 'X')
    $iY = DllStructGetData($tPoint, 'Y')
 
    If $iMouse Then
        $iX = MouseGetPos(0)
        $iY = MouseGetPos(1)
    EndIf
 
    DllCall('user32.dll', 'int', 'TrackPopupMenuEx', 'hwnd', $hMenu, 'int', 0, 'int', $iX, 'int', $iY, 'hwnd', $hWnd, 'ptr', 0)
EndFunc
 
Последнее редактирование:
Автор
L

liond66

Новичок
Сообщения
94
Репутация
1
Спасибо за отклик.

ra4o
Я с этого начинал, но когда кнопка попадает на другий элемент, они начинают "драться" кто сверху и получается некрасиво.

Se7enstars
При добавлении ещё одного элемента ввода под уже имеющимся, выявляются недостатки.
Я добавил GUIGetCursorInfo по щелчку левой кнопкой и относительно координат самого элемента ввода.
(Сейчас не могу вставить код).
При клике на нижний ввод и попытке кликнуть на кнопку, срабатывает клик на верхний ввод.
Кроме того сейчас заметил, как и в моём коде, кнопка продолжает висеть и при переходе на другие программы (Autoit Help, SciTE).

CreatoR
Понравился второй пример.
Но имеется один недостаток, как и в первом Вашем примере, нет свободного ввода текста!
Это можно исправить?

Спасибо.
 
Последнее редактирование:

ra4o

AutoIT Гуру
Сообщения
1 066
Репутация
206
но когда кнопка попадает на другий элемент, они начинают "драться" кто сверху и получается некрасиво.
Если поставить стиль "$GUI_ONTOP" , то кнопка будет поверх всех элементов при наведении курсора
 
Автор
L

liond66

Новичок
Сообщения
94
Репутация
1
ra4o
У Вас в коде уже есть
Код:
GuiCtrlSetState($OptButton,$GUI_ONTOP)
.
Добавил также после
Код:
GuiCtrlSetState($OptButton,$GUI_SHOW)
.
Это не спасает! Попробуйте сами в нижних полях ввода: 3,6,9.
 

joiner

Модератор
Локальный модератор
Сообщения
3 200
Репутация
540
не знаю как там в той программе. но я бы сделал так
Код:
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <WinAPIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiMenu.au3>
Global Enum $p1 = 1000, $p2, $p3
Global $iInputTmp
Local $hMainGUI = GUICreate('Main', 600, 440, 190, 120)
Local $iSubWin_Bttn = GUICtrlCreateButton('Sub Window', 180, 160, 150, 40)

GUISetState(@SW_SHOW, $hMainGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $iSubWin_Bttn
            _SubWin($hMainGUI)
    EndSwitch
WEnd

Func _SubWin($hWND)
    GUISetState(@SW_DISABLE, $hWND)
    Local $hSubGUI
    Local $SimpleInput1, $SimpleInput2, $SimpleInput3
    Local $aParam_Inputs[10]
    Local $iOK_Bttn, $iCancel_Bttn
    Local $iButtonCH, $whPos, $aCurInfo, $aMsg
    $hSubGUI = GUICreate('Sub GUI', 523, 420, 192, 124, -1, -1, $hMainGUI)
    GUISetFont(11)
    $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)
    GUISetState(@SW_SHOW, $hSubGUI)

    GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
    While 1
        $aMsg = GUIGetMsg()
        Switch $aMsg
            Case $GUI_EVENT_CLOSE
                GUIRegisterMsg($WM_COMMAND, "")
                GUISetState(@SW_ENABLE, $hWND)
                GUIDelete($hSubGUI)
                Return
            Case $iCancel_Bttn, $iOK_Bttn
                GUIRegisterMsg($WM_COMMAND, "")
                GUISetState(@SW_ENABLE, $hWND)
                GUIDelete($hSubGUI)
                Return
            Case $GUI_EVENT_PRIMARYUP
                $aCurInfo = GUIGetCursorInfo($hSubGUI)
                If @error Or Not $aCurInfo[4] Then
                    ContinueLoop
                EndIf
                If $aCurInfo[4] = $SimpleInput1 Or $aCurInfo[4] = $SimpleInput2 Or $aCurInfo[4] = $SimpleInput3 Then
                    GUICtrlDelete($iButtonCH)
                    $whPos = ControlGetPos($hSubGUI, '', $aCurInfo[4])
                    $iButtonCH = GUICtrlCreateButton('...', $whPos[0] + $whPos[2] + 5, $whPos[1], 20, 20)
                    $iInputTmp = $aCurInfo[4]
                Else
                    For $i = 1 To 9
                        If $aCurInfo[4] = $aParam_Inputs[$i] Then
                            GUICtrlDelete($iButtonCH)
                            $whPos = ControlGetPos($hSubGUI, '', $aCurInfo[4])
                            $iButtonCH = GUICtrlCreateButton('...', $whPos[0] + $whPos[2] + 5, $whPos[1], 20, 20)
                            $iInputTmp = $aCurInfo[4]
                            ExitLoop
                        EndIf
                    Next
                EndIf
            Case $iButtonCH
                If $iButtonCH > 0 Then _MenuItem($hSubGUI)
        EndSwitch
    WEnd
EndFunc   ;==>_SubWin

Func _MenuItem($HW)
    Local $hMenu = _GUICtrlMenu_CreatePopup(1)
    _GUICtrlMenu_InsertMenuItem($hMenu, 0, 'item 1', $p1)
    _GUICtrlMenu_InsertMenuItem($hMenu, 1, 'item 2', $p2)
    _GUICtrlMenu_InsertMenuItem($hMenu, 2, 'item 3', $p3)
    _GUICtrlMenu_TrackPopupMenu($hMenu, $HW)
    _GUICtrlMenu_DestroyMenu($hMenu)
EndFunc   ;==>_MenuItem

Func WM_COMMAND($hWND, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $lParam
    Switch $wParam
        Case $p1
            GUICtrlSetData($iInputTmp, "Item 1")
        Case $p2
            GUICtrlSetData($iInputTmp, "Item 2")
        Case $p3
            GUICtrlSetData($iInputTmp, "Item 3")
    EndSwitch
EndFunc   ;==>WM_COMMAND
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 397
Репутация
2 384
нет свободного ввода текста!
А почему не использовать просто Combo?

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

$hMainGUI = GUICreate('Main', 600, 440, 190, 120)
$iSubWin_Bttn = GUICtrlCreateButton('Sub Window', 180, 160, 150, 40)

GUISetState(@SW_SHOW, $hMainGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $iSubWin_Bttn
            _SubWin()
    EndSwitch
WEnd

Func _SubWin()
    Local $hSubGUI
    Local $SimpleInput1, $SimpleInput2, $SimpleInput3
    Local $aParam_Inputs[10]
    Local $iOK_Bttn, $iCancel_Bttn
    
    $hSubGUI = GUICreate('Sub GUI', 523, 420, 192, 124, -1, -1, $hMainGUI)
    GUISetFont(11)
    
    $iDummy = GUICtrlCreateLabel('', -999, -999)
    
    #Region Inputs
    $SimpleInput1 = GUICtrlCreateCombo('', 170, 102, 60, 22)
    $SimpleInput2 = GUICtrlCreateCombo('', 170, 132, 60, 22)
    $SimpleInput3 = GUICtrlCreateCombo('', 300, 132, 60, 22)
    
    GUICtrlCreateLabel('1', 30, 210, 20, 20)
    $aParam_Inputs[1] = GUICtrlCreateCombo('', 40, 210, 100, 20)
    GUICtrlCreateLabel('2', 30, 235, 20, 20)
    $aParam_Inputs[2] = GUICtrlCreateCombo('', 40, 235, 100, 20)
    GUICtrlCreateLabel('3', 30, 260, 20, 20)
    $aParam_Inputs[3] = GUICtrlCreateCombo('', 40, 260, 100, 20)
    GUICtrlCreateLabel('4', 190, 210, 20, 20)
    $aParam_Inputs[4] = GUICtrlCreateCombo('', 205, 210, 100, 20)
    GUICtrlCreateLabel('5', 190, 235, 20, 20)
    $aParam_Inputs[5] = GUICtrlCreateCombo('', 205, 235, 100, 20)
    GUICtrlCreateLabel('6', 190, 260, 20, 20)
    $aParam_Inputs[6] = GUICtrlCreateCombo('', 205, 260, 100, 20)
    GUICtrlCreateLabel('7', 350, 210, 20, 20)
    $aParam_Inputs[7] = GUICtrlCreateCombo('', 360, 210, 100, 20)
    GUICtrlCreateLabel('8', 350, 235, 20, 20)
    $aParam_Inputs[8] = GUICtrlCreateCombo('', 360, 235, 100, 20)
    GUICtrlCreateLabel('9', 350, 260, 20, 20)
    $aParam_Inputs[9] = GUICtrlCreateCombo('', 360, 260, 100, 20)
    #EndRegion Inputs
    
    For $i = $SimpleInput1 To $SimpleInput3
        GUICtrlSetData($i, 'Opt1|Opt2', '')
    Next
    
    For $i = 1 To 9
        GUICtrlSetData($aParam_Inputs[$i], 'Opt1|Opt2', '')
    Next
    
    $iOK_Bttn = GUICtrlCreateButton('OK', 120, 380, 105, 25)
    $iCancel_Bttn = GUICtrlCreateButton('Cancel', 240, 380, 105, 25)
    
    GUISetState(@SW_SHOW, $hSubGUI)
    GUICtrlSetState($iDummy, $GUI_FOCUS)
    
    While 1
        $aMsg = GUIGetMsg(1)
        
        Switch $aMsg[0]
            Case $GUI_EVENT_CLOSE
                If $aMsg[1] = $hSubGUI Then
                    GUIDelete($hSubGUI)
                    Return
                ElseIf $aMsg[1] = $hMainGUI Then
                    Exit
                EndIf
            Case $iCancel_Bttn, $iOK_Bttn
                GUIDelete($hSubGUI)
                Return
            Case $SimpleInput1 To $SimpleInput3, $aParam_Inputs[1] To $aParam_Inputs[9]
                GUICtrlSetState($iDummy, $GUI_FOCUS)
            Case $GUI_EVENT_PRIMARYUP
                If StringLeft(ControlGetFocus($hSubGUI), 6) = 'Static' Then
                    ContinueLoop
                EndIf
                
                Local $tPoint = _WinAPI_GetMousePos()
                Local $iID = _WinAPI_GetDlgCtrlID(_WinAPI_GetParent(_WinAPI_WindowFromPoint($tPoint)))
                
                If $iID = $SimpleInput1 Or $iID = $SimpleInput2 Or $iID = $SimpleInput3 Then
                    _GUICtrlComboBoxEx_ShowDropDown($iID, True)
                    ContinueLoop
                EndIf
                
                For $i = 1 To 9
                    If $iID = $aParam_Inputs[$i] Then
                        _GUICtrlComboBoxEx_ShowDropDown($iID, True)
                        ExitLoop
                    EndIf
                Next
        EndSwitch
    WEnd
EndFunc
 
Автор
L

liond66

Новичок
Сообщения
94
Репутация
1
joiner
Вы поставили кнопки там, где они первоначально и были. Там специально для них оставлено место. Их даже скрывать не надо.
Но смысл в том, чтобы в любом окне на любой элемент ввода при необходимости "навесить" меню выбора,
не заботясь о том, попадают ли они на другой элемент.

CreatoR
ComboBox было бы отличное решение, если бы вместо текста можно было бы вставить результат функции. Это возможно?
А по предыдущему Вашему примеру: можно ли его улучшить, добавив свободный ввод текста?
Я алгоритм представляю так:
- по клику левой кнопки показывать элемент с меню, но оставить фокус на вводе текста.
- при наведении мышки на элемент с меню фокус установить на этот элемент, давая возможность нажать на него.
Естественно элемент добавляется одним из тех способов, когда он не дерётся с другими элементами.

xXx
Сейчас поищу, как вставить картинку :scratch:
 

joiner

Модератор
Локальный модератор
Сообщения
3 200
Репутация
540
в коде вставляются кнопки исходя из позиции элемента. их изначально нет
 
Автор
L

liond66

Новичок
Сообщения
94
Репутация
1
Вот картинка, два в одном. Клик на верхний ввод и клик на второй ввод.

vTask.png
Сообщение автоматически объединено:

joiner
Вы нашли смещение, когда кнопка не попадает на другой элемент, но смысл в том, чтобы не оставлять специально пустое место под кнопку.
А если в приведённом вами примере сместить кнопку на какой то элемент, то отображаться они будут криво.
Не получается сделать кнопку гарантировано поверх других случайных элементов.
И вдобавок применение стилей типа $WS_EX_TOPMOST приводит к тому, что элемент повисает поверх других приложений.
Видел висящую кнопку своего приложения поверх Autoit Help и SciTE !
А вот ComboBox и ContextMenu, насколько я видел, отображаются без проблем.
 
Последнее редактирование:
Автор
L

liond66

Новичок
Сообщения
94
Репутация
1
ra4o
Сейчас я на Windows 7 Pro
Запускаю исправленный вами код, клик на ввод 6 и получаю

Input6.png
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 397
Репутация
2 384
ComboBox было бы отличное решение, если бы вместо текста можно было бы вставить результат функции. Это возможно?
Конечно.

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

$hMainGUI = GUICreate('Main', 600, 440, 190, 120)
$iSubWin_Bttn = GUICtrlCreateButton('Sub Window', 180, 160, 150, 40)

GUISetState(@SW_SHOW, $hMainGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $iSubWin_Bttn
            _SubWin()
    EndSwitch
WEnd

Func _SubWin()
    Local $hSubGUI, $iDummy
    Local $aInputs[13][3] = [[12]]
    Local $iOK_Bttn, $iCancel_Bttn
    
    $hSubGUI = GUICreate('Sub GUI', 523, 420, 192, 124, -1, -1, $hMainGUI)
    GUISetFont(11)
    
    $iDummy = GUICtrlCreateLabel('', -999, -999)
    
    #Region Inputs
    $aInputs[1][0] = GUICtrlCreateCombo('', 170, 102, 60, 22)
    $aInputs[2][0] = GUICtrlCreateCombo('', 170, 132, 60, 22)
    $aInputs[3][0] = GUICtrlCreateCombo('', 300, 132, 60, 22)
    
    GUICtrlCreateLabel('1', 30, 210, 20, 20)
    $aInputs[4][0] = GUICtrlCreateCombo('', 40, 210, 100, 20)
    GUICtrlCreateLabel('2', 30, 235, 20, 20)
    $aInputs[5][0] = GUICtrlCreateCombo('', 40, 235, 100, 20)
    GUICtrlCreateLabel('3', 30, 260, 20, 20)
    $aInputs[6][0] = GUICtrlCreateCombo('', 40, 260, 100, 20)
    GUICtrlCreateLabel('4', 190, 210, 20, 20)
    $aInputs[7][0] = GUICtrlCreateCombo('', 205, 210, 100, 20)
    GUICtrlCreateLabel('5', 190, 235, 20, 20)
    $aInputs[8][0] = GUICtrlCreateCombo('', 205, 235, 100, 20)
    GUICtrlCreateLabel('6', 190, 260, 20, 20)
    $aInputs[9][0] = GUICtrlCreateCombo('', 205, 260, 100, 20)
    GUICtrlCreateLabel('7', 350, 210, 20, 20)
    $aInputs[10][0] = GUICtrlCreateCombo('', 360, 210, 100, 20)
    GUICtrlCreateLabel('8', 350, 235, 20, 20)
    $aInputs[11][0] = GUICtrlCreateCombo('', 360, 235, 100, 20)
    GUICtrlCreateLabel('9', 350, 260, 20, 20)
    $aInputs[12][0] = GUICtrlCreateCombo('', 360, 260, 100, 20)
    #EndRegion Inputs
    
    For $i = 1 To $aInputs[0][0]
        $aInputs[$i][1] = 'Opt1|Opt2'
        $aInputs[$i][2] = '_MyOptFunc1|_MyOptFunc2'
        GUICtrlSetData($aInputs[$i][0], $aInputs[$i][1], '')
    Next
    
    $iOK_Bttn = GUICtrlCreateButton('OK', 120, 380, 105, 25)
    $iCancel_Bttn = GUICtrlCreateButton('Cancel', 240, 380, 105, 25)
    
    GUISetState(@SW_SHOW, $hSubGUI)
    GUICtrlSetState($iDummy, $GUI_FOCUS)
    
    While 1
        $aMsg = GUIGetMsg(1)
        
        Switch $aMsg[0]
            Case $GUI_EVENT_CLOSE
                If $aMsg[1] = $hSubGUI Then
                    GUIDelete($hSubGUI)
                    Return
                ElseIf $aMsg[1] = $hMainGUI Then
                    Exit
                EndIf
            Case $iCancel_Bttn, $iOK_Bttn
                GUIDelete($hSubGUI)
                Return
            Case $aInputs[1][0] To $aInputs[$aInputs[0][0]][0]
                GUICtrlSetState($iDummy, $GUI_FOCUS)
                
                For $i = 1 To $aInputs[0][0]
                    If $aMsg[0] = $aInputs[$i][0] Then
                        $aText = StringSplit($aInputs[$i][1], '|')
                        $aFuncs = StringSplit($aInputs[$i][2], '|')
                        
                        For $j = 1 To $aText[0]
                            If $aText[$j] = GUICtrlRead($aMsg[0]) Then
                                ControlSetText($hSubGUI, '', $aMsg[0], Call($aFuncs[$j], $aText[$j]))
                                ExitLoop 2
                            EndIf
                        Next
                    EndIf
                Next
            Case $GUI_EVENT_PRIMARYUP
                If StringLeft(ControlGetFocus($hSubGUI), 6) = 'Static' Then
                    ContinueLoop
                EndIf
                
                Local $tPoint = _WinAPI_GetMousePos()
                Local $iID = _WinAPI_GetDlgCtrlID(_WinAPI_GetParent(_WinAPI_WindowFromPoint($tPoint)))
                
                For $i = 1 To $aInputs[0][0]
                    If $iID = $aInputs[$i][0] Then
                        _GUICtrlComboBoxEx_ShowDropDown($iID, True)
                        ExitLoop
                    EndIf
                Next
        EndSwitch
    WEnd
EndFunc

Func _MyOptFunc1($sText)
    Return $sText & ' + Ret'
EndFunc

Func _MyOptFunc2($sText)
    Return $sText & ' + Ret'
EndFunc
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 397
Репутация
2 384
Вопрос - У каждого поля ввода должен быть свой набор функции, или это некий глобальный набор функции который должен работать для всех полей одинаково?
 
Верх