HomeC&C++WainTutorialsSamplesTip&TrickTools


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