CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    Aug 2009
    Posts
    20

    Bitmaps cutting off

    I have a problem with bitmaps cutting off after being displayed. When another window moves over my program's window the bitmap is erased and the back of the window is visible.

    Here's a pic to show what I mean


    http://img23.imageshack.us/img23/1706/16493978.jpg


    And here's the code I use to load the bitmap
    Code:
    int LoadFile(int XDest, int YDest, char *FileName, HWND hWnd)
    {
    
     static BITMAPFILEHEADER *pbmfh;
     static BITMAPINFO *pbmi;
     static BYTE *pBits;
     static int cxDib, cyDib;
    
           DWORD dwFileSize, dwHighSize, dwBytesRead;
           HANDLE hFile;
    
           char *NameOfFile;
           NameOfFile = new char[50];
           NameOfFile = FileName;
    
           hFile = CreateFile (NameOfFile, GENERIC_READ,
           FILE_SHARE_READ, NULL,
           OPEN_EXISTING,
           FILE_FLAG_SEQUENTIAL_SCAN,
           NULL);
    
       dwFileSize = GetFileSize (hFile, &dwHighSize);
       pbmfh = (BITMAPFILEHEADER *) malloc (dwFileSize);
       ReadFile (hFile, pbmfh, dwFileSize, &dwBytesRead, NULL);
       pbmi = (BITMAPINFO *) (pbmfh + 1);
       pBits = (BYTE *) pbmfh + pbmfh->bfOffBits;
       cxDib = pbmi->bmiHeader.biWidth;
       cyDib = abs(pbmi->bmiHeader.biHeight);
       HDC hdc;
       hdc = GetDC (hWnd);
    
       SetDIBitsToDevice (hdc,
                          XDest,
                          YDest,
                          cxDib,
                          cyDib,
                          0,
                          0,
                          0,
                          cyDib,
                          pBits,
                          pbmi,
                          DIB_RGB_COLORS);
      ReleaseDC (hWnd, hdc);
      free (pbmfh);
    return 0;
    }
    The function is called like this:

    LoadFile(0, 0, "Graphics\\TITLE-SCREEN.BMP", hWnd);



    What do I need to do to make the window retain it's contents when it goes behind other windows?

    If it helps, here's the whole code.
    Code:
    #include <windows.h>
    #include <malloc.h>
    
    int Dude_Tile_X = 3;
    int Dude_Tile_Y = 5;
    
    int Dude_Pos_X;
    int Dude_Pos_Y;
    
    int LoadFile(int XDest, int YDest, char *FileName, HWND hWnd);
    int DudePosX(void);
    int DudePosY(void);
    
    int DudePosX(int dudex)
    {
    return (dudex * 32) + 16;
    }
    
    int DudePosY(int dudey)
    {
    return (dudey * 32) + 16;
    }
    
    int LoadFile(int XDest, int YDest, char *FileName, HWND hWnd)
    {
    
     static BITMAPFILEHEADER *pbmfh;
     static BITMAPINFO *pbmi;
     static BYTE *pBits;
     static int cxDib, cyDib;
    
           DWORD dwFileSize, dwHighSize, dwBytesRead;
           HANDLE hFile;
    
           char *NameOfFile;
           NameOfFile = new char[50];
           NameOfFile = FileName;
    
           hFile = CreateFile (NameOfFile, GENERIC_READ,
           FILE_SHARE_READ, NULL,
           OPEN_EXISTING,
           FILE_FLAG_SEQUENTIAL_SCAN,
           NULL);
    
       dwFileSize = GetFileSize (hFile, &dwHighSize);
       pbmfh = (BITMAPFILEHEADER *) malloc (dwFileSize);
       ReadFile (hFile, pbmfh, dwFileSize, &dwBytesRead, NULL);
       pbmi = (BITMAPINFO *) (pbmfh + 1);
       pBits = (BYTE *) pbmfh + pbmfh->bfOffBits;
       cxDib = pbmi->bmiHeader.biWidth;
       cyDib = abs(pbmi->bmiHeader.biHeight);
       HDC hdc;
       hdc = GetDC (hWnd);
    
       SetDIBitsToDevice (hdc,
                          XDest,
                          YDest,
                          cxDib,
                          cyDib,
                          0,
                          0,
                          0,
                          cyDib,
                          pBits,
                          pbmi,
                          DIB_RGB_COLORS);
      ReleaseDC (hWnd, hdc);
      free (pbmfh);
    return 0;
    }
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow )
    {
    WNDCLASS WndClass;
    WndClass.style = 0;
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 1;
    WndClass.lpfnWndProc = WndProc;
    WndClass.hInstance = hInstance;
    WndClass.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
    WndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
    WndClass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    WndClass.lpszMenuName = 0;
    WndClass.lpszClassName = "WinProg";
    
    RegisterClass(&WndClass);
    HWND hWindow;
    hWindow = CreateWindow("WinProg","Window",
                           WS_OVERLAPPEDWINDOW,
                           0,0,647,433,NULL,NULL,
                           hInstance, NULL);
    
    ShowWindow (hWindow, nCmdShow);
    UpdateWindow (hWindow);
    MSG Message;
    
    while (GetMessage(&Message, NULL, 0, 0))
    {
          DispatchMessage(&Message);
    }
     return (Message.wParam);
    }
    LRESULT CALLBACK WndProc (HWND hWnd, UINT uiMessage,
                              WPARAM wParam,LPARAM lParam)
    {
     switch(uiMessage)
     {
      case WM_LBUTTONDOWN:
                LoadFile(0, 0, "Graphics\\SCREEN-PURGE.BMP", hWnd);
                LoadFile(0, 0, "Graphics\\TITLE-SCREEN.BMP", hWnd);
                return 0;
                break;
      case WM_KEYDOWN:
    			switch(wParam)
                {
    				case VK_ESCAPE:
                         PostQuitMessage( 0 );
                         return 0;
                         break;
       	             case VK_NUMPAD4:
                     //LEFT
    				 
    				 if(Dude_Tile_X != 0)
    				 {
    				 LoadFile((DudePosX(Dude_Tile_X)), (DudePosY(Dude_Tile_Y)), "Graphics\\Tiles\\Null.bmp", hWnd);
                       Dude_Tile_X = Dude_Tile_X - 1;
                       LoadFile((DudePosX(Dude_Tile_X)), (DudePosY(Dude_Tile_Y)), "Graphics\\Tiles\\Dude_Obj.bmp", hWnd);
                     }
    				  
                        return 0;
                        break;
       	             case VK_NUMPAD6:
                     //RIGHT
    				 if(Dude_Tile_X != 17)
    				 {
    				 LoadFile((DudePosX(Dude_Tile_X)), (DudePosY(Dude_Tile_Y)), "Graphics\\Tiles\\Null.bmp", hWnd);
                       Dude_Tile_X = Dude_Tile_X + 1;
                       LoadFile((DudePosX(Dude_Tile_X)), (DudePosY(Dude_Tile_Y)), "Graphics\\Tiles\\Dude_Obj.bmp", hWnd);
                     }
    				 return 0;
                        break;
       	             case VK_NUMPAD8:
                     //UP
    				 if(Dude_Tile_Y != 0)
    				 {
    				 LoadFile((DudePosX(Dude_Tile_X)), (DudePosY(Dude_Tile_Y)), "Graphics\\Tiles\\Null.bmp", hWnd);
                       Dude_Tile_Y = Dude_Tile_Y - 1;
                       LoadFile((DudePosX(Dude_Tile_X)), (DudePosY(Dude_Tile_Y)), "Graphics\\Tiles\\Dude_Obj.bmp", hWnd);
                     }
                       return 0;
                        break;
       	             case VK_NUMPAD2:
                     //DOWN
    				 if(Dude_Tile_Y != 7)
    				 {
    				 LoadFile((DudePosX(Dude_Tile_X)), (DudePosY(Dude_Tile_Y)), "Graphics\\Tiles\\Null.bmp", hWnd);
                       Dude_Tile_Y = Dude_Tile_Y + 1;
                       LoadFile((DudePosX(Dude_Tile_X)), (DudePosY(Dude_Tile_Y)), "Graphics\\Tiles\\Dude_Obj.bmp", hWnd);
                     }
                       return 0;
                        break;
       	             case VK_NUMPAD5:
                     //WAIT
                LoadFile(0, 0, "Graphics\\SCREEN-PURGE.BMP", hWnd);
                LoadFile(0, 0, "Graphics\\HUD-RESET.BMP", hWnd);
                       LoadFile((DudePosX(Dude_Tile_X)), (DudePosY(Dude_Tile_Y)), "Graphics\\Tiles\\Dude_Obj.bmp", hWnd);
                        return 0;
                        break;
                     default:
                     return 0;
                     break;
               }
       LoadFile((DudePosX(Dude_Tile_X)), (DudePosY(Dude_Tile_Y)), "Graphics\\Tiles\\Dude_Obj.bmp", hWnd);
       return 0;
       break;
     case WM_DESTROY:
          PostQuitMessage(0);
          return 0;
          break;
     default:
          return DefWindowProc (hWnd, uiMessage,
                                wParam, lParam);
       }
    }

  2. #2
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Bitmaps cutting off

    Each time the window needs redrawing, the WM_PAINT message is sent to it. So you need to handle it and restore your current window state.

    And this must bring in absolutely different logic. You must always modify a bitmap in memory dc but never in window dc directly. The window dc is updated from your memory dc on WM_PAINT.
    Best regards,
    Igor

  3. #3
    Join Date
    Aug 2009
    Posts
    20

    Re: Bitmaps cutting off

    So you're saying that I need to load the bitmaps into memory dc and WM_PAINT whenever the screen regains focus? I think I follow you, but I don't know much about using the tools of the trade. Is there any sample code out there that shows how to load a bitmap into a memory DC? I've done console programming for years but have only been using WinAPI for a few months. So much more complicated than simple cin/cout stuff.

    Is what I'm doing is loading the bitmap directly into the window dc?

  4. #4
    Join Date
    Nov 2009
    Posts
    15

    Re: Bitmaps cutting off

    code snippet


    Code:
    case WM_PAINT:
    
    
            Hdc=BeginPaint (hwnd,&ps);
            hdcMem = CreateCompatibleDC (Hdc);
    
            SelectObject(hdcMem, hBitmap);
    
    
            BitBlt(Hdc,10,10,cxSource,cySource,hdcMem,0,0,SRCCOPY);
    
    
            DeleteDC(hdcMem);
            EndPaint (hwnd, &ps) ;
    
            return 0;
    Hope this helps

  5. #5
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Bitmaps cutting off

    Quote Originally Posted by Dispiacere View Post
    So you're saying that I need to load the bitmaps into memory dc and WM_PAINT whenever the screen regains focus?
    Well, not exactly. What I'm saying is: the logic of manipulations with the bitmaps should be adapted to the new requirement of being able always to restore window areas, and using memory dc is the technique you should learn an use.

    I think I follow you, but I don't know much about using the tools of the trade. Is there any sample code out there that shows how to load a bitmap into a memory DC?
    Sure, see the attachment. The sample gives you a main idea: the image is stored all the time in the bitmap object (g_hbm) and painted to a window whenever it is needed involving memory dc.

    Another idea related to the one above: to change the window image you apply the changes to the bitmap object (again by means of memory dc), but painting procedure remains intact.

    I've done console programming for years but have only been using WinAPI for a few months. So much more complicated than simple cin/cout stuff.
    Basicly, yes. For the first glance.

    Is what I'm doing is loading the bitmap directly into the window dc?
    Exactly. When you GetDC, make operations against it and ReleaseDC you operate directly with window dc.

    Do you have Windows Platform SDK? Its Samples folder contains various sample programs you could read and dissect. But before doing this, you definitely need to read Charles Petzold's Programming Windows to catch the very basic principles of Windows.
    Attached Files Attached Files
    Best regards,
    Igor

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured