StyleDialog - 一个带有可选自定义框架的透明对话框类






4.84/5 (20投票s)
StyleDialog 可独立使用,也可与 Style Toolkit 结合使用。
引言
CodeProject 上有几个透明对话框;但是,它们都没有提供一个通用的对话框,允许您在透明区域上绘图。原因在于 Windows 最初并不有效支持透明的 CWnd
对象。
上图显示 StyleDialog 与 Style Toolkit[^] 1.1 版结合使用。但是,StyleDialog 可以有或没有工具包,有或没有透明度。
创建透明对话框的问题
StyleDialog 所需的关键功能是使用透明区域的能力。这意味着您可以在其上绘图、着色和添加控件。
以下是一些常用的方法和相关的缺点
- 在
OnCtlColor
中返回HOLLOW_BRUSH
– 这对于控件来说效果不错,因为应用程序控制背景。它也适用于对话框,只要您不移动它,这使得它相对无用。它还会导致子控件停止接收其OnCtlColor
消息。 - 使用区域 – 这个解决方案效果相当好;但是,您不能使用透明区域。此外,由于您无法对边框进行抗锯齿处理,因此边缘看起来有点粗糙。
- 分层窗口 – 这是创建真正透明窗口的唯一方法。这对于创建淡入淡出效果效果很好,但由于透明度应用于整个
CWnd
,因此您不能将某些东西设置为透明,而将其他东西设置为不透明。 - 分层
CWnd
– 这些解决方案看起来和行为最好,但它们不通用,而且您也不能在透明区域上绘图。
StyleDialog 设计考虑
其他难以克服的问题包括拖动窗口时的抖动,以及当应用程序不处于活动状态时保持正确背景。
为了克服这些问题,StyleDialog 规定了以下设计规则
- 当不处于活动应用程序时,显示替代背景。这解决了应用程序可见但不活动时背景在应用程序下方发生变化的问题。
- 拖动应用程序时,显示替代背景。实际上,StyleDialog 在拖动时可以显示正确的背景,但是分层窗口存在不希望的抖动。
StyleDialog 通过使用不透明的分层窗口并利用它在离屏位图中维护的事实来实现透明度。
使用 StyleDialog
步骤 1 - 在 StyleDialog.h 中配置用法
// comment out this line if Style Toolkit is not used #define USE_STYLE_TOOLKIT // comment out this line if transparency is not supported #define USE_LAYERED_WINDOWS
步骤 2 – 从 StyleDialog 派生对话框
像往常一样使用向导创建基于对话框的应用程序。将所有 CDialog
实例替换为 StyleDialog
。注意:替换时跳过 CAboutDlg
,除非您希望它也成为 StyleDialog
。
对于子对话框,只需将它们声明为 StyleDialog
。请参阅演示程序中的示例。
步骤 3 – 配置 StyleDialog
在调用 OnInitDialog
或 DoModal
之前执行以下操作。
// configure StyleDialog before calling the init function SetTransparent(TRUE); SetControls(ALL_CONTROLS); SetTitle(_T("Style Dialog Demo"));
SetTransparent
启用透明度。默认情况下禁用,因为它不使用时只会浪费带宽。SetControls
告诉StyleDialog
在有自定义框架时使用哪些控件。下面会更详细地描述。默认情况下没有控件。SetTitle
是在使用自定义框架时将在任务栏中显示的标题。默认值是一个空字符串。
步骤 4 – 为对话框添加样式 [可选]
使用 AddBackGroundStyle(style)
将样式加载到对话框中。
StyleDialog 的最小实现
下面的图片和代码来自演示程序的“对话框 3”按钮。
StyleDialog dlg(IDD_DIALOG3); dlg.SetTransparent(TRUE); dlg.SetTitle(_T("Standard Frame")); dlg.DoModal();
此示例使用标准框架,不使用 Style Toolkit。实际上没有必要设置标题,但如果不设置,它只会显示“对话框”。
控制替代背景
如果启用了透明度,当 StyleDialog
不是活动应用程序或窗口正在移动时,它将显示替代背景。替代背景将位于可能已绘制在透明区域上的任何内容下方。
默认情况下,替代背景将是桌面背景颜色的纯色填充。这可以通过以下方法之一覆盖
SetOpaqueColor(clr)
– 将纯色填充更改为另一种颜色。AddOpaqueStyle(style)
– 将填充更改为样式。
“对话框 2”按钮演示了背景样式的用法。
此示例使用不带控件的自定义框架,以及带有半透明 PNG 图像的背景样式。
这显示了非活动状态。它使用相同图像的完全不透明版本作为不透明样式。
创建自定义框架
StyleDialog
在创建自定义框架时需要知道客户矩形的大小。这对于标题栏区域的点击测试和支持重写的 GetClientRect()
函数是必需的。
StyleDialog
维护一个外部框架,可以使用 GetFrameRect
检索,以及一个客户框架,可以使用 GetClientRect
检索。请注意,Windows 不认为这是客户矩形。在绘图或擦除时,有时应该使用 GetFrameRect
或 CDialog::GetClientRect
来获取 Windows 定义的客户矩形。
方法 1 – 使用 SetClientRect
调用 GetFrameRect()
获取外部框架矩形,根据边框和标题栏大小进行调整,然后调用 SetClientRect()
。
方法 2 – 使用资源编辑器
使用资源编辑器并使用静态控件创建客户矩形。这样做的优点是可以在设计对话框时调整标题和边框大小。使用静态图片控件,因为它没有任何偏移量。
将控件的 ID 设置为 SytleDialog
的关键字 ID 之一 – IDC_SC_CLIENT
。当 StyleDialog
在 resource.h 文件中检测到此 ID 时,它将自动创建客户矩形。
还有用于控件的关键字 ID,如下图所示。
如果 StyleDialog
看到任何控件 ID,它将为它们创建 StyleButton
,并加载相关的图像。它还将为每个按钮创建预期功能。
其他注意事项
StyleDialog 不支持最大化;实际上,它禁用了最大化。原则上,这可以支持,但我将来不打算添加此功能。
我并没有真正打算支持带有透明子对话框的透明对话框;然而,它似乎工作正常,并且演示程序实际上就是这样做的。
为了在打开子对话框时避免烧穿效应,可以禁用父级的透明度,然后重新启用。但是,打开和关闭分层窗口可能存在时间问题,因此请谨慎使用此功能。
问题
- 使用自定义框架时最小化和恢复 – 如果您单击任务栏图标,StyleDialog 将进入正确的活动或非活动状态,但它不会最小化和恢复。我认为这与系统菜单没有此功能有关,我希望在将来的版本中修复此问题。
- VC6 用户 – 如果您注释掉分层窗口功能,StyleDialog 将按原样工作。分层窗口将在 Win2K SP3 及更高版本上工作,但您需要获取更新版本的 winuser.h、user32.lib 和 user32.dll。
修订历史
- 版本 1.0 – 2008 年 8 月 3 日
初始发布。