Jump to content

ComboBox Questions


Recommended Posts

Dear community

My need is to get the simpliest combo box possible. I mean no border, no on over highlight, no Windows theme aso, so I can insert it into a more modern GUI look. 
I tried this control and regular _GUICtrlComboBoxEx_Create and _GUICtrlComboBox_Create, trying all Styles and Extended style.

The "Option 1" is a trick to insert a regular combo box into a rounded rectangle WinAPI drawn. I am unable to get rid of up, down, let and right edges of the original combo box, even by painting over it 😕

The second box is a written from scracth but it does not expands, and do not understand why
The button is a bit uglly because being of text, but the main problem is to make it functionnal

Does someone may help me on this ?

#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <GuiComboBox.au3>
#include <WindowsConstants.au3>
#include <FontConstants.au3>

; Définitions spéciales combobox
Global Const $SS_CENTERIMAGE = 0x0200
Global Const $SS_NOTIFY = 0x0100
Global Const $BS_CENTER = 0x0300
Global Const $LBS_NOTIFY = 0x0001
Global Const $SW_HIDE = 0
Global Const $SW_SHOW = 5
Global Const $LB_ADDSTRING = 0x0180
Global Const $LB_GETCURSEL = 0x0188
Global Const $LB_GETTEXT = 0x0189
Global Const $BN_CLICKED = 0
Global Const $LBN_SELCHANGE = 1

; Définition des variables et constantes
Const $cBlack = 0x000000
Const $cDeep_Grey = 0x252525
Const $cMid_Grey = 0x404040
Const $cLig_Grey = 0x808080
Const $cXLig_Grey = 0xBDBDBD
Const $cXXLig_Grey = 0xEEEEEE
Const $colWhite = 0xFFFFFF

; Définition de la font de la GUI
Const $sFont_Name = "Roboto", $Font_Size = 20
Global $hFont, $hEdit

; Définition des GUIs
Const $GUI_Main_Width = 1100, $GUI_Main_Height = 805, $GUI_Menu_Height = 40, $GUI_Task_Bar_Height = 110, $Corner_Radius = 14, $GUI_Box_Height = 26
Global $hGUI_Main, $hGUI_Color

; Définition pinceaux et stylos
Global $hBrush_Deep_Grey, $hBrush_Mid_Grey, $hBrush_Lig_Grey, $hBrush_XLig_Grey, $hBrush_XXLig_Grey
Global $hPen_Deep_Grey, $hPen_Mid_Grey, $hPen_Lig_Grey, $hPen_XLig_Grey, $hPen_XXLig_Grey

; Créer une GUI avec des options de transparence et composition
$hGUI_Main = GUICreate("GUI", $GUI_Main_Width, $GUI_Main_Height, -1, -1, BitOR($WS_OVERLAPPEDWINDOW, $WS_VISIBLE), 0)
GUISetBkColor ( $cXLig_Grey, $hGUI_Main )

; Créer la fenêtre Color (GUI Color)
$hGUI_Color = GUICreate("", $GUI_Main_Width, $GUI_Main_Height - $GUI_Menu_Height - $GUI_Task_Bar_Height, 0, $GUI_Menu_Height, $WS_CHILD, Default, $hGUI_Main)
GUISetBkColor($cDeep_Grey, $hGUI_Color)
GUICtrlSetDefColor($cXLig_Grey, $hGUI_Color)
GUISetFont($Font_Size, $FW_NORMAL, $GUI_FONTNORMAL, $sFont_Name, $hGUI_Color, $CLEARTYPE_QUALITY)

GUISetState(@SW_SHOW, $hGUI_Main)
GUISetState(@SW_SHOW, $hGUI_Color)

; Initialiser les objets GDI
_MyWinAPI_Init_GDI_Objects( )

GUISwitch ( $hGUI_Color )
_MyWinAPI_ComboBox_Create( $hGUI_Color, 50, 200, 150, $GUI_Box_Height, $Corner_Radius, $hPen_XXLig_Grey )
Local $aOptions = ["Option 1", "Option 2", "Option 3", "Option 4"]
_MyWinAPI_ComboBox_Create2( $hGUI_Color, 50, 250, 170, $GUI_Box_Height, 10, $aOptions )

While 1
        Switch GUIGetMsg ( )
                Case $GUI_EVENT_CLOSE
                _MyWinAPI_Release_GDI_Objects( )
                ExitLoop
        EndSwitch
WEnd

