good known that GWLP_USERDATA
can be used to associate some pointer size data with the specified window. but who has the right do it ? obviously if two piece of code independently do this - one piece is overwrite data of another - so there must only be one owner. but it must be clear determined a general rule - who is owner of GWLP_USERDATA
cell ? whom it belong ?
can be two internally consistent agreements:
- code that created the window is owner. belong to the creator of the window
- code which implement window class. belong to the window class implementer
what of this two solutions must be used ?
1. from MSDN:
GWLP_USERDATA:
Sets the user data associated with the window. This data is intended for use by the application that created the window. Its value is initially zero.
how need understand This data is intended for use by the application that created the window
?
so code which call CreateWindowEx
, CreateDialogParam
, DialogBoxParam
, etc - and only this code can use GWLP_USERDATA
. from this also follows that window class implementer can not use GWLP_USERDATA
. so huge number of examples where GWLP_USERDATA
used for bind instance of class to the specified window is incorrect. Managing Application State - official MSDN example, where GWLP_USERDATA
used for bind data structure to window is incorrect ?!
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
is error under this rule.
what can be said in favor of this version ?
i check different windows versions (from xp to win10) - how i can see all windows built-in window classes ( WC_*
and others) use
SetWindowLongPtr(hwnd, 0, (LONG_PTR)pThis);
for bind instance of class to the specified window. always index 0 used instead GWLP_USERDATA
many can say - so what ? even if now this is true, what about future windows versions ?
but if think, what sense migrate from index 0 (really private implementer index in all senses) to GWLP_USERDATA
?
change existing SetWindowLongPtr(hwnd, 0, (LONG_PTR)pThis);
to SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
what prize ? or additional begin use GWLP_USERDATA
with index 0 too ? this already absolute senseless - one pointer is enough for bind window to data structure, all additional pointers must be (and in case windows code will be) in this structure already. so i personally can assume that this is not changed
also can note an error in the documentation for SetWindowLongPtr
and GetWindowLongPtr
here:
The zero-based offset to the value to be set. Valid values are in the range zero through the number of bytes of extra window memory, minus the size of an integer
really minus the size of an pointer which 8 bytes on x64, when size of an integer always 4.
2. look at a reputable blog - The bonus window bytes at GWLP_USERDATA:
Note that this value, ..., belongs to the window class and not to the code that creates the window... only the window class implementer may read or write the values.
but exist also next two author remarks:
Interesting. I’m checking into that. But even if it does belong to the creator of the window, enough window class implementations use it that you still should stay away for safety’s sake.
and
I asked around and guidance is "unclear", though leaning slightly towards "it belongs to the person who called CreateWindow". For safety’s sake, then, you should just avoid it unless you can establish clear ownership
again look for Managing Application State MSDN example - window class implementer used GWLP_USERDATA
!
look for ATL
atlhost.h
- AtlAxWindowProc
used GWLP_USERDATA
//case WM_CREATE:
::SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD_PTR)pAxWindow);
again class implementer used GWLP_USERDATA
but under this agreement we can not use GWLP_USERDATA
with CreateDialogParam
, DialogBoxParam
because here we not implementer (The DialogProc
function is an application-defined callback function called from DefDlgProc
- real class implementation code for dialogs - so only DefDlgProc
can potential use GWLP_USERDATA
cell)
so application that created the window or window class implementer is owner ?
if think - the variant application that created the window is more logical. window class implementer have two choice: can set cbWndExtra
to sizeof(PVOID)
and use index 0 or use GWLP_USERDATA
index. when application that created the window - have no choice - only GWLP_USERDATA
index or use another (less effective and more complex) way like SetProp
, SetWindowSubclass
, etc. so be logical if window class implementer use index 0 for bind self data to window and leave free GWLP_USERDATA
for code that created the window. again how about CreateDialogParam
, DialogBoxParam
- most native way here for use data structure binds to dialog use GWLP_USERDATA
index, but here we window creator, not dialog class implementer ! so can use GWLP_USERDATA
or not ?
in all case need take to account that enough existing custom window class implementations use GWLP_USERDATA
my assumptions:
- if we call
CreateWindowEx
for non windows core built-in class - we must not useGWLP_USERDATA
here - if we call
CreateDialogParam
,DialogBoxParam
- i assume that we can here useGWLP_USERDATA
- if we call
CreateWindowEx
for windows built-in class (WC_* named) we also can useGWLP_USERDATA
- if we window class implementer - the best choice - set
cbWndExtra
tosizeof(PVOID)
and use index 0