Reputation: 1281
Has anyone implemented Lightbox style background dimming on a modal dialog box in a MFC/non .net app.
I think the procedure would have to be something like:
steps:
Get dialog parent HWND or CWnd*
Get the rect of the parent window and draw an overlay with a translucency over that window
Are there any existing libraries/frameworks to do this, or what's the best way to drop a translucent overlay in MFC?
edit Here's a mockup of what i'm trying to achieve if you don't know what 'lightbox style' means
Some App:
with a lightbox dialog box
Upvotes: 4
Views: 2457
Reputation: 1281
Here's what I did* based on Brian's links
First create a dialog resource with the properties:
and you should end up with a dialog window with no frame or anything, just a grey box. override the Create function to look like this:
BOOL LightBoxDlg::Create(UINT nIDTemplate, CWnd* pParentWnd)
{
if(!CDialog::Create(nIDTemplate, pParentWnd))
return false;
RECT rect;
RECT size;
GetParent()->GetWindowRect(&rect);
size.top = 0;
size.left = 0;
size.right = rect.right - rect.left;
size.bottom = rect.bottom - rect.top;
SetWindowPos(m_pParentWnd,rect.left,rect.top,size.right,size.bottom,NULL);
HWND hWnd=m_hWnd;
SetWindowLong (hWnd , GWL_EXSTYLE ,GetWindowLong (hWnd , GWL_EXSTYLE ) | WS_EX_LAYERED ) ;
typedef DWORD (WINAPI *PSLWA)(HWND, DWORD, BYTE, DWORD);
PSLWA pSetLayeredWindowAttributes;
HMODULE hDLL = LoadLibrary (_T("user32"));
pSetLayeredWindowAttributes =
(PSLWA) GetProcAddress(hDLL,"SetLayeredWindowAttributes");
if (pSetLayeredWindowAttributes != NULL)
{
/*
* Second parameter RGB(255,255,255) sets the colorkey
* to white LWA_COLORKEY flag indicates that color key
* is valid LWA_ALPHA indicates that ALphablend parameter
* is valid - here 100 is used
*/
pSetLayeredWindowAttributes (hWnd,
RGB(255,255,255), 100, LWA_COLORKEY|LWA_ALPHA);
}
return true;
}
then create a small black bitmap in an image editor (say 48x48) and import it as a bitmap resource (in this example IDB_BITMAP1)
override the WM_ERASEBKGND message with:
BOOL LightBoxDlg::OnEraseBkgnd(CDC* pDC)
{
BOOL bRet = CDialog::OnEraseBkgnd(pDC);
RECT rect;
RECT size;
m_pParentWnd->GetWindowRect(&rect);
size.top = 0;
size.left = 0;
size.right = rect.right - rect.left;
size.bottom = rect.bottom - rect.top;
CBitmap cbmp;
cbmp.LoadBitmapW(IDB_BITMAP1);
BITMAP bmp;
cbmp.GetBitmap(&bmp);
CDC memDc;
memDc.CreateCompatibleDC(pDC);
memDc.SelectObject(&cbmp);
pDC->StretchBlt(0,0,size.right,size.bottom,&memDc,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
return bRet;
}
Instantiate it in the DoModal of the desired dialog, Create it like a Modal Dialog i.e. on the stack(or heap if desired), call it's Create manually, show it then create your actual modal dialog over the top of it:
INT_PTR CAboutDlg::DoModal()
{
LightBoxDlg Dlg(m_pParentWnd);//make sure to pass in the parent of the new dialog
Dlg.Create(LightBoxDlg::IDD);
Dlg.ShowWindow(SW_SHOW);
BOOL ret = CDialog::DoModal();
Dlg.ShowWindow(SW_HIDE);
return ret;
}
and this results in something exactly like my mock up above
*there are still places for improvment, like doing it without making a dialog box to begin with and some other general tidyups.
Upvotes: 4
Reputation: 14579
I think you just need to create a window and set the transparency. There is an MFC CGlassDialog sample on CodeProject that might help you. There is also an article on how to do this with the Win32 APIs.
Upvotes: 2