Поделиться через


Расширение стеклянной рамки в приложении WPF

В этом разделе показано, как расширить стеклянную рамку Windows Vista в клиентской области приложения Windows Presentation Foundation (WPF).

Заметка

Этот пример будет работать только на компьютере Windows Vista под управлением диспетчера окон рабочего стола (DWM) с включенным стеклом. Выпуск Windows Vista Home Basic не поддерживает прозрачный стеклянный эффект. Области, которые в других выпусках Windows Vista обычно отображаются с прозрачным стеклянным эффектом, в этом издании отображаются непрозрачными.

Увеличенная стеклянная рамка в адресной строке

На следующем рисунке показана рамка стекла, расширенная в адресную строку Internet Explorer 7:

снимок экрана, показывающий, как стеклянная рамка простирается за адресной строкой IE7.

Чтобы расширить рамку окна в приложении WPF, требуется доступ к неуправляемому API. В следующем примере кода выполняется вызов платформы (pinvoke) для двух API, необходимых для расширения кадра в клиентской области. Каждый из этих 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. MARGINS используется для того, чтобы сообщить DWM, сколько дополнительных кадров должно быть расширено в клиентской области.

Расширенный стеклянный кадр для загруженного события

Чтобы использовать функцию DwmExtendFrameIntoClientArea, необходимо получить дескриптор окна. В WPF дескриптор окна можно получить из свойства Handle объекта HwndSource. В следующем примере кадр расширяется в клиентскую область во время события 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;
   }
}

Расширенная стеклянная рамка в области клиента

В следующем примере показано простое окно, в котором рамка расширяется в клиентской области. Рамка расширена за верхней границей, содержащей два объекта 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.

См. также