Size/move loop and delay in DefWindowProc

Started by
20 comments, last by MicroVirus 12 years, 12 months ago
It's down to a 500ms wait on an event when there are no mouse, keyboard, or sync messages in the queue. The event seems to be signalled when there are input messages available. There's also lots of resource locking which is mostly block-until-available so 500ms would be a lower bound to the stall. Lots of calls to user mode as well for hooking purposes so there's a few context switches to account for too.

The "highlights" from WM_SYSCOMMAND to WM_MOVING:
xxxSysCommand-    Calls some hook back in UM    xxxIsDragging-	  GetKeyState(VK_LBUTTON)-		Just checks some bits, nothing heavy	  Sets mouse capture to window-		Locks and unlocks the window		Checks if the thread's impersonation token or the process token is restricted		Checks user has WINSTA_WRITEATTRIBUTES permission on the Window Station	  xxxInternalGetMessage (..., WM_MOUSEFIRST, WM_XBUTTONDBLCLK..)-if any mouse action		Calls mouse hooks -> back to UM		Removes WM_LBUTTONUP from Queue		Calls mouse hooks again -> back to UM		seems it loops around couple of timesotherwise	  	Exits without doing anything of note	  xxxInternalGetMessage(..., WM_QUEUESYNC, WM_QUEUESYNC)	  if no message-	  xxxInternalGetMessage(..., WM_KEYFIRST, WM_KEYLAST)	  if no message-	  xxxSleepThread(7, 500, 1)		KeClearEvent()		KeWaitForSingleObject(ClearedEvent, -500ms) // seems to be for inputend if	  Releases mouse capture on window-	  	Locks and unlocks the window again	  	Puts WM_MOUSEMOVE in message queue	  	Calls window proc with WM_CAPTURECHANGED (0x0215)        returns whether the message x/y pos was within a specified rect (if there was a message)if dragging    xxxSetWindowPos(PWND, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) -	  BeginDeferWindowPos(1)	  DeferWindowPos()	  EndDeferWindowPosEx()		Z-Order checking stuff for a few windows		Call app WndProc with WM_WINDOWPOSCHANGING		Updates the previous top most window if there was one		Locks screen and blits the valid bits		Unlocks the screen		Sends any WM_WINDOWPOSCHANGED messages		returns          not checked beyond here for this case	  returnsend if     xxxMoveSize-	   Clips cursor to area	   Call app WndProc with WM_GETMINMAXINFO	   Draw the drag rectange-		SetWindowPos(PVOID, 0, x, y, width, height, (SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOZORDER))-			Locks screen and blits the valid bits to the new pos			Unlocks the screen		Updates relevant Windows	   Fakes a mouse move	   Call app WndProc with WM_ENTERSIZEMOVE	   Locks Capture Window	   Show Cursor	   GetMessage(wnd, no filter)-		Scan's system queue for all messages-		   GetNextSysMessage-			WM_MOUSEMOVE posted (prob due to fake move above)		Mouse hooks called		WM_MOUSEMOVE consumed (deleted from queue)		Hooks called again		Updates drag rect-			Calls WndProc with WM_MOVING			Redraws the rect		Wait for messages
Advertisement
Hello all,

I know this is a very late reply but I felt I might be able to help people searching for answers to this question by adding some information.
What happens in the 'stall' is that DefWindowProc takes over complete control. You enter DefWindowProc and it doesn't return until the move is completed.
During that time, DefWindowProc will send a lot of WM_* messages to your own window procedure (including move updates), one important one being WM_PAINT (and I'm guessing only if your system settings are such that the windows are drawn during move and resize operations). So, you can draw and therefore update your window during the stalls by responding to WM_PAINT with a scene draw.
The bad news is that all your regular game code, starting with your message pump and ending with the normal process & draw loops, don't get called during the entire operation.
Testing with a couple of other applications, I think I may have found the one compelling reason for applications to supply their own customised title bar with system menu: so as to avoid DefWindowProc hanging on non-client messages (NC_* window messages).
It seems then that the solution is either to remove all the non-client regions from your window (by setting the appropriate window styles) and implementing your own move/resize and title bar.
Or, you somehow use multi-threading to keep the core going and the window updated; somehow having your gui be pretty much a stub thread while the 'real' thread does all the work (not sure how easy this is to do...).

Hopefully, this can still help someone.
Best Regards,
MicroVirus

This topic is closed to new replies.

Advertisement