Ive been using this for ages in my own private apps for generic subclassing

SubClassWin proc MyhWin
__ GetWindowLong,MyhWin,GWL_USERDATA
__ SetWindowLong,MyhWin,GWL_USERDATA,eax
__ SetWindowLong,MyhWin,GWL_WNDPROC,lp SubClsProc
ret
SubClassWin endp

; and then this for invoking the original proc
__ GetWindowLong,hWin,GWL_USERDATA
__ CallWindowProc,eax,hWin,uMsg,wParam,lParam

This means different windows can be subclassed to the same proc.
I get no performance impact from this however i've never tried this on anything lower than 2.2 ghz machine. Is this method acceptable for 'public release' programming?
Posted on 2006-07-04 07:46:53 by asmrixstar
I personally use GetProp/SetProp since there's less chance for problems (even if those would mostly show up in pretty special situations). I never did any thorough benchmarking, but I didn't see any noticable performance problems (ie, taskmgr CPU usage raising) even on a p2-350 testbox.
Posted on 2006-07-04 09:23:55 by f0dder
Cool  8) thx fodder
I dont know how it happened but GetProp/SetProp completly passed me by until now, some very cool functions, perhaps it should be added to iczs tut's, just a thought.

PS. Did you ever play that old amiga game cannon fodder? You should its funny.
Posted on 2006-07-04 09:48:04 by asmrixstar

I dont know how it happened but GetProp/SetProp completly passed me by until now, some very cool functions, perhaps it should be added to iczs tut's, just a thought.

It's a pair of not-so-known functions indeed. As for adding to Icz' tutotirals, ho humm - I don't think that anybody should add to those, to be honest. Or well, perhaps as a footnote or something.


PS. Did you ever play that old amiga game cannon fodder? You should its funny.

Yeah, I played it :) - not the reason behind this name though.
Posted on 2006-07-04 12:01:13 by f0dder
Measured it quickly with RDTSC
Ouch 600..1300 cycles for GetWindowLong,hWnd,GWL_USERDATA
:(

In most cases, I also use Get/SetWindowLong (once set, many get) , and in just one app I maintain a vector (resizable array) with hWnds and their corresponding pointers to custom data.
Posted on 2006-07-04 12:26:55 by Ultrano
As for Set/GetProp... they're also new to me ... But looking at their definition and requirements, I have never needed them, and I'll never need them. A string and a HANDLE - no, thanks :)

The only problem around GWL_USERDATA is that you'd best set it in WM_CREATE, and be ready for the first WM_SIZE,  WM_MOVE, WM_GETMINMAX messages, where you still have GWL_USERDATA=0. (thus you can't dispatch them to your object's message handlers with "pThis"=0 )


More importantly, to answer asmrixstar's important question
"Is this method acceptable for 'public release' programming?":
Yes, this is exactly what professional software uses. In 1% of the cases, you can use a vector (like I mentioned) - if you need to somehow hide your class-object data (it's all objects in the end, no matter what you do :) ), or want to have an even higher speed of dispatching window messages to their objects. (balanced binary tree does the trick well).
Posted on 2006-07-04 12:37:32 by Ultrano
The string can be an ATOM, and "The data handle can identify any value useful to the application" (ie, just a DWORD value).

This means you can use Get/SetProp for subclassing, which isn't safe with GWL_USERDATA.
Posted on 2006-07-04 12:42:40 by f0dder
Ah, then it's better than I had understood.
But still there is the problem of having to use a string, (or even worse - register an atom), and then "must use the RemoveProp function" before deleting the window.
And there's the problem of GetProp taking 6000-8000 cycles, instead of GetWindowLong's 600-1300. :(

Hmm with specifying an ATOM instead of string, GetProp takes 1400-1600 cycles only, so I guess my arguments just vanished
Posted on 2006-07-04 12:54:37 by Ultrano
Having to RegisterAtom and RemoveProp aren't too bad, IMHO - ATOM registration is done at program startup, and you can usually get around with only a single ATOM for this. If RemoveProp becomes a problem, I wonder how your window management is done ;)

I don't think GetProp would be a problem even on very slow CPUs? - and it *is* safer for subclassing.
Posted on 2006-07-04 13:22:59 by f0dder
Anyway, finally made some real benchmarking, instead of once-call rdtsc, the results are:

GetWindowLong - 102 cycles
GetProp - with text: 2073 cycles
GetProp - with atom: 198 cycles
Benchmark done on Sempron 2200+, 512MB DDR400, Win2kSP4


So, in the end - if your window isn't subclassed, use GetWindowLong, but otherwise you must use GetProp with an atom.

Posted on 2006-07-04 14:29:49 by Ultrano
fodder could u throw up an link/example of anywhere you've used this method.
thx :)
Posted on 2006-07-04 17:22:05 by asmrixstar
Sure thing, just beware that this is C++ code... and it looks pretty ugly :)... you need to do a lot of typecasting when doing win32 programming, because the PlatformSDK was created for C and is a big mess. Furthermore I use new-style typecasts instead of old-style, which also looks a bit ugly. And the code could be cleaner if I used some temporary variables (that would be optimized out anyway). But you asked for it ;)


LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
static char const* propName = "fSekrit::dispatch";

switch(msg)
{
case WM_CREATE:
::SetProp(hwnd, propName, reinterpret_cast<CREATESTRUCT*>(lp)->lpCreateParams);
// intentional fallthrough!

default:
HANDLE prop = ::GetProp(hwnd, propName);
if(prop)
{
return reinterpret_cast<Editor*>(prop)->Dispatch(hwnd, msg,
static_cast<unsigned>(wp), static_cast<unsigned>(lp));
} else
{
return ::DefWindowProc(hwnd, msg, wp, lp);
}
}
}

Posted on 2006-07-05 01:18:32 by f0dder