Jump to content
  • Advertisement
Sign in to follow this  
Evil Steve

Size/move loop and delay in DefWindowProc

This topic is 2739 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to start a timer when the user starts to drag the window, so I can render a frame on the WM_TIMER message, to prevent the stall that happens when the user drags the window. I added some logging and found that DefWindowProc() for WM_SYSCOMMAND (With a wParam of 0xf012, which doesn't seem to be a recognised SC_* value) and WM_NCLBUTTONDOWN takes a considerable time to return (Over 500ms). With some more logging, it seems that WM_NCLBUTTONDOWN comes first, and calling DefWindowProc causes a WM_SYSCOMMAND message to be sent (So it's recursing into the window proc, hence the delay on both messages). The call stack at the time if I break with F12 isn't very exciting:
ntdll.dll!_KiFastSystemCallRet@0() 	
user32.dll!_NtUserMessageCall@28()  + 0xc bytes	
user32.dll!_RealDefWindowProcWorker@20()  - 0x79d6 bytes	
user32.dll!_RealDefWindowProcW@16()  + 0x27 bytes	
uxtheme.dll!DoMsgDefault()  + 0x29 bytes	
uxtheme.dll!OnDwpSysCommand()  + 0x29 bytes	
uxtheme.dll!_ThemeDefWindowProc()  + 0x61a8 bytes	
uxtheme.dll!_ThemeDefWindowProcW@16()  + 0x18 bytes	
user32.dll!_DefWindowProcW@16()  + 0x815 bytes	
>	Tutorial02.exe!D3DWindow::WndProc(unsigned int uMsg=274, unsigned int wParam=61458, long lParam=5636612)  Line 227 + 0x1b bytes	C++
Tutorial02.exe!D3DWindow::StaticWndProc(HWND__ * hWnd=0x000a06fa, unsigned int uMsg=274, unsigned int wParam=61458, long lParam=5636612)  Line 169 + 0x1a bytes	C++
user32.dll!_InternalCallWinProc@20()  + 0x23 bytes	
user32.dll!_UserCallWinProcCheckWow@32()  - 0xddcf bytes	
user32.dll!_DispatchClientMessage@20()  + 0x4b bytes	
user32.dll!___fnDWORD@4()  + 0x24 bytes	
ntdll.dll!_KiUserCallbackDispatcher@12()  + 0x2e bytes	
user32.dll!_NtUserMessageCall@28()  + 0xc bytes	
user32.dll!_RealDefWindowProcWorker@20()  - 0x79d6 bytes	
user32.dll!_RealDefWindowProcW@16()  + 0x27 bytes	
uxtheme.dll!DoMsgDefault()  + 0x29 bytes	
uxtheme.dll!OnDwpNcLButtonDown()  + 0x32 bytes	
uxtheme.dll!_ThemeDefWindowProc()  + 0x61a8 bytes	
uxtheme.dll!_ThemeDefWindowProcW@16()  + 0x18 bytes	
user32.dll!_DefWindowProcW@16()  + 0x815 bytes	
Tutorial02.exe!D3DWindow::WndProc(unsigned int uMsg=161, unsigned int wParam=2, long lParam=5636612)  Line 227 + 0x1b bytes	C++
Tutorial02.exe!D3DWindow::StaticWndProc(HWND__ * hWnd=0x000a06fa, unsigned int uMsg=161, unsigned int wParam=2, long lParam=5636612)  Line 169 + 0x1a bytes	C++
user32.dll!_InternalCallWinProc@20()  + 0x23 bytes	
user32.dll!_UserCallWinProcCheckWow@32()  + 0xb3 bytes	
user32.dll!_DispatchMessageWorker@8()  + 0xe6 bytes	
user32.dll!_DispatchMessageW@4()  + 0xf bytes	
Tutorial02.exe!WinMain(HINSTANCE__ * hInstance=0x009f0000, HINSTANCE__ * __formal=0x00000000, HINSTANCE__ * __formal=0x00000000, HINSTANCE__ * __formal=0x00000000)  Line 22 + 0xf bytes	C++
Tutorial02.exe!__tmainCRTStartup()  Line 578 + 0x35 bytes	C
Tutorial02.exe!WinMainCRTStartup()  Line 403	C
kernel32.dll!@BaseThreadInitThunk@12()  + 0x12 bytes	
ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes	
ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes	

Obviously returning 0 from WM_NCLBUTTONDOWN doesn't cause WM_SYSCOMMAND to be sent, and no delay, but it also prevents the window from being moved. So, does anyone know what's going on here and if there's any way of stopping it? Cheers, Steve

Share this post


Link to post
Share on other sites
Advertisement
How complex are your renders and what kind of delay are you putting on your timer? If you have a relatively simple render and a relatively low update frequency, then you might want to just start the timer up when the window is created and let it run.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
How complex are your renders and what kind of delay are you putting on your timer? If you have a relatively simple render and a relatively low update frequency, then you might want to just start the timer up when the window is created and let it run.
Currently the render is very basic (A single triangle), and the timer is set to 0ms, so just "as fast as possible".

