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.

Tuesday, January 24, 2006

custom setf forms

Norvig presents several ways of creating custom setf forms, but none of them as elegant as Grahams:

(defun get-route (id table)
...)

(defun (setf get-route) (rt id table)
...)

The other options are something like the macro defsetf, or even more complicated beasts. I ran across the above need in code I was writing, and happened to be reading Norvig. He shows the ugly (to my mind) way of doing it, and I had to pull out my ANSI Common Lisp by Graham to find the pattern that had been tickling the back of my head.

There is an annoying downside to the setf form in something like our routing table when it comes to testing. Our routes are objects with several properties, including id, address, proximity, etc. I have a convenience function called make-random-route, that generates a route for me with all the slots, um well randomized (I'm figure you could have guessed that). Previously, I could insert a test route with (insert-route (make-random-route)). I wanted to use the setf form, since that seemed to follow lisp conventions better. This means that to do the same means

(let ((rt (make-random-route))
(setf (get-route (id rt)) rt))

Practically speaking, in the real world, we would be creating a route object before we would ever consider inserting it, so the let form is not really an additional burden. I just happened to run into it because of the testing.

Monday, January 23, 2006

apply'ing a list

I was wanting to create a convenience function for a class, and wanted to pass along &key parameters to the make-instance function. I couldn't figure out how to use a &rest argument, which puts everything in a list, and I need to get the keywords. My first pass was to use a macro:

(defmacro make-routing-table (&rest args)
`(make-instance 'routing-table ,@args))

worked, but ugly... much better is:

(defun make-routing-table (&rest args)
(apply #'make-instance 'routing-table args))

this from norvig.