DwmExtendFrameIntoClientArea без Aero Glass - PullRequest
       28

DwmExtendFrameIntoClientArea без Aero Glass

11 голосов
/ 10 февраля 2010

Использование вызова API DwmExtendFrameIntoClientArea с включенным 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.

Ответы [ 3 ]

7 голосов
/ 03 сентября 2010

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

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

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

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

enter image description here

Примечание: Для получения дополнительной информации о классах, деталях и состояниях см. Классы, детали и состояния Aero Style

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

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

и получите код цвета 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 голосов
/ 10 марта 2013

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

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
2 голосов
/ 10 марта 2010

Вы должны нарисовать его, чтобы он был похож на рамку.

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

Тогда вам придется отделить способ рисования окна, если DWM включен, вы используете DwmExtendFrameIntoClientArea, если он отключен, вы сами рисуете «рамку».

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

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

...