Func _MyWinAPI_ComboBox_Create( $hGUI, $Pos_X, $Pos_Y, $Width, $Height, $Corner_Radius, $hPen )
        ; Décalage de la zone de saisie pour éviter chevauchement
        Local $Offset_XY = Ceiling ( $Corner_Radius / 2.8 )
    
        ; Définir les rectangles pour la boîte et le texte
        Local $tBoxRect = _WinAPI_CreateRect( 0, 0, $Width, $Height )
    
        ; Initialiser le dessin en mémoire (double buffering) pour éviter le flickering
        Local $hDC = _WinAPI_GetDC( $hGUI )
        Local $hMemDC = _WinAPI_CreateCompatibleDC ( $hDC )
        Local $hBitmap = _WinAPI_CreateCompatibleBitmap ( $hDC, $Width, $Height )
    
        ; Sauvegarder les objets existants et sélectionner les nouveaux objets GDI
        Local $hOldBitmap = _WinAPI_SelectObject ( $hMemDC, $hBitmap )
        Local $hOldPen = _WinAPI_SelectObject ( $hMemDC, $hPen )
        Local $hOldBrush = _WinAPI_SelectObject ( $hMemDC, $hBrush_XXLig_Grey )
    
        ; Définir le mode de fond transparent pour le texte
        _WinAPI_SetBkMode ( $hMemDC, $TRANSPARENT )
    
        ; Remplir la zone de la boîte avec le pinceau de fond
        _WinAPI_FillRect ( $hMemDC, $tBoxRect, $hBrush_Deep_Grey )
    
        ; Dessiner un rectangle arrondi pour la boîte
        _WinAPI_RoundRect ( $hMemDC, $tBoxRect, $Corner_Radius, $Corner_Radius )
    
        ; Restaurer les objets GDI précédents (pinceau et stylo)
        _WinAPI_SelectObject ( $hMemDC, $hOldBrush )
        _WinAPI_SelectObject ( $hMemDC, $hOldPen )    
    
        ; Créer un ComboBox avec WinAPI sans bordures
        Local $hComboBox = _WinAPI_CreateWindowEx ( $WS_EX_CLIENTEDGE, "ComboBox", "", BitOR( $WS_CHILD, $WS_VISIBLE, $CBS_DROPDOWNLIST, $WS_VSCROLL ), _
            $Pos_X + $Offset_XY, $Pos_Y, $Width - 2 * $Offset_XY, $Height - 5, $hGUI, 0 )
    
        ; Ajouter des éléments à la ComboBox via DllCall en utilisant des chaînes encodées en UTF-16
        DllCall ( "user32.dll", "lresult", "SendMessageW", "hwnd", $hComboBox, "uint", $CB_ADDSTRING, "wparam", 0, "wstr", "Option 1" )
        DllCall ( "user32.dll", "lresult", "SendMessageW", "hwnd", $hComboBox, "uint", $CB_ADDSTRING, "wparam", 0, "wstr", "Option 2" )
        DllCall ( "user32.dll", "lresult", "SendMessageW", "hwnd", $hComboBox, "uint", $CB_ADDSTRING, "wparam", 0, "wstr", "Option 3" )
    
        ; Sélectionner un élément dans la ComboBox via DllCall
        DllCall ( "user32.dll", "lresult", "SendMessageW", "hwnd", $hComboBox, "uint", $CB_SETCURSEL, "wparam", 0, "lparam", 0 )
    
        ; Appliquer la police définie globalement via DllCall
        DllCall ( "user32.dll", "lresult", "SendMessageW", "hwnd", $hComboBox, "uint", $WM_SETFONT, "wparam", $hFont, "lparam", 1 )
        
        ; Copier le contenu du contexte mémoire vers le contexte de la fenêtre pour afficher le résultat final
        _WinAPI_BitBlt ( $hDC, $Pos_X, $Pos_Y, $Width, $Height, $hMemDC, 0, 0, $SRCCOPY )
    
        ; Nettoyage : restaurer les objets initiaux et libérer les ressources GDI
        _WinAPI_SelectObject ( $hMemDC, $hOldBitmap )
        _WinAPI_DeleteObject ( $hBitmap )
        _WinAPI_DeleteDC ( $hMemDC )
        _WinAPI_ReleaseDC ( $hGUI, $hDC )    
    
        ; Retourner le handle du ComboBox pour une utilisation future
        Return $hComboBox
EndFunc

