2
votes

I'm working on a project translating old Windows 95 MFC code into C++11 using Cairo. Since I'm not familiar with MFC, I'm getting confused about the different coordinate spaces for drawing in the original program, and it's difficult finding information and examples explaining these functions.

So here's what I'm seeing. In the code, it seems that at one point there is a new CDC device context that is being created using CreateCompatibleDC. A bitmap object is then subsequently created. This bitmap is then set to the new device context using the SelectObject function. From what I can glean, this is a DDB device dependent bitmap.

For example:

    bmp_dc = new CDC();
    bmp_dc->CreateCompatibleDC(NULL);

    int num_bits_per_pixel = bmp_dc->GetDeviceCaps(NUMBITSPIXEL);
    int num_planes = bmp_dc->GetDeviceCaps(NUMPLANES);
    c_bmp = new CBitmap();
    c_bmp->CreateBitmap(width, height,num_planes,num_bits_per_pixel,NULL);

    bmp_dc->SelectObject(c_bmp);

This new device context then gets passed around to a number of classes that perform drawing operations using it (bmp_dc->MoveTo(), LineTo, Ellipse, etc.). My question is, are all these drawing operations that use that device context getting draw directly into the bitmap, and not onto the display screen? And, do they assume that the bitmap top-left corner is the origin when drawing?

I noticed that there's a number of BitBlt function calls that happen later, and I think they're drawing the bitmap out onto the actual display screen using the display screens coordinates. But I'm really not sure, and was hoping for some clarification. Thanks!

1

1 Answers

2
votes

It sounds like you understood perfectly!

The code uses CreateCompatibleDC to create a memory DC that is the same format as the physical display (it passes NULL as the argument, which means use the dektop DC). Then, to draw to a bitmap, it is necessary to select the bitmap into the memory DC using SelectObject, as you said.

Then any drawing to the DC is actually drawing to the bitmap "inside" the memory DC.

Finally, BitBlt can display the bitmap contents (from the memory DC) to the display device. This is a classic implementation of double-buffered drawing to avoid flickering during display.

The drawing commands all use the same coordinate system - the top left is the (0,0) origin.

Is there anything happening that contradicts this? If so, perhaps you can post some more code.