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