Func _MyWinAPI_ComboBox_Create2( $hGUI, $Pos_X, $Pos_Y, $Width, $Height, $Corner_Radius, $aOptions )
        ; Créer la zone de sélection (zone d affichage)
        Local $hStatic = _WinAPI_CreateWindowEx(0, "Static", "", BitOR ( $WS_CHILD, $WS_VISIBLE, $SS_CENTERIMAGE, $SS_NOTIFY ), _
                $Pos_X + 2, $Pos_Y + 1, $Width - $Height + 2, $Height - 2, $hGUI, 0 )
                
        ; Définir le rectangle pour la combo box et la combo box + bouton
        Local $tBoxRect = _WinAPI_CreateRect ( 0, 0, $Width - 20, $Height )
        Local $tBoxRectFull = _WinAPI_CreateRect ( 0, 0, $Width, $Height )

        ; Initialiser le dessin en mémoire (double buffering) pour éviter le flickering
        Local $hDC = _WinAPI_GetDC ( $hGUI )
        Local $hMemDC = _WinAPI_CreateCompatibleDC ( $hDC )
        Local $hBitmap = _WinAPI_CreateCompatibleBitmap ( $hDC, $Width, $Height )

        ; Sauvegarder les objets existants et sélectionner les nouveaux objets GDI
        Local $hOldBitmap = _WinAPI_SelectObject ( $hMemDC, $hBitmap )
        Local $hOldPen = _WinAPI_SelectObject ( $hMemDC, $hPen_XXLig_Grey )
        Local $hOldBrush = _WinAPI_SelectObject ( $hMemDC, $hBrush_XXLig_Grey )

        ; Définir le mode de fond transparent pour le texte
        _WinAPI_SetBkMode ( $hMemDC, $TRANSPARENT )

        ; Remplir la zone de la boîte avec le pinceau de fond
        _WinAPI_FillRect ( $hMemDC, $tBoxRectFull, $hBrush_Deep_Grey )

        ; Dessiner le rectangle arrondi avec remplissage et contour
        _WinAPI_RoundRect ( $hMemDC, $tBoxRect, $Corner_Radius, $Corner_Radius )

        ; Copier le contenu du contexte mémoire vers le contexte de la fenêtre pour afficher le résultat final
        _WinAPI_BitBlt ( $hDC, $Pos_X, $Pos_Y, $Width, $Height, $hMemDC, 0, 0, $SRCCOPY )

        ; Restaurer les objets GDI précédents (pinceau et stylo)
        _WinAPI_SelectObject ( $hMemDC, $hOldBrush )
        _WinAPI_SelectObject ( $hMemDC, $hOldPen )
        _WinAPI_SelectObject ( $hMemDC, $hOldBitmap )

        ; Nettoyage : libérer les ressources GDI
        _WinAPI_DeleteObject ( $hBitmap )
        _WinAPI_DeleteDC ( $hMemDC )
        _WinAPI_ReleaseDC ( $hGUI, $hDC )

        ; Appliquer la police définie globalement
        DllCall ( "user32.dll", "lresult", "SendMessageW", "hwnd", $hStatic, "uint", $WM_SETFONT, "wparam", $hFont, "lparam", 1) 

        ; Créer le bouton de déroulement
        Local $hButton = _WinAPI_CreateWindowEx ( 0, "Button", "▼", BitOR($WS_CHILD, $WS_VISIBLE, $BS_CENTER), _
                $Pos_X + $Width - 20, $Pos_Y + 3, 20, 20, $hGUI, 0 )

        ; Créer la ListBox pour afficher les options, cachée par défaut
        Local $hListBox = _WinAPI_CreateWindowEx ( 0, "ListBox", "", BitOR($WS_CHILD, $WS_VSCROLL, $LBS_NOTIFY), _
                $Pos_X, $Pos_Y + $Height, $Width, 100, $hGUI, 0 )
        _WinAPI_ShowWindow ( $hListBox, $SW_HIDE )

        ; Ajouter les options à la ListBox
        For $option In $aOptions
                DllCall ( "user32.dll", "lresult", "SendMessageW", "hwnd", $hListBox, "uint", $LB_ADDSTRING, "wparam", 0, "wstr", $option )
        Next

        ; Enregistrer les événements pour le bouton et la ListBox
        GUIRegisterMsg ( $WM_COMMAND, "_ComboBox_CustomEvents" )

        ; Stocker les handles pour l'utilisation dans la fonction d'événements
        Global $g_hCustomCombo [3] = [$hStatic, $hButton, $hListBox]

        Return $g_hCustomCombo
EndFunc

