半透明对话框的实现与优化

在现代的图形用户界面(GUI)设计中,半透明对话框为用户提供了更加丰富的视觉体验。本文将展示如何创建具有标准控件、ActiveX控件(如WebBrowser控件、Flash控件)以及与Windows 2000及更高版本兼容的半透明控件的对话框。

Jerry.Wang在他的文章《Cool, Semi-transparent and Shaped Dialogs with Standard Controls for Windows 2000 and Above》中提出了一种实现半透明对话框的方法。他创建了两个对话框:一个用于处理用户输入事件和Windows消息(真实对话框),另一个用于展示(假对话框)。假对话框通过CreateWindowEx函数创建,使用WS_EX_LAYEREDWS_EX_TRANSPARENTWS_EX_NOACTIVATE样式,并始终保持与真实对话框相同的大小和位置。真实对话框几乎透明,因为它的透明度值通过SetLayeredWindowAttributes函数修改为5。

现有实现的问题

尽管Jerry.Wang的方法在视觉上令人印象深刻,但它存在一些限制:

  • 对话框不是真正的形状化对话框,即鼠标事件的检测不是基于对话框的形状和透明度。这意味着,对话框中颜色键或透明度值为零的区域不会传递鼠标消息。
  • 并非所有标准控件都得到支持。一些控件,如滑块,不能与WM_PRINT消息一起工作,导致这些控件无法正确显示。
  • ActiveX控件不受支持。ActiveX控件如WebBrowser控件和Flash控件支持广泛的OLE功能,并且可以定制以适应多种软件需求,但它们也不能与WM_PRINT消息一起工作。
  • 如果对话框需要更新一个像素,整个窗口将被刷新。因此,如果对话框非常大且复杂,或者有许多子控件,可能会导致性能问题。

提出的解决方案

为了解决上述问题,提出了一种新的方法。以下是实现机制的示意图:

半透明对话框使用WS_EX_LAYEREDWS_OVERLAPPED样式创建。在创建时,通过CreateWindowEx函数创建一个标准对话框,使用WS_EX_LAYEREDWS_POPUP、无边框、无大小框和无对话框框架的样式。半透明对话框负责处理半透明背景和半透明控件;标准对话框负责处理标准控件和ActiveX控件。标准对话框始终保持与半透明对话框相同的大小和位置。

实现步骤

以下是使用原生C++/MFC实现半透明对话框的步骤:

  1. 将/Core/*.*中的所有文件复制到项目中。
  2. 需要一个图像文件作为对话框背景。最好选择支持alpha通道的PNG或TIFF格式。图像文件可以嵌入到资源中,也可以放置在磁盘上,由自行决定。
  3. 在资源视图中设计标准对话框。在属性窗口中,设置以下属性:
    • 边框:无
    • 重叠窗口:否
    • 样式:弹出
    最好选择一种颜色(即透明颜色)作为颜色键,并拖动一些标准控件或ActiveX控件到它上面。将对话框基类从CDialog更改为CStandardDialog
  4. 在资源视图中设计半透明对话框。在属性窗口中,设置以下属性:
    • 重叠窗口:否
    • 样式:重叠
    将对话框基类从CDialog更改为CTranslucentDialog
  5. (可选)如果需要一些半透明控件,请将一些控件(如按钮、复选框、进度条)拖动到半透明对话框上。将半透明控件子类化到相应的CTranslucentWnd类,如将CButton子类化为CTranslucentButton。以下演示源代码来自演示程序: // 在 CDemoTranslucentDlg.h 中 CTranslucentButton m_btnTest; CTranslucentProgressBar m_ctrlProgress; // 在 CDemoTranslucentDlg.cpp 中 void CDemoTranslucentDlg::DoDataExchange(CDataExchange* pDX) { CTranslucentDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_BUTTON1, m_btnTest); DDX_Control(pDX, IDC_PROGRESS, m_ctrlProgress); }
  6. 覆盖半透明对话框类中的CreateStandardDialogOnInitChildrenWnds方法。CreateStandardDialog方法负责创建相应的标准对话框,OnInitChildrenWnds方法负责设置半透明控件的属性并将它们注册到半透明对话框。以下演示源代码来自演示程序: // 在 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); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485