![]() |
| | #1 |
| Registered User Join Date: Dec 2003
Posts: 164
| drawing on bitmaps I’ve been reading Petzold about DIB’s and been playing about with some ideas. One problem I’m having trouble with at the moment is drawing on the same bitmap where an image has been loaded. The code below (mostly pulled in from various parts of Petzolds book) loads a bitmap using a DIB section. Drawing on top of this bitmap with the cursor and then resizing the screen results in the sketch being erased on a repaint. How do I draw directly onto the memory set aside via the DIB section? Code: #include <windows.h>
#define IDM_FILE_OPEN 40001
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("DibSect") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("DIB Section Display"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
HBITMAP CreateDibSectionFromDibFile (PTSTR szFileName)
{
BITMAPFILEHEADER bmfh ;
BITMAPINFO * pbmi ;
BYTE * pBits ;
BOOL bSuccess ;
DWORD dwInfoSize, dwBytesRead ;
HANDLE hFile ;
HBITMAP hBitmap = NULL;
// Open the file: read access, prohibit write access
hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL) ;
if (hFile == INVALID_HANDLE_VALUE)
return NULL ;
// Read in the BITMAPFILEHEADER
bSuccess = ReadFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER),
&dwBytesRead, NULL) ;
if (!bSuccess || (dwBytesRead != sizeof (BITMAPFILEHEADER))
|| (bmfh.bfType != * (WORD *) "BM"))
{
CloseHandle (hFile) ;
return NULL ;
}
// Allocate memory for the BITMAPINFO structure & read it in
dwInfoSize = bmfh.bfOffBits - sizeof (BITMAPFILEHEADER) ;
pbmi = malloc (dwInfoSize) ;
bSuccess = ReadFile (hFile, pbmi, dwInfoSize, &dwBytesRead, NULL) ;
if (!bSuccess || (dwBytesRead != dwInfoSize))
{
free (pbmi) ;
CloseHandle (hFile) ;
return NULL ;
}
// Create the DIB Section
hBitmap = CreateDIBSection (NULL, pbmi, DIB_RGB_COLORS, (VOID *)&pBits, NULL, 0) ;
if (hBitmap == NULL)
{
free (pbmi) ;
CloseHandle (hFile) ;
return NULL ;
}
// Read in the bitmap bits
ReadFile (hFile, pBits, bmfh.bfSize - bmfh.bfOffBits, &dwBytesRead, NULL) ;
free (pbmi) ;
CloseHandle (hFile) ;
return hBitmap ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HBITMAP hBitmap;
static BOOL fLeftButtonDown, fRightButtonDown ;
static int cxClient, cyClient, xMouse, yMouse ;
static OPENFILENAME ofn ;
static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
static TCHAR szFilter[] = TEXT ("Bitmap Files (*.BMP)\0*.bmp\0")
TEXT ("All Files (*.*)\0*.*\0\0") ;
BITMAP bitmap ;
HDC hdc, hdcMem ;
PAINTSTRUCT ps ;
switch (message)
{
case WM_CREATE:
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof (OPENFILENAME) ;
ofn.hwndOwner = hwnd ;
ofn.lpstrFilter = szFilter ;
ofn.lpstrFile = szFileName ;
ofn.nMaxFile = MAX_PATH ;
ofn.lpstrFileTitle = szTitleName ;
ofn.nMaxFileTitle = MAX_PATH ;
ofn.lpstrDefExt = TEXT ("bmp") ;
return 0 ;
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDM_FILE_OPEN:
// Show the File Open dialog box
if (!GetOpenFileName (&ofn))
return 0 ;
// If there's an existing bitmap, delete it
if (hBitmap)
{
DeleteObject (hBitmap);
hBitmap = NULL ;
}
// Create the DIB Section from the DIB file
SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
ShowCursor (TRUE) ;
hBitmap = CreateDibSectionFromDibFile (szFileName) ;
ShowCursor (FALSE) ;
SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
// Invalidate the client area for later update
InvalidateRect (hwnd, NULL, TRUE) ;
if (hBitmap == NULL)
{
MessageBox (hwnd, TEXT ("Cannot load DIB file"),
szAppName, MB_OK | MB_ICONEXCLAMATION) ;
}
return 0 ;
}
break ;
case WM_LBUTTONDOWN:
if (!fRightButtonDown)
SetCapture (hwnd) ;
xMouse = LOWORD (lParam) ;
yMouse = HIWORD (lParam) ;
fLeftButtonDown = TRUE ;
return 0 ;
case WM_LBUTTONUP:
if (fLeftButtonDown)
SetCapture (NULL) ;
fLeftButtonDown = FALSE ;
return 0 ;
case WM_RBUTTONDOWN:
if (!fLeftButtonDown)
SetCapture (hwnd) ;
xMouse = LOWORD (lParam) ;
yMouse = HIWORD (lParam) ;
fRightButtonDown = TRUE ;
return 0 ;
case WM_RBUTTONUP:
if (fRightButtonDown)
SetCapture (NULL) ;
fRightButtonDown = FALSE ;
return 0 ;
case WM_MOUSEMOVE:
if (!fLeftButtonDown && !fRightButtonDown)
return 0 ;
hdc = GetDC (hwnd) ;
SelectObject (hdcMem, hBitmap);
SelectObject (hdc, hBitmap);
SelectObject (hdc,
GetStockObject (fLeftButtonDown ? BLACK_PEN : WHITE_PEN)) ;
SelectObject (hdcMem,
GetStockObject (fLeftButtonDown ? BLACK_PEN : WHITE_PEN)) ;
MoveToEx (hdc, xMouse, yMouse, NULL) ;
MoveToEx (hdcMem, xMouse, yMouse, NULL) ;
xMouse = (short) LOWORD (lParam) ;
yMouse = (short) HIWORD (lParam) ;
LineTo (hdc, xMouse, yMouse) ;
LineTo (hdcMem, xMouse, yMouse) ;
ReleaseDC (hwnd, hdc) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
if (hBitmap)
{
GetObject (hBitmap, sizeof (BITMAP), &bitmap) ;
hdcMem = CreateCompatibleDC (hdc) ;
SelectObject (hdcMem, hBitmap) ;
BitBlt (hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight,
hdcMem, 0, 0, SRCCOPY) ;
DeleteDC (hdcMem) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
if (hBitmap)
DeleteObject (hBitmap) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
Code: #define IDM_FILE_OPEN 40001
DIBSECT MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open", IDM_FILE_OPEN
END
END
__________________ Open source isn't a matter of life or death...... .......its much more important than that!! SuSE Linux - GCC 3.4.2 XP Pro - Visual Studio 2005 TS, MinGW 3.4.2 |
| eth0 is offline | |
| | #2 |
| Registered User Join Date: Aug 2001 Location: Newport, South Wales, UK
Posts: 1,094
| The first thing you've got to understand is that you can't select the same bitmap into more than one DC. Selecting into your memory DC and then the window's DC means that it's not in the memory DC anymore. Also, you should create your memory DC once, in your WM_CREATE handler, then delete it in WM_DESTROY (like your bitmap there). Forget about using GetObject to grab your bitmap's dimensions in WM_PAINT, they're not important. Instead use the update rectangle provided for you in PAINTSTRUCT by BeginPaint:- Code: BitBlt (ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, hdcMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY) ; P.S. Make sure that you keep the handle returned by SelectObject when you first select your bitmap into your memory DC! A 1x1 bitmap is created for every DC you created, select it back into the DC before you delete it to prevent memory leakage! Last edited by SMurf; 03-23-2006 at 11:29 AM. |
| SMurf is offline | |
| | #3 |
| Registered User Join Date: Dec 2003
Posts: 164
| Thanks for the clarification, all is working now
__________________ Open source isn't a matter of life or death...... .......its much more important than that!! SuSE Linux - GCC 3.4.2 XP Pro - Visual Studio 2005 TS, MinGW 3.4.2 |
| eth0 is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Drawing HBITMAP into CWnd, Acquired from "screenshot" | DeusAduro | Windows Programming | 6 | 07-02-2009 03:41 PM |
| Drawing bitmaps efficiently | scwizzo | Windows Programming | 28 | 06-30-2009 08:25 PM |
| DX9 Not Displaying Bitmaps | Sentral | Game Programming | 9 | 01-31-2006 05:35 AM |
| Interesting problem with bmp drawing | Victor | C++ Programming | 3 | 04-12-2005 10:39 AM |
| Drawing Bitmaps | filler_bunny | Windows Programming | 6 | 05-05-2004 04:32 PM |