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?
Posted on 2001-10-19 13:10:11 by gscundiff

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.

Posted on 2001-10-19 14:59:26 by anon
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:
Posted on 2001-10-20 05:03:32 by gscundiff
You should put WM_CTLCOLORLISTBOX handling inside your DlgProc:
.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);
Posted on 2001-10-20 05:31:08 by LuHa
gscundiff


I hope this my help you.
Posted on 2001-10-20 05:50:53 by forge
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 ?
Posted on 2001-10-20 08:17:01 by gscundiff
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.

int SetBkMode(
HDC hdc, // handle of device context
int iBkMode // flag specifying background mode
);

COLORREF SetTextColor(
HDC hdc, // handle to device context
COLORREF crColor // text color
);

COLORREF SetBkColor(
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?
Posted on 2001-10-20 08:52:32 by LuHa
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.
Posted on 2001-10-20 09:23:32 by LuHa
And here is the source code.
Posted on 2001-10-20 09:24:35 by LuHa
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!
Posted on 2001-10-20 09:26:10 by gscundiff
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.
Posted on 2001-10-20 09:34:13 by LuHa
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:
Posted on 2001-10-20 09:55:44 by gscundiff
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
Posted on 2001-10-20 17:41:40 by hutch--
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.
Posted on 2001-10-20 17:52:18 by LuHa
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
Posted on 2001-10-20 20:56:41 by KetilO
Wow, KetilO, I will use your psychedelic edit box in my next app, it is ultra-cool :grin:.
Posted on 2001-10-21 07:54:07 by LuHa
Hi LuHa

I was thinking of doing this on the edit windows in RadASM.

Shoul I make this an option?:grin:

KetilO
Posted on 2001-10-21 08:50:46 by KetilO
You must, and set it on by default ;).
Posted on 2001-10-21 09:31:05 by LuHa