Jump to content

ComboBox with radiobuttons and checkboxes


funkey
 Share

Recommended Posts

Here is a nice workaround with a menu control.

#include <GUIConstantsEx.au3>

Global $hGui = GUICreate("ComboBox with radiobuttons and checkboxes", 400, 100)
GUIRegisterMsg(0x111, "_WM_COMMAND")

Global $hCombo = GUICtrlCreateCombo("Choose option", 10, 10, 100, 0, 0x3)

Global $hMenu = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
Global $nOpt1 = GUICtrlCreateMenuItem("Option1", $hMenu, -1, 1)
GUICtrlSetState(-1, $GUI_CHECKED)
Global $nOpt2 = GUICtrlCreateMenuItem("Option2", $hMenu, -1, 1)
Global $nOpt3 = GUICtrlCreateMenuItem("Option3", $hMenu, -1, 1)
GUICtrlCreateMenuItem("", $hMenu)
Global $nOpt4 = GUICtrlCreateMenuItem("Option4", $hMenu, -1, 0)
GUICtrlSetState(-1, $GUI_CHECKED)
Global $nOpt5 = GUICtrlCreateMenuItem("Option5", $hMenu, -1, 0)
Global $nOpt6 = GUICtrlCreateMenuItem("Option6", $hMenu, -1, 0)

GUISetState()

Local $msg
Do
    $msg = GUIGetMsg()
    Switch $msg
        Case $nOpt4 To $nOpt6
            If BitAND(GUICtrlRead($msg), $GUI_CHECKED) = $GUI_CHECKED Then
                GUICtrlSetState($msg, $GUI_UNCHECKED)
            Else
                GUICtrlSetState($msg, $GUI_CHECKED)
            EndIf
    EndSwitch
Until $msg = -3


Func _WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0x0000FFFF)
    Static $iVisible = 0
    
    If $nID = $hCombo Then
        If $nNotifyCode = 7 Then
            GUICtrlSendMsg($hCombo, 335, 1, 0)  ;hide dropdownlist
            If $iVisible = 0 Then
                ShowMenu($hGui, $hCombo, $hMenu)
                GUICtrlSendMsg($hCombo, 335, 1, 0)  ;hide dropdownlist again
                $iVisible = 1
            Else
                $iVisible = 0
            EndIf
        EndIf
    Else
        $iVisible = 0
    EndIf
        
    Return "GUI_RUNDEFMSG"
EndFunc   ;==>MY_WM_COMMAND


; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func ShowMenu($hWnd, $CtrlID, $nContextID)
    Local $arPos, $x, $y
    Local $hMenu = GUICtrlGetHandle($nContextID)
    
    $arPos = ControlGetPos($hWnd, "", $CtrlID)
    
    $x = $arPos[0]
    $y = $arPos[1] + $arPos[3]
    
    ClientToScreen($hWnd, $x, $y)
    TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc   ;==>ShowMenu

; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
    Local $stPoint = DllStructCreate("int;int")
    
    DllStructSetData($stPoint, 1, $x)
    DllStructSetData($stPoint, 2, $y)

    DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint))
    
    $x = DllStructGetData($stPoint, 1)
    $y = DllStructGetData($stPoint, 2)
    ; release Struct not really needed as it is a local
    $stPoint = 0
EndFunc   ;==>ClientToScreen

; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd)
Func TrackPopupMenu($hWnd, $hMenu, $x, $y)
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc   ;==>TrackPopupMenu

Have fun!

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

Interesting idea. If that's the functionality you want though, why not use a button or split button (so you still get the arrow)? That would avoid the empty dropdown. You could even change the text on the button if it suits your purpose to display some information about the choice made.

I suggest this, cause those kind of dropdowns on Win7 look just like buttons.

Link to comment
Share on other sites

Thanks.

Yes, maybe it is better to use a simple button, this would be easier to handle.

@jscript: For me on WinXP it never failed.

I'll test it on Win7 in a few hours.

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

On Win7 x64 the combobox is showing the "Choose option" while it shows afterwards the menu.

You can use

_GUICtrlComboBoxEx_SetItemHeight (GUICtrlGetHandle($hCombo), 0, 1)
to limit the height of the combobox.

It looks fine on WinXP.

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Looks pretty good, but like above, for me on win 7 32, it acts a little strangely, as though it takes to long to open and then when it closes, it kind of does this little bounce thing.

Difficult to explain, but maybe if you double click it it will open and close fast, and thats what it does each time for me.

Great idea.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

Thank you UEZ and JohnOne.

Now I tested it on Win7 too.

Looks like Win7 always wants to show the dropdown list because of the animation. _GUICtrlComboBoxEx_SetItemHeight just works down to one pixel and you see the animation a little bit.

So best way is simply to use a standard button I think.

#include <GUIConstantsEx.au3>
Global $hGui = GUICreate("ComboBox with radiobuttons and checkboxes", 400, 100)
Global $nCombo = GUICtrlCreateButton("Choose option", 10, 10, 140, 25)
Global $nMenu = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
Global $nOpt1 = GUICtrlCreateMenuItem("Option1", $nMenu, -1, 1)
GUICtrlSetState(-1, $GUI_CHECKED)
Global $nOpt2 = GUICtrlCreateMenuItem("Option2", $nMenu, -1, 1)
Global $nOpt3 = GUICtrlCreateMenuItem("Option3", $nMenu, -1, 1)
GUICtrlCreateMenuItem("", $nMenu)
Global $nOpt4 = GUICtrlCreateMenuItem("Option4", $nMenu, -1, 0)
GUICtrlSetState(-1, $GUI_CHECKED)
Global $nOpt5 = GUICtrlCreateMenuItem("Option5", $nMenu, -1, 0)
Global $nOpt6 = GUICtrlCreateMenuItem("Option6", $nMenu, -1, 0)
GUISetState()
Local $msg
Do
 $msg = GUIGetMsg()
 Switch $msg
  Case $nOpt4 To $nOpt6
   If BitAND(GUICtrlRead($msg), $GUI_CHECKED) = $GUI_CHECKED Then
    GUICtrlSetState($msg, $GUI_UNCHECKED)
   Else
    GUICtrlSetState($msg, $GUI_CHECKED)
   EndIf
  Case $nCombo
   ShowMenu($hGui, $nCombo, $nMenu)
 EndSwitch
Until $msg = -3
 
; Show a menu in a given GUI window which belongs to a given GUI ctrl
Func ShowMenu($hWnd, $CtrlID, $nContextID)
 Local $arPos, $x, $y
 Local $hMenu = GUICtrlGetHandle($nContextID)
 $arPos = ControlGetPos($hWnd, "", $CtrlID)
 $x = $arPos[0]
 $y = $arPos[1] + $arPos[3]
 ClientToScreen($hWnd, $x, $y)
 TrackPopupMenu($hWnd, $hMenu, $x, $y)
EndFunc   ;==>ShowMenu
; Convert the client (GUI) coordinates to screen (desktop) coordinates
Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
 Local $stPoint = DllStructCreate("int;int")
 DllStructSetData($stPoint, 1, $x)
 DllStructSetData($stPoint, 2, $y)
 DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint))
 $x = DllStructGetData($stPoint, 1)
 $y = DllStructGetData($stPoint, 2)
 ; release Struct not really needed as it is a local
 $stPoint = 0
EndFunc   ;==>ClientToScreen
; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd)
Func TrackPopupMenu($hWnd, $hMenu, $x, $y)
 DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc   ;==>TrackPopupMenu

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...