Jump to content
  • Advertisement
Sign in to follow this  
d1sc0rd

Using BM_SETIMAGE (button control send message)

This topic is 5016 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to use sendmessage to set a button to a bitmap. The bitmap loads properly (I can display it elsewhere in WM_CREATE) but the LRESULT returned from SendMessage is always null and the bitmap is never displayed on the button. Whats wrong with this code?
HWND hWndButton = CreateWindow( 
	"BUTTON",   // predefined class 
	NULL,       // button text 
	WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON |BS_BITMAP,  // styles 
        //EDIT: ADDED BS_BITMAP
	// Size and position values are given explicitly, because 
	// the CW_USEDEFAULT constant gives zero values for buttons. 
	10,         // starting x position 
	10,         // starting y position 
	31,        // button width 
	31,        // button height 
	(HWND) hWnd,       // parent window 
	NULL,       // No menu 
	(HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE), 
	NULL); // pointer not needed 
HBITMAP oldBMP = (HBITMAP)SendMessage(      
	// returns LRESULT in lResult     
	(HWND) hWndButton,	// handle to destination control     
	(UINT) BM_SETIMAGE, // message ID     
	(WPARAM) IMAGE_BITMAP,    // = (WPARAM) () wParam; 
	(LPARAM) (HBITMAP) bm_right_arrow   	// = (LPARAM) () lParam; 
	);  
	if (!oldBMP)
	{
		MessageBox (hWnd, "lResult = NULL", "NULL", MB_OK);
	}


Any ideas? [Edited by - d1sc0rd on January 18, 2005 7:16:24 PM]

Share this post


Link to post
Share on other sites
Advertisement
Your right, I was definitly missing that. Thank you.

It still doesn't work. I tried sending a different message in the same way. Tried sending BM_GETSTATE. It returns a null value as well. Still no bitmap displayed.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The LRESULT should be null, because it returns the handle to the prev bitmap [if any], and since you have just created the button, it shouldn't have a bitmap set yet.

One possible reason the bmp isn't getting displayed is if it doesn't have the right lifetime, and is getting destroyed somewhere. For example if you use the MFC
CBitmap class and do this

SetBmpButton() //this is just pseudo-code, don't woory about syntax
{
CBitmap temp;
Temp.Load(IDB_BITMAP);
Button.SetBitmap(Temp);
}//since temp is local to this function, it gets destroyed here
//causeing the button to display nothing

Share this post


Link to post
Share on other sites
Couple of things.

I declared the bitmap locally. I did load the bitmap in WM_CREATE but I declared the bitmap at the top of the file (only file at this point). I also tried BitBlting the bitmap right after the call, and it works just fine.

I tried checking the return from the BM_GETSTATE as well. It should be returning 0 I think, which would be different from null, right?

Also I was wondering, I know that many GDI objects come with default settings that need to be sent back in, such as pens. I was under the impression that the BS_BITMAP setting would cause the Button to have an default object that would need to be returned in order to be destroyed. Would this not register as somehting other than null? I really don't know.

Share this post


Link to post
Share on other sites
I think you need to post more code since obviously the error doesn't lie in what you've shown us already. Also, If you're able to blit it to the window, why not just go ahead and make the button ownerdraw instead?

Share this post


Link to post
Share on other sites
If you loaded the bitmap locally, does that mean the HBITMAP is a local variable to your WndProc()? If so, is it declared static? If not then it wont keep its value between calls to WndProc().

Share this post


Link to post
Share on other sites
I added a second message to load the bitmap twice. The null check no longer shows up, so the send message is working somewhat anyway.
#define	WIN_CLASS_NAME	"UIClass"
#define WIN_APP_NAME "U101"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include ".\resource.h"
static HBITMAP bm_right_arrow;

HINSTANCE hInst;
HWND hWnd;
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// The main window message handler
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
bm_right_arrow = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_RIGHT_ARROW));
if (!bm_right_arrow)
{
MessageBox(NULL, "Didn't Load", "ERROR", MB_OK);
}

HWND hWndButton = CreateWindow(
"BUTTON", // predefined class
NULL, // button text
WS_VISIBLE | WS_CHILD | BS_BITMAP | BS_PUSHBUTTON, // styles

// Size and position values are given explicitly, because
// the CW_USEDEFAULT constant gives zero values for buttons.
10, // starting x position
10, // starting y position
30, // button width
30, // button height
(HWND) hWnd, // parent window
NULL, // No menu
(HINSTANCE) hInst,
NULL); // pointer not needed
HBITMAP oldBMP = (HBITMAP)SendMessage(
// returns LRESULT in lResult
(HWND) hWndButton, // handle to destination control
(UINT) BM_SETIMAGE, // message ID
(WPARAM) IMAGE_BITMAP, // = (WPARAM) () wParam;
(LPARAM) bm_right_arrow // = (LPARAM) () lParam;
);
oldBMP = (HBITMAP)SendMessage(
// returns LRESULT in lResult
(HWND) hWndButton, // handle to destination control
(UINT) BM_SETIMAGE, // message ID
(WPARAM) IMAGE_BITMAP, // = (WPARAM) () wParam;
(LPARAM) bm_right_arrow // = (LPARAM) () lParam;
);
if (!oldBMP)
{
MessageBox (hWnd, "lResult = NULL", "NULL", MB_OK);
}

break;
}
case WM_DESTROY:
PostQuitMessage(wParam);
break;


case WM_PAINT:
{
HDC hDC;
PAINTSTRUCT ps;

hDC = BeginPaint(hWnd, &ps);
HDC hDCMem = CreateCompatibleDC(hDC);

HBITMAP oldBM = (HBITMAP) SelectObject(hDCMem, (HBITMAP) bm_right_arrow);
BitBlt(hDC, 80, 80, 80, 80, hDCMem, 0, 0, SRCPAINT);

// What to do, oh, what to do...

EndPaint(hWnd, &ps);
break;
}
case WM_COMMAND:
{
switch (LOWORD (wParam))
{

}
}
}

return DefWindowProc(hWnd, msg, wParam, lParam);
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
hInst = hInstance;
WNDCLASSEX wcx;
MSG msg;

int cxScr = GetSystemMetrics(SM_CXSCREEN);
int cyScr = GetSystemMetrics(SM_CYSCREEN);

// Define elements of the window class, register
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wcx.lpfnWndProc = WndProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInstance;
wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcx.lpszMenuName = MAKEINTRESOURCE(IDMAINMENU);
wcx.lpszClassName = WIN_CLASS_NAME;
wcx.hIconSm = NULL;

if(!RegisterClassEx(&wcx))
return 0;

// Create the window: centered, and half the height and width of the screen
if(!(hWnd = CreateWindowEx(NULL,
WIN_CLASS_NAME,
WIN_APP_NAME,
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
(int)(cxScr / 4), (int)(cyScr / 4),
(int)(cxScr / 2), (int)(cyScr / 2),
NULL,
NULL,
hInstance,
NULL)))
return 0;

// Main loop here
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}

Share this post


Link to post
Share on other sites
It looks to me like your problem is scope. You create hWndButton inside of the WM_CREATE case, so as soon as the windows procedure exits, your handle to the button is destroyed.

I believe that windows (such as buttons) get detroyed automatically, without you having to call a release function.

I'd say try making your button global, or static inside the WndProc.


kingnosis

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!