Thursday, January 26, 2006

double buffering

Now, for something completely different (i.e. NOT lisp). I'm working on a new mini installer, and wanted to create a small ~200KB stand-alone executable that could be quickly downloaded, and then used to download and install the application itself. For windows, if you want to be small, portable and pretty, you are basically talking about some hard-core Win32 GDI hacking. No GDI+, no MFC, and certainly no .NET WinForms.

To make things look good, everthing is pretty much painted by hand. This means I have to deal with issues of flickering, and the way to do that is through double-buffering. In GID, you do that by creating a memory contect, and drawing into THAT context behind the scenes. When you are ready to show the results to the world, you then BitBlt the final image onto the screen.

hdc = BeginPaint(hWnd, &ps);

memDC = CreateCompatibleDC(hdc);
memBM = CreateCompatibleBitmap(hdc, 512, 316);
SelectObject(memDC, memBM);

Draw(memDC);
BitBlt(hdc, 0, 0, 512, 316, memDC, 0, 0, SRCCOPY);

DeleteObject(memBM);
DeleteObject(memDC);

EndPaint(hWnd, &ps);

Note, just creating a compatible DC is not enough. This creates a 1x1 drawing area. You actually have to select a bitmap INTO it to size it. You can imagine how long it took me to figure this little gem out. Also, note that you are not creating the compatible bitmap using the new memory device context, but using the screen dc because that is what you want your bitmap to be compatible with. Once you have your memory device context all set up, you can pass it to all of your drawing functions like it was the screen, and then you are ready to go, just copy it in one BitBlt. No more flicker.

0 Comments:

Post a Comment

<< Home