On day4 we have the animated weird gradient. To do this we have a backbuffer to which we write the pixels of the gradient using the RenderWeirdGradient
function. And we put those pixels onto the screen using the StretchDIBits
function by giving it a HDC
.
However, this StretchDIBits
function is called twice (through Win32UpdateWindow
) for each iteration of the main loop we run. Once in the loop itself:
while(Running) { // -----snip----- HDC DeviceContext = GetDC(Window); // ----snip------ Win32UpdateWindow(DeviceContext, &ClientRect, 0, 0, WindowWidth, WindowHeight); // ----snip----- }
and once through the handler for WM_PAINT
:
case WM_PAINT: { HDC DeviceContext = BeginPaint(Window, &Paint); //-----snip---- Win32UpdateWindow(DeviceContext, &ClientRect, X, Y, Width, Height); //-----snip---- } break;
Since, it is getting called in the WM_PAINT
I tried removing it from the mainloop. And this led to nothing getting painted on the screen because no WM_PAINT
messages were coming unless I moved the window around.
So, then I tried removing the handler for WM_PAINT
. And this got me the gradient back. So, it appears that just calling the StretchDIBits
is somehow making windows send the WM_PAINT
messsage and the only thing we need to do inside the WM_PAINT
handler is call BeginPaint
and EndPaint
(I tried this and it works) or just leave it to the default handler.
So are we calling the StretchDIBits
function in the mainloop just to trigger the WM_PAINT
?
I also tried to trigger WM_PAINT
by other means:
Method: 1
UpdateWindow(Window); /* HDC DeviceContext = GetDC(Window); RECT ClientRect; GetClientRect(Window, &ClientRect); int WindowWidth = ClientRect.right - ClientRect.left; int WindowHeight = ClientRect.bottom - ClientRect.top; Win32UpdateWindow(DeviceContext, &ClientRect); ReleaseDC(Window, DeviceContext); */
Method: 2
/* HDC DeviceContext = GetDC(Window); RECT ClientRect; GetClientRect(Window, &ClientRect); int WindowWidth = ClientRect.right - ClientRect.left; int WindowHeight = ClientRect.bottom - ClientRect.top; Win32UpdateWindow(DeviceContext, &ClientRect); ReleaseDC(Window, DeviceContext); */ RECT ClientRect; GetClientRect(Window, &ClientRect); InvalidateRect( Window, &ClientRect, false );
I found that UpdateWindow
does not do the job while InvalidateRect
does it with the last parameter set to either true
or false
. So based on this, I feel we are doing a wasteful copy of the buffer into windows's memory? And why does the UpdateWindow
not work? The docs say that UpdateWindow
will send WM_PAINT
to the window directly but my breakpoint on WM_PAINT
never trips even though UpdateWindow
is tripping with each iteration.