Results 1 to 7 of 7

Thread: Displaying bitmaps with button click

  1. #1

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    5

    Displaying bitmaps with button click

    My first request for help here. I'm fairly new to c++.
    I'm trying to display a bitmap with a button click. I can get the bitmap to
    display when the code is put under the WM_PAINT section of WndProc.
    (you'll see where I have that code commented out)

    Everything compiles that I've included below. I use Code::Blocks. (Window XP Pro SP3) Some of those includes aren't needed here but it compiles with it anyway. This is just part of a larger program I'm working on with PRNG's. Those code sections work great. This part is giving me fits.

    Code:
    #include "resource.h"
    #include <windows.h>
    #include <windef.h>
    #include <stdafx.h>
    #include <stdio.h>
    #include <string.h>
    
    HBITMAP g_hbmDieThree = NULL;
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, 
    WPARAM wParam, LPARAM lParam);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow)
    {
    char szClassName[] = "myWindowClass";
    HWND hwnd;
    MSG msg;
    WNDCLASSEX wc;
            wc.cbSize  = sizeof(WNDCLASSEX);
            wc.style  = 0;
            wc.lpfnWndProc = WndProc;  
            wc.cbClsExtra  = 0;
            wc.cbWndExtra  = 0;
            wc.hInstance  = hInstance;
            wc.hIcon  = LoadIcon(NULL, IDI_APPLICATION);
            wc.hCursor  = LoadCursor(NULL, IDC_ARROW);
            wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
            wc.lpszMenuName  = NULL;
            wc.lpszClassName  = szClassName;
            wc.hIconSm  = LoadIcon(NULL, IDI_APPLICATION);
    
        if(!RegisterClassEx(&wc))
        {
            MessageBox(NULL, "Window Registration Failed!", "Error!",
                MB_ICONEXCLAMATION | MB_OK);
            return 0;
        }
    
        hwnd = CreateWindowEx(
    		WS_EX_CLIENTEDGE,
    		szClassName,
    		"My Window", 
    		WS_OVERLAPPEDWINDOW,
    		100, 100, 400, 400,
    		NULL, NULL, hInstance, NULL);
    
            if(hwnd == NULL)
            {
            MessageBox(NULL, "Window Creation Failed!", "Error!",
                MB_ICONEXCLAMATION | MB_OK);
            return 0;
            }
    
    	ShowWindow(hwnd, nCmdShow);
    	UpdateWindow(hwnd);
    
    	while(GetMessage(&msg, NULL, 0, 0) > 0)
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    	return msg.wParam;
    
    }  // end of WinMain
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam)
    {
    
        // HDC hdc;
        HWND hCtl;
        PAINTSTRUCT ps;
        HBITMAP  g_hbmDieThree = NULL;
    
        switch(msg)
        {
         case WM_CREATE: {
             hCtl = CreateWindowEx (
             0, "BUTTON", "ROLL",
             WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
             70, 300, 100, 35, hwnd,
             (HMENU) IDC_BTN_ROLL,
             GetModuleHandle(0),
             NULL);
    
             hCtl = CreateWindowEx (
             0, "BUTTON", "Exit",
             WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
             220, 300, 100, 35, hwnd,
             (HMENU) IDC_BTN_QUIT,
             GetModuleHandle(0),
             NULL);
    
    // LOAD THE BITMAP IN MEMORY
             g_hbmDieThree = LoadBitmap(GetModuleHandle(NULL), 
                         MAKEINTRESOURCE(IDB_DieThree));
              if
              (g_hbmDieThree == NULL)
              MessageBox(hwnd, "Could not find IDB_DieThree.", "Error", 
                   MB_OK | MB_ICONEXCLAMATION);
              }
              break;
              
              case WM_CLOSE:
              DestroyWindow(hwnd);
              break;
    
              case WM_DESTROY:
                PostQuitMessage(0);
              break;
    
    
        case WM_PAINT:
            {
             
             return TRUE;
             }
             break;
    
        case WM_COMMAND:
    
        switch(LOWORD(wParam)) {
    
        case IDC_BTN_QUIT:
        {
        DestroyWindow(hwnd);
        return TRUE;
        }
        break;
    
        case IDC_BTN_ROLL:
        {
    
            BITMAP bm;
            HBITMAP g_hbmDieThree = (HBITMAP) LoadImage(
                         NULL, "C:\\temp\\DieThree.bmp", IMAGE_BITMAP, 0, 0,
                         LR_CREATEDIBSECTION | LR_DEFAULTSIZE | 
                         LR_LOADFROMFILE);
            HDC hdc = BeginPaint(hwnd, &ps);
            HDC hdcMem = CreateCompatibleDC(hdc);
            HBITMAP hbmOld = (HBITMAP)SelectObject (hdcMem, g_hbmDieThree);
    
            GetObject(g_hbmDieThree, sizeof(bm), &bm);
            BitBlt(hdc, 50, 20, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
    
            SelectObject(hdcMem, hbmOld);
            // DeleteDC(hdcMem);
            DeleteObject(g_hbmDieThree);
            EndPaint(hwnd, &ps);
    
            return TRUE;
        }
        break;
        }
        break;  // END OF SWITCH(LOWORD)wParam))
        default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
        }
        return 0;  // END OF SWITCH(msg)
    
    }  // end of WndProc
    
    // I also have a RC and H file that goes with this.  If needed I'll post it too.
    I hope I didn't remove any important code when I removed all my
    multitudes of comments I use to keep track of my thought processes.

    I've searched MSDN and many other sites and haven't found any answers that work yet.

    Any help would be appreciated.
    (I tried following the post rules but if I need to change how I did this let me know and I'll do better next time)
    Last edited by codie; Jul 13th, 2010 at 02:02 PM.

  2. #2

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    5

    Re: Displaying bitmaps with button click

    very strange behavior with this post

    Some words like "windows", "color", "APPLICATION" are blue and underlined and when you put your cursor over it a box pops up. Then the word will disappear from the code leaving blank spaces when you scroll the window.

    very odd

  3. #3
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: Displaying bitmaps with button click

    In order to display something in a window it must be drawn to the window.
    All drawing should be done when you receive the WM_PAINT message (like you have done in your commented block).
    So the only problem you have right now is that you are drawing the bitmap at all times, but you only want it to be displayed when a button has been clicked. A fast way to accomplish that is simply a conditional inside that checks whether or not the button has been clicked. That would be pretty bad design though and you say that this is part of a larger program, so I'd suggest designing it well from scratch.
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  4. #4

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    5

    Re: Displaying bitmaps with button click

    Thanks for the recommendations. I'll give that a try even though its not the best way. I'll keep at it to improve my overall design of the program.

    All of my prior c++ stuff was console app so this windows stuff is a new challenge. I know I could use Visual C++ and do this faster (which I've already done some things like this with vc++) but I want to learn the bare bones of the language first.

    Have a nice day

  5. #5
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: Displaying bitmaps with button click

    Alright. I wish you the best of luck!

    On a side note;
    I can really recommend you try the Qt framework if you're working on a serious project. It contains a vast amount of classes that'll speed up development alot, and a GUI designer.
    Best of all - it's cross platform. Your application and the GUI will look native on Windows and Linux (and ..ugh... OS X), aswell as embedded systems.

    Have a nice day!
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  6. #6

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    5

    Re: Displaying bitmaps with button click

    kuurap!! I had the answer in front of me. ... chess blindness was filling my eyes

    All I had to do was remove this line from the IDC_BTN_ROLL case:
    DeleteDC(hdcMem);

    I commented that out and the button works. It displays the no. 3 dice bitmap just as I wanted.

    I then cleaned out the WM_PAINT case and all's good. Thanks for your help.

    FYI, my other code parts are basically a set of three pseudo random number generators. One basic c++ method (srand() ... rand()); a widely accepted PRNG called the Marsenne Twister; and my own contraption I call a loopty loop (nested randomly iterating loops that spits out a prng at the end of the random loops).

    I'm ready to read up on Qt now.

  7. #7

    Thread Starter
    New Member
    Join Date
    Jan 2010
    Posts
    5

    Re: Displaying bitmaps with button click

    I continued developing this simple die roll program but ran into a roadblock.

    I've only posted the code that changed in the WndProc section and a piece of code in the WinMain (w/notes). If you need me to post the whole enchilada of code, let me know and I'll replace this with everything. I had hoped I could get help by just looking at my code.

    Everything compiles and when I click on the ROLL button, I get exactly what I want; a bitmap image of the dice that corresponds to the random number that's generated with my simple PRNG calculation.

    But, when I click the ROLL button again the original bitmap image remains. While running debug the PRNG is working (I can watch that variable change each time it goes the rollDice routine). Also, you can watch the program run through and stop on the appropriate IF statement then run through its subroutine (If(dieRoll == 1, 2, etc etc)).

    It seems the new bitmap is not being painted. Any help would be appreciated.

    Code:
    // this is the first line under WinMain
    
        srand(GetTickCount());  // to seed the rand()
    
    // the WinMain code I posted above is basically the same except I added references to all the dice bitmap files
    // the problems I'm having seem to be in the WndProc section
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        int rollDice();
        int dieRoll;
    
        HWND hCtl;
        PAINTSTRUCT ps;
    
        switch(msg)
        {
            case WM_CREATE: {
    
                hCtl = CreateWindowEx (
                0, "BUTTON", "ROLL",
                WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                70, 300, 100, 35,
                hwnd,   // handle of the parent window
                (HMENU) IDC_BTN_ROLL, GetModuleHandle(0),
                NULL);
    
                hCtl = CreateWindowEx (
                0, "BUTTON", "Exit",
                WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                220, 300, 100, 35,
                hwnd, (HMENU) IDC_BTN_QUIT,
                GetModuleHandle(0),
                NULL);
    
                // LOAD THE BITMAPS IN MEMORY
                g_hbmDieOne = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_DieOne));
                            if
                            (g_hbmDieOne == NULL)
                            MessageBox(hwnd, "Could not find IDB_DieOne.", "Error", MB_OK | MB_ICONEXCLAMATION);
    
                // ditto for DieTwo, Three, Four, and five // ...
    
                 g_hbmDieSix = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_DieSix));
                            if
                            (g_hbmDieSix == NULL)
                            MessageBox(hwnd, "Could not find IDB_DieSix.", "Error", MB_OK | MB_ICONEXCLAMATION);
                // THEN CHECK TO BE SURE THEY LOADED
    
                }
                break;  // END OF WM_CREATE
    
            case WM_CLOSE:
                DestroyWindow(hwnd);
            break;
    
            case WM_DESTROY:
                PostQuitMessage(0);
            break;
    
      //////////////////////////////////////////////////////
            case WM_PAINT:
            {
            return TRUE;
            }
            break;
    
            case WM_COMMAND:
    
                switch(LOWORD(wParam))
                {
    
                        case IDC_BTN_QUIT:
                        {
                        DestroyWindow(hwnd);
                        return TRUE;
                        }
                        break;
    
                        case IDC_BTN_ROLL:
                        {
                        //////////////////////////// generate the random number /
                        //////////////////////////// then load the graphic 
                        //  THIS IS WHERE THE PROBLEM BEGINS - I THINK
    
                        dieRoll = rollDice();
    
                        if(dieRoll == 1) {
                            BITMAP bm;
                            HBITMAP g_hbmDieOne = (HBITMAP) LoadImage(
                                                    NULL, "C:\\temp\\DieOne.bmp", IMAGE_BITMAP, 0, 0,
                                                    LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
                            HDC hdc = BeginPaint(hwnd, &ps);
                            HDC hdcMem = CreateCompatibleDC(hdc);
                            HBITMAP hbmOld = (HBITMAP)SelectObject (hdcMem, g_hbmDieOne);
    
                            GetObject(g_hbmDieOne, sizeof(bm), &bm);
                            BitBlt(hdc, 50, 20, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
                            UpdateWindow(hwnd);
                            SelectObject(hdcMem, hbmOld);
                            DeleteObject(g_hbmDieOne);
                            EndPaint(hwnd, &ps);
                        return 0;
                        }
    
    // ditto for DieTwo, Three, Four, and five // ... There's probably a more eloquent way
    // this method compiles with no errors and for the first button click loads the bitmap for
    // whatever random number is generated 1 through 6
                     
                        if(dieRoll == 6) {
                            BITMAP bm;
                            HBITMAP g_hbmDieSix = (HBITMAP) LoadImage(
                                                    NULL, "C:\\temp\\DieSix.bmp", IMAGE_BITMAP, 0, 0,
                                                    LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
                            HDC hdc = BeginPaint(hwnd, &ps);
                            HDC hdcMem = CreateCompatibleDC(hdc);
                            HBITMAP hbmOld = (HBITMAP)SelectObject (hdcMem, g_hbmDieSix);
                            GetObject(g_hbmDieSix, sizeof(bm), &bm);
                            BitBlt(hdc, 50, 20, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
    
                            UpdateWindow(hwnd);
                            SelectObject(hdcMem, hbmOld);
                            DeleteObject(g_hbmDieSix);
                            EndPaint(hwnd, &ps);
                        return 0;
                        }
                        // END of last if(dirRoll == #)
                        break;
                        // return TRUE;
    
                        }
                        // END OF case IDC_BTN_ROLL
                        break;
                        // return TRUE;
    
                }
                // END OF SWITCH(LOWORD)wParam))
                break;
                default:
                return DefWindowProc(hwnd, msg, wParam, lParam);
        }
        // END OF SWITCH(msg)
        return 0;
    
    }  ///////////////// END of WndProc /////////////////////
    
    int rollDice()
    {
        int dieRoll;
        int N = 6;
        // dieRoll = (int)(((double)rand() / ((double)RAND_MAX + 1) * N)) + 1;
        dieRoll = (rand() / (RAND_MAX / N + 1)) + 1;
        return dieRoll;
    }

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