In UI development, we have to implement some nice effects usually, and making some controls to be transparent is a problem that we often meet. In this article, I present an approach to implement the transparency of controls. The source code includes the class
CTransparentHelper based on the Win32 API, and it can be used in MFC, ATL, WTL, Win32 applications, or may be some other framework. I developed a new version because I used it at my work, so if you have any suggestions, bug reports, or problems, please send it to me. And, you can also visit my technical blog to get more information.
I wrote this code because I needed some transparent controls such as buttons, slider controls, and progress controls. I found that some methods available online are not effective when the parent window moves, or when the control moves; this is a problem when we want to use a transparent control in a resizable dialog. So, I wrote the
CTransparentHelper; you can have a smooth transparency effect when
MoveWindow is called, and the class is suitable for all controls.
- No framework dependency.
- Can be used for controls of different types.
- Can be used for multi-layer transparency.
- Easy to use in the current code.
Using the code
Before introducing how to use the source code, I suggest using a memory DC to store the background DC of the parent dialog. This is convenient for the transparency of child controls, and also boosts the efficiency of drawing. For detailed information, please refer to the source code.
Include “TransparentHelper.h” in the file of the control which needs to be transparent. And, add an object of type
class CSliderCtrlEx : public CSliderCtrl
Initialize the object of CTransparentHelper
Call the function TransparentBk of CTransparentHelper when you need
BOOL CSliderCtrlEx::OnSliderDrawChannel( CDC* pDC, CRect& rect, UINT nState)
if ( m_objTrans.IsValid() )
m_objTrans.TransparentBk( pDC->GetSafeHdc(), GetSafeHwnd());
Add code to the control’s parent window
Sometimes, the parent window is a dialog. I need to deal with the message
WM_TRANSPARENT_BK, which is sent from the transparent control in order to get back the DC.
LRESULT CTransparentControlDlg::OnTransaprentBk( WPARAM wParam, LPARAM lParam)
HDC hdc = ( HDC)wParam;
HWND hwnd = ( HWND)lParam;
m_pMemDC is the memory DC of the dialog, which will be changed when the dialog’s size changes.
Notfiy children when background changes
When the dialog’s memory DC changes, it must notify the child which has a transparent tag.
The message WM_NOTIFY_TRANSPARENT
The transparent control needs to deal with the message
WM_NOTIFY_TRANSPARENT sent by the parent, when the background changes.
LRESULT CSliderCtrlEx::OnNotifyTransparent( WPARAM wParam, LPARAM lParam)
if ( ::IsWindowEnabled( GetSafeHwnd()))
Remark: For some controls under some drawing methods (e.g.,
Invalidate will not cause a real repaint. So, I adde the
WM_NOTIFY_TRANSAPRENT message to make it compatible. If the transparent control will repaint itself after calling
Invalidate, it needn’t deal with the message.