Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ Threading Message
Hello to everybody,
 
I have an application that show video images but sometimes stop paint frames.
After experienced this problem I did some debug with spy++ and found that windows messages don't come to my window therefore it doesn't repaint, unless I go with mousepointer on the window and in this case messages come.
This behaviour happen on exe release and debug also.
System is intel i7 8 cores and cpu is not really loaded 50-60% max, sometimes less and I have the feel that the problem is not correlated to the cpu because sometimes I've seen the problem happen just with 15% cpu load.
Did anyone experience problem like this and have any idea how can I face it?
thank you.
 
ADDED INFO AND QUESTION
 
I need receive WM_PAINT message regularly, how can I force to regularly retrieve this message from the queue?
Posted 25-Apr-12 23:39pm
Edited 26-Apr-12 3:50am
v3
Comments
Richard MacCutchan at 26-Apr-12 4:53am
   
This has nothing to do with hardware. Windows messages are posted by the Windows OS to the active window, so you need to investigate why your program is not considered active at some point.
druscelli at 26-Apr-12 9:51am
   
but I think I should receive WM_PAINT messages also if the app is not active, isn't it?
Richard MacCutchan at 26-Apr-12 10:42am
   
It depends. Under some circumstances the WM_PAINT messages are queued in the system and then one message is sent instead of all the ones in the queue. This often happens if the program is busy performing other functions or if the system is handling other issues.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

If windows doesn't know that your window needs to be repainted, then it won't send a WM_PAINT message.
 
This isn't a message that you should use to drive animation. You can't depend on Windows guessing when you'll need it.
 
You have two options that you may try for this scenario.
 
Use the WM_TIMER Message to call Invalidate(FALSE); This will force a WM_PAINT message.
 
Or turn the OnPaint function into an empty call for normal drawing and do your painting in a background thread at a regular interval. If you do this, do not mix the two. If your background thread and the the OnPaint are drawing at the same time, bad things will happen.
  Permalink  
Comments
druscelli at 27-Apr-12 10:45am
   
unserstand. I already call invalidate at the end of my frame callback, just when I need to draw and it should be enough to receive the WM_PAINT message, but I analysed the problem furhter. With small number of frames (less than 300) everything work fine, when I need to play more cameras and have more than 300 frames to redraw don't know why but when they are too many they are not dispatched correctly to my object. Note: I have a main window and some childs in a multimonitor app. When this happen in the active window they are dispatched (the messages) but in the no active window some objects stop receive WM_PAINT and frames are not redrawed.
Use WM_TIMER I think is not suitable because it is a low priority message and windows does not guarantee it will be dispatched, I think with WM_TIMER the problem would be bigger.
 
The last advice you give me sounds good, but I don't know how to implement it, I will think about and ask more info, in the while any suggest will be appreciate. thaNk you.
JackDingler at 27-Apr-12 13:01pm
   
By design, WM_PAINT is a low priority message too. When it arrives it's guaranteed to be the last message you get when the message queue is emptied. What you may be seeing is that the message queue isn't empty before you expect to draw again.
 
If you really want this to be responsive, you'll have to draw with background threads.
 
Further, you'll want to make sure you're avoiding using GDI calls for performance reasons. On Vista and Windows 7, the GDI has been moved from the kernel / device layers to the application layer, resulting in a huge hit in performance. This will effect common painting operations like bitblt().
 
OpengGL or DirectX should work, and possibly the WPF Framework, though I have no experience using that to draw in a background thread.
JackDingler at 27-Apr-12 13:03pm
   
For the person who gave me four stars, what could I do to improve this answer?
druscelli at 2-May-12 4:46am
   
I moved the draw code to a new my own generated message: WM_DRAWFRAME. I still use old architecture normally but also use new message in certain conditions for garantee at least a certain number of redraws. I will evaluate to use an external thread or directx.
 
thanks to everybody
druscelli at 2-May-12 6:30am
   
5 stars given
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

I had problems with WM_TIMER messages not coming to window. Maybe it is not the same. I solved it by using PeekMessage instead of GetMessage function. If PeekMessage does not work, then it means the message is not posted in your message queue. In this case you have to do redraw on timer, or invalidate the window rect.
By using Spy++ you don't see the message queue. You see only messages which are already dispatched to the window.
  Permalink  
Comments
druscelli at 26-Apr-12 8:46am
   
I had too a similar problem to armagedescu with WM_TIMER, because WM_TIMER is a loww priority message and I used different message for my porpuse in that context.
But now I don't receive messages as WM_PAINT so I don't redraw the window. I think WM_PAINT should not affect low pripority issue as WM_TIMER, so my problem is not in the priority of message.
armagedescu at 26-Apr-12 9:03am
   
When in program something happened, and window have to be updated you need to call InvalidateRect. You may pass FALSE to erase, to avoid flickering. And call UpdateWindow in order to have WM_PAINT message passed.
armagedescu at 26-Apr-12 9:09am
   
And yes, you may call directly UpdateWindow, without InvalidateRect. WM_PAINT most likely to be passed. But you may still need InvalidateRect if you use painting PAINTSTRUCT from the BeginPaint.
druscelli at 26-Apr-12 9:46am
   
I tryed to use updatewindow at the end of any wm_paint execution in order to force the next paint but nothing change, same issue. With invalidaterect the problem is more evident.
armagedescu at 26-Apr-12 11:04am
   
The key is not to do InvalidateRect/UpdateWindow on WM_PAINT. On WM_PAINT you only have to paint current img/bitmap in the window, nothing more. But updating the image have to be done on some kind of WM_TIME'd manner. After ending of updating current frame of video content and call InvalidateRect/UpdateWindow. As result you will handle WM_PAINT and will update the window contend with the image/bitmap of current video frame.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

The lower CPU usage seems just the result, but not the reason. Could you give more details about this issue, such as what message you need to handle window update, and what happened when the program stop working.
 
You could see more debugging technique with a book named Why Programs Fail.
 
To Richard, it seems that not all type messages need the target window is actived. And in my experience, the program could still work even through the window is not actived.
  Permalink  
Comments
druscelli at 26-Apr-12 8:52am
   
I need receive WM_PAINT message regularly, how can I force to regularly retrieve this message from the queue?
 
note: the program does not stop working, just my window doesn't receive messages so it's unrefreshed.
armagedescu at 4-Jul-12 5:15am
   
Sometimes messages are still in the queue, but there are other higher priority messages. So, sometimes it might never get processed. In this case need to call PeekMessage to take your message. And processing of WM_PAINT is not the place to generate other WM_PAINT. WM_PAINT must only reflect current data or state change. For instance frame changed, or recover of picture after being covered by other window. Logically this message itself must not generate other WM_PAINT.
Updating video in the frame is a timed process, which have to be linked to WM_TIME. Here you have to compute the image, not in WM_PAINT. After that you can notify window to repaint.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Advertise | Privacy | Mobile
Web01 | 2.8.1411022.1 | Last Updated 26 Apr 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100