Click here to Skip to main content
Click here to Skip to main content

Perfect Semi-transparent & Shaped Dialogs with Standard, ActiveX, and Translucent Controls for Windows 2000+

, 9 Feb 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
This article tries to find a way to show standard controls, ActiveX controls, translucent controls on layered windows. Native MFC source code provided.

Introduction 

First, let me show you some screenshots captured from the demo program. The program demonstrates semi-transparent dialogs with standard, ActiveX (like WebBrowser Control, Flash Control) and translucent controls which are compatible with Windows 2000 and higher.  

Translucent Dialog with Standard Control

Translucent Dialog with WebPage

Translucent Dialog with WebPage

Background

Jerry.Wang has given a way in his article: Cool, Semi-transparent and Shaped Dialogs with Standard Controls for Windows 2000 and Above. In short, he creates two dialogs: one (the real dialog) is in charge of processing user input events and Windows messages, the other (the fake dialog) is in charge of the presentation. The fake one is created by CreateWindowEx with the styles WS_EX_LAYERED, WS_EX_TRANSPARENT, and WS_EX_NOACTIVATE, and always kept the same size / position as the real one. The real one is almost transparent because its alpha value is modified to 5 by SetLayeredWindowAttributes.

In his article, when the presentation needs to be refreshed, the background image is painted first. All the standard child controls will be captured by sending the WM_PRINT message, and painted at the same position on the fake window. Especially, for EDIT controls, EditBox / Editable ComboBox / etc., we need to draw the caret by ourselves.

But, there are some problems:

  • The dialog is NOT a real shaped one, i.e. the hit testing is NOT based on the shape and transparency of the dialog. This means that the areas of the dialog that are color-keyed or whose alpha value is zero will NOT let the mouse messages through.
  • NOT All standard controls are supported. Some of the controls such as slider, cannot work with WM_PRINT; in that case, the controls won't display correctly.
  • The ActiveX control is NOT supported. The ActiveX control like the WebBrowser control and Flash control is used to support a wide variety of OLE functionality and can be customized to fit many software needs. It cannot work with WM_PRINT too.
  • The dialog works in a way that if there is one pixel that needs to be updated, the whole window will be refreshed. Therefore, if the dialog is very large and complex, or has a lot of child controls, it may cause performance issues.

I'm going to propose another approach which can solve the above problems. The following picture shows the mechanism:

Showing the mechanism of translucent dialog

The translucent dialog is created with the styles WS_EX_LAYERED, and WS_OVERLAPPED. When it is being created, a standard dialog is created by CreateWindowEx with the styles WS_EX_LAYERED, WS_POPUP, NO WS_BORDER, NO WS_SIZEBOX, and NO WS_DLGFRAME.

The translucent dialog is in charge of processing the translucent background and the translucent controls; the standard dialog is in charge of processing the standard controls and ActiveX controls. The standard dialog is always kept the same size / position as the translucent one.

A translucent control which supports the per-pixel alpha value must be derived from the class CTranslucentWnd. You can override the method Render to draw it. In the source code, I has provided two translucent controls: CTranslucentButton and CTranslucentProgressBar. The CTranslucentButton is used to replace the CBitmapButton, and CTranslucentProgressBar is used to replace the CProgressCtrl.

For the standard controls and Active controls, you must put them on the standard dialog. Because the standard dialog covers the translucent dialog, the translucent controls cannot process the user input. How to solve it? The solution is making the standard dialog fully transparent. The API SetLayeredWindowAttributes with the zero alpha value can help you. But all the controls on it are also fully transparent.

But how to make the standard dialog fully transparent while the controls on it are opaque? This can be done by calling SetLayeredWindowAttributes with the color-key. In the OnInitDialog of the standard dialog, the API SetLayeredWindowAttributes is called with a certain color. In the processing of the message WM_CTLCOLOR with nCtlColor == CTLCOLOR_DLG, if it returns the solid brush that has the specified color, the standard dialog is fully transparent while the controls on it are also opaque.

You can get more details by looking into the source code.

Using the Code in Native C++ / MFC

Step 1

Copy all the files in /Core/*.* to your project.

Step 2

You need an image file to be the dialog background. You'd better choose PNG or TIFF which support the alpha channel. The image file can be embedded into a resource or placed on disk, judged by yourself.

Step 3

Design your standard dialog in the Resource View. In the Properties window, set the following properties:

Border: None
Overlapped Window: False
Style: Popup 

You'd better choose a certain color (i.e. transparent color) as the color-key, and drag some standard controls or ActiveX controls to it. Replace the dialog base class from CDialog to CStandardDialog.

// Here, the transparent color is green.

CDemoStandardDlg::CDemoStandardDlg(CWnd* pParent /*=NULL*/)
    : CStandardDialog(CDemoStandardDlg::IDD, RGB(0, 255, 0), pParent)
{

}

Step 4

Design your translucent dialog in the Resource View. In the Properties window, set the following properties:

Overlapped Window: False
Style: Overlapped 

Replace the dialog base class from CDialog to CTranslucentDialog.

// Load from disk file

CDemoTranslucentDlg::CDemoTranslucentDlg(LPCTSTR lpszFile, CWnd* pParent /*=NULL*/)
	: CTranslucentDialog(CDemoTranslucentDlg::IDD, lpszFile, pParent)
{
}

// Load from resource 
CDemoTranslucentDlg::CDemoTranslucentDlg(UINT nImgID, LPCTSTR lpszType
	/*=_T("PNG")*/, HINSTANCE hResourceModule/*=NULL*/, CWnd* pParent /*=NULL*/)
	: CTranslucentDialog(CDemoTranslucentDlg::IDD, nImgID, 
	lpszType, hResourceModule, pParent)
{
}

Step 5 (optional)

If you need some translucent controls, drag some controls (like button, checkbox, progress bar) to the translucent dialog. Subclasses your translucent controls to the corresponding CTranslucentWnd class, like subclass CButton to CTranslucentButton. The following demo source is from the demo program:

// In the CDemoTranslucentDlg.h
    CTranslucentButton m_btnTest;
    CTranslucentProgressBar m_ctrlProgress;

// In the CDemoTranslucentDlg.cpp
void CDemoTranslucentDlg::DoDataExchange(CDataExchange* pDX)
{
    CTranslucentDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_BUTTON1, m_btnTest);
    DDX_Control(pDX, IDC_PROGRESS, m_ctrlProgress);
}

Step 6

Override the method CreateStandardDialog and OnInitChildrenWnds of your translucent dialog class. The method CreateStandardDialog is in charge of creating the corresponding standard dialog, and the method OnInitChildrenWnds is in charge of setting the translucent controls' properties and registering them to the translucent dialog. The following demo source is from the demo program:

// In the CDemoTranslucentDlg.cpp
CStandardDialog* CDemoTranslucentDlg::CreateStandardDialog()
{
	return ::new CDemoStandardDlg(this);
}

void CDemoTranslucentDlg::OnInitChildrenWnds()
{
	LPCTSTR szImageList[TWS_BUTTON_NUM] = { _T("res\\close_normal.PNG"), 
		_T("res\\close_disable.png"), _T("res\\close_over.PNG"), 
		_T("res\\close_down.PNG"), 0};
	m_btnTest.LoadImageList(szImageList);
	RegisterTranslucentWnd(&m_btnTest);

	m_ctrlProgress.MoveWindow(400, 400, 146, 61, TRUE);
	m_ctrlProgress.SetPos(50);
	m_ctrlProgress.SetFgImage(_T("res\\progress.png"));
	RegisterTranslucentWnd(&m_ctrlProgress);
}

Something Important

The article is based on the Jerry.Wang's article, and uses his CUtility class to load image. Thank you very much, Jerry.Wang.

The source code uses the GdiPlus to draw the translucent controls, so you must setup the Gdiplus environment before using my code.

The source code only provides two kinds of translucent controls. You can extend the CTranslucentWnd to support some other controls. But in my own projects, they are enough. If you can provide some other translucent controls, please share them with me.

If some controls on the standard dialog have some pixels whose colors are the same as the transparent color of the dialog, the pixels are also fully transparent. You can make use of the feature to create some effects, like making some controls become irregular.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

D.K.Wang
Team Leader
China China
D.K.Wang is working for a leading interactive entertainment media company located in Shanghai, China. Skilled in Windows C++, MFC, WTL, PHP etc. Started with professional games development since 2005, now devoted to the core functionality such as graphics rendering, physics simulation and scene management for a household game engine.

Comments and Discussions

 
Question进度条卡死窗口操作! Pinmemberkukuf62120-Jan-14 5:15 
QuestionI cannot download source code, why? Pinmemberle_tian6823-Dec-13 6:51 
BugToo many memory leaks and GDI calling errors PinmemberTomPeakz15-Dec-13 4:03 
QuestionTranslucent controls moved when translucent dialog is dragged [modified] Pinmemberjrl1378246757-Oct-13 19:18 
QuestionMemory Leak in TranslucentDialog::UpdateView PinmemberTill Toenshoff3-Sep-13 18:25 
AnswerRe: Memory Leak in TranslucentDialog::UpdateView PinmemberTill Toenshoff10-Sep-13 5:06 
QuestionWhy must the translucent dialog be created with WS_OVERLAPPED? PinmemberZhixiang Zhu1-Aug-13 23:10 
GeneralMy vote of 5 Pinmemberqazxsw889822-Jan-13 23:00 
QuestionCan you provide a sample to show web page? thank you. Pinmemberpinchen23-Sep-12 22:24 
Question透明按钮是放在TranslucentDialog,而其他一些控件却放在StandardDialog,数据交互的时候很麻烦 Pinmemberpangguigao27-Aug-12 2:11 
AnswerRe: 透明按钮是放在TranslucentDialog,而其他一些控件却放在StandardDialog,数据交互的时候很麻烦 PinmemberMember 824082226-Oct-13 6:11 
QuestionGOOD JOB PinmemberHaflBit31-Jul-12 23:08 
Questionwindow can't be dragged, why? Pinmemberbeyonddoor14-Jun-12 22:43 
Hi, your post really helps, and i use your project in my program, i find that the main translucent window can't be dragged, after debugging it, the standard window receives mouse messages (such as WM_MOUSEMOVE), but the translucent window don't. In your demo project, the situation is totally different, and i don't know why.
Also, the return values of ::IsDialogMessage for the above 2 windows are different,
::IsDialogMessage(hwndStandard, WM_MOUSEMOVE) == TRUE
.
GeneralMy Vote of 5 Pinmembercosfrist13-Jun-12 3:13 
QuestionGreat article but usage of the Translucent controls in demo would have been great. [modified] PinmemberTyfix28-Apr-12 5:05 
Questionplease share google like of sample to me Pinmembermcodeproject33437-Sep-11 0:21 
General如何做一个镂空窗体 Pinmemberunidoz1-Jun-11 19:01 
GeneralRe: 如何做一个镂空窗体 Pinmembershenyingj@gmail.com4-Aug-11 0:46 
GeneralMy vote of 5 Pinmemberhangh1-Apr-11 17:42 
QuestionDalog crashed when minimizing windows continually. Pinmemberfisker.cui25-Mar-11 22:26 
AnswerRe: Dalog crashed when minimizing windows continually. PinmemberMember 273388418-Jul-12 6:02 
Questioncan provide the source of TranslucentDialogLib.exe in demo Pinmemberbloken9-Mar-11 22:45 
GeneralThis is beautiful ! Pinmemberevan36910-Feb-11 16:41 
GeneralCompiler errors when using MFC in Static Library PinmemberNico Cuppen7-Feb-11 6:26 
GeneralRe: Compiler errors when using MFC in Static Library PinmemberNico Cuppen10-Feb-11 0:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 9 Feb 2010
Article Copyright 2009 by D.K.Wang
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid