Bitmap Display Problem

Started by
7 comments, last by Dave Hunt 19 years, 2 months ago
I have tried everthing with this code i can not get my bitmap to display it loads properly but it doesnt display :( its coded in c++

// <^>|<^>|<^>|<^>|<^>|<^>|<^>|<^>|<^>|<^>|<^>|<^>|<^ 
// * Shawn McBroom                                  * 
// * Gor435@gdnmail.net                             *  
// * 1/24/2005                                      * 
// <^>|<^>|<^>|<^>|<^>|<^>|<^>|<^>|<^>|<^>|<^>|<^>|<^ 
#define WIN32_LEAN_AND_MEAN
#define ID_FILE_EXIT 0
#define ID_FILE_NEW 1
#define ID_HELP_ABOUT 1000
#define PD_ICON "Battle Paddles.ico"

#include <windows.h> // include our windows header of course 
#include <assert.h>

const char wndclass[] = "The Window Class";// declair our window class name 
const char wndname[]= "Battle Paddles"; // The title text for our window 

// prototype our windows procedure funtion which handles messages 
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE wndins, HINSTANCE windpins, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;// wc will be our WNDCLASSEX structure object 
    HWND hWnd; //window 
    MSG msg; // messages 
    
    wc.cbSize = sizeof (WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = wndins;
    wc.hIcon = LoadIcon(NULL, PD_ICON);
    wc.hIconSm =(HICON) LoadImage(NULL, "Battle Paddles.ico", IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR | LR_LOADFROMFILE);
    wc.hCursor = LoadCursor(NULL, IDC_HAND);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = wndclass;
    wc.hbrBackground = (HBRUSH)(2);
    
    
    if(!RegisterClassEx(&wc)) // if the window didnt register right you want to display a 
                              // message box that explains with ok button when clicked close 
                              // the program 
    {
       MessageBox(NULL, "Window Registration Failed!", " UH OH ", MB_ICONEXCLAMATION | MB_OK);
       return 0;
    }
    
    hWnd = CreateWindowEx( WS_EX_CLIENTEDGE, wndclass, wndname, WS_OVERLAPPEDWINDOW, // make hWnd equal too CreateWindowEx funtion
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, wndins, NULL);
    
    if(hWnd == NULL) // if the window was not properly created post message and quit 
    {
        MessageBox(NULL, "Failed to create window", " UH OH ", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
    
    ShowWindow(hWnd, nCmdShow);// we have to show the window to the screen so you can see it
    UpdateWindow(hWnd);// update the window 
    
        while(GetMessage(&msg, NULL, 0, 0) > 0)//message loop 
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        
     return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)// windows procedure funtion
{
    switch(msg)
    {
        case WM_CREATE: // when the window is created do this 
          {
             HMENU hMenu, hSubMenu, hsubmenu;
                             
             hMenu = CreateMenu();
                              
             hSubMenu = CreatePopupMenu();
             hsubmenu = CreatePopupMenu();
                          
             AppendMenu(hSubMenu, MF_STRING, ID_FILE_NEW, "&New");
             AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
             AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu,"&File");
             
             AppendMenu(hsubmenu, MF_STRING, ID_HELP_ABOUT, "&About");
             AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hsubmenu,"&Help");
                
             SetMenu(hWnd, hMenu);
               
           }
                break;
         case WM_COMMAND:// when something on one of the menus are selected 
           {     
               switch(LOWORD(wParam))// we need to figure out which menu option was selected 
                 {
                    case ID_FILE_EXIT:// if the exit option was chosen 
                      {  
                    PostQuitMessage(WM_QUIT);// quit the program 
                    break;
                      }
                    case ID_FILE_NEW:// if the new option was chosen 
                        {
                            
                            break;
                        }
                    case ID_HELP_ABOUT://if help option was chosen 
                        {
                            MessageBox(NULL, "          Spark Software\n\n          Shawn McBroom\n\nE-mail me at gor435@gdnmail.net          ", "About", MB_ICONASTERISK | MB_OK);
                            break;
                        }                       
                 }
               break;
            }      
            
        case WM_CLOSE://if user chooses to close the window 
            {
                DestroyWindow(hWnd);//get rid of the window 
                break;
            }            
        case WM_DESTROY:// when you get rid of the window you need to stop the program 
            {
                PostQuitMessage(0);//quit the program 
                break;
            }
        case WM_COMPACTING:// this gets sent to all top level programs when the system is low on memory 
            {
                MessageBox(NULL, "Oh, your system is low on memery this program should close", "Low Memory", MB_ICONEXCLAMATION | MB_OK);
                return 0;
            }
        case WM_LBUTTONDOWN:
            {
                HBITMAP hbitmap;
                HDC hdc, bhdc;
                tagPAINTSTRUCT bm;
                tagBITMAPINFO bmi;
                
                
                hdc = GetWindowDC(hWnd);
                
                
                
                hbitmap = (HBITMAP)LoadImage(NULL, "background.bmp", IMAGE_BITMAP, 100, 100, LR_LOADFROMFILE | LR_DEFAULTCOLOR );
                
                if(hbitmap == NULL)
                {
                    MessageBox(NULL, "Bitmap load failed :(", "FAILURE", MB_ICONEXCLAMATION | MB_OK);
                }
                else
                {
                    MessageBox(NULL, "Bitmap load success :)", "SUCCESS!!", MB_ICONEXCLAMATION | MB_OK);
                    
                }
                //bhdc = GetDC((HWND)hbitmap);
                //bhdc = (HDC)SelectObject(GetDC((HWND)hbitmap), hbitmap);
                
                
                GetDIBits(bhdc, hbitmap, 1, 100, NULL, &bmi, DIB_PAL_COLORS);
                SetDIBitsToDevice(bhdc, 30, 30, 100, 100, 100, 100, 1, 100, NULL, &bmi, DIB_PAL_COLORS);
                
                //assert(bhdc != 0);
                
                BeginPaint(hWnd, &bm);
                
                BitBlt(hdc, 10, 10, 100, 100, bhdc, 0, 0, SRCCOPY);
                
                EndPaint(hWnd, &bm);
                
                UpdateWindow(hWnd);
                ReleaseDC(hWnd, hdc);
                break;        
            }       
            default:
                return DefWindowProc(hWnd, msg, wParam, lParam);//what to do if you get a message we are not looking for    
        } 
    return 0;   
} 

and yes i do want to be able to click the window to display it any ideas??
Gor435 - My Journal - MySpace - Facebook
Advertisement
You need to do the bitmap drawing in the WM_PAINT message. What you can do in your WM_LBUTTONDOWN handler is load the bitmap, saving the HBITMAP somewhere safe, and force an update (InvalidateRect() I think). Then, add a WM_PAINT handler, and do the bitmap drawing there using the saved HBITMAP. The WM_PAINT handler can check the saved bitmap handle, and if it's not NULL, draw the bitmap.

According to MSDN, "an application should not call BeginPaint except in response to a WM_PAINT message".

Also, since your window can become corrupted by moving/resizing/insert-reason-here, you would need to redraw your bitmap any time you received a WM_PAINT message, anyway.
ok i may have misunderstood your post but when i do the WM_PAINT it still didnt do anything :(
Gor435 - My Journal - MySpace - Facebook
Are you using InvalidateRect() (I think that's it) in your mouse handle? That will get a WM_PAINT message sent to you.
Ok maybe I wasnt the one confused because everytime the window refreshes it sends a WM_PAINT message. So using the InvalidateRect() function will not help me to get a WM_PAINT message.

Quote:According to MSDN, "an application should not call BeginPaint except in response to a WM_PAINT message".


yes but they never said it "can not call" it "should not call" because it is the only time the windows procedure should draw to the window but no body ever said it could not be done with a click :)
Gor435 - My Journal - MySpace - Facebook
Quote:Original post by Gor435
Ok maybe I wasnt the one confused because everytime the window refreshes it sends a WM_PAINT message. So using the InvalidateRect() function will not help me to get a WM_PAINT message.



No you were right the first time, you are the one confused. InvalidateRect() should eventually call a WM_PAINT message.

Edit: I don't think you need the BeginPaint and Endpaint functions. In this case I don't see what they do since they are normally used to return a HDC which you already do with the GetDC() function. I think the problem with your code is no paint message is being generated. With the InvalidateRect function it should work.
You can draw outside of the WM_PAINT message anytime you want (but not using BeginPaint/EndPaint). However, when the WM_PAINT message is processed, anything you've drawn will be lost. One of the messages sent when the system determines that a redraw is necessary is a WM_ERASEBKGND. The default message handler will clear the background of your window when it processes that message. When that happens, your image is gone.

The correct way to do what you want to do is set a flag and issue an InvalidateRect() when the WM_LBUTTONDOWN occurs. Then add a WM_PAINT handler that draws your bitmap when the flag is set.

And I don't think Microsoft said "should not" simply because they didn't want you to become an Uber God and know the deep, dark mysteries of the GDI. They said it because either it won't work, or it is not in your best interest to do so.
Ok here is what MSDN says
Quote:
WM_PAINT
The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window. The message is sent when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage function when the application obtains a WM_PAINT message by using the GetMessage or PeekMessage function.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_88ac.asp

really i dont think i was all that confused reads pretty clearly
Quote:
InvalidateRect
The InvalidateRect function adds a rectangle to the specified window's update region. The update region represents the portion of the window's client area that must be redrawn.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_7ano.asp

which I do not see how this will help if i am using BitBlt
Quote:
BeginPaint
The BeginPaint function prepares the specified window for painting and fills a PAINTSTRUCT structure with information about the painting.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_7b78.asp
Quote:
BitBlt
The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_0fzo.asp

Anyways don't worry about it I got it to work
Gor435 - My Journal - MySpace - Facebook
Also on the BeginPaint page you linked:

Quote:The BeginPaint function automatically sets the clipping region of the device context to exclude any area outside the update region. The update region is set by the InvalidateRect or InvalidateRgn function and by the system after sizing, moving, creating, scrolling, or any other operation that affects the client area. If the update region is marked for erasing, BeginPaint sends a WM_ERASEBKGND message to the window.

An application should not call BeginPaint except in response to a WM_PAINT message. Each call to BeginPaint must have a corresponding call to the EndPaint function.


Also on the InvalidateRect page you linked:

Quote:The system sends a WM_PAINT message to a window whenever its update region is not empty and there are no other messages in the application queue for that window.


You've got to read the entire page, not just the short description.

At any rate, congratulations on getting it to work.

This topic is closed to new replies.

Advertisement