I\'m interested to know the best / common way of storing a this
pointer for use in the WndProc
. I know of several approaches, but each as I underst
ATL's thunk is the most efficent. the thunk executes once and replaces the callback function for the WINPROC to the classes own message processing member function. subsiquent messages are passed by a direct call to the classes member function by windows. it doesnt get any faster than that.
With regard to SetWindowLong() / GetWindowLong() security, according to Microsoft:
The SetWindowLong function fails if the window specified by the hWnd parameter does not belong to the same process as the calling thread.
Unfortunately, until the release of a Security Update on October 12, 2004, Windows would not enforce this rule, allowing an application to set any other application's GWL_USERDATA. Therefore, applications running on unpatched systems are vulnerable to attack through calls to SetWindowLong().
In your constructor, call CreateWindowEx with "this" as the lpParam argument.
Then, on WM_NCCREATE, call the following code:
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) ((CREATESTRUCT*)lParam)->lpCreateParams);
SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
Then, at the top of your window procedure you could do the following:
MyWindowClass *wndptr = (MyWindowClass*) GetWindowLongPtr(hwnd, GWL_USERDATA);
Which allows you to do this:
wndptr->DoSomething();
Of course, you could use the same technique to call something like your function above:
wndptr->WndProc(msg, wparam, lparam);
... which can then use its "this" pointer as expected.
In order to prevent the problem that occurred in the Zeus editor, simply specify the window in the GetMessage function:
BOOL GetMessage(
LPMSG lpMsg,
HWND hWnd, /*A handle to the window whose messages are to be retrieved.*/
UINT wMsgFilterMin,
UINT wMsgFilterMax
);
NOTE The window must belong to the current thread.
Easy to read Documentation of the function
I've used SetProp/GetProp to store a pointer to data with the window itself. I'm not sure how it stacks up to the other items you mentioned.
You can use GetWindowLongPtr
and SetWindowLongPtr
; use GWLP_USERDATA
to attach the pointer to the window. However, if you are writing a custom control I would suggest to use extra window bytes to get the job done. While registering the window class set the WNDCLASS::cbWndExtra
to the size of the data like this, wc.cbWndExtra = sizeof(Ctrl*);
.
You can get and set the value using GetWindowLongPtr
and SetWindowLongPtr
with nIndex
parameter set to 0
. This method can save GWLP_USERDATA
for other purposes.
The disadvantage with GetProp
and SetProp
, there will be a string comparison to get/set a property.