Archived

This topic is now archived and is closed to further replies.

Outcast

To or To Not use WM_PAINT

Recommended Posts

I was reading through the DirectX device initialization example, and in this simple example, they place their render code in the WM_PAINT message. However, in the BSP tutorial I''m reading, they forgo the WM_PAINT, and simply render after they process any messages they''ve received. Is there a disadvantage to just sticking with convention and using WM_PAINT? Does it get called less often, or is their the possibility that it could be stalled by previous message events? The tutorial author does many things in his code that I don''t agree with stylistically, so I''m not sure if this is a stylistic difference or something done for speed. Outcast

Share this post


Link to post
Share on other sites
The problem with putting your code in WM_PAINT is that the code will only execute if Windows thinks the window needs repainting and posts a WM_PAINT message.

I check if there are any messages, if there are process them if not I go to Game_Main and do the rendering stuff(and other things you need to do each frame).

Share this post


Link to post
Share on other sites
You probably shouldn''t place your rendering code inside the WM_PAINT message. The WM_PAINT message is only used like the above poster said to redraw the window when it has been minimized, maximized, or another window is on top of it and things of that sort. Me personally, I have my game loop after all the windows messages have been processed and I let windows handle its own WM_PAINT message, although depending on how your doing the drawing, you might have to add a line in the WM_PAINT message handler to present your scene when it gets called. This isn''t even an issue in full screen, so if you are using a full screen app you don''t have to worry about wm_paint at all.

Evillive2
E-Mail

Share this post


Link to post
Share on other sites
You could render both in WM_PAINT and in the post-message loop. This would avoid ugly screen flashing on updates. Also, it makes sense if you can pause the game and/or use windowed mode; if you dont'' update/render when paused, the machine is free for the user to use for other things. Meanwhile, painting in WM_PAINT means that the image will still be in the window, avoiding uglyness.

Thus: call your painting function BOTH from WM_PAINT and from the post-message-processing-and-update code. Just don''t rely on WM_PAINT alone for things that need high frame rate.

Share this post


Link to post
Share on other sites
Donavan,

While the technique you describe in the linked post is interesting and I applaude your ingenuity, there is no way I would use that in production code.

I would be concerned that the behavior you''re relying on could change as a result of a patch or service pack and all of a sudden my app is broken (or worse, I get random reports of odd drawing behavior or performance problems from users who can''t provide a reliable repro).

Share this post


Link to post
Share on other sites
Sure, that''s a valid concern. However I believe it''s all documented. Let''s make sure...

BeginPaint is documented as validating the entire client area (see ValidateRect), as is DefWindowProc. And you shouldn''t call DefWindowProc if you''re handling the message -- it validates because the app is basically saying "I''m not going to handle this message."

The behavior of WM_PAINT being sent only when there are no queued messages is documented on the WM_PAINT and GetMessage pages. It stands to implication then that if the window is never validated, you''ll receive a continuous stream of WM_PAINT messages, interrupted only by queued messages as and when they arrive.

Like I say, it''s essentially the same as invalidating the window after painting it. If that feels safer, you can always take that approach.

One thing to beware of, whether you do it this way or by avoiding BeginPaint/EndPaint, is that WM_TIMER messages are handled similarly to WM_PAINT -- they''re not queued, they''re generated by GetMessage whenever the queue is empty. (See the docs for GetMessage.) Since they''re behind WM_PAINT in priority, you''ll never see one. I''ve seen this come up for people who accidentally failed to call BeginPaint/EndPaint and then wonder why their timer doesn''t seem to work. Of course you can always SetTimer with a callback instead.

The PeekMessage approach has what you may or may not consider a problem, namely that when the window is being dragged or a menu is open, the message pumping is halted while the app enters a modal message loop -- and the game freezes. However WM_PAINT messages are still delivered to your WNDPROC. So as hplus0603 said, if you use PeekMessage, it''s still a good idea to handle WM_PAINT.

Share this post


Link to post
Share on other sites
From what I''ve heard I like the idea of updating it both after message processing and in the WM_PAINT event. Once I started reading the posts, it did come back to me that WM_PAINT is only sent after all the messages in the queue have been processed, making it unreliable for keeping a consistent framerate.

I will look into your suggestion as well, Donavon. Even if I don''t use that method, it''s good to have a better understanding of how the system is working, and it looks like your trick is exploiting that fact. I''ve only briefly looked it over, so I can''t comment more than that.

Thanks for everyone''s help, hopefully someday I can return the favor to another newbie learning DX.

Outcast

Share this post


Link to post
Share on other sites
> WM_PAINT is only sent after all the messages in the queue have been processed, making it unreliable for keeping a consistent framerate.

Not really, not in my experience. It''s better to handle messages as soon as possible after they''re queued, and the time spend handling them tends to be a very small percentage of overall processing time. A good PeekMessage loop only proceeds with processing a new frame after *all* pending messages have been processed -- which is very nearly the same thing as what I''m describing. The point I''m making is that essentially the same thing can be accomplished in a simpler way.

A naieve approach, which I remember doing back before I had much understanding of how this stuff works, was to update and draw a frame after every message. IOW, at most one message would be processed per frame. This is not a good idea. It can create a backlog of messages and really bog your app down, particularly if it''s windowed. You go to drag the window and you might have to wait several seconds before it responds. If you''re using Windows messages for input, it can create a lot of lag between user input and when it''s actually visible on the screen.

The majority of the time you''ll won''t have any messages needing to be processed. At most you might have two or three. The key to a responsive app is to knock them out quickly and then get on with the game.

Share this post


Link to post
Share on other sites