没有Aero Glass的DwmExtendFrameIntoClientArea

使用启用Aero Glass的DwmExtendFrameIntoClientArea API调用可以正常工作。 但是,我希望它也可以在Aero Glass被禁用时工作,就像它在Windows控制面板中的工作方式一样:

在此处输入图像描述

请注意框架已扩展到客户区域,即使Aero Glass已禁用? 当我在我的应用程序中进行DwmExtendFrameIntoClientArea API调用时,返回的HRESULT肯定不成功,我的应用程序最终看起来像这样:

http://img197.imageshack.us/img197/9629/clientapplication.png

通常,启用Aero Glass后,边框会向下延伸到导航按钮下方,就像在控制面板中一样。 我该怎么做呢? DwmExtendFrameIntoClientArea显然无法正常工作。

顺便说一句,如果它是相关的,我的应用程序是一个WPF应用程序。

尼尔的回答是正确的; 当组合被禁用时,你必须自己绘制该区域。

我可以向我展示我在表单顶部的面板的绘制处理程序中的代码 – 通常负责绘制0x00000000透明黑色以使玻璃显示的面板:

伪代码:

 procedure DrawGlassHeaderArea(g: Graphics; r: Rectangle; IsFormFocused: Boolean); const clFakeGlassColor = $00EAD1B9; //(185, 209, 234) This is the fake foreground glass color (for use when composition is disabled) clFakeGlassColorUnfocused = $00F2E4D7; //(215, 228, 242) This is the fake background glass color (for use when composition is disabled) begin if Dwm.IsCompositionEnabled then begin g.FillRectangle(r, 0x00000000); //fill rectangle with transparent black end else //Composition disabled; fake it like Microsoft does //The color to use depends if the form has focused or not Color glassColor; if (IsFormFocused) then c = clFakeGlassColor else c = clFakeGlassColorUnfocused; g.FillRectangle(r, glassColor); //fill rectangle with fake color //Now we have to draw the two accent lines along the bottom Color edgeHighlight = ColorBlend(Colors.White, glassColor, 0.33); //mix 33% of glass color to white Color edgeShadow = ColorBlend(Colors.Black, glassColor, 0.33); //mix 33% of glass color to black //Draw highlight as 2nd-last row: g.DrawLine(edgeHighlight, Point(r.Left, r.Bottom-2), Point(r.Right, r.Bottom-2); //Draw shadow on the very last row: g.DrawLine(edgeHighlight, Point(r.Left, r.Bottom-1), Point(r.Right, r.Bottom-1); end; end; 

样品用法

 procedure MyForm.PaintBox1Paint(PaintEventArgs e) begin DrawGlassHeaderArea(e.Graphics, PaintBox1.ClientRectangle, this.HasFocus); end; 

奖金截图

在此处输入图像描述

2014年7月9日更新

@JakePetroules是对的,我错了。 用于假玻璃的“蓝色” 不是硬编码到Windows中。 并且可以使用GetThemeColor访问它。

我编写了可用于Window类的所有可用颜色( TMT_COLOR ):

在此处输入图像描述

注意:有关类,部件和状态的详细信息,请参阅Aero样式类,部件和状态

使用时:

  • Window
  • 部分WP_CAPTION
  • 状态不适用(StateID不用于Caption部分,也不用于整个Window类)

并获取颜色代码propertyID

  • TMT_FILLCOLORHINT :用于窗口具有焦点时
  • TMT_BORDERCOLORHINT :用于窗口没有焦点时

你得到两个重要的颜色:

在此处输入图像描述

伪代码我现在用来获得假玻璃颜色:

 public Color GetFakeClassColor(Boolean isWindowFocused=true) { static Color fakeGlass= 0x00B8D0E9; //the correct answer anyway if ((GetThemeAppProperties() && STAP_ALLOW_CONTROLS) == 0) return fakeGlass; hTheme = OpenThemeData(GetDesktopWindow(), "Window"); if (hTheme = 0) return fakeGlass; Int32 propID; if (isWindowFocused) propID= TMT_FILLCOLORHINT; //The color used as a fill color hint for custom controls. else propID= TMT_BORDERCOLORHINT; //The color used as a border color hint for custom controls. DWORD rgb; if (Failed(GetThemeColor(hTheme, WP_CAPTION, 0, propID, ref rgb)) return fakeGlass; Result = new Color(rgb); } 

实际上,因为我使用Delphi,我的实际代码是:

 function GetFakeGlassColor(IsWindowFocused: Boolean=True): TColor; var ted: TThemedElement; hTheme: THandle; propID: Integer; rgb: DWORD; begin Result := $00B8D0E9; //the correct answer anyway //We can't use the ThemeServcies.ThemesEnabled, as that mistakenly checks for version 6 of the common controls library //Themes can be enabled without using ComCtl V6, or common controls at all if not ThemeServices.ThemesAvailable then Exit; if (GetThemeAppProperties and STAP_ALLOW_CONTROLS) = 0 then Exit; htheme := ThemeServices.Theme[teWindow]; if hTheme = 0 then Exit; if IsWindowFocused then propID := TMT_FILLCOLORHINT //The color used as a fill color hint for custom controls. else propID := TMT_BORDERCOLORHINT; //The color used as a border color hint for custom controls. if Failed(GetThemeColor(hTheme, WP_CAPTION, 0, propID, {var}rgb)) then Exit; Result := rgb; end; 

你必须自己把它描绘成框架状。

您必须使用DwmIsCompositionEnabled来检查DWM是否已启用并处理WM_DWMCOMPOSITIONCHANGED以检测DWM状态已更改。

然后你必须分开绘制窗口的方式,如果启用DWM你使用DwmExtendFrameIntoClientArea ,如果它被禁用你自己绘制“框架”。

我不知道如何在WPF中复制Aero框架(在我的应用程序中,我有自己的配色方案,我没有使用Auro框架)。

这很烦人但是当DWM被禁用时,系统会回退到XP风格的绘图,并且DWM的服务都不起作用 – 即使那些与玻璃效果无关的服务也是如此。

你需要自己绘制窗口背景。 您不应该像以前的post建议的那样对颜色进行硬编码,而是使用主题函数来检索它们,如下所示(半伪代码):

 DWORD rgb; HANDLE hTheme = OpenThemeData(GetDesktopWindow(), L"WINDOW"); GetThemeColor(hTheme, WP_CAPTION, CS_ACTIVE,  ? TMT_FILLCOLORHINT : TMT_BORDERCOLORHINT, &rgb); // Can use these functions to retrieve the individual RGB values BYTE r = GetRValue(rgb); BYTE g = GetGValue(rgb); BYTE b = GetBValue(rgb); 

即使用户更改控制面板中的标题栏颜色,这些颜色仍将保持正确(与使用COLOR_ACTIVECAPTION / COLOR_GRADIENTACTIVECAPTION不同)。 在尝试获取主题颜色之前,您还应该使用IsThemeActive()检查主题是否处于活动状态。

用于快速参考的常量值:

  • WP_CAPTION:1
  • CS_ACTIVE:1
  • TMT_FILLCOLORHINT:3821
  • TMT_BORDERCOLORHINT:3822