11

Aero Glass を有効にして API 呼び出しを使用すると、DwmExtendFrameIntoClientArea問題なく動作します。ただし、Windows コントロール パネルでの動作と同様に、Aero Glass が無効になっている場合にも動作するようにしたいと考えています。

ここに画像の説明を入力

Aero グラスが無効になっているにもかかわらず、フレームがクライアント領域に拡張されていることに注意してください。アプリケーションで API 呼び出しを行うDwmExtendFrameIntoClientAreaと、返された HRESULT は間違いなく成功せず、アプリケーションは次のようになります。

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

通常、Aero Glass を有効にすると、境界線はコントロール パネルのようにナビゲーション ボタンの下まで伸びます。どうすればいいですか?DwmExtendFrameIntoClientArea明らかに機能していません。

ところで、関係があれば、私のアプリケーションは WPF アプリケーションです。

4

3 に答える 3

7

Nir の答えは正しいです。コンポジションが無効になっている場合は、その領域を自分で描画する必要があります。

フォームの上部にあるパネルのペイント ハンドラーにあるコードを表示できます。パネルは通常、ガラスを表示するために 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: ウィンドウにフォーカスがない場合

2 つの重要な色を取得します。

ここに画像の説明を入力

偽のガラスの色を取得するために現在使用している疑似コード:

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

フレームのように自分でペイントする必要があります。

DwmIsCompositionEnabledDWM が有効になっているかどうかを確認し、 WM_DWMCOMPOSITIONCHANGEDDWM の状態が変化したことを検出するために使用する必要があります。

次に、ウィンドウを描画する別の方法が必要です。DWM が有効になっている場合は を使用しDwmExtendFrameIntoClientArea、無効になっている場合は自分で「フレーム」を描画します。

WPF で Aero フレームを複製する方法がわかりません (私のアプリでは独自の配色があり、Auro フレームを使用していません)。

これは厄介なことですが、DWM を無効にすると、システムは XP スタイルの描画にフォールバックし、DWM のサービスはどれも動作しなくなります (ガラス効果に関係のないものも含む)。

于 2010-03-10T10:36:20.973 に答える
2

ウィンドウの背景を自分でペイントする必要があります。以前の投稿で示唆されているように実際に色をハードコーディングするべきではありませんが、テーマ関数を使用して色を取得する必要があります (半疑似コード):

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_アクティブ: 1
  • TMT_FILLCOLORHINT: 3821
  • TMT_BORDERCOLORHINT: 3822
于 2013-03-10T00:50:31.250 に答える