I have a window created with the WS_EX_LAYERED
window style. I am currently drawing onto a memory bitmap using GDI+, and using UpdateLayeredWindow
to update the graphical content of my layered window. I intend to use this window as the main window of my application, which would require it to redraw frequently.
Seeing as layered windows do not receive the WM_PAINT
windows message [?] , I need to come up with an appropriate method for re-drawing the window. Optimisation is not essential , but it's always nice to have your cake and eat it too. Therefore, I am in search of the "correct" method to use.
Here are my thoughts so far:
I would guess that it's a good idea to render onto an off-screen bitmap before BitBlt
ing or similar.
60 frames rendered per second should be (more than?) enough (but how does this compare to other applications' frame rates?).
Possible solutions:
Use SetTimer
to send the WM_TIMER
message on a regular basis.
Useful because through specifying the time-out value, I can achieve my desired frames per second, without the requirement to measure the duration a "frame" takes to be rendered.
Would likely cause input or other lags due to the frequency and speed of the messages.
Render frames only when particular events occur, such as a window resize.
Would require me to figure out all events that would require a redraw.
Would greatly reduce the amount of unnecessary frames being rendered.
Render frames when there are no messages in the message queue, by checking PeekMessage
.
This might slow down the processing of window messages.
This will cause a high CPU usage because more frames than necessary are being processed.
Create a new thread to perform the render loop.
Layered windows don't receive WM_PAINT
messages that would otherwise be generated after window visibility changed, but it won't prevent them to receive this message at all.
You can continue to use InvalidateRect
to change window update region, wait for WM_PAINT
in you window procedure, draw contents in bitmap and call UpdateLayeredWindow
to change window contents. You can use this method to request redraw when content of window changes, for example, when button was pressed, or window has been resized (or activated/deactivated).
It shouldn't be so complicated, this is the pseudo code for you message loop:
while (true)
{
// GetMessages
while (PeekMessage(&msg, hWnd, 0, 0, PM_NOREMOVE))
{
if (!GetMessage(&msg, hWnd, 0, 0 ))
{
// Need to handle WM_QUIT
...
break;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
}
// Check if we need to draw
if (TimeForANewFrameHasCome() ||
IfWeNeedToDrawAfterInputOrInvalidate() ||
AnyOtherCaseThatCausesAnUpdate())
{
// Render
UpdateMemoryDCOrBitmap(...);
// Display it
UpdateLayeredWindow(...);
}
// May sleep a while
// Either Sleep(20); or better MsgWaitForMultipleObjects, that makes it possible
// to wake up upon an Event too...
MsgWaitForMultipleObjects(...);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.