And finnal one last feature to the applcation. I will show how to save the image as a .bmp file.
First a new menu item is added, when it is selected a new OnSaveBmp function will be called, se the final source for details.
First we ask the user for a destination filename, as usual:
void OnSaveBmp() { static char Filter[] = "bmp (*.bmp)\0*.bmp\0All (*.*)\0*.*\0"; OPENFILENAME OpenFilename; memset(&OpenFilename, 0, sizeof(OpenFilename)); OpenFilename.lStructSize = sizeof(OpenFilename); OpenFilename.hwndOwner = MainWindow; OpenFilename.hInstance = InstanceHandle; OpenFilename.lpstrFilter = Filter; OpenFilename.lpstrFile = CurrentFileName; OpenFilename.nMaxFile = sizeof(CurrentFileName); OpenFilename.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; OpenFilename.lpstrDefExt = "bmp"; if(GetSaveFileName(&OpenFilename)) { std::ofstream File(CurrentFileName); if(File) {Then we get a Device Context, and from this dc we create a Memory Device Context:
HDC DC = GetDC(MainWindow); HDC MemDc = CreateCompatibleDC(dc);Then we must get the dimension of the client area of our application:
RECT Rect; GetClientRect(MainWindow, &Rect); LONG Width = Rect.right - Rect.left; LONG Height = Rect.bottom - Rect.top;Now we will create the bitmap, based on this size, select it into the memory dc and fill it with white:
HBITMAP Bitmap = CreateCompatibleBitmap(dc, Width, Height); HGDIOBJ OldBitmap = SelectObject(MemDc, Bitmap); HBRUSH Brush = CreateSolidBrush(RGB(255, 255, 255)); FillRect(MemDc, &Rect, Brush);There is one problem, the area occupied by the toolbar and the status bar is included in the client are. So we have to get the height of these:
RECT Temp; GetWindowRect(ToolBarWindow, &Temp); LONG ToolBarHeight = Temp.bottom - Temp.top; GetWindowRect(StatusBarWindow, &Temp); LONG StatusBarHeight = Temp.bottom - Temp.top;Now we will offset the origin of the memory context device by the height of the statusbar, to make the objects Draw functions draw at the right spot:
SetViewportOrgEx(MemDc, 0, -ToolBarHeight, 0);And now the usual drawing:
size_t i; for(i = 0; i < Objects.size(); i++) Objects[i]->Draw(MemDc);Next we will increase the height by the height of the toolbar and status bar, to get the real size of the image:
Height -= StatusBarHeight + ToolBarHeight;And get various information for the bitmap, here mainly the number of bits per pixel:
BITMAP Bm; GetObject(Bitmap, sizeof(Bm), &Bm);Now we has the informations needed to start writing the file. First a header:
BITMAPINFOHEADER Header = WriteHeader(File, Width, Height, Bm.bmBitsPixel);You can see the WriteHeader function in the source, its a rather voluminous function which just writes a standard bitmap header to the file.
Then we allocate space for the bitmap data itself, gets the data, and writes them to the file:
char *Buffer = new char [Width*Height*Bm.bmBitsPixel/8]; GetDIBits(MemDc, Bitmap, 0, Height, Buffer, (BITMAPINFO *)&Header, DIB_RGB_COLORS); File.write(Buffer, Height*Width*Bm.bmBitsPixel/8);And with a bit cleanup, we are done:
delete [] Buffer; SelectObject(MemDc, OldBitmap); DeleteDC(MemDc); DeleteDC(dc); DeleteObject(Brush); DeleteObject(Bitmap);The complete code for the application can be found here