Jump to content
Sign in to follow this  
qwert

Can a combo box have colored text?

Recommended Posts

qwert

From the Help File:

Only Button, Label, Checkbox, Group, Radio, Edit, Input, List, Listview, ListviewItem, Treeview, TreeviewItem, Graphic and Progress controls can currently be colored.

I've tried GUICtrlSetDefColor and GUICtrlSetColor and all I get is black on white. Is there a workaround? A font change works fine.

Thanks for any help.

Share this post


Link to post
Share on other sites
Hawkwing

I have always found the helpfile to be very accurate, and, since this is the first reply, I would guess that no one has a workaround.


The Wheel of Time turns, and Ages come and pass, leaving memories that become legend. Legend fades to myth, and even myth is long forgotten when the Age that gave it birth comes again.

Share this post


Link to post
Share on other sites
Authenticity

Refer to this page to gather a better understanding of the subject. One approach is to use an owner-drawn ComboBox:

#include <GUIComboBox.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

Global Const $ODT_MENU          = 1
Global Const $ODT_LISTBOX       = 2
Global Const $ODT_COMBOBOX      = 3
Global Const $ODT_BUTTON        = 4
Global Const $ODT_STATIC        = 5
Global Const $ODT_HEADER        = 100
Global Const $ODT_TAB           = 101
Global Const $ODT_LISTVIEW      = 102

Global Const $ODA_DRAWENTIRE    = 1
Global Const $ODA_SELECT        = 2
Global Const $ODA_FOCUS         = 4
Global Const $ODS_SELECTED      = 1
Global Const $ODS_GRAYED        = 2
Global Const $ODS_DISABLED      = 4
Global Const $ODS_CHECKED       = 8
Global Const $ODS_FOCUS         = 16
Global Const $ODS_DEFAULT       = 32
Global Const $ODS_HOTLIGHT      = 64
Global Const $ODS_INACTIVE      = 128
Global Const $ODS_NOACCEL       = 256
Global Const $ODS_NOFOCUSRECT   = 512
Global Const $ODS_COMBOBOXEDIT  = 4096

Global Const $clrWindowText     = _WinAPI_GetSysColor($COLOR_WINDOWTEXT)
Global Const $clrHighlightText  = _WinAPI_GetSysColor($COLOR_HIGHLIGHTTEXT)
Global Const $clrHightlight     = _WinAPI_GetSysColor($COLOR_HIGHLIGHT)
Global Const $clrWindow         = _WinAPI_GetSysColor($COLOR_WINDOW)

Global Const $tagDRAWITEMSTRUCT = _
    'uint CtlType;' & _
    'uint CtlID;' & _
    'uint itemID;' & _
    'uint itemAction;' & _
    'uint itemState;' & _
    'hwnd hwndItem;' & _
    'hwnd hDC;' & _
    $tagRECT & _
    ';ulong_ptr itemData;'
    
Global Const $tagMEASUREITEMSTRUCT = _
    'uint CtlType;' & _
    'uint CtlID;' & _
    'uint itemID;' & _
    'uint itemWidth;' & _
    'uint itemHeight;' & _
    'ulong_ptr itemData;'


Global $hGUI
Global $ComboBox
Global $sStr = ''

$hGUI = GUICreate('Test', 200, 200)
$ComboBox = GUICtrlCreateCombo('', 0, 0, 200, 200, BitOR($WS_CHILD, $CBS_OWNERDRAWFIXED, $CBS_HASSTRINGS, $CBS_DROPDOWNLIST))

For $i = 1 To 20
    $sStr &= 'String ' & $i & '|'
Next

GUICtrlSetData($ComboBox, StringTrimRight($sStr, 1))
;~ GUIRegisterMsg($WM_MEASUREITEM, '_WM_MEASUREITEM')
GUIRegisterMsg($WM_DRAWITEM, '_WM_DRAWITEM')
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

GUIDelete()
Exit

;~ Func _WM_MEASUREITEM($hWnd, $iMsg, $iwParam, $ilParam)
;~  Local $tMIS = DllStructCreate($tagMEASUREITEMSTRUCT, $ilParam)
;~  Local $iCtrl, $iType, $iItem
;~  
;~  Return $GUI_RUNDEFMSG
;~ EndFunc


Func _WM_DRAWITEM($hWnd, $iMsg, $iwParam, $ilParam)
    Local $tDIS = DllStructCreate($tagDRAWITEMSTRUCT, $ilParam)
    Local $iCtlType, $iCtlID, $iItemID, $iItemAction, $iItemState
    Local $clrForeground, $clrBackground
    Local $hWndItem, $hDC
    Local $tRect
    Local $sText
    
    $iCtlType    = DllStructGetData($tDIS, 'CtlType')
    $iCtlID      = DllStructGetData($tDIS, 'CtlID')
    $iItemID     = DllStructGetData($tDIS, 'itemID')
    $iItemAction = DllStructGetData($tDIS, 'itemAction')
    $iItemState  = DllStructGetData($tDIS, 'itemState')
    $hWndItem    = DllStructGetData($tDIS, 'hwndItem')
    $hDC         = DllStructGetData($tDIS, 'hDC')
    $tRect       = DllStructCreate($tagRECT)

    If $iCtlType = $ODT_COMBOBOX And $iCtlID = $ComboBox Then
        Switch $iItemAction
            Case $ODA_DRAWENTIRE
                For $i = 1 To 4
                    DllStructSetData($tRect, $i, DllStructGetData($tDIS, $i+7))
                Next
                
                _GUICtrlComboBox_GetLBText($hWndItem, $iItemID, $sText)
                
                $clrForeground = _WinAPI_SetTextColor($hDC, Random(13369344, 13434879, 1))
                If BitAND($iItemState, $ODS_SELECTED) Then
                    $clrBackground = _WinAPI_SetBkColor($hDC, $clrHightlight)
                Else
                    $clrBackground = _WinAPI_SetBkColor($hDC, $clrWindow)
                EndIf
                
                _WinAPI_DrawText($hDC, $sText, $tRect, $DT_LEFT)
                _WinAPI_SetTextColor($hDC, $clrForeground)
                _WinAPI_SetBkColor($hDC, $clrBackground)
                
            Case $ODA_SELECT
                For $i = 1 To 4
                    DllStructSetData($tRect, $i, DllStructGetData($tDIS, $i+7))
                Next
                
                _GUICtrlComboBox_GetLBText($hWndItem, $iItemID, $sText)
                
                $clrForeground = _WinAPI_SetTextColor($hDC, Random(13369344, 13434879, 1))
                If BitAND($iItemState, $ODS_SELECTED) Then
                    $clrBackground = _WinAPI_SetBkColor($hDC, $clrHightlight)
                Else
                    $clrBackground = _WinAPI_SetBkColor($hDC, $clrWindow)
                EndIf
                
                _WinAPI_DrawText($hDC, $sText, $tRect, $DT_LEFT)
                _WinAPI_SetTextColor($hDC, $clrForeground)
                _WinAPI_SetBkColor($hDC, $clrBackground)
                
        EndSwitch
    EndIf
    
    Return $GUI_RUNDEFMSG
EndFunc

Edit: Selection...

Edited by Authenticity

Share this post


Link to post
Share on other sites
qwert

One approach is to use an owner-drawn ComboBox ...

Thank you. That's a very comprehensive example, which makes the good point that there's a way to do almost anything.

I am, however, struggling a bit to simplify it to fit my need -- which is only to have red characters in a 20-point font (in both the box and the dropdown list). I have the red part working, but the box doesn't accommodate my font and the draw rectangle part isn't making sense. I'm guessing it's in the $tRect defintion, but I can't see it.

Would you mind pointing out what controls box height?

Thanks.

post-29172-12504600586084_thumb.png

Share this post


Link to post
Share on other sites
Authenticity

Please next time follow the link if you need the necessary information.

#include <GUIComboBox.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

Global Const $ODT_MENU          = 1
Global Const $ODT_LISTBOX       = 2
Global Const $ODT_COMBOBOX      = 3
Global Const $ODT_BUTTON        = 4
Global Const $ODT_STATIC        = 5
Global Const $ODT_HEADER        = 100
Global Const $ODT_TAB           = 101
Global Const $ODT_LISTVIEW      = 102

Global Const $ODA_DRAWENTIRE    = 1
Global Const $ODA_SELECT        = 2
Global Const $ODA_FOCUS         = 4
Global Const $ODS_SELECTED      = 1
Global Const $ODS_GRAYED        = 2
Global Const $ODS_DISABLED      = 4
Global Const $ODS_CHECKED       = 8
Global Const $ODS_FOCUS         = 16
Global Const $ODS_DEFAULT       = 32
Global Const $ODS_HOTLIGHT      = 64
Global Const $ODS_INACTIVE      = 128
Global Const $ODS_NOACCEL       = 256
Global Const $ODS_NOFOCUSRECT   = 512
Global Const $ODS_COMBOBOXEDIT  = 4096

Global Const $clrWindowText     = _WinAPI_GetSysColor($COLOR_WINDOWTEXT)
Global Const $clrHighlightText  = _WinAPI_GetSysColor($COLOR_HIGHLIGHTTEXT)
Global Const $clrHightlight     = _WinAPI_GetSysColor($COLOR_HIGHLIGHT)
Global Const $clrWindow         = _WinAPI_GetSysColor($COLOR_WINDOW)

Global Const $tagDRAWITEMSTRUCT = _
    'uint CtlType;' & _
    'uint CtlID;' & _
    'uint itemID;' & _
    'uint itemAction;' & _
    'uint itemState;' & _
    'hwnd hwndItem;' & _
    'hwnd hDC;' & _
    $tagRECT & _
    ';ulong_ptr itemData;'
    
Global Const $tagMEASUREITEMSTRUCT = _
    'uint CtlType;' & _
    'uint CtlID;' & _
    'uint itemID;' & _
    'uint itemWidth;' & _
    'uint itemHeight;' & _
    'ulong_ptr itemData;'


Global $hGUI
Global $ComboBox
Global $sStr = ''

GUIRegisterMsg($WM_MEASUREITEM, '_WM_MEASUREITEM')
GUIRegisterMsg($WM_DRAWITEM, '_WM_DRAWITEM')

$hGUI = GUICreate('Test', 200, 200)
$ComboBox = GUICtrlCreateCombo('', 0, 0, 200, 200, BitOR($WS_CHILD, $CBS_OWNERDRAWFIXED, $CBS_HASSTRINGS, $CBS_DROPDOWNLIST))
GUICtrlSetFont($ComboBox, 14, 800)

For $i = 1 To 20
    $sStr &= 'String ' & $i & '|'
Next

GUICtrlSetData($ComboBox, StringTrimRight($sStr, 1))
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

GUIDelete()
Exit

Func _WM_MEASUREITEM($hWnd, $iMsg, $iwParam, $ilParam)
    Local $tMIS = DllStructCreate($tagMEASUREITEMSTRUCT, $ilParam)
    Local $iCtlType, $iCtlID, $iItemID, $iItemWidth, $iItemHeight
    Local $hComboBox
    Local $tSize
    Local $hDC
    
    $iCtlType    = DllStructGetData($tMIS, 'CtlType')
    $iCtlID      = DllStructGetData($tMIS, 'CtlID')
    $iItemID     = DllStructGetData($tMIS, 'itemID')
    $iItemWidth  = DllStructGetData($tMIS, 'itemWidth')
    $iItemHeight = DllStructGetData($tMIS, 'itemHeight')
    $hComboBox   = GUICtrlGetHandle($iCtlID)
    
    If $iCtlType = $ODT_COMBOBOX Then
        $hDC = _WinAPI_GetDC($hComboBox)
        $tSize = _WinAPI_GetTextExtentPoint32($hDC, 'S')
        DllStructSetData($tMIS, 'itemHeight', DllStructGetData($tSize, 'Y')+8)
    EndIf
    
    Return $GUI_RUNDEFMSG
EndFunc


Func _WM_DRAWITEM($hWnd, $iMsg, $iwParam, $ilParam)
    Local $tDIS = DllStructCreate($tagDRAWITEMSTRUCT, $ilParam)
    Local $iCtlType, $iCtlID, $iItemID, $iItemAction, $iItemState
    Local $clrForeground, $clrBackground
    Local $hWndItem, $hDC
    Local $tRect
    Local $sText
    
    $iCtlType    = DllStructGetData($tDIS, 'CtlType')
    $iCtlID      = DllStructGetData($tDIS, 'CtlID')
    $iItemID     = DllStructGetData($tDIS, 'itemID')
    $iItemAction = DllStructGetData($tDIS, 'itemAction')
    $iItemState  = DllStructGetData($tDIS, 'itemState')
    $hWndItem    = DllStructGetData($tDIS, 'hwndItem')
    $hDC         = DllStructGetData($tDIS, 'hDC')
    $tRect       = DllStructCreate($tagRECT)

    If $iCtlType = $ODT_COMBOBOX And $iCtlID = $ComboBox Then
        Switch $iItemAction
            Case $ODA_DRAWENTIRE
                For $i = 1 To 4
                    DllStructSetData($tRect, $i, DllStructGetData($tDIS, $i+7))
                Next
                
                _GUICtrlComboBox_GetLBText($hWndItem, $iItemID, $sText)
                
                $clrForeground = _WinAPI_SetTextColor($hDC, 0xFF)
                If BitAND($iItemState, $ODS_SELECTED) Then
                    $clrBackground = _WinAPI_SetBkColor($hDC, $clrHightlight)
                Else
                    $clrBackground = _WinAPI_SetBkColor($hDC, $clrWindow)
                EndIf
                
                _WinAPI_DrawText($hDC, $sText, $tRect, $DT_LEFT)
                _WinAPI_SetTextColor($hDC, $clrForeground)
                _WinAPI_SetBkColor($hDC, $clrBackground)
                
            Case $ODA_SELECT
                For $i = 1 To 4
                    DllStructSetData($tRect, $i, DllStructGetData($tDIS, $i+7))
                Next
                
                _GUICtrlComboBox_GetLBText($hWndItem, $iItemID, $sText)
                
                $clrForeground = _WinAPI_SetTextColor($hDC, 0xFF)
                If BitAND($iItemState, $ODS_SELECTED) Then
                    $clrBackground = _WinAPI_SetBkColor($hDC, $clrHightlight)
                Else
                    $clrBackground = _WinAPI_SetBkColor($hDC, $clrWindow)
                EndIf
                
                _WinAPI_DrawText($hDC, $sText, $tRect, $DT_LEFT)
                _WinAPI_SetTextColor($hDC, $clrForeground)
                _WinAPI_SetBkColor($hDC, $clrBackground)
                
        EndSwitch
    EndIf
    
    Return $GUI_RUNDEFMSG
EndFunc

ridiculously strange combo >_<

Share this post


Link to post
Share on other sites
qwert

... next time follow the link if you need the necessary information...

Sorry ... my intent wasn't to trouble you for a rewrite. The hint I needed was something like: "Enable the WM_MEASUREITEM function ... that's what controls the height." I did read down the MSDN material but I passed by WM_MEASUREITEM since it was disabled in your first example. I thought I had missed something simpler.

Thanks for your help. I do appreciate the extra time you spent. Maybe others will benefit, as well.

Share this post


Link to post
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
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.