Advertisement

Forward Windows messages to a derived class's virtual CallWindowProc() method

Started by July 18, 2017 03:56 AM
20 comments, last by Kylotan 7 years, 4 months ago

Looks good. Two notes:

  • You explicitly call GetWindowLongPtrW(); you shouldn't need to do this, especially as you don't explicitly call the other wide-character overloads. Just call GetWindowLongPtr(). Needing to explicitly call the *W or *A variant of some Win32 function is usually a sign you're doing something tricky (this is not) or something wrong.
  • Instead of passing 0 to GetWindowLongPtr (or SetWindowLongPtr), consider passing the constant GLWP_USERDATA. Passing a value >= 0 is asking to retrieve sizeof(LONG_PTR) worth of data from the "extra" memory you asked the API to allocate when you created the window style (via the cbWndExtra field)... which most people never do. If you've actually done that, great. But if you haven't done that, you're reading from and writing to garbage memory which is likely to crash you soon or later. Using GLWP_USERDATA is, in my experience, more common than manually bothering to allocate extra instance data.

 

Good points, the GetWindowLongPtrW() was totally a distraction mistake, thanks!

I also fixed in the code above just to not further confuse people that may copy paste it in the future :)

Advertisement

Wait a second, watch what happens every time windows has a message for WindowProc, 


LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	D3DApp* pD3dApp = reinterpret_cast<D3DApp*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
	if (pD3dApp) { return pD3dApp->MsgProc(hwnd, msg, wParam, lParam); }
	else { return DefWindowProc(hwnd, msg, wParam, lParam); }
}

we keep creating a pointer, calling a function GetWindowLonhPtr, testing the pointer and calling our MsgProc function.

This looks horrible, I start to think that the original book's author on my first reply totally won in terms of performance, in fact I think I may go back to use it :D

Creating a pointer costs absolutely nothing.

Calling a function like GetWindowLongPtr is very cheap.

Testing the pointer is almost entirely free. But take it out if you like; it's not like your program can do anything useful if it's null anyway.

Calling MsgProc is what you had to do anyway.

You're worrying about nothing.

50 minutes ago, Kylotan said:

You're worrying about nothing.

I often do :D 

One time I was worried about bool taking 8 bit instead of 1 and another time I was worried about "burn" the bits of the memory by using too much of loops :D

 "Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."

- Donald Knuth.

 

In this case, you're in the 97% part, not the 3% part.

If you're so keen on optimizing, consider optimizing your thought process. Don't waste brain cycles on stuff that has no measurable/noticable impact.

Hello to all my stalkers.

Advertisement
8 minutes ago, Lactose said:

If you're so keen on optimizing, consider optimizing your thought process. Don't waste brain cycles on stuff that has no measurable/noticable impact.

Not wasted, I am learning out of it ;)

Also to be precise, he is not saying to not optimize that 97% of the time, I should stress the word "premature". He talks only about premature optimization, meaning sooner or later you have to go around and do something about that 97% regardless :D 

I heard it from Scott Meyers on a youtube video that people often misinterpret that quote, that why I point it out

Well, no - most of the time that 97% never matters, because they're "noncritical parts of their programs". You need to get a feeling for what is truly expensive and what is not. You're worrying about the performance of code where (a) it is called relatively infrequently, and (b) the operations are already near-optimal anyway.

Got it.

Though in order in order for the "get feeling" part to happen, I'm pretty sure I will need to learn how to debug, the tools to analyze my code and lots and lots of tests/experiments that show me consistent patterns, so is still a far thing in the future I guess :P 

16 hours ago, Kylotan said:

Testing the pointer is almost entirely free. But take it out if you like; it's not like your program can do anything useful if it's null anyway.

Lol, careful with this :D

I wrote from scratch a D2D framework as practice and lost quite some time troubleshooting this.

You get a HWND from the CreateWindow function and SetWindowLongPtr call comes after that function. It turns out that CreateWindow immediately calls the WindowProc during its setup so my line


return pD2DApp->WinProc(hwnd, msg, wParam, lParam);

was working with a nullptr, so the check for nullptr is kind of mandatory, learned it the hard way :P 

This topic is closed to new replies.

Advertisement