Func _ComboBox_CustomEvents($hWnd, $Msg, $wParam, $lParam)
        ; Vérifie si l événement est pour le bouton de déroulement ou la ListBox
        Local $nCtrlID = BitAND($wParam, 0xFFFF)
        Local $nEvent = BitShift($wParam, 16)

        ; Vérification si le bouton est cliqué
        If $g_hCustomCombo[1] = $nCtrlID And $nEvent = $BN_CLICKED Then
                ; Basculer la visibilité de la ListBox
                If _WinAPI_IsWindowVisible($g_hCustomCombo[2]) Then
                _WinAPI_ShowWindow($g_hCustomCombo[2], $SW_HIDE)
                Else
                _WinAPI_ShowWindow($g_hCustomCombo[2], $SW_SHOW)
                EndIf
        EndIf

        ; Vérification si un élément est sélectionné dans la ListBox
        If $g_hCustomCombo[2] = $nCtrlID And $nEvent = $LBN_SELCHANGE Then
                Local $index = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $g_hCustomCombo[2], "uint", $LB_GETCURSEL, "wparam", 0, "lparam", 0)[0]
                Local $text = DllStructCreate("char[256]")
                DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $g_hCustomCombo[2], "uint", $LB_GETTEXT, "wparam", $index, "ptr", DllStructGetPtr($text))
                ; Mettre à jour la zone de sélection
                DllCall("user32.dll", "lresult", "SetWindowTextW", "hwnd", $g_hCustomCombo[0], "wstr", DllStructGetData($text, 1))
                _WinAPI_ShowWindow($g_hCustomCombo[2], $SW_HIDE)
        EndIf
EndFunc

; Fonction pour gérer le message WM_CTLCOLOREDIT et appliquer le fond personnalisé
Func _MyWinAPI_EditControl_Background( $hWnd, $Msg, $wParam, $lParam )
        If $Msg = $WM_CTLCOLOREDIT Then
            ; Créer le pinceau personnalisé pour la couleur de fond
            Local $hBrush_Custom = _WinAPI_CreateSolidBrush ( $cXXLig_Grey )
            _WinAPI_SetTextColor ( $wParam, $cBlack )
            _WinAPI_SetBkColor ( $wParam, $cXXLig_Grey )
            Return $hBrush_Custom
        EndIf
    EndFunc
    
; Initialiser les objets GDI une seule fois pour éviter les réinitialisations répétitives
Func _MyWinAPI_Init_GDI_Objects( )
        ; Pinceaux
        $hBrush_Deep_Grey = _WinAPI_CreateSolidBrush ( $cDeep_Grey )
        $hBrush_Mid_Grey = _WinAPI_CreateSolidBrush ( $cMid_Grey )
        $hPen_Lig_Grey = _WinAPI_CreateSolidBrush ( $cLig_Grey )
        $hBrush_XLig_Grey = _WinAPI_CreateSolidBrush ( $cXLig_Grey )
        $hBrush_XXLig_Grey = _WinAPI_CreateSolidBrush ( $cXXLig_Grey )

        ; Stylo
        $hPen_Deep_Grey = _WinAPI_CreatePen ( $PS_SOLID, 1, $cDeep_Grey )    
        $hPen_Mid_Grey = _WinAPI_CreatePen ( $PS_SOLID, 1, $cMid_Grey )    
        $hPen_Lig_Grey = _WinAPI_CreatePen ( $PS_SOLID, 1, $cLig_Grey )
        $hPen_XLig_Grey = _WinAPI_CreatePen ( $PS_SOLID, 1, $cXLig_Grey )
        $hPen_XXLig_Grey = _WinAPI_CreatePen ( $PS_SOLID, 1, $cXXLig_Grey )

        ; Font
        $hFont = _WinAPI_CreateFont ( $Font_Size, 0, 0, 0, $FW_NORMAL, False, False, False, $DEFAULT_CHARSET, $OUT_TT_PRECIS, $CLIP_DEFAULT_PRECIS, $CLEARTYPE_QUALITY, $DEFAULT_PITCH, $sFont_Name )
EndFunc

; Libération des objets GDI à la fin
Func _MyWinAPI_Release_GDI_Objects( )
        ; Pinceaux
        If $hBrush_Deep_Grey Then _WinAPI_DeleteObject ( $hBrush_Deep_Grey )
        If $hBrush_Mid_Grey Then _WinAPI_DeleteObject ( $hBrush_Mid_Grey )
        If $hBrush_XXLig_Grey Then _WinAPI_DeleteObject ( $hBrush_XXLig_Grey )

        ; Stylo
        If $hPen_Mid_Grey Then _WinAPI_DeleteObject ( $hPen_Mid_Grey )
        If $hPen_Lig_Grey Then _WinAPI_DeleteObject ( $hPen_Lig_Grey )
        If $hPen_XXLig_Grey Then _WinAPI_DeleteObject ( $hPen_XXLig_Grey )

        ; Font
        If $hFont Then _WinAPI_DeleteObject ( $hFont )
EndFunc



image.png.d9a7be5e921026402beba468b3236d97.png

Edited by Ebola57
Link to comment
Share on other sites

  • Moderators

Split from a 2 year old topic in Examples.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

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...