I've been playing around with LordRhesus mp3play program from Iczelion's source page (Mini MP3 Player) and was wondering...What's the best way to change the background color and text color in a DialogBoxParam listbox?
The WM_CTLCOLORLISTBOX message is sent to the parent window of a list box before the system draws the list box. By responding to this message, the parent window can set the text and background colors of the list box by using the specified display device context handle.
A window receives this message through its WindowProc function.
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // WM_CTLCOLORLISTBOX
WPARAM wParam, // handle to DC (HDC)
LPARAM lParam // handle to list box (HWND)
);
Parameters
wParam
Handle to the device context for the list box.
lParam
Handle to the list box.
Return Values
If an application processes this message, it must return a handle to a brush. The system uses the brush to paint the background of the list box.
Remarks
By default, the DefWindowProc function selects the default system colors for the list box.
The system does not automatically destroy the returned brush. It is the application's responsibility to destroy the brush when it is no longer needed.
Thanks anon. I've seen quite a few posts/info's on this; when using CreateWindowEx and you spawn a dialogbox with a list control on it.
And maybe I'm just overlooking the obvious, but the program I'm referring to uses Dialog As Main:
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL,addr DlgProc,NULL
and has the Listbox control in the .rc file:
BEGIN
LISTBOX IDC_LISTMP3, 3,7,171,141, LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | WS_HSCROLL | WS_VSCROLL | WS_TABSTOP, , 0
PUSHBUTTON "Play", IDC_BTNPLAY, 16,156,39,12, 0, , 0
PUSHBUTTON "Pause", IDC_BTNPAUSE, 67,156,40,12, 0, , 0
PUSHBUTTON "Stop", IDC_BTNSTOP, 120,156,40,12, 0, , 0
END
When the invoke DialogBoxParam instruction pops up the window, the listbox/buttons from the .rc are already on the DialogBox and - I don't understand where there's an entry point to "respond to the WM_CTLColorListBox message before the system draws the listbox."
Before I gave up and converted this program to use CreateWindowEX instead of DialogBoxParam, I thought I'd ask you much more knowledgeable people if there was a way to set the listbox background to BLACK and listbox text color to GREEN!
gscundiff
:stupid:
And maybe I'm just overlooking the obvious, but the program I'm referring to uses Dialog As Main:
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL,addr DlgProc,NULL
and has the Listbox control in the .rc file:
BEGIN
LISTBOX IDC_LISTMP3, 3,7,171,141, LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | WS_HSCROLL | WS_VSCROLL | WS_TABSTOP, , 0
PUSHBUTTON "Play", IDC_BTNPLAY, 16,156,39,12, 0, , 0
PUSHBUTTON "Pause", IDC_BTNPAUSE, 67,156,40,12, 0, , 0
PUSHBUTTON "Stop", IDC_BTNSTOP, 120,156,40,12, 0, , 0
END
When the invoke DialogBoxParam instruction pops up the window, the listbox/buttons from the .rc are already on the DialogBox and - I don't understand where there's an entry point to "respond to the WM_CTLColorListBox message before the system draws the listbox."
Before I gave up and converted this program to use CreateWindowEX instead of DialogBoxParam, I thought I'd ask you much more knowledgeable people if there was a way to set the listbox background to BLACK and listbox text color to GREEN!
gscundiff
:stupid:
You should put WM_CTLCOLORLISTBOX handling inside your DlgProc:
It is a normal message sent to list box parent window (aka your dialog box). To set black background with green text you can use something like this (sorry, it is written in C, but I don't use asm)
.IF uMsg==WM_INITDIALOG
...
.ELSEIF uMsg==WM_CLOSE
...
...
.ELSEIF uMsg==WM_CTLCOLORLISTBOX
It is a normal message sent to list box parent window (aka your dialog box). To set black background with green text you can use something like this (sorry, it is written in C, but I don't use asm)
case WM_CTLCOLORLISTBOX
SetTextColor((HDC)wParam, RGB(0, 255, 0));
SetBkMode((HDC)wParam, TRANSPARENT);
return GetStockObject(BLACK_BRUSH);
gscundiff
I hope this my help you.
I hope this my help you.
hi forge and anon, thanks for the replies.
With the LISTBOX control given as:
IDC_LISTMP3 equ 3001
I am now trying to use this:
DlgProc proc uses ebx hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_INITDIALOG
invoke GetDlgItem,hWnd,3001 ;get the handle of a control in the specified dialog box
mov hListBox,eax ;save the ListBox control handle
...
s'more uMsg checks
...
.elseif uMsg == WM_CTLCOLORLISTBOX
mov eax,lParam
.if eax == hListBox
invoke SetBkMode,wParam,2 ; 1 = TRANSPARENT or 2 = OPAQUE
invoke SetTextColor,wParam,0000FF00h ; text color value
invoke SetBkColor,wParam,00000000h ; Backgrn color value
invoke CreateSolidBrush, 0000ff00h ; brush color value
.endif
(also tried - invoke GetStockObject, BLACK_BRUSH instead)
This doesn't work. I tried responding to WM_CTLCOLORDLG, and WM_CTLCOLORSTATIC too, and instead of wParam I tried hListBox and hWnd, but I can't make any of it work. :confused:
I guess I'm having trouble understanding which values to use in the SetBkMode, SetTextColor, SetBkColor invokes, or how to go about using them maybe ?
With the LISTBOX control given as:
IDC_LISTMP3 equ 3001
I am now trying to use this:
DlgProc proc uses ebx hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_INITDIALOG
invoke GetDlgItem,hWnd,3001 ;get the handle of a control in the specified dialog box
mov hListBox,eax ;save the ListBox control handle
...
s'more uMsg checks
...
.elseif uMsg == WM_CTLCOLORLISTBOX
mov eax,lParam
.if eax == hListBox
invoke SetBkMode,wParam,2 ; 1 = TRANSPARENT or 2 = OPAQUE
invoke SetTextColor,wParam,0000FF00h ; text color value
invoke SetBkColor,wParam,00000000h ; Backgrn color value
invoke CreateSolidBrush, 0000ff00h ; brush color value
.endif
(also tried - invoke GetStockObject, BLACK_BRUSH instead)
This doesn't work. I tried responding to WM_CTLCOLORDLG, and WM_CTLCOLORSTATIC too, and instead of wParam I tried hListBox and hWnd, but I can't make any of it work. :confused:
I guess I'm having trouble understanding which values to use in the SetBkMode, SetTextColor, SetBkColor invokes, or how to go about using them maybe ?
hi forge and anon, thanks for the replies.
And me ;) ? Anyway, here is some MSDN quoting:
WM_CTLCOLORLISTBOX
hdcLB = (HDC) wParam; // handle to list box display context
hwndLB = (HWND) lParam; // handle to list box
Return Values
If an application processes this message, it must return a handle to a brush. The system uses the brush to paint the background of the list box.
hdcLB = (HDC) wParam; // handle to list box display context
hwndLB = (HWND) lParam; // handle to list box
Return Values
If an application processes this message, it must return a handle to a brush. The system uses the brush to paint the background of the list box.
int SetBkMode(
HDC hdc, // handle of device context
int iBkMode // flag specifying background mode
);
HDC hdc, // handle of device context
int iBkMode // flag specifying background mode
);
COLORREF SetTextColor(
HDC hdc, // handle to device context
COLORREF crColor // text color
);
HDC hdc, // handle to device context
COLORREF crColor // text color
);
COLORREF SetBkColor(
HDC hdc, // handle of device context
COLORREF crColor // background color value
);
HDC hdc, // handle of device context
COLORREF crColor // background color value
);
So, first parameter is always the handle to device context of list box (passed via wParam by WM_CTLCOLORLISTBOX). Other parameters are simply color values. With your code you should see a green background with green text inside black boxes. When you say it doesn't work do you mean that the background is white and text is black? Or aren't the colors you obtain the ones you want?
I wrote a simple test app (sorry, it is in C, but I'm sure you can translate in asm without any problem). It show a black list with green text.
And here is the source code.
And of course thanks to LuHa (sorry, I didn't mention U B 4 !!)
quote:
WM_CTLCOLORLISTBOX
hdcLB = (HDC) wParam; // handle to list box display context
hwndLB = (HWND) lParam; // handle to list box
Return Values
If an application processes this message, it must return a handle to a brush. The system uses the brush to paint the background of the list box.
endquote
LuHa, you got me thinking about how I'm suppossed to "return a handle to a brush" since "The system uses the brush to paint the background of the list box." And it dawned on me that YEAH the system should use the CreateSolidBrush I invoked but how? There's no instruction there telling it to. So I decided maybe it does it itself after I return from handling the WM_CTLCOLORLISTBOX uMsg. So I tried using a "ret" after the .endif in my proc:
elseif uMsg == WM_CTLCOLORLISTBOX
mov eax,lParam
.if eax == hListBox
invoke SetBkMode,wParam,2 ; 1 = TRANSPARENT or 2 = OPAQUE
invoke SetTextColor,wParam,0000FF00h ; text color value
invoke SetBkColor,wParam,00000000h ; Backgrn color value
invoke CreateSolidBrush, 0000ff00h ; brush color value
.endif
ret
As soon as I did that, it worked !!
Sorry for bothering you all about this, but I don't remember seeing that "ret" in any of the texts/tuts/info's I've seen. But it does make some sense to me now: the system paints as soon as I ret from handling it's uMsg by giving it a Brush to work with!
DOH!
quote:
WM_CTLCOLORLISTBOX
hdcLB = (HDC) wParam; // handle to list box display context
hwndLB = (HWND) lParam; // handle to list box
Return Values
If an application processes this message, it must return a handle to a brush. The system uses the brush to paint the background of the list box.
endquote
LuHa, you got me thinking about how I'm suppossed to "return a handle to a brush" since "The system uses the brush to paint the background of the list box." And it dawned on me that YEAH the system should use the CreateSolidBrush I invoked but how? There's no instruction there telling it to. So I decided maybe it does it itself after I return from handling the WM_CTLCOLORLISTBOX uMsg. So I tried using a "ret" after the .endif in my proc:
elseif uMsg == WM_CTLCOLORLISTBOX
mov eax,lParam
.if eax == hListBox
invoke SetBkMode,wParam,2 ; 1 = TRANSPARENT or 2 = OPAQUE
invoke SetTextColor,wParam,0000FF00h ; text color value
invoke SetBkColor,wParam,00000000h ; Backgrn color value
invoke CreateSolidBrush, 0000ff00h ; brush color value
.endif
ret
As soon as I did that, it worked !!
Sorry for bothering you all about this, but I don't remember seeing that "ret" in any of the texts/tuts/info's I've seen. But it does make some sense to me now: the system paints as soon as I ret from handling it's uMsg by giving it a Brush to work with!
DOH!
If you don't want to use GetStockObject(BLACK_BRUSH) remember also to destroy the brush you created with CreateSolidBrush, windows will not do it for yourself.
LuHa,
TEN DASH FOUR on destroying the brush.
And many thanks again for your help (I was really getting tired of messing with it) :alright:
TEN DASH FOUR on destroying the brush.
And many thanks again for your help (I was really getting tired of messing with it) :alright:
In relation to creating a brush, there is something slightly wrong here, when you create a brush, all you are doing is producing a COLORREF number for an RGB colour. A COLORREF number is in the form 00BBGGRR hex, being the respective RGB colours as BYTE values.
Where you have to allocate and deallocate resources is where you use SelectObject().
When you select an object, in this instance a brush, you save the old brush in a variable, perform the action you want with the brush and then reselect the old brush from the variable you saved it in, THEN you delete the object you selected.
Regards,
hutch@pbq.com.au
Where you have to allocate and deallocate resources is where you use SelectObject().
When you select an object, in this instance a brush, you save the old brush in a variable, perform the action you want with the brush and then reselect the old brush from the variable you saved it in, THEN you delete the object you selected.
Regards,
hutch@pbq.com.au
I was only repeating what MSDN says:
The system does not automatically destroy the returned brush. It is the application's responsibility to destroy the brush when it is no longer needed.
Hi Hutch & LuHa, 1-0 to LuHa
You must destroy the brush. From what I know a brush is a bitmap.
Try uncommenting the code that destroys the brush in my little test project, and your machine will run out of memory in seconds.
KetilO
You must destroy the brush. From what I know a brush is a bitmap.
Try uncommenting the code that destroys the brush in my little test project, and your machine will run out of memory in seconds.
KetilO
Wow, KetilO, I will use your psychedelic edit box in my next app, it is ultra-cool :grin:.
Hi LuHa
I was thinking of doing this on the edit windows in RadASM.
Shoul I make this an option?:grin:
KetilO
I was thinking of doing this on the edit windows in RadASM.
Shoul I make this an option?:grin:
KetilO
You must, and set it on by default ;).