11.04.2014 Views

Advanced MFC Programming

Advanced MFC Programming

Advanced MFC Programming

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Chapter 11. Sample: Simple Paint<br />

Problems<br />

Now we have a very basic graphic editor. Before the editor becomes perfect, we still have a lot of<br />

things to do: we need to add new tools for drawing curves, rectangles, ellipses, and so on; also we need to<br />

support more bitmap formats, for example: 16-color DIB format, 24-bit DIB format. We can even add<br />

image processing commands to adjust color balance, brightness and contrast to make it like a commercial<br />

graphic editor.<br />

Besides these, there are still two problems remained to be solved. One is that after loading an image<br />

with this simple editor, if we switch to another graphic editor and load a colorful image then switch back,<br />

the color of the image contained in our editor may change. Another problem is the unpleasant flickering<br />

effect when we draw lines with the grid on.<br />

Message WM_PALETTECHANGED<br />

The first problem is caused by the change on the system palette. Because each application has its own<br />

logical palette, and the system has only one physical palette, obviously the system palette can not be<br />

occupied by only one application all the time. Since the operating system always tries to first satisfy the<br />

needs of the application that has the current focus, if we switch to another graphic editor and leave our<br />

editor working in the background, most entries of the system palette will be occupied by that application<br />

and very few entries are left for our application. In this case, the system palette represents the logical<br />

palette of another application rather than ours, so if we still keep the original logical-to-system palette<br />

mapping, most colors will not be implemented correctly. This situation remains unchanged until we realize<br />

the logical palette again, which will cause the logical palette to be mapped to the system palette.<br />

Under Windows, there is a message associated with system palette changing. When the system<br />

palette is mapped to certain logical palette and this causes its contents to change, a WM_PALETTECHANGED<br />

message will be sent out. All the applications that implement logical palette should handle this message and<br />

re-map the logical palette to the system palette whenever necessary to avoid color distortion.<br />

In the sample, whenever we draw the image in CGDIView::OnDraw(…), function CDC::<br />

RealizePalette() is always called to update the logical palette. So when receiving message<br />

WM_PALETTECHANGED, we can just update the client window to cause the palette to be mapped again.<br />

Usually message WM_PALETTECHANGED is handled in the mainframe window. This is because an<br />

application may have several views attached to a single document. By handing this message in the<br />

mainframe window, it is relatively easy to update all views. The following is the message handler<br />

CMainFarme::OnPaletteChanged(…) that is implemented in the sample for handling the above message:<br />

void CMainFrame::OnPaletteChanged(CWnd* pFocusWnd)<br />

{<br />

CFrameWnd::OnPaletteChanged(pFocusWnd);<br />

GetActiveDocument()->UpdateAllViews(NULL);<br />

}<br />

This function is quite simple. With the above implementation, the first problem is solved.<br />

Flickering<br />

The second problem will be present only if the grid is on. This is because the grid is drawn directly to<br />

the client window: whenever the image needs to be updated, we must first draw the bitmap, and this<br />

operation will erase the grid. The user will see a quick flickering effect when the grid appears again. If we<br />

keep on updating the client window, this flickering will become very frequent and the user will experience<br />

very unpleasant effect.<br />

We already know that one way to get rid of flickering is to prepare everything in the memory and<br />

output the final result in one stroke. This is somehow similar to that of drawing bitmap image with<br />

transparency (See Chapter 10). To solve the flickering problem, we can prepare a memory bitmap whose<br />

size is the same with the zoomed source image, before updating the client window, we can output<br />

everything (image + grid) to the memory bitmap, then copy the image from the memory bitmap to the<br />

client window.<br />

366

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!