Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Color Highlight of ListBox or ComboBox Entries
#1
Hi Gintaras, Happy Xmas and New Year to you...another fantastic year of QM-scripting!!!!!!

Do you know if there is a way similar to RichEditHighlight to supply color to ListBox or ComboBox entry depending on what the entry text is...e.g. if findrx is >= 0 for the word "green" it would be painted green, etc....

Thanks, Stuart
#2
Function CB_ItemColor
Code:
Copy      Help
;/
function# hDlg message wParam lParam ctrlId callbackFunc [param]

;Draws combo or list box items with custom background and text colors.

;This is how to create a combo or list box and set colors:
;1. The dialog must be a smart dialog, ie with dialog function.
;2. In the dialog editor, add a combo or list box.
;3. In the Styles dialog:
;;;;For combo box, select CBS_OWNERDRAWFIXED and CBS_HASSTRINGS styles.
;;;;For list box, select LBS_OWNERDRAWFIXED and LBS_HASSTRINGS styles.
;4. Create callback function similar to SampleCbItemColorProc. The function sets colors.
;5. In the dialog function, call CB_ItemColor before 'sel messages' line. Pass address of the callback function. Call it for each such control.

;hDlg, message, wParam, lParam - hDlg, message, wParam, lParam.
;ctrlId - combo/list box id.
;callbackFunc - address of a callback function. See SampleCbItemColorProc.
;param - a user-defined value that will be passed to the callback function.


type CBITEMCOLOR str'text bkColor textColor hwnd item itemData !selected !isLB dtFlags param

sel message
,case WM_DRAWITEM
,if(wParam=ctrlId)
,,DRAWITEMSTRUCT* ds=+lParam
,,if(ds.itemID<0) ret
,,RECT r=ds.rcItem
,,
,,CBITEMCOLOR c
,,c.hwnd=ds.hWndItem
,,c.item=ds.itemID
,,c.itemData=ds.itemData
,,c.isLB=ds.CtlType=ODT_LISTBOX
,,c.param=param
,,c.dtFlags=DT_NOPREFIX
,,c.selected=ds.itemState&(ODS_SELECTED|ODS_COMBOBOXEDIT)=ODS_SELECTED
,,c.bkColor=GetSysColor(iif(c.selected COLOR_HIGHLIGHT COLOR_WINDOW))
,,c.textColor=GetSysColor(iif(c.selected COLOR_HIGHLIGHTTEXT COLOR_WINDOWTEXT))
,,GetItemText c.hwnd c.item c.text c.isLB
,,
,,call callbackFunc &c
,,
,,SetBkMode ds.hDC TRANSPARENT
,,__GdiHandle brush=CreateSolidBrush(c.bkColor)
,,FillRect ds.hDC &r brush
,,SetTextColor ds.hDC c.textColor
,,
,,r.left+4; r.top+2
,,DrawTextW ds.hDC @c.text -1 &r c.dtFlags

sample dialog
Function dialog_combo_item_colors
Code:
Copy      Help
\Dialog_Editor
function# hDlg message wParam lParam
if(hDlg) goto messages

str controls = "3 4 5"
str cb3 cb4 lb5
cb3="&yellow background[]blue text[]default colors[]black & green"
cb4="&yellow background[]blue text[]default colors[]black & green"
lb5="yellow background[]blue text[]default colors[]black & green"
if(!ShowDialog("dialog_combo_item_colors" &dialog_combo_item_colors &controls)) ret
out cb3
out cb4
out lb5

;BEGIN DIALOG
;0 "" 0x90C80A44 0x100 0 0 204 98 "Dialog"
;1 Button 0x54030001 0x4 4 80 48 14 "OK"
;2 Button 0x54030000 0x4 56 80 48 14 "Cancel"
;3 ComboBox 0x54230253 0x0 4 6 96 215 ""
;4 ComboBox 0x54230252 0x0 4 30 96 215 ""
;5 ListBox 0x54230151 0x200 106 6 96 64 ""
;END DIALOG
;DIALOG EDITOR: "" 0x2030109 "" "" ""

ret
;messages

CB_ItemColor hDlg message wParam lParam 3 &SampleCbItemColorProc
CB_ItemColor hDlg message wParam lParam 4 &SampleCbItemColorProc
CB_ItemColor hDlg message wParam lParam 5 &SampleCbItemColorProc

sel message
,case WM_INITDIALOG
,case WM_DESTROY
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
ret 1

sample callback function
Function SampleCbItemColorProc
Code:
Copy      Help
;/
function# CBITEMCOLOR&c

;This is a sample callback function that can be used with CB_ItemColor.
;Shows how to set combo/list box item background and text colors depending on item text.
;The function will be called for each item when displaying it.
;c contains various info that can be useful to draw the item.
;To set colors, change c.bkColor and/or c.textColor.
;Also you can change c.dtFlags and c.text.

;c.text - item text. In/out.
;c.bkColor - item background color. In/out.
;c.textColor - item text color. In/out.
;c.hwnd - control handle.
;c.item - item index.
;c.itemData - item data. To set item data, use message CB_SETITEMDATA or LB_SETITEMDATA, documented in MSDN.
;c.selected - 1 if the item is selected, 0 if not.
;c.isLB - 1 if the control is listbox, 0 if combobox.
;c.dtFlags - DrawText flags. Documented in the MSDN Library on the Internet. In/out.
;c.param - an user-defined value, passed to CB_ItemColor.


if(c.selected) ret

sel c.text
,case "yellow background" c.bkColor=0xa0ffff
,case "blue text" c.textColor=0xff0000
,case "black & green" c.bkColor=0; c.textColor=0x00ff00
#3
Not at a computer yet to try it but looks FanTAsTic!!!!
Thanks so much!!!!
S
#4
Unbelievable...works fantastically...exactly what I was trying to accomplish!!!.
Thanks, Stuart
#5
Hi Gintaras,
How do you set a certain character string to be transparent i.e. background color?
Also is it possible to define the color assignments by a RegEx instead of just * wildcards?
Thanks so much!
S
#6
Quote:How do you set a certain character string to be transparent i.e. background color?
Why?

Quote:Also is it possible to define the color assignments by a RegEx instead of just * wildcards?
Edit the callback function. It parses item text and defines colors.
#7
The second answer solves the first...thanks!!!!
S
#8
Hi Gintaras,
Hope all is well with you. Is it possible to have ico/bmp's in ListBox along with background/text color? It seems that it is only 1 or the other - i.e. if I un-comment


Code:
Copy      Help
str BrowseIcoFilepath =  "$qm$\browse.ico"
;CB_DrawImages hDlg message wParam lParam 5 BrowseIcoFilepath 1|16



then it loses colors or vice-versa.

Thanks,
S

Function dialog_combo_item_colors
Code:
Copy      Help
\Dialog_Editor
function# hDlg message wParam lParam
if(hDlg) goto messages

str controls = "3 4 5"
str cb3 cb4 lb5
cb3="&yellow background[]blue text[]default colors[]black & green"
cb4="&yellow background[]blue text[]default colors[]black & green"
lb5="yellow background[]blue text[]default colors[]black & green"
if(!ShowDialog("dialog_combo_item_colors" &dialog_combo_item_colors &controls)) ret
out cb3
out cb4
out lb5

;BEGIN DIALOG
;0 "" 0x90C80A48 0x100 0 0 204 98 "Dialog"
;1 Button 0x54030001 0x4 4 80 48 14 "OK"
;2 Button 0x54030000 0x4 56 80 48 14 "Cancel"
;3 ComboBox 0x54230253 0x0 4 6 96 215 ""
;4 ComboBox 0x54230252 0x0 4 30 96 215 ""
;5 ListBox 0x54230151 0x200 106 6 96 64 ""
;END DIALOG
;DIALOG EDITOR: "" 0x2030109 "" "" ""

ret
;messages

CB_ItemColor hDlg message wParam lParam 3 &SampleCbItemColorProc
CB_ItemColor hDlg message wParam lParam 4 &SampleCbItemColorProc
CB_ItemColor hDlg message wParam lParam 5 &SampleCbItemColorProc

str BrowseIcoFilepath =  "$qm$\browse.ico"
;CB_DrawImages hDlg message wParam lParam 5 BrowseIcoFilepath 1|16

sel message
,case WM_INITDIALOG
,case WM_DESTROY
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
ret 1
#9
Hybrid: CB_DrawImages + CB_ItemColor = CB_ItemImageAndColor.

Function CB_ItemImageAndColor
Code:
Copy      Help
;/
function# hDlg message wParam lParam ctrlId [$icons] [flags] [imgWidth] [imgHeight] [dtFlags] [callbackFunc] [param] ;;flags: 1 listbox (default combobox), 2 item data is image index, 4 icons is imagelist, 16 not icons (bmp, jpg, gif)

;Adds icons or bmp/jpg/gif images to a combo box or list box.
;Also can draw items with custom background and text colors.

;This is what you have to do to create a combo or list box:
;1. The dialog must be a smart dialog, ie with dialog procedure.
;2. In the dialog editor, add a combo or list box.
;3. In the Styles dialog:
;;;;For combo box, select CBS_OWNERDRAWFIXED and CBS_HASSTRINGS styles. Make sure that CBS_SORT is not selected (sorted combo boxes are not supported).
;;;;For list box, select LBS_OWNERDRAWFIXED and LBS_HASSTRINGS styles. Make sure that LBS_SORT is not selected (sorted list boxes are not supported).
;4. In the dialog procedure, insert CB_ItemImageAndColor before 'sel messages' line, for each such control. If need colors, create a callback function and pass its address.

;hDlg, message, wParam, lParam - hDlg, message, wParam, lParam.
;ctrlId - combo/list box id.
;icons - list of icon files. If flag 16 used, list of image files of type bmp, jpg or gif. If flag 4 used, imagelist file. Can be 0 if don't need images.
;flags:
;;;;1 the control is a listbox.
;;;;2 item image index is stored in item data (default - same as item index).
;;;;4 icons is .bmp file created with QM imagelist editor.
;;;;16 use bitmap (default - use icon). Don't use with flag 4.
;imgWidth, imgHeight - width and height of images. Default: 16 pixels.
;dtFlags - DrawText flags. Documented in the MSDN Library on the Internet. Xored with DT_NOPREFIX.
;callbackFunc - address of a callback function that sets text colors. Optional. See SampleCbItemColorProc.
;param - a user-defined value that will be passed to the callback function.


type CBITEMCOLOR str'text bkColor textColor hwnd item itemData !selected !isLB dtFlags param

int i n il hi hb hcb; str s
hcb=id(ctrlId hDlg)
if(!imgWidth and icons) imgWidth=16
if(!imgHeight) imgHeight=16

sel message
,case WM_CREATE
,SendMessage hcb iif(flags&1 LB_SETITEMHEIGHT CB_SETITEMHEIGHT) 0 imgHeight+2
,
,case WM_INITDIALOG
,if icons
,,if(flags&4)
,,,il=__ImageListLoad(icons)
,,else
,,,n=numlines(icons)
,,,il=ImageList_Create(imgWidth imgHeight ILC_MASK|ILC_COLOR32 0 n)
,,,for(i 0 n)
,,,,s.getl(icons -i)
,,,,if(flags&16)
,,,,,hb=LoadPictureFile(s 0); if(!hb) goto g1
,,,,,ImageList_Add(il hb 0)
,,,,,if(hb) DeleteObject hb
,,,,else
,,,,,hi=GetFileIcon(s 0 (imgWidth>=24 or imgHeight>=24))
,,,,,;g1
,,,,,ImageList_ReplaceIcon(il -1 iif(hi hi _dialogicon))
,,,,,if(hi) DestroyIcon hi
,,SetProp hcb "qm_il" il
,
,case WM_DESTROY
,if(icons) ImageList_Destroy RemoveProp(hcb "qm_il")
,
,case WM_DRAWITEM
,if(wParam=ctrlId) goto gDraw
ret

;gDraw
DRAWITEMSTRUCT* ds=+lParam
if(ds.itemID<0) ret
RECT r=ds.rcItem

CBITEMCOLOR c
c.hwnd=ds.hWndItem
c.item=ds.itemID
c.itemData=ds.itemData
c.isLB=ds.CtlType=ODT_LISTBOX
c.param=param
c.dtFlags=dtFlags^DT_NOPREFIX
c.selected=ds.itemState&(ODS_SELECTED|ODS_COMBOBOXEDIT)=ODS_SELECTED
c.bkColor=GetSysColor(iif(c.selected COLOR_HIGHLIGHT COLOR_WINDOW))
c.textColor=GetSysColor(iif(c.selected COLOR_HIGHLIGHTTEXT COLOR_WINDOWTEXT))
GetItemText c.hwnd c.item c.text c.isLB

if(callbackFunc) call callbackFunc &c

;background
__GdiHandle brush=CreateSolidBrush(c.bkColor)
FillRect ds.hDC &r brush
;icon
if icons
,il=GetProp(hcb "qm_il")
,int ii=iif(flags&2 ds.itemData ds.itemID)
,n=ImageList_GetImageCount(il); if(ii>=n) ii=n-1
,ImageList_Draw il ii ds.hDC r.left+1 r.top+1 0
;text
SetBkMode ds.hDC TRANSPARENT
SetTextColor ds.hDC c.textColor
r.left+imgWidth+4; r.top+2
DrawTextW ds.hDC @c.text -1 &r c.dtFlags

example
Macro dialog_combo_images_and_colors
Code:
Copy      Help
\Dialog_Editor

str dd=
;BEGIN DIALOG
;0 "" 0x90C80A48 0x100 0 0 204 98 "Dialog"
;1 Button 0x54030001 0x4 4 80 48 14 "OK"
;2 Button 0x54030000 0x4 56 80 48 14 "Cancel"
;3 ComboBox 0x54230253 0x0 4 6 96 215 ""
;4 ComboBox 0x54230252 0x0 4 30 96 215 ""
;5 ListBox 0x54230151 0x200 106 6 96 64 ""
;END DIALOG
;DIALOG EDITOR: "" 0x2030109 "" "" ""

str controls = "3 4 5"
str cb3 cb4 lb5
cb3="&yellow background[]blue text[]default colors[]black & green"
cb4="&yellow background[]blue text[]default colors[]black & green"
lb5="yellow background[]blue text[]default colors[]black & green"
if(!ShowDialog(dd &sub.DlgProc &controls)) ret
out cb3
out cb4
out lb5


#sub DlgProc
function# hDlg message wParam lParam

CB_ItemImageAndColor hDlg message wParam lParam 3 "$qm$\browse.ico[]$qm$\cut.ico[]$qm$\copy.ico[]$qm$\paste.ico" 0 0 0 0 &sub.ColorCallback
CB_ItemImageAndColor hDlg message wParam lParam 4 "shell32.dll,3" 0 32 32 DT_VCENTER|DT_SINGLELINE &sub.ColorCallback
CB_ItemImageAndColor hDlg message wParam lParam 5 "shell32.dll,3" 1 32 32 DT_WORDBREAK &sub.ColorCallback

sel message
,case WM_INITDIALOG
,case WM_DESTROY
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case IDOK
,case IDCANCEL
ret 1


#sub ColorCallback
function# CBITEMCOLOR&c

;This is a sample callback function that can be used with CB_ItemImageAndColor.
;Shows how to set combo/list box item background and text colors depending on item text.
;The function will be called for each item when displaying it.
;c contains various info that can be useful to draw the item.
;To set colors, change c.bkColor and/or c.textColor.
;Also you can change c.dtFlags and c.text.

;c.text - item text. In/out.
;c.bkColor - item background color. In/out.
;c.textColor - item text color. In/out.
;c.hwnd - control handle.
;c.item - item index.
;c.itemData - item data. To set item data, use message CB_SETITEMDATA or LB_SETITEMDATA, documented in MSDN.
;c.selected - 1 if the item is selected, 0 if not.
;c.isLB - 1 if the control is listbox, 0 if combobox.
;c.dtFlags - DrawText flags. Documented in the MSDN Library on the Internet. In/out.
;c.param - an user-defined value, passed to CB_ItemColor.


if(c.selected) ret

sel c.text
,case "yellow background" c.bkColor=0xa0ffff
,case "blue text" c.textColor=0xff0000
,case "black & green" c.bkColor=0; c.textColor=0x00ff00
#10
This is truly amazing and looks like a lot of work - much much appreciated!
S
#11
I realized what I really needed to do was also change the background color of the combobox regardless of whether there was any items i.e.
For a listbox this is easy (after searching the forum!):


Code:
Copy      Help
int textcolor=0xff
int backcolor=0x00ff00
int-- hbrush

sel message
,case WM_INITDIALOG
,hbrush=CreateSolidBrush(backcolor)
,
,case WM_DESTROY
,DeleteObject hbrush
,
,case WM_COMMAND goto messages2
,
,case WM_CTLCOLORLISTBOX
,,if(lParam=id(4 hDlg))
,,,SetTextColor wParam textcolor ;;text
,,,SetBkMode wParam TRANSPARENT
,,,ret hbrush ;;background
but it seems like there is no way to do this for ComboBox. Is it possible?
Also, is there a version of DT_SetBackgroundColor that works on child object (edit, richedit, listbox, button, etc) rather than just dialog/window as a whole?
Thanks,
S
#12
Quote:change the background color of the combobox regardless of whether there was any items

Can't answer.


Quote:is there a version of DT_SetBackgroundColor that works on child object (edit, richedit, listbox, button, etc)
Probably exist functions in the forum for some control types, don't remember. Usually need to either disable control theme (then looks not good) or draw entire control (difficult).
#13
ok. Thanks. I have some ideas. Will share later. S
#14
Hello, 

I'm using the above functions   CB_ItemColor,  dialog_combo_item_colors  and   SampleCbItemColorProc  (which are also supplied in the archive) to change the color of some items in a listbox, and it works. Thanks for supplying these functions. 

I would also like to change the fontsize for all items in the listbox. I've placed the following lines after WM_INITDIALOG message to change the font of my listbox which has identifier 3:

        __Font-- dfont
        dfont.Create("Arial" 18 1)
        dfont.SetDialogFont(hDlg "3")

The listbox font indeed changes to size 18, but now the items in the listbox overlap (not enough vertical space is used to draw the items).   When I don't use the LBS_OWNERDRAWFIXED style the items don't overlap and have the right fontsize, but then of course the coloring of the items doesn't work. 

I've also tried to place the lines above before the call to CB_Itemcolor, but it doesn't work. 

Is there a way to change the code in the functions above so that I can change the fontsize of the list box but so that the items don't overlap.  If it is possible, what would the code look like?

Thanks, 
Artuur.


Forum Jump:


Users browsing this thread: 1 Guest(s)