C Board  

Go Back   C Board > Platform Specific Boards > Windows Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 03-23-2006, 06:31 AM   #1
Registered User
 
eth0's Avatar
 
Join Date: Dec 2003
Posts: 164
drawing on bitmaps

Hi all.

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   Reply With Quote
Old 03-23-2006, 11:27 AM   #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) ;
You don't need to select the bitmap into the window DC in your WM_MOUSEMOVE handler, it'll already be visible thanks to WM_PAINT. All you want it to do is draw your lines, by doing them to hdcMem at the same time with your bitmap selected, the changes will be "saved".

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   Reply With Quote
Old 03-24-2006, 05:56 PM   #3
Registered User
 
eth0's Avatar
 
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   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

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


All times are GMT -6. The time now is 03:35 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22