Hej,
Jeg har skrevet dette lille tegneprogram, som tillader en at tegne streger i vinduets klientområde og derefter gemme billedet i en bmp-fil via menuen, men når jeg gemmer bitmap'et og forsøger at åbne det med Paint, siger Paint, det er ugyldigt.
Her er koden:
#include<windows.h>
#include<vector>
#include<fstream>
#define IDM_FILE_SAVE 101
typedef struct tagLINE
{
POINT pt1, pt2;
tagLINE(POINT _pt1, POINT _pt2) : pt1(_pt1), pt2(_pt2) { }
} LINE, *PLINE;
std::vector<LINE> _lines;
OPENFILENAME ofn; // Used in conjunction with SaveFileName function, not OpenFileName
TCHAR szFile[MAX_PATH];
TCHAR szTitle[MAX_PATH];
// GDI-resources
HBRUSH hbrBack;
HPEN hpLines;
VOID DrawLines(HDC);
VOID SaveFile();
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// Drawing-specific
static PAINTSTRUCT ps;
static HDC mem;
static HBITMAP canvas;
static RECT rcClient;
// Other structures
static POINT pt1;
static POINT pt2;
switch (uMsg)
{
case WM_CREATE:
// Load GDI-resources
hbrBack = (HBRUSH)GetStockObject(WHITE_BRUSH);
hpLines = CreatePen(PS_SOLID, 5, RGB(0, 64, 128));
// Denotes no line started
pt1.x = -1;
// Prepare SAVEFILENAME struct
ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
ofn.hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
ofn.hwndOwner = hwnd;
ofn.lpstrDefExt = TEXT("bmp");
ofn.lpstrFile = szFile;
ofn.lpstrFileTitle = szTitle;
ofn.lpstrFilter = TEXT("Bitmaps (*.bmp)\0*.bmp\0");
ofn.lpstrTitle = TEXT("Save bitmap");
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.nMaxFile = MAX_PATH;
ofn.nMaxFileTitle = MAX_PATH-10;
return 0;
case WM_SIZE:
GetClientRect(hwnd, &rcClient);
InvalidateRect(hwnd, NULL, FALSE);
return 0;
case WM_PAINT:
BeginPaint(hwnd, &ps);
mem = CreateCompatibleDC(ps.hdc);
canvas = CreateCompatibleBitmap(ps.hdc, rcClient.right, rcClient.bottom);
SelectObject(mem, canvas);
SelectObject(mem, hpLines);
FillRect(mem, &rcClient, hbrBack);
DrawLines(mem);
BitBlt(ps.hdc, 0, 0, rcClient.right, rcClient.bottom, mem, 0, 0, SRCCOPY);
DeleteObject(canvas);
DeleteDC(mem);
EndPaint(hwnd, &ps);
return 0;
case WM_MOUSEMOVE:
if (wParam & MK_LBUTTON)
{
int X = LOWORD(lParam);
int Y = HIWORD(lParam);
if (pt1.x == -1)
{
pt1.x = X;
pt1.y = Y;
return 0;
}
pt2.x = X;
pt2.y = Y;
_lines.push_back(*new LINE(pt1, pt2));
pt1.x = pt2.x;
pt1.y = pt2.y;
InvalidateRect(hwnd, NULL, FALSE);
}
return 0;
case WM_LBUTTONUP:
pt1.x = -1;
return 0;
case WM_COMMAND:
if (HIWORD(wParam) == 0) // Menu
{
switch (LOWORD(wParam))
{
case IDM_FILE_SAVE:
if (GetSaveFileName(&ofn))
SaveFile();
break;
}
}
return 0;
case WM_DESTROY:
DeleteObject(hbrBack);
DeleteObject(hpLines);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
LPCSTR lpszClass = TEXT("SaveBitmapApp");
WNDCLASS wc;
HWND hwnd;
MSG msg;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = lpszClass;
wc.lpszMenuName = NULL;
wc.style = 0;
RegisterClass(&wc);
hwnd = CreateWindow(lpszClass, TEXT("Bitmap Saver"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL,
hInstance, NULL);
// Create and apply a simple menu
HMENU hMenu = CreateMenu();
HMENU hFile = CreateMenu();
AppendMenu(hFile, MF_STRING, IDM_FILE_SAVE, TEXT("Save..."));
AppendMenu(hMenu, MF_POPUP, (UINT)hFile, TEXT("&File"));
SetMenu(hwnd, hMenu);
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
VOID DrawLines(HDC hdc)
{
// Draw lines
for (int i = 0; i < _lines.size(); ++i)
{
MoveToEx(hdc,
_lines[i].pt1.x,
_lines[i].pt1.y,
NULL);
LineTo(hdc,
_lines[i].pt2.x,
_lines[i].pt2.y);
}
}
VOID SaveFile()
{
static PAINTSTRUCT ps;
static HDC mem;
static HBITMAP canvas;
static RECT rcClient;
static HWND hwnd = ofn.hwndOwner;
static BITMAP bm;
static BITMAPFILEHEADER file;
static BITMAPINFOHEADER info;
static INT nWordsPerLine;
memset(&bm, 0, sizeof(BITMAP));
memset(&file, 0, sizeof(BITMAPFILEHEADER));
memset(&info, 0, sizeof(BITMAPINFOHEADER));
BeginPaint(hwnd, &ps);
mem = CreateCompatibleDC(ps.hdc);
canvas = CreateCompatibleBitmap(ps.hdc, rcClient.right, rcClient.bottom);
SelectObject(mem, canvas);
SelectObject(mem, hpLines);
FillRect(mem, &rcClient, hbrBack);
DrawLines(mem);
GetObject(canvas, sizeof(BITMAP), &bm);
nWordsPerLine = (bm.bmWidth*bm.bmBitsPixel+31)/32;
// Setup bitmap file header
file.bfOffBits = 0x36+8;
file.bfSize = sizeof(file) + sizeof(info) + 4*nWordsPerLine*bm.bmHeight;
file.bfType = 0x4D42; // 'BM' signature
// Setup bitmap info header
info.biBitCount = bm.bmBitsPixel;
info.biClrImportant = 0;
info.biClrUsed = 0;
info.biCompression = BI_RGB;
info.biHeight = bm.bmHeight;
info.biPlanes = 1;
info.biSize = sizeof(BITMAPINFOHEADER);
info.biSizeImage = 0;
info.biWidth = bm.bmWidth;
info.biXPelsPerMeter = 0;
info.biYPelsPerMeter = 0;
// Write header and info to file
std::ofstream os(szFile);
os.write((char*)&file, sizeof(file));
os.write((char*)&info, sizeof(info));
// Now write the bits
char* pBuffer = new char[bm.bmWidth*bm.bmHeight*bm.bmBitsPixel/8];
GetDIBits(mem, canvas, 0, bm.bmHeight, pBuffer, (BITMAPINFO*)&info, DIB_RGB_COLORS);
os.write(pBuffer, bm.bmWidth*bm.bmHeight*bm.bmBitsPixel/8);
// Close output stream and free resources
os.close();
DeleteObject(canvas);
DeleteDC(mem);
EndPaint(hwnd, &ps);
}
Hilsen Thomas