In Windows, suppose you have multiple windows (HWNDs) of the same window class open. How do you keep track of the context data in the window procedure so that, for example, window 1 does not get modified when the user tried to type in window 2?
CreateWindow() does not return until after the WndProc() has been called several times, so you can't simply set the resulting HWND to the context data and do a lookup in the WndProc(); you do need to set it in the WndProc().
WndProc() doesn't directly have the context information passed to it except on window creation messages, but unfortunately window creation messages aren't exactly the first messages to be passed to WndProc(). Nay, I find things such as WM_SIZE, WM_NCSIZE, and even some others are passed before I ever see WM_CREATE.
Storing the HWND in a linked list type of storage mechanism would be inefficient with large amounts of windows: each control in a window is simply another type of window and therefore another HWND of which you need to keep track; after a few hundred controls, searching the linked list for the HWND will be a major bottleneck in the program after a few dozen messages are passed to the program in a short amount of time!
From what I hear, some people use SetWindowLong() - but I also hear that some libraries like to use that too to store their own context information separate from the program and that window data collisions can sometimes occur. How can that be avoided?
if I'm understanding you correctly, you want to avoid one window to catch the messages from another. One way to avoid this is to use the solution proposed in this thread, which keeps track of the windows that is created by you and makes sure that the correct windows gets the messages associated to it by storing the pointer for the caller in the GWL_USERDATA .
// ...
m_hWnd = CreateWindowEx(0,"Classname","Title",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
320,200,NULL,NULL,hInstance, /*the magic pointer*/ this);
// ...
if(uMsg == WM_CREATE)
{
// collected here..
pParent = (CWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
// .. and then stored for later lookup
SetWindowLongPtr(hWnd,GWL_USERDATA,(LONG_PTR)pParent);
}
// ...
You can also catch the WM_NCCREATE message, as proposed by Moo-Juice.
And I don't think you should worry about the messages pre-WM_CREATE, because the window isn't even fully initialized at that point. If you need to set text you do that after the call to CreateWindow(Ex), be it user input or a SendMessagecall.
Whoever creates the window owns that window 100%. If you are the one to call CreateWindow(), then you can use GetWindowLong, knowing that it's yours.
If a library creates the window, however, you can't because it's not yours.
(Aside: Nothing is stopping anyone from stepping on anyone else's toes, but the convention is pretty standard).
If you are using a library that does this, it will generally have some mechanism to associate your own data with a window. Of course, you will need to refer to the documentation for that.
Use Windows properties : SetProp( HWND ,... ) , Getprop( HWND ,... ) and RemoveProp( HWND ,... )
Can't you use WNDCLASS.cbWndExtra to declare whatever private storage your class needs and then it will be allocated by Windows whenever it creates a window of that class.
From the native Win32 API using C++ is there a way to determine whether the window associated with an HWND is still valid?
You could use the Win32 API IsWindow.
It is not recommended to use it though for 2 reasons:
Windows handles can be re-used once the window is destroyed, so you don't know if you have a handle to an entirely different window or not.
The state could change directly after this call and you will think it is valid, but it may really not be valid.
From MSDN (same link as above):
A thread should not use IsWindow for a
window that it did not create because
the window could be destroyed after
this function was called. Further,
because window handles are recycled
the handle could even point to a
different window.
What can be done?
Perhaps your problem can be re-architected so that you do not have the need to check for a valid handle. Maybe for example you can establish a pipe from the client to the server.
You could also create a windows hook to detect when certain messages occur, but this is probably overkill for most needs.
This question is old, but I needed this functionality myself and was a bit disappointed after reading about the caveats. However, after doing a bit more digging it seems that all is well. Unless you're dealing with 16bit programs, IsWindow appears to be the way to go. The problem of handle re-use appears to have been sufficiently addressed according to this:
http://blogs.msdn.com/b/oldnewthing/archive/2007/07/17/3903614.aspx
So, because of the upper 16bit reuse counter, it is highly unlikely that you'll run into a window reuse problem.
You can use IsWindow() or also try to send the window a WM_NULL message with SendMessage(hWnd, WM_NULL) and see if it is successful.
Also, it is true that the window could be destroyed at any time if it isn't under your control. As others have stated the handle could potentially belong to another window as the handles are reused. In reality I don't know how likely that is.
The only solution that I know of the to create a system wide hook that looks for messages indicating a window is destroyed (WM_CLOSE, WM_DESTROY). Then you would compare the message window handle to ones you are holding to see if any of the windows you care about are affected. See here for more information on system wide hooks.
Maybe a combination of IsWindow, FindWindow and GetWindowThreadProcessId will be more accurate
HWND windowHandle = FindWindow(NULL, TEXT("window_title"));
LPDWORD oldpid = 0;
GetWindowThreadProcessId(windowHandle, &oldpid);
//after some time
if (IsWindow(windowHandle))
{
LPDWORD newpid = 0;
GetWindowThreadProcessId(windowHandle, &newpid);
if (newpid == oldpid)
{
//the window is still running
}else
{
//the window exists but has changed
}
}
If the window procedure for the window in question is under your control (or if you can subclass it), then I would suggest registering a custom message that the window responds to with a non-zero result. Sending that message to any other window (or an invalid HWND) will result in 0.
Of course, that only tells you if the HWND refers to one of the windows that you control -- but perhaps given other answers above that might even be advantageous.
Use RegisterWindowMessage to register the message, using a sufficiently unique name.
if(IsWindow(FindWindow(NULL , TEXT("Example Window Name")))){
// do stuff
}
will check if the window exists and has the appropriate name
I am having trouble getting a global system hook to work. I want to be notified whenever a window is moving, as early as possible, and change the window size. This means the CBT hook HCBT_MOVESIZE won't cut it, it only happens after the window has been moved. I want to hook the actual movement of the window, and be able to change the window size during the move.
The hooks are set from a DLL, and the callback function is within that DLL. This is what I've tried.
WH_CALLWNDPROC. It does alert me when a window is moved (WM_MOVING is received for windows from other applications), but I cannot change the contents of the message.
WH_CALLWNDPROCRET Same as WH_CALLWNDPROC.
CBT hook HCBT_MOVESIZE. Event happens to late.
WH_GETMESSAGE. Never receive WM_MOVE, WM_MOVING or WM_WINDOWPOSCHANGING. This hook would allow me to change the messages.
Update: Windows event hooks seem to allow me to capture it:
hWinEventHook = SetWinEventHook(EVENT_SYSTEM_MOVESIZESTART,
EVENT_SYSTEM_MOVESIZEEND, NULL, WinEventProc,
0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
However, this creates a different problem: changing the size of the window using SetWindowPos() does not work (it changes size alright, but immediately changes back to its previous size), even though I use SWP_NOSENDCHANGING. Ideas?
Update 2: Subclassing seems to work, however Visual Studio crashes after each program run (so does a lot of other windows). It works well if I place breakpoints and walk through the "unsubclassing", but not when I let the program run by itself. Ideas?
I have a CBT hook (it was there from earlier), and whenever HCBT_ACTIVATE is sent for a new window, I remove any previous subclassing using SetWindowLongPtr() (this has to run on 64-bit as well), and then subclass the new window. If I put a breakpoint anywhere, and immediately resume the session when it breaks, everything works fine. However, when I do not have any breakpoints, Visual Studio crashes when the program exits.
Hm, I would've thought that HCBT_MOVESIZE is precisely what you want, given that the MSDN says this about CBT hooks:
The system calls this function before activating, creating, destroying,
minimizing, maximizing, moving, or sizing a window.
and in particular:
HCBT_MOVESIZE
A window is about to be moved or sized.
(these quotes were taken from http://msdn.microsoft.com/en-us/library/ms644977%28VS.85%29.aspx)
...so I'd have thought that you get the HCBT_MOVESIZE call in time. The hook function which handles HCBT_MOVESIZE is also allowed to return an integer so that the system can determine whether the operation is allowed or should be prevented. Hence, given that the HCBT_MOVESIZE hook should get an option to prevent the operation, I'd say it's called before the move event occurred.
Are you really sure the hook function is called after the move event? If you do a GetWindowRect call on the particular handle within your hook function, does the returned rect equal the rectangle which is passed to the hook function?
Hooks are pretty heavy. You only want to use them when you absolutely have to.
That said, you could use one of the basic hooks simply as a way to get into the process. Once in the process, you could subclass the window you're interested in and handle the sizing messages in your subclass proc rather than trying to catch everything at the hook level.
Depending on what you want to do in response to the resize, you might need some interprocess communication.
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 understand it have their own drawbacks. My questions are:
What different ways are there of producing this kind of code:
CWindow::WndProc(UINT msg, WPARAM wParam, LPARAM)
{
this->DoSomething();
}
I can think of Thunks, HashMaps, Thread Local Storage and the Window User Data struct.
What are the pros / cons of each of these approaches?
Points awarded for code examples and recommendations.
This is purely for curiosities sake. After using MFC I've just been wondering how that works and then got to thinking about ATL etc.
Edit: What is the earliest place I can validly use the HWND in the window proc? It is documented as WM_NCCREATE - but if you actually experiment, that's not the first message to be sent to a window.
Edit: ATL uses a thunk for accessing the this pointer. MFC uses a hashtable lookup of HWNDs.
This question has many duplicates and almost-duplicates on SO, yet almost none of the answers I've seen explore the pitfalls of their chosen solutions.
There are several ways how to associate an arbitrary data pointer with a window, and there are 2 different situations to consider. Depending on the situation, the possibilities are different.
Situation 1 is when you are authoring the window class. This means you are implementing the WNDPROC, and it is your intention that other people use your window class in their applications. You generally do not know who will use your window class, and for what.
Situation 2 is when you are using a window class that already exists in your own application. In general, you do not have access to the window class source code, and you cannot modify it.
I'm assuming that the problem isn't getting the data pointer into the WNDPROC initially (that would just be the through the CREATESTRUCT with the lpParam parameter in CreateWindow[ExW]), but rather, how to store it for subsequent calls.
Method 1: cbWndExtra
When Windows creates an instance of a window, it internally allocates a WND struct. This struct has a certain size, contains all sorts of window-related things, like its position, its window class, and its current WNDPROC. At the end of this struct, Windows optionally allocates a number of additional bytes that belong to the struct. The number is specified in WNDCLASSEX.cbWndExtra, which is used in RegisterWindowClassEx.
This implies that this method can only be used if you are the person who registers the window class, i.e. you are authoring the window class.
Applications cannot directly access the WND struct. Instead, use GetWindowLong[Ptr]. Non-negative indices access memory inside the extra bytes at the end of the struct. "0" will access the first extra bytes.
This is a clean, and fast way of doing it, if you are authoring the window class. Most Windows internal controls seem to use this method.
Unfortunately, this method does not play so well with dialogs (DialogBox family). You would have a dialog window class in addition to providing the dialog template, which can become cumbersome to maintain (unless you need to do so for other reasons anyway). If you do want to use it with dialogs, you must specify the window class name in the dialog template, make sure this window class is registered before showing the dialog, and you need to implement a WNDPROC for the dialog (or use DefDlgProc). Furthermore, all dialogs already reserve a certain amount of bytes in cbWndExtra for the dialog manager to function properly. The number of extra bytes needed is the DLGWINDOWEXTRA constant. This means your stuff needs to come after the extra bytes which are already reserved by the dialog. Offset all accesses to the extra memory by DLGWINDOWEXTRA (including the value of cbWndExtra which you specify in your window class).
See also below for an extra method exclusive to dialogs.
Method 2: GWLP_USERDATA
The aforementioned WND struct happens to contain one pointer-sized field, which is not used by the system. It is accessed using GetWindowLongPtr with a negative index (namely, GWLP_USERDATA). A negative index will access fields inside the WND structure. Note that according to this, the negative indices do not seem to represent memory offsets, but are arbitrary.
The problem with GWLP_USERDATA is that it is not clear, and it has not been clear in the past, what exactly the purpose of this field is, and hence, who the owner of this field is. See also this question. The general consensus is that there is no consensus. It is likely that GWLP_USERDATA was meant to be used by users of the window, and not authors of the window class. This implies that using it inside of the WNDPROC is strictly incorrect, as the WNDPROC is always provided by the window class author.
I am personally convinced that this is the intention of the engineers that came up with GWLP_USERDATA simply because if it is true, then the API as a whole is sound, extensible, and future-proof. But if it is not true, then the API is neither of those, and it would be redundant with cbWndExtra.
All standard windows controls that I am aware of (e.g. BUTTON, EDIT, etc.) adhere to this and do not use GWLP_USERDATA internally, leaving it free for the window which uses these controls. The problem is that there are WAY too many examples, including on MSDN and on SO, which break this rule and use GWLP_USERDATA for implementation of the window class. This effectively takes away the cleanest and simplest method for a control user to associate a context pointer with it, simply because way too many people are doing it "wrong" (according to my definition of "wrong"). At worst, the user code does not know that GWLP_USERDATA is occupied, and may overwrite it, which would likely crash the application.
Because of this longstanding dispute about the ownership of GWLP_USERDATA, it is not generally safe to use it. If you are authoring a window class, you probably never should have used it anyway. If you are using a window, you should only do so if you are certain that it is not used by the window class.
Method 3: SetProp
The SetProp family of functions implements access to a property table. Each window has its own, independent properties. The key of this table is a string at API surface level, but internally it is really an ATOM.
SetProp can be used by window class authors, and window users, and it has issues too, but they are different from GWLP_USERDATA. You must make sure that the strings used as the property keys do not collide. The window user may not necessarily know what strings the window class author is using internally. Even though conflicts are unlikely, you can avoid them entirely by using a GUID as string, for example. As is evident when looking at the contents of the global ATOM table, many programs use GUIDs this way.
SetProp must be used with care. Most resources do not explain the pitfalls of this function. Internally, it uses GlobalAddAtom. This has several implications, which need to be considered when using this function:
When calling SetProp (or any other API that uses the global ATOM table), instead of a string, you can use an ATOM, which you get when you register a new string GlobalAddAtom. An ATOM is just an integer which refers to one entry in the ATOM table. This will improve performance; SetProp internally always uses ATOMs as property keys, never strings. Passing a string causes SetProp and similar functions to internally search the ATOM table for a match first. Passing an ATOM directly skips searching the string in the global atom table.
The number of possible string atoms in the global atom table is limited to 16384, system-wide. This is because atoms are 16-bit uints ranging from 0xC000 to 0xFFFF (all values below 0xC000 are pseudo-atoms pointing to fixed strings (which are perfectly fine to use, but you cannot guarantee that nobody else is using them)). It is a bad idea to use many different property names, let alone if those names are dynamically generated at runtime. Instead, you can use a single property to store a pointer to a structure that contains all the data you need.
If you are using a GUID, it is safe to use the same GUID for every window you are working with, even across different software projects, since every window has its own properties. This way, all of your software will only use up at most two entries in the global atom table (you'll need at most one GUID as a window class author, and at most one GUID as a window class user). In fact, it might make sense to define two de-facto standard GUIDs everyone can use for their context pointers (realistically not going to happen).
Because properties use GlobalAddAtom, you must make sure that the atoms are unregistered. Global atoms are not cleaned up when the process exists and will clog up the global atom table until the operating system is restarted. To do this, you must make sure that RemoveProp is called. A good place for this is usually WM_NCDESTROY.
Global atoms are reference-counted. This implies that the counter can overflow at some point. To protect against overflows, once the reference count of an atom reaches 65536, the atom will stay in the atom table forever, and no amount of GlobalDeleteAtom can get rid of it. The operating system must be restarted to free the atom table in this case.
Avoid having many different atom names if you want to use SetProp. Other than that, SetProp/GetProp is a very clean and defensive approach. The dangers of atom leaks could be greatly mitigated if developers agreed upon using the same 2 atom names for all windows, but that is not going to happen.
Method 4: SetWindowSubclass
SetWindowSubclass is meant to allow overriding the WNDPROC of a specific window, so that you can handle some messages in your own callback, and delegate the rest of the messages to the original WNDPROC. For example, this can be used to listen for specific key combinations in an EDIT control, while leaving the rest of the messages to its original implementation.
A convenient side effect of SetWindowSubclass is that the new, replacement WNDPROC is not actually a WNDPROC, but a SUBCLASSPROC.
SUBCLASSPROC has 2 additional parameters, one of them is DWORD_PTR dwRefData. This is arbitrary pointer-sized data. The data comes from you, through the last parameter to SetWindowSubclass. The data is then passed to every invocation of the replacement SUBCLASSPROC. If only every WNDPROC had this parameter, then we wouldn't be in this horrible situation!
This method only helps the window class author.(1) During the initial creation of the window (e.g. WM_CREATE), the window subclasses itself (it can allocate memory for the dwRefData right there if that's appropriate). Deallocation probably best in WM_NCDESTROY. The rest of the code that would normally go in WNDPROC is moved to the replacement SUBCLASSPROC instead.
It can even be used in a dialog's own WM_INITDIALOG message. If the dialog is shown with DialogParamW, the last parameter can be used as dwRefData in a SetWindowSubclass call in the WM_INITDIALOG message. Then, all the rest of the dialog logic goes in the new SUBCLASSPROC, which will receive this dwRefData for every message. Note that this changes semantics slightly. You are now writing at the level of the dialog's window procedure, not the dialog procedure.
Internally, SetWindowSubclass uses a property (using SetProp) whose atom name is UxSubclassInfo. Every instance of SetWindowSubclass uses this name, so it will already be in the global atom table on practically any system. It replaces the window's original WNDPROC with a WNDPROC called MasterSubclassProc. That function uses the data in the UxSubclassInfo property to get the dwRefData and call all registered SUBCLASSPROC functions. This also implies that you should probably not use UxSubclassInfo as your own property name for anything.
Method 5: Thunk
A thunk is a small function whose machine code is dynamically generated at run-time in memory. Its purpose is to call another function, but with additional parameters that seem to magically come out of nowhere.
This would let you define a function which is like WNDPROC, but it has one additional parameter. This parameter could be the equivalent of a "this" pointer. Then, when creating the window, you replace the original stub WNDPROC with a thunk that calls the real, pseudo-WNDPROC with an additional parameter.
The way this works is that when the thunk is created, it generates machine code in memory for a load instruction, loading the value of the extra parameter as a constant, and then a jump instruction to the address of the function which would normally require an additional parameter. The thunk itself can then be called as if it were a regular WNDPROC.
This method can be used by window class authors and is extremely fast. However, the implementation is not trivial. The AtlThunk family of functions implements this, but with a quirk. It does not add an extra parameter. Instead, it replaces the HWND parameter of WNDPROC with your arbitrary piece of data (pointer-sized). However, that is not a big problem since your arbitrary data may be a pointer to a struct containing the HWND of the window.
Similarly to the SetWindowSubclass method, you would create the thunk during window creation, using an arbitrary data pointer. Then, replace the window's WNDPROC with the thunk. All the real work goes in the new, pseudo-WNDPROC which is targeted by the thunk.
Thunks do not mess with the global atom table at all, and there are no string uniqueness considerations either. However, like everything else that is allocated in heap memory, they must be freed, and after that, the thunk may no longer be called. Since WM_NCDESTROY is the last message a window receives, this is the place to do that. Otherwise, you must make sure to reinstall the original WNDPROC when freeing the thunk.
Note that this method of smuggling a "this" pointer into a callback function is practically ubiquitous in many ecosystems, including C# interop with native C functions.
Method 6: Global lookup table
No long explanation needed. In your application, implement a global table where you store HWNDs as keys and context data as values. You are responsible for cleaning up the table, and, if needed, to make it sufficiently fast.
Window class authors can use private tables for their implementations, and window users can use their own tables to store application-specific information. There are no concerns about atoms or string uniqueness.
Bottom line
These methods work if you are the Window Class Author:
cbWndExtra, (GWLP_USERDATA), SetProp, SetWindowSubclass, Thunk, Global lookup table.
Window Class Author means that you are writing the WNDPROC function. For example, you may be implementing a custom picture box control, which allows the user to pan and zoom. You may need additional data to store pan/zoom data (e.g. as a 2D transformation matrix), so that you can implement your WM_PAINT code correctly.
Recommendation: Avoid GWLP_USERDATA because the user code may rely on it; use cbWndExtra if possible.
These methods work if you are the Window User:
GWLP_USERDATA, SetProp, Global lookup table.
Window User means you are creating one or more of the windows and use them in your own application. For example, you may be creating a variable number of buttons dynamically, and each of them is associated with a different piece of data that is relevant when it is being clicked.
Recommendation: Use GWLP_USERDATA if it's a standard Windows control, or you are sure that the control doesn't use it internally. Otherwise, SetProp.
Extra mention when using dialogs
Dialogs, by default, use a window class that has cbWndExtra set to DLGWINDOWEXTRA. It is possible to define your own window class for a dialog, where you allocate, say, DLGWINDOWEXTRA + sizeof(void*), and then access GetWindowLongPtrW(hDlg, DLGWINDOWEXTRA). But while doing so you will find yourself having to answer questions you won't like. For example, which WNDPROC do you use (answer: you can use DefDlgProc), or which class styles do you use (the default dialogs happen to use CS_SAVEBITS | CS_DBLCLKS, but good luck finding an authoritative reference).
Within the DLGWINDOEXTRA bytes, dialogs happen to reserve a pointer-sized field, which can be accessed using GetWindowLongPtr with index DWLP_USER. This is kind of an additional GWLP_USERDATA, and, in theory, has the same problems. In practice I have only ever seen this used inside the DLGPROC which ends up being passed to DialogBox[Param]. After all, the window user still has GWLP_USERDATA. So it is probably safe to use for the window class implementation in practically every situation.
While using the SetWindowLongPtr and GetWindowLongPtr to access the GWL_USERDATA might sound like a good idea, I would strongly recommend not using this approach.
This is the exactly the approached used by the Zeus editor and in recent years it has caused nothing but pain.
I think what happens is third party windows messages are sent to Zeus that also have their GWL_USERDATA value set. One application in particular was a Microsoft tool that provied an alternative way to enter Asian characters in any windows application (i.e. some sort of software keyboard utility).
The problem is Zeus always assumes the GWL_USERDATA data was set by it and tries to use the data as a this pointer, which then results in a crash.
If I was to do it all again with, what I know now, I would go for a cached hash lookup approach where the window handle is used as the key.
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.
You should use GetWindowLongPtr()/SetWindowLongPtr() (or the deprecated GetWindowLong()/SetWindowLong()). They are fast and do exactly what you want to do. The only tricky part is figuring out when to call SetWindowLongPtr() - You need to do this when the first window message is sent, which is WM_NCCREATE.
See this article for sample code and a more in-depth discussion.
Thread-local storage is a bad idea, since you may have multiple windows running in one thread.
A hash map would also work, but computing the hash function for every window message (and there are a LOT) can get expensive.
I'm not sure how you mean to use thunks; how are you passing around the thunks?
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.
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().
I recommend setting a thread_local variable just before calling CreateWindow, and reading it in your WindowProc to find out the this variable (I presume you have control over WindowProc).
This way you'll have the this/HWND association on the very first message sent to you window.
With the other approaches suggested here chances are you'll miss on some messages: those sent before WM_CREATE / WM_NCCREATE / WM_GETMINMAXINFO.
class Window
{
// ...
static thread_local Window* _windowBeingCreated;
static thread_local std::unordered_map<HWND, Window*> _hwndMap;
// ...
HWND _hwnd;
// ...
// all error checking omitted
// ...
void Create (HWND parentHWnd, UINT nID, HINSTANCE hinstance)
{
// ...
_windowBeingCreated = this;
::CreateWindow (YourWndClassName, L"", WS_CHILD | WS_VISIBLE, x, y, w, h, parentHWnd, (HMENU) nID, hinstance, NULL);
}
static LRESULT CALLBACK Window::WindowProcStatic (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
Window* _this;
if (_windowBeingCreated != nullptr)
{
_hwndMap[hwnd] = _windowBeingCreated;
_windowBeingCreated->_hwnd = hwnd;
_this = _windowBeingCreated;
windowBeingCreated = NULL;
}
else
{
auto existing = _hwndMap.find (hwnd);
_this = existing->second;
}
return _this->WindowProc (msg, wparam, lparam);
}
LRESULT Window::WindowProc (UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
// ....
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.
In the past I've used the lpParam parameter of CreateWindowEx:
lpParam [in, optional] Type: LPVOID
Pointer to a value to be passed to the window through the CREATESTRUCT
structure (lpCreateParams member) pointed to by the lParam param of
the WM_CREATE message. This message is sent to the created window by
this function before it returns. If an application calls CreateWindow
to create a MDI client window, lpParam should point to a
CLIENTCREATESTRUCT structure. If an MDI client window calls
CreateWindow to create an MDI child window, lpParam should point to a
MDICREATESTRUCT structure. lpParam may be NULL if no additional data
is needed.
The trick here is to have a static std::map of HWND to class instance pointers. Its possible that the std::map::find might be more performant than the SetWindowLongPtr method. Its certainly easier to write test code using this method though.
Btw if you are using a win32 dialog then you'll need to use the DialogBoxParam function.
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'm developing an interface for an add-on to a game. I can't use the game API (for several reasons including the fact that the code must be game-agnostic) and I need to get keyboard input from the user so I've decided to use a keyboard hook (WH_KEYBOARD) to process user input when certain conditions are met.
The problem is that while I can receive and process the input correctly, when my hook returns TRUE instead of CallNextHookEx the system seems to take up a lot of time (well over 800ms) before letting things go on as expected and that's not acceptable because it doesn't even allow for a fluid typing experience.
What I have to achieve is preventing the key press message to reach the WndProc, so the question is: what can I do to achieve my target without hurting the game performance so much that the result will be unacceptable?
EDIT: due to specific requirements (games using anticheats which might create problems with my code despite it's not cheating-related) subclassing the active wndproc is not an option.
First you need your DLL to be injected into the target process, either by hooks, or by any other way.
Find the window handle of interest.
Obtain the current window procedure of that window, by calling GetWindowLongPtr(wnd, GWLP_WNDPROC), and save it.
Sub-class the window, by calling SetWindowLongPtr( wnd, GWLP_WNDPROC, &NewWndProc ) where NewWndProc is your DLL-implemented message procedure.
Inside NewWndProc you'll want to process keyboard messages (there're a dozen of them, type "keyboard input" in MSDN index, I can't post more then 1 link). For the rest of windows messages call the original window procedure you've saved during (3), and return the value it returned. Don't call it directly, use CallWindowProc instead.
This way is not very reliable, some antivirus and anti-bot (e.g. "warden client") software might not like it, and debugging may be challenging.
However it should work.
A keyboard hook should not make things that slow. There's probably something else going on that causes the 800ms delay. Is it still slow if your hook does nothing and simply returns TRUE?
If you want to prevent from message to arrive to the WndProc then you need to subclass using SetWindowLong, this way you will be able to catch all messages and decide if to continue their route.
As much as I don't like answering my own question I've found the cause of the delay. The message pump of the games I've tested my code against was implemented with a while(PeekMessage) { GetMessage... } and removing the keyboard input message somehow caused GetMessage to block for sometime. Using PostMessage and WM_NULL helped preventing GetMessage from blocking.