SetWindowLong & DWLP_USER

Recommended Posts

Impz0r    166
Heya, currently i'm programming an input driver, which residents within a dll and to bypass WM_*Input* messages, i subclass the application window. Therefore i have my very own WinProc function within the input driver. And because my input driver is implemented as a class i need to pass the "this ptr" to the WinProc function to reroute the relevant input data. And that's where i have some trouble getting it to work. The thing is, i can't use the "user data" of the application window, because i don't know if there is allready data stored or not. So i tried something like this to get along with it:
// Resize the extra window bytes, because we wanna store something there ...
::SetClassLongPtr (hWnd, GCL_CBWNDEXTRA, DWLP_USER+12);
long32 ulError = ::GetLastError (); // works fine, no error here

// Subclassing the application window
WNDPROC pOrginalWinProc = reinterpret_cast<WNDPROC> (::SetWindowLongPtr (hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR> (SubclassWinProc)));

::SetWindowLongPtr (hWnd, DWLP_USER, reinterpret_cast<LONG_PTR> (this));
::SetWindowLongPtr (hWnd, DWLP_USER+4, reinterpret_cast<LONG_PTR> (pOrginalWinProc));
ulError = ::GetLastError (); // got a 1413 error (meaning: invalid index)


But this isn't quite working right now ... any ideas how to solve this ? Thanks in advance. Impz0r

Share on other sites
d_emmanuel    271
Hi again,

the problem is that SetClassLongPtr doesn't actually allocate extra memory for the window structure, it only specifies how much should be available.
See the MSDN doc.

In order to allocate additional memory you need to specify the number of bytes in the cbWndExtra member of the WNDCLASS when you register your window class.

Share on other sites
Anon Mike    1098
It isn't clear to me whether or not you own the windows that you're trying to muck with. If you do then you should already know whether or not you've set things up already. If you only need to store a pointer or pointer-sized value then GWLP_USERDATA is the way to go, otherwise you need to set up the "window extra" data as emmanuel described.

If you don't own the window you can't touch either of those. An alternative would be to used SetProp with (say) a stringized GUID for the property name. Of course you could always just keep an external map of HWND's to your own structures as well.

Share on other sites
Impz0r    166
Thanks to both of you!

@d_emmanuel

I see, so i can't change the extra data size after the window is allready created. To bad. I guess i need to try something else, like Anon Mike posted.

@Anon Mike

Funny, i tried this approach just before and it works, but its not very "fast". I guess it has something to do with the string lookup. And of course, that i call ::GetProp(...) every time the subclassed WinProc is called. Maybe thats just plain wrong ...

Well, the thing is, i use the driver within my main application (game) and within my editor, but i use an external widget lib therefore and i have no idea if they store something to the user data or not, most likely tho. So i can't use the user data.

Ah and besides, what do you mean with this "external map of HWND's" ?

Impz0r

Share on other sites
Anon Mike    1098
Quote:
 Original post by Impz0rAh and besides, what do you mean with this "external map of HWND's" ?

typedef std::map<HWND, WindowData*> WindowMap;WindowMap map;...WindowMap::iterator i = map.find(hWnd);if (i == map.end()){    p = new WindowData(...);    i = map.insert(WindowMap::value_type(hWnd, p)).first;}WindowData * p = i->second;

Or something along those lines. The whole pair based interface to std::map is to wierd for me to remember off the top of my head so I probably have a few details wrong. The point is to keep your window/data mappings in your own data structure rather than trying to stick them on the window itself.

Share on other sites
Impz0r    166
Thanks Anon Mike for the explanation!

I see now what you're mean, it's probably a good idea. One thing tho, the map has to be a "global" variable otherwise i can't access it within the WinProc function. Or did i miss something ?

Impz0r