65.9K
CodeProject 正在变化。 阅读更多。
Home

为 Windows 2000 及以上版本打造的炫酷、半透明且异形对话框及标准控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (88投票s)

2009年3月15日

CPOL

3分钟阅读

viewsIcon

2943916

downloadIcon

33042

本文尝试寻找一种在分层窗口上显示 Windows 标准控件的方法。提供了原生 MFC 和 WinForms 的源代码。

引言

首先,让我向您展示一些从演示程序截取的屏幕截图。

SemiTranDlgWithCtrls/8.jpg

SemiTranDlgWithCtrls/3.jpg

该程序演示了与 **Windows 2000 及更高版本兼容** 的半透明对话框。

背景

分层窗口(从 Windows NT 5.0 开始支持)提供了一种创建具有复杂形状和 Alpha 混合效果的窗口的方法。主要的挑战是如何在分层窗口上显示标准控件。

以下显示了工作机制

SemiTranDlgWithCtrls/4.jpg

在创建对话框时,通过 CreateWindowEx 创建一个带有 WS_EX_LAYEREDWS_EX_TRANSPARENTWS_EX_NOACTIVATE 样式的假窗口。通过 SetLayeredWindowAttributes 将真实窗口的 Alpha 值修改为 5,使其几乎透明。

真实窗口负责处理用户输入事件和 Windows 消息;假窗口负责呈现。假窗口始终保持与真实窗口相同的大小/位置。

我们如何在假窗口上显示标准控件?当需要刷新显示时,首先绘制背景图像。然后,通过发送 WM_PRINT 消息捕获所有子控件,并在假窗口的相同位置绘制它们。特别是对于 EDIT 控件、EditBox/Editable ComboBox 等,我们需要自己绘制插入符号。

我们何时应该刷新显示?当 UI 有更新时,我们需要刷新假窗口。在演示中,它递归地钩住所有子控件,并通过 SetWindowLongPtrGWLP_WNDPROC 参数更改 WNDPROC 地址。

您可以通过查看源代码获得更多详细信息。

在原生 C++/MFC 中使用代码

第一步

/Src/*.* 中的所有文件复制到您的项目中。

第二步

您需要一个图像文件作为对话框背景。最好选择支持 Alpha 通道的 PNG 或 TIFF。图像文件可以嵌入到资源中,也可以放在磁盘上,由您自己决定。

最后一步

将对话框基类从 CDialog 替换为 CImgDialogBase

// Load from disk file
CDemo2Dlg::CDemo2Dlg(CWnd* pParent /*=NULL*/)
    : CImgDialogBase( CDemo2Dlg::IDD
    , CUtility::GetModulePath() + _T("background.png")
    , pParent
    )
{

}

// Or load from resource
CDemo3Dlg::CDemo3Dlg(CWnd* pParent /*=NULL*/)
    : CImgDialogBase(CDemo3Dlg::IDD
    , IDB_PNG_DLG2
    , _T("PNG")
    , AfxGetResourceHandle()
    , pParent
    )
{

}

在 WinForms/.NET 中使用代码

第一步

/Src/*.* 目录中的文件复制到您的项目中。

第二步

您需要一个图像文件作为对话框背景。最好选择支持 Alpha 通道的 PNG 或 TIFF。

最后一步

将对话框基类从 Form 替换为 ImageDlgBase

public partial class Form2 : CoolImageDlg.ImageDlgBase
{
    public Form2()
    {
        base.DlgBgImg = ImgDlgSample.Properties.Resources.DemoDlgBg2;
        //......
    }
}

重要提示

该对话框的工作方式是,如果有一个像素需要更新,则整个窗口都会被刷新。因此,如果对话框非常大且复杂,或者有很多子控件,可能会导致性能问题。

某些控件无法与 WM_PRINT 一起使用;在这种情况下,控件将无法正确显示。换句话说,并非所有控件都受支持。

示例代码使用了来自 Zoltan Csizmadia 的 GDI+ 辅助类。对于不想使用 GDIPlus.dll 的用户,CxImage 是另一个选择。

大多数计算机的显示器设置为 96 DPI。对于那些使用不寻常 DPI 设置的计算机,请注意,该演示不适用于此类设置,子控件将错位。如果您确实需要支持不寻常的 DPI,则需要添加自己的代码来重新布局子控件。

© . All rights reserved.