11

在启用 Aero Glass 的情况下使用DwmExtendFrameIntoClientAreaAPI 调用效果很好。但是,我希望它在 Aero Glass 被禁用时也能工作,就像它在 Windows 控制面板中的工作方式一样:

在此处输入图像描述

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

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

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

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

4

3 回答 3

7

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

我可以向您展示我在表单顶部面板的油漆处理程序中拥有的代码 - 该面板通常负责绘制 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
  • State : n/a (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;
于 2010-09-03T17:53:31.930 回答
2

You need to paint the window background yourself. You should not actually hard-code the colors as previous posts have suggested, but use the theme functions to retrieve them, like so (semi-pseudocode):

DWORD rgb;
HANDLE hTheme = OpenThemeData(GetDesktopWindow(), L"WINDOW");
GetThemeColor(hTheme, WP_CAPTION, CS_ACTIVE,
    <is active window> ? 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);

These colors will remain correct even if the user changes title bar colors in the control panel (unlike using COLOR_ACTIVECAPTION / COLOR_GRADIENTACTIVECAPTION). You should also check that themes are active using IsThemeActive() before attempting to get theme colors.

The values of the constants for quick reference:

  • WP_CAPTION: 1
  • CS_ACTIVE: 1
  • TMT_FILLCOLORHINT: 3821
  • TMT_BORDERCOLORHINT: 3822
于 2013-03-10T00:50:31.250 回答
2

你必须把它画成像框架一样的自己。

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

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

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

这很烦人,但是当 DWM 被禁用时,系统会退回到 XP 样式的绘图,并且 DWM 的任何服务都不起作用——即使是那些与玻璃效果无关的服务。

于 2010-03-10T10:36:20.973 回答