If you add an extra data space to the DialogBox class that GetWindowLongPtr can access, should you add DLGWINDOWEXTRA to access that extra space?
When creating a window class for use with DialogBox, you need to add DLGWINDOWEXTRA to cbWndExtra. If you add extra data space to the DialogBox class that GetWindowLongPtr can access, should you add DLGWINDOWEXTRA to access that extra space?
(I admit, I think I know the answer so that the code won't break. But I want my reasons to match the collective wisdom.)
The main reason Dialogs are used with their own class (rather than the default) is to allow each Dialog class to have its own icon. Each window also has two separate pieces of additional data attached to it.
...
wndclass.cbWndExtra = DLGWINDOWEXTRA+EXTRASPACE;
wndclass.lpfnWndProc = (WNDPROC) DefDlgProc;
wndclass.hIcon = LoadIcon(hInstance, "ICON_MAIN");
wndclass.lpszClassName = WND_CLASS_VLIST_POPUP;
wndclass.hIconSm = LoadImage(hInstance,
"ICON_MAIN",
IMAGE_ICON,
16,
16,
LR_DEFAULTCOLOR);
...
Later edit (removed wrong GWLP_USERDATA and replaced with 0):
The effect is as follows:
GetWindowLongPtr(hWnd, 0 + DLGWINDOWEXTRA + SOMETHING_IN_EXTRASPACE);
or
GetWindowLongPtr(hWnd, 0 + SOMETHING_IN_EXTRASPACE);
?
a source to share
Actually ... I think you are wrong. The value in GWLP_USERDATA
and the space allocated in accordance with cbWndExtra
are two separate things ...
The value GWLP_USERDATA
is the fraction of the space that Windows allocates for each window. Window classes very often require a bit of memory with a pointer size, which Windows simply includes the base cost of the window as well as all other predefined "window words". Have a look at the documentation for the parameter nIndex
at GetWindowLongPtr()
:
Specifies a zero-based offset for the return value. Valid values โโare in range zero based on the number of bytes of extra window memory minus the size of the integer.
So, GetWindowLongPtr(hWnd, 0)
retrieves the first sizeof(LONG_PTR)
bytes allocated in response to cbWndExtra
, GetWindowLongPtr(hWnd, sizeof(LONG_PTR))
gives you the next pointer size data, and so on. As its name suggests, nIndex
acts like an index into a byte array (although it always returns the size of the pointer). Now take a look at the index values โโassigned to the predefined window data constants: they are all negative, including GWLP_USERDATA
! In fact, it GetWindowLongPtr()
starts indexing in the middle of the window data, with the data shared by all windows "before" index 0 and any window class data after it.
Dialog boxes are built on top of the basic support provided for regular windows. Since they require more data than normal windows, you need to specify at least DLGWINDOWEXTRA
bytes in the cbWndExtra
. Like any other such data, it was accessed via a positive value passed to GetWindowLongPtr()
.
So when you ask
GetWindowLongPtr(hWnd, GWLP_USERDATA + DLGWINDOWEXTRA + 0);
... you actually get the data by index -21 + 30 + 0 = 9
: a value somewhere in the dialog manager's own data. Not what you want!
Now you should understand that when accessing data allocated through cbWndExtra = DLGWINDOWEXTRA + extra
, you only need to compensate for your request DLGWINDOWEXTRA
. So:
GetWindowLongPtr(hWnd, DLGWINDOWEXTRA + 0);
... will give you the first piece of additional data. GWLP_USERDATA
should only be used when you want to get or set one pointer to the always assigned user data associated with each window.
a source to share