Hi all
I'm working on a custom window control wich will go into a dll file. When my control processes WM_CREATE I will allocate some memory for use by the control. My question is where to store it (or where to store the pointer to the memory) I can't use LOCALs since they will be cleared every time the proc ends and I can't use the data section since my control can be used more then once, so where do controls usually store there data?
Posted on 2002-04-25 10:20:56 by Kudos
If storage for one pointer suits your needs, you can use SetWindowLong(hWnd, GWL_USERDATA , value) and value = GetWindowLong(hWnd, GWL_USERDATA).

Posted on 2002-04-25 10:22:14 by Thomas
Storage for one pointer will allways be sufficient :), since you can
HeapAlloc a block of memory. However, if you need something like
12 or 16 bytes, it might be smarter to specify some bytes in
cbWndExtra to avoid doing (possibly) lots of small heap allocs.
Posted on 2002-04-25 11:04:08 by f0dder
Exactly, this is one of the points discussed in my tutorial.

However, i thought i would point out that you *should* (might get away with not doing so) also specify 4 bytes at the very least if you wish to store the pointer by GWL_USERDATA.

I did some research on this and heres what i dug up:
Extra Window Memory
The system maintains an internal data structure for each window. When registering a window class, an application can specify a number of additional bytes of memory, called extra window memory. When creating a window of the class, the system allocates and appends the specified amount of extra window memory to the end of the window's structure. An application can use this memory to store window-specific data.

Because extra memory is allocated from the system's local heap, an application should use extra window memory sparingly. With system version 4.0 or later, the RegisterClassEx function fails if the amount of extra window memory requested is greater than 40 bytes. If an application requires more than 40 bytes, it should allocate its own memory and store a pointer to the memory in the extra window memory.

The SetWindowLong function copies a value to the extra memory. The GetWindowLong function retrieves a value from the extra memory. The cbWndExtra member of the WNDCLASSEX structure specifies the amount of extra window memory to allocate. An application that doesn't use the memory must initialize cbWndExtra to zero.

So you get a few more bytes than 12 or 16 :) , however for my uses 40 was still not enough (Storing Drawing "rects" are 16 bytes a pop!)

Hope it helps
Posted on 2002-04-25 11:22:05 by NaN
I don't think it's necessary to specify any cbWndExtra to use
GWL_USERDATA, I'm pretty sure all windows has these 4 bytes by default.
At least I've never run into any trouble using GWL_USERDATA on
any flavour of NT or 9x.
Posted on 2002-04-25 11:26:58 by f0dder
Thanx for replies

I think I'll just use 4 byte and point to a structure containing all of the control's data (not sure of the exact format yet). I had know idea it would work without setting cbWndExtra
Posted on 2002-04-25 11:59:08 by Kudos
Just remember to put that struct on the heap, don't use a local struct ;)
Posted on 2002-04-25 12:02:48 by f0dder

Thanx for replies
... (not sure of the exact format yet). I had know idea it would work without setting cbWndExtra

Take a look at my custom menu-button control .

The way i formatted it is simple and flexible for changes.
    [*]First create a Structure that will represent your private memory for the control
    [*]In the WM_CREATE call HeapAlloc to the size of the structure. Then take the pointer and store it with SetWindowLong.
    [*]Before any message is handled, i call GetWindowLong, and retrieve the pointer, and place it in EBX such that is wont be corrupted by API's. This allows me to treat EBX as the private memory for the control throughout the control.
    [*]When closing, call HeapFree on the EBX pointer.

    The advantage to this format is you can make changes to your private memory simply by adding or removing structure entries, as everything else is done dynamically and based on the structure size.

    Hope this is some help.
Posted on 2002-04-25 14:00:01 by NaN