However, this is for a tutorial / article on D3D rendering, and I'd like to do things as "correctly" as possible, even if it means leaving the 500ms lag.

Also, this is D3D (In case that's not obvious from the call stack function names [smile]), so running rendering in another thread is out of the question.

EDIT: And I'm curious about what exactly is going on under the hood here.

[Edited by - Evil Steve on January 14, 2009 3:33:36 PM]

Share this post


Link to post
Share on other sites
What kind of stall are you referring to? To my knowledge the window will NEVER update while it's being dragged. Your program will keep executing though. Have you considered throwing your timer code into the main loop instead of relying on your window procedure? I recommend QueryPerformanceCounter() if you do. 64-bit calculations... Nummy. Also, what is your definition of "correctly?"

Share this post


Link to post
Share on other sites
There are some other things that cause about a 500ms stall, such as grabbing a window title bar. In fact, now that I think about it, grabbing a window title bar causes WM_SYSCOMMAND with a wparam value of 0xf012 which is in fact (SC_MOVE + HTCAPTION).

EDIT: You may find Spy++ will give you useful information about what messages are occuring. To me it is worlds easier than a call stack for windows message monitoring.

Share this post


Link to post
Share on other sites
This is a guess, but I'm thinking DefWindowProc is waiting to see whether you're about to double-click or not. Try setting your double-click delay really slow or really fast to see if that affects things.

If that's the case, then there's probably not a lot you can do about it (but maybe make a note in your tutorial or something [smile]).

Share this post


Link to post
Share on other sites
Thanks for the replies.

Quote:
Original post by kittycat768
What kind of stall are you referring to? To my knowledge the window will NEVER update while it's being dragged. Your program will keep executing though. Have you considered throwing your timer code into the main loop instead of relying on your window procedure? I recommend QueryPerformanceCounter() if you do. 64-bit calculations... Nummy. Also, what is your definition of "correctly?"
For the stall, DefWindowProc doesn't return for over 500ms. It's as if it's an extremely expensive function call. Putting a timer in the main loop wouldn't help, and for now GetTickCount() is accurate enough (You don't need to render at full speed when the user is moving the window).
My definition of "correctly" is to render in the main loop, not from a timer handler - the timer handler isn't called all that frequently as far as I'm aware.

Quote:
Original post by lordikon
There are some other things that cause about a 500ms stall, such as grabbing a window title bar. In fact, now that I think about it, grabbing a window title bar causes WM_SYSCOMMAND with a wparam value of 0xf012 which is in fact (SC_MOVE + HTCAPTION).

EDIT: You may find Spy++ will give you useful information about what messages are occuring. To me it is worlds easier than a call stack for windows message monitoring.
Ah, I didn't notice that the wParam can include HTCAPTION, thanks. It's the WM_SYSCOMMAND handling in DefWindowProc that causes the 500ms stall - that's what I'm trying to fix or work around.

Quote:
Original post by Codeka
This is a guess, but I'm thinking DefWindowProc is waiting to see whether you're about to double-click or not. Try setting your double-click delay really slow or really fast to see if that affects things.

If that's the case, then there's probably not a lot you can do about it (but maybe make a note in your tutorial or something [smile]).
I don't think that's it, I always have my double click delay set to as fast as possible, and that should be less than 500ms. I'll give that a try when I get a chance though.

Cheers,
Steve

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
My definition of "correctly" is to render in the main loop, not from a timer handler - the timer handler isn't called all that frequently as far as I'm aware.

You could try starting a timer at window creation and calling InvalidateRect() in the timer handler, which will cause WM_PAINT messages to be generated even when your window is being dragged.

Share this post


Link to post
Share on other sites
Could this be because you've got a Direct3d device open inside the window?

Does that stall also happen without D3D? It might be because you're actually losing the device.

If it is because of D3D, could it be the debug runtimes?

Share this post


Link to post
Share on other sites
Quote:
Original post by Codeka
This is a guess, but I'm thinking DefWindowProc is waiting to see whether you're about to double-click or not. Try setting your double-click delay really slow or really fast to see if that affects things.
Setting my double click speed to extremely slow still takes the same time for DefWindowProc to return, so that doesn't seem to be related.

Quote:
Original post by SiCrane
You could try starting a timer at window creation and calling InvalidateRect() in the timer handler, which will cause WM_PAINT messages to be generated even when your window is being dragged.
Hmm, it's possible - but still seems a bit ugly to me. This is beginning to look like the only option though...

Quote:
Original post by Endurion
Could this be because you've got a Direct3d device open inside the window?
Disabling D3D completely (Commenting out any reference to any D3D interface) still yields the same problem.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!