Jump to content
  • Advertisement
Sign in to follow this  
floatingwoods

How to display a dynamic rgb image in a windows dialog

This topic is 2957 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

Hello,

I have a MFC dialog where I'd like to display a picture from a simple RGB buffer (24 bits/pixel), nothing fancy. The content of the buffer may change at some time, so I cannot use a simple picture control. I know that I will have to override some "onPaint" functions to actualize my picture, but where I am having trouble with is how to update my picture? Or where do I have to write-in my buffer?

I read a lot of complicated things (well, to me ;) ), where one has to use a device context, create a bitmap, etc.

Any help is greatly appreciated!

Share this post


Link to post
Share on other sites
Advertisement
It's been years since I did that in MFC, so I'll tell you how I do it with a Windows dialog. It shouldn't be too difficult to convert (famous last words).

The basis is to substitute the window procedure in a STATIC control, and intercept the WM_PAINT and WM_ERASEBKGND messages.

In the dialog template, include a simple STATIC control, sized as you see fit.

In InitDialog():

HWND button = GetDlgItem(hDlg, IDC_PIXCTL); // get window handle of the control
(WNDPROC)SetWindowLongPtr (button, GWLP_WNDPROC, (LONG_PTR)BmDisplayProc); // change the window procedure
SetWindowLongPtr(button, GWLP_USERDATA, (LONG_PTR)this); // store a pointer to the dialog instance itself


I'm not sure about MFC, so you may have to experiment. But, in Windows, a Windows procedure (WNDPROC) has to be static and have the following form:

BOOL CALLBACK DlgChooseTex::BmDisplayProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

In the DlgChooseTex class header, BmDisplayProc is declared with the static keyword, but not in the cpp file.

Also, in the DlgChooseTex class header, I declare:
void PaintBitmap(HDC dc);

Then, the static control's window procedure becomes:

DlgChooseTex *dlg = (DlgChooseTex*)GetWindowLongPtr(hwnd,GWLP_USERDATA); // retrieve the pointer to the dialog instance
switch(message) {
case WM_PAINT:
PAINTSTRUCT ps;
BeginPaint(hwnd,&ps);
dlg->PaintBitmap(ps.hdc); // however you want to display it
EndPaint(hwnd,&ps);
return TRUE; // indicates the message was handled
case WM_ERASEBKGND:
HDC dc = (HDC)wParam;
RECT r;
GetClientRect(hwnd,&r);
FillRect(dc,&r,(HBRUSH)(COLOR_WINDOW+1)); // choose your background color
return TRUE; // the message was handled
}
return DefWindowProc(hwnd, message, wParam, lParam);






To display a bitmap (texBM in this procedure is HBITMAP) in a window (that's all the static control is) with the correct aspect ratio as the original image:

void DlgChooseTex::PaintBitmap(HDC dc)
{
HWND texHwnd = GetDlgItem(hDlg,IDC_PIXCTL);
if( texBM != NULL )
{
RECT srect;
GetClientRect(texHwnd,&srect);

BITMAP bminfo;
GetObject(texBM,sizeof(BITMAP),&bminfo);
float aspect = (float)bminfo.bmWidth/(float)bminfo.bmHeight;
float rWidth = float(srect.right-srect.left);
float rHeight = float(srect.bottom-srect.top);
float newWidth = rWidth;
float newHeight = rHeight;
if( aspect >= 1.0f ) // wider than high - reduce height of rect
{
newHeight = rHeight/aspect;

}
else // higher than wide - reduce width of rect
{
newWidth = rHeight * aspect;
}
srect.right = LONG(newWidth);
srect.bottom = LONG(newHeight);
HDC memdc = CreateCompatibleDC(dc);
HBITMAP oldbm = (HBITMAP)SelectObject(memdc,texBM);
BOOL blkOK = StretchBlt(dc,0,0,LONG(newWidth),LONG(newHeight),memdc,0,0,bminfo.bmWidth,bminfo.bmHeight,SRCCOPY);
SelectObject(memdc,oldbm);
DeleteDC(memdc);
}
}




Share this post


Link to post
Share on other sites
Thanks a lot buckeye!

I was wondering if there wasn't an easier way...
I tried following:

CBitmap* bm=new CBitmap();
BYTE pixels[64*64*3];
for (int i=0;i<64*64*3;i++)
pixels=0; // black for now
bm->CreateBitmap(64,64,3,8,pixels);
((CStatic*)GetDlgItem(IDC_SPLASH_CONTAINER))->SetBitmap(HBITMAP(bm) );




But that dind't display the black buffer as expected

Share this post


Link to post
Share on other sites
When you create the bitmap, you're loading 3 bytes per pixel; then you tell the bitmap it's 8 bits/pixel, rather than 24. Not good. I don't know what it'll do trying to use 3 bitplanes with only 8 bits! It's likely that function fails but you don't check for success or failure. See last comment below.

Also, if I remember, the HBITMAP() operator takes an object, not a pointer. Try HBITMAP(*bm);

From the docs for CStatic:
Quote:
// If no bitmap is defined for the static control, define the bitmap
// to the system close bitmap.
if (myStatic.GetBitmap() == NULL)
myStatic.SetBitmap(::LoadBitmap(NULL, MAKEINTRESOURCE(OBM_CLOSE)));

You might try that.

Looking at your code and looking at mine.. uh, yeah, your way may be easier.

I notice you don't check for any errors. You need to get out of that habit immediately! [wink]

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!