windows - 所有版本的 Windows 上的 Win32 透明控件

标签 windows winapi user-interface

我正在使用纯 Win32 API(无 MFC 或 .NET)开发 Win32 GUI 应用程序。我遇到的问题是使控件显得透明。我提出了一种适用于大多数情况的方法,在 Windows Vista+ 中,我在 WndProc 中执行此操作:

case WM_CTLCOLORSTATIC:
{
    SetBkMode((HDC)wParam, TRANSPARENT);
    return (INT_PTR)::GetStockObject(NULL_PEN);
}
break;

在 Windows XP 中,我在 WndProc 中执行此操作:

case WM_CTLCOLORSTATIC:
{
    HBRUSH hbr = (HBRUSH)DefWindowProc(hDlg, message, wParam, lParam);
    ::DeleteObject(hbr);
    SetBkMode((HDC)wParam, TRANSPARENT);
    return (LRESULT)(HBRUSH)(COLOR_WINDOW);
}

现在这适用于大多数控件,但是我在组框控件顶部的标签上获得透明背景,该控件通过文本绘制组框线。我开始着手处理一个仅用于分组框的案例,但我确信这是一个以前必须解决的问题,我不想重新发明轮子。

是否有一种久经考验的方法可以使控件看起来透明?

谢谢, J

最佳答案

要实现透明控制,您必须注意:

  • 你真的不能。标准的 Windows 控件只是不支持“透明”绘画。
  • 即使你做对了,如果你调整它的大小,对话框也会严重闪烁。
  • 如果主题打开或关闭,以及 Windows 版本之间的变化,使控件透明绘制工作的“技巧”往往会有所不同。

通常使控件“透明”的目的是让控件下的位图皮肤显示出来。实现这种透明度的方法是为控件的背景创建位图。然后使用位图中的 CreatePatternBrush

这段 DialogProc 代码实现了最简单的蒙皮方法,然后将负责绘制对话框的背景以及支持这种绘制形式的大多数控件:

  // _hwnd is the dialogs handle
  // _hbrSkin is a pattern brush handle
  HWND hwndCtl;
  POINT pt;
  HDC hdc;
case WM_CTLCOLORDLG:
  return (INT_PTR)_hbrSkin;
case WM_CTLCOLORSTATIC:
case WM_CTLCOLORBTN:
  hdc = (HDC)wParam;
  SetBkMode(hdc,TRANSPARENT); // Ensure that "static" text doesn't use a solid fill
  pt.x = 0; pt.y = 0;
  MapWindowPoints(hwndCtl,_hwnd,&pt,1);
  SetBrushOrgEx(hdc,-pt.x,-pt.y,NULL);
  return (INT_PTR)_hbrSkin;

重叠的控件将无法正确绘制,因为一个控件会将其“透明”背景绘制在另一个控件之上。您可以通过以下方式减少闪烁:

  • 不允许调整对话框的大小。
  • 在对话框中设置 WS_EX_COMPOSITED 样式,但由于 Windows NT 6 DWM 不支持它,从 Vista 开始它基本上没用了。
  • 在对话框上设置 WS_CLIPCHILDREN 样式或 WS_CLIPSIBLINGS - 这些样式阻止使用组框和选项卡控件,因为它们依赖于控件重叠。
  • 对所有控件进行子类化,使用 WM_PRINTCLIENT 消息将它们绘制到后备缓冲区,然后一次性将准备好的后备缓冲区 blit。努力工作,并非所有控件都支持 WM_PRINTCLIENT。

关于windows - 所有版本的 Windows 上的 Win32 透明控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4430559/

相关文章:

c++ - 您是否可以在不使用GetAsyncKeyState或线程的情况下同时为Windows程序在C++中运行功能的同时获得用户输入?

linux - 嵌入式网络浏览器

windows - 配置 Qt Creator 以使用 Git 的正确方法是什么?

c++ - Windows 的免费内存调试器?

python - 在 Windows 上部署 Python 包,编译依赖项,而不安装 Visual Studio?

c# - 使用c#从另一个进程调用一个函数

c++ - 如何通过其 HWND 句柄更改另一个进程中 TDateTimePicker 控件中当前选定的日期?

delphi - 如何过滤 Windows 中执行的应用程序?

Java GUI 不显示在 Ubuntu 上的 Eclipse 中

ios - 不同 iPhone 尺寸的 UI 资源分辨率,包括 iPhone 6+、iPhone X、iPhone Max