Подтвердить что ты не робот

DwmExtendFrameIntoClientArea без Aero Glass

Использование API DwmExtendFrameIntoClientArea API с поддержкой Aero Glass работает очень хорошо. Тем не менее, я хочу, чтобы он работал, когда Aero Glass также отключен, например, как он работает на панели управления Windows:

enter image description here

Обратите внимание, что кадр расширен в клиентскую область, даже если Aero Glass отключен? Когда я делаю вызов API DwmExtendFrameIntoClientArea в моем приложении, возвращаемый HRESULT определенно не удался, и мое приложение выглядит следующим образом:

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

Как правило, при включенном Aero Glass граница растягивается вниз под навигационными кнопками, например, на панели управления. Как мне это сделать? DwmExtendFrameIntoClientArea явно не работает.

Кстати, если это актуально, мое приложение является приложением WPF.

4b9b3361

Ответ 1

Ответ Нир правильный; когда состав отключен, вы должны сами нарисовать эту область.

Я могу показать вам код, который у меня есть в обработчике краски панели в верхней части моей формы - панель, обычно отвечающая за рисование прозрачного черного 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;

Бонус Скриншот

enter image description here

Обновление 7/9/2014

@JakePetroules был прав, и я ошибся. "Синий", используемый для поддельного стекла, не жестко закодирован в Windows. И доступен, используя GetThemeColor.

Я закодировал все доступные цвета (TMT_COLOR), доступные для класса Window:

enter image description here

Примечание.. Дополнительные сведения о классах, частях и состояниях см. в разделе Классы, части и классы Aero Style Государства

При использовании:

  • Класс: Window
  • Часть: WP_CAPTION
  • Состояние: n/a (StateID не используется для части Caption или всего класса Window)

и выберите цветовой код propertyID:

  • TMT_FILLCOLORHINT: когда фокус фокуса окна
  • TMT_BORDERCOLORHINT: если окно не имеет фокуса

вы получаете два важных цвета:

enter image description here

Псевдокод я теперь используется, чтобы получить поддельный цвет стекла:

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;

Ответ 2

Вы должны нарисовать его как фреймоподобный.

Вы должны использовать DwmIsCompositionEnabled, чтобы проверить, включен ли DWM, и обрабатывать WM_DWMCOMPOSITIONCHANGED для обнаружения состояния DWM.

Затем вам нужно отделить способ рисования окна, если DWM включен, вы используете DwmExtendFrameIntoClientArea, если он отключен, вы сами рисуете "фрейм".

Я не знаю, как дублировать рамку Aero в WPF (в моем приложении у меня есть собственная цветовая схема, и я не использую кадр Auro).

Это раздражает, но когда DWM отключен, система возвращается к рисунку стиля XP, и ни одна из служб DWM не работает, даже те, которые не связаны со стеклянным эффектом.

Ответ 3

Вам нужно покрасить задний фон окна. Вы не должны на самом деле жестко кодировать цвета по мере того, как предлагали предыдущие сообщения, но использовать функции темы для их получения, например (полу-псевдокод):

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);

Эти цвета останутся правильными, даже если пользователь изменяет цвета строки заголовка на панели управления (в отличие от COLOR_ACTIVECAPTION/COLOR_GRADIENTACTIVECAPTION). Вы также должны проверить, что темы активны с помощью IsThemeActive(), прежде чем пытаться получить цвета тем.

Значения констант для быстрой справки:

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