|
-
Jul 12th, 2010, 02:58 PM
#1
Thread Starter
New Member
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.
-
Jul 13th, 2010, 08:39 AM
#2
Thread Starter
New Member
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
-
Jul 13th, 2010, 09:16 AM
#3
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.
-
Jul 13th, 2010, 09:27 AM
#4
Thread Starter
New Member
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
-
Jul 13th, 2010, 09:32 AM
#5
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!
-
Jul 13th, 2010, 01:48 PM
#6
Thread Starter
New Member
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.
-
Aug 19th, 2010, 03:29 PM
#7
Thread Starter
New Member
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|