WPF アプリケーションへのガラス フレームの拡張

このトピックでは、Windows Presentation Foundation (WPF) アプリケーションのクライアント領域に Windows Vista ガラス フレームを拡張する方法について説明します。

この例は、ガラスが有効になっているデスクトップ ウィンドウ マネージャー (DWM) を実行している Windows Vista コンピューターでのみ機能します。 Windows Vista Home Basic エディションでは、透明ガラス効果はサポートされていません。 通常、Windows Vista の他のエディションで透明なガラス効果でレンダリングされる領域は不透明にレンダリングされます。

アドレス バーの拡張ガラス フレーム

次の図は、Internet Explorer 7 のアドレス バーに拡張されたガラス フレームを示しています。

IE7 アドレス バーの背後に拡張されたガラス フレームを示すスクリーンショット。

WPF アプリケーションでガラス フレームを拡張するには、アンマネージ API へのアクセスが必要です。 次のコード例では、フレームをクライアント領域に拡張するために必要な 2 つの API のプラットフォーム呼び出し (pinvoke) を実行します。 これらの各 API は、NonClientRegionAPIというクラスで宣言されます。

[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
    public int cxLeftWidth;      // width of left border that retains its size
    public int cxRightWidth;     // width of right border that retains its size
    public int cyTopHeight;      // height of top border that retains its size
    public int cyBottomHeight;   // height of bottom border that retains its size
};

[DllImport("DwmApi.dll")]
public static extern int DwmExtendFrameIntoClientArea(
    IntPtr hwnd,
    ref MARGINS pMarInset);
<StructLayout(LayoutKind.Sequential)>
Public Structure MARGINS
    Public cxLeftWidth As Integer ' width of left border that retains its size
    Public cxRightWidth As Integer ' width of right border that retains its size
    Public cyTopHeight As Integer ' height of top border that retains its size
    Public cyBottomHeight As Integer ' height of bottom border that retains its size
End Structure

<DllImport("DwmApi.dll")>
Public Shared Function DwmExtendFrameIntoClientArea(ByVal hwnd As IntPtr, ByRef pMarInset As MARGINS) As Integer
End Function

DwmExtendFrameIntoClientArea は、フレームをクライアント領域に拡張する DWM 関数です。 ウィンドウ ハンドルと MARGINS 構造体の 2 つのパラメーターを受け取ります。 MARGINS は、フレームをクライアント領域に拡張する必要がある量を DWM に通知するために使用されます。

Loaded イベントで拡張されたガラスフレーム

DwmExtendFrameIntoClientArea 関数を使用するには、ウィンドウ ハンドルを取得する必要があります。 WPF では、ウィンドウ ハンドルは HandleHwndSource プロパティから取得できます。 次の例では、ウィンドウの Loaded イベントのクライアント領域にフレームが拡張されています。

void OnLoaded(object sender, RoutedEventArgs e)
{
   try
   {
      // Obtain the window handle for WPF application
      IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
      HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
      mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);

      // Get System Dpi
      System.Drawing.Graphics desktop = System.Drawing.Graphics.FromHwnd(mainWindowPtr);
      float DesktopDpiX = desktop.DpiX;
      float DesktopDpiY = desktop.DpiY;

      // Set Margins
      NonClientRegionAPI.MARGINS margins = new NonClientRegionAPI.MARGINS();

      // Extend glass frame into client area
      // Note that the default desktop Dpi is 96dpi. The  margins are
      // adjusted for the system Dpi.
      margins.cxLeftWidth = Convert.ToInt32(5 * (DesktopDpiX / 96));
      margins.cxRightWidth = Convert.ToInt32(5 * (DesktopDpiX / 96));
      margins.cyTopHeight = Convert.ToInt32(((int)topBar.ActualHeight + 5) * (DesktopDpiX / 96));
      margins.cyBottomHeight = Convert.ToInt32(5 * (DesktopDpiX / 96));

      int hr = NonClientRegionAPI.DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins);
      //
      if (hr < 0)
      {
         //DwmExtendFrameIntoClientArea Failed
      }
   }
   // If not Vista, paint background white.
   catch (DllNotFoundException)
   {
      Application.Current.MainWindow.Background = Brushes.White;
   }
}

クライアント領域における拡張ガラスフレーム

次の例は、フレームがクライアント領域に拡張される単純なウィンドウを示しています。 フレームは、2つの TextBox オブジェクトを含む上の境界線の後ろまで拡張されます。

<Window x:Class="SDKSample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Extended Glass in WPF" Height="300" Width="400"
    Loaded="OnLoaded" Background="Transparent"
    >
  <Grid ShowGridLines="True">
    <DockPanel Name="mainDock">
      <!-- The border is used to compute the rendered height with margins.
           topBar contents will be displayed on the extended glass frame.-->
      <Border Name="topBar" DockPanel.Dock="Top" >
        <Grid Name="grid">
          <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="100" Width="*"/>
            <ColumnDefinition Width="Auto"/>
          </Grid.ColumnDefinitions>
          <TextBox Grid.Column="0" MinWidth="100" Margin="0,0,10,5">Path</TextBox>
          <TextBox Grid.Column="1" MinWidth="75" Margin="0,0,0,5">Search</TextBox>
        </Grid>
      </Border>
      <Grid DockPanel.Dock="Top" >
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="0" AcceptsReturn="True"/>
      </Grid>
    </DockPanel>
  </Grid>
</Window>

次の図は、WPF アプリケーションに拡張されたガラス フレームを示しています。

WPF アプリケーションに拡張されたガラス フレームを示すスクリーンショット。

こちらも参照ください