Thursday, April 19, 2007

cbClsExtra parameter in WNDCLASS structure

I have created a custom control with win32. It is a fill bar control.


I want to set the color of the fill color at design time. I put the
color value in the WNDCLASS in the cbClsExtra or cbWndExtra parameter.
How can the custom control get the values of these 2 parameters?


I know i can also send the color value with a message to the custom
control, but that is not what i want. I have found a function named :
GetWindowLong , but i don't know how to use this function and if it
is the right one to get those 2 parameters.



Answers :

Get/SetClassLong and Get/SetWindowLong are the right functions to access
this data. Using them is pretty straigtforward - the second parameter
is an offset to where you want to start reading data. If you allocate
8 extra bytes in cbWndExtra you would access them like this:

lValue1 = GetWindowLong(hwnd, 0);
lValue2 = GetWindowLong(hwnd, 4);


and the same w/ cbClsExtra and GetClassLong. Win32 also provides a bunch
of predefined values like GCL_STYLE and GCL_WNDPROC which give you access
to default data that is available for all windows and window classes. All
of the default values are negative numbers so as not to clash with accessing
extra user data bytes.


Answer2

You're not using the Extra parameters correctly. Those
values are used to reserve extra bytes in the block of
memory associated with the class or window. You can
then store things later in that location with SetWindowLong()
or SetClassLong() and retrieve with GetWindowLong()
or GetClassLong().

So if you say:
WNDCLASS wc;
wc.cbWndExtra=4;


then it reserves an extra 4 bytes for you. That's big enough
to hold a pointer to a block of memory if you so desire.
If all you have is a COLORREF, then 4 bytes will handle
that nicely. For clarity in your code, you should use:
wc.cbWndExtra=sizeof(COLORREF);


When you call CreateWindow(), you can pass a 4-byte
value as the last parameter, i.e.:
CreateWindow("mycustomcontrol",.....,RGB(50,100,150));


At WM_CREATE, you pick up the COLORREF and store it:
case WM_CREATE:
{LPCREATESTRUCT cs=(LPCREATESTRUCT)lparam;
COLORREF colour=cs->lpCreateParams;
SetWindowLong(hwnd,0,colour); //offset 0
}
break;


at any given time, you can retrieve it with:
case WM_someothermessage:
COLORREF colour=GetWindowLong(hwnd,0); //offset 0
break;


The classic book for learning Windows programming is
"Programming Windows 95" by Charles Petzold (Microsoft
Press). Almost everyone recommends this book, as do I.
It has excellent examples - source & .exe included.

No comments: