2014-01-13 77 views
1

我有一個看起來像這樣在設計一個WPF窗口大小調整因爲在這兩個元素之間繪製了一個DropShadow。WPF無邊框窗口內利潤

我的問題是,我不能使用WPF的本地工具來重新調整窗口大小。如果我將ResizeMode設置爲CanResize,則手柄是透明的,因此您無法實際抓住它們。如果將ResizeMode設置爲CanResizeWithGrip,則可以看到夾點,但它位於整個窗口的右下角。有沒有什麼辦法可以讓調整大小的手柄顯示內部網格開始的地方,而不是在窗體的外部邊緣?

這裏是把手上的設計師

designer with grip

回答

0

您可以通過創建自定義窗口樣式做到這一點。下面是實現的例子:

DropShadowedWindowStyle.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        x:Class="DropShadowedWindow.DropShadowedWindowStyle"> 
    <Style x:Key="DropShadowedWindowStyle" TargetType="{x:Type Window}"> 
     <Setter Property="WindowStyle" Value="None"></Setter> 
     <Setter Property="AllowsTransparency" Value="True"></Setter> 
     <Setter Property="ResizeMode" Value="CanResize"></Setter> 
     <Setter Property="Background" Value="#FFF"></Setter> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type Window}"> 
        <Border Margin="10"> 
         <Border.Effect> 
          <DropShadowEffect BlurRadius="10"/> 
         </Border.Effect> 
         <Grid> 
          <Border Background="{TemplateBinding Background}"> 
           <ContentPresenter Name="ContentPresenter" ClipToBounds="True"></ContentPresenter> 
          </Border> 
          <Grid x:Name="ResizeDummies"> 
           <Line Cursor="SizeNS" MouseDown="p_OnSizeN" X1="0" X2="{TemplateBinding ActualWidth}" StrokeThickness="4" Y1="0" Y2="0" Stroke="Transparent" VerticalAlignment="Top"></Line> 
           <Line Cursor="SizeNS" MouseDown="p_OnSizeS" X1="0" X2="{TemplateBinding ActualWidth}" StrokeThickness="4" Y1="{TemplateBinding ActualHeight}" Y2="{TemplateBinding ActualHeight}" Stroke="Transparent" VerticalAlignment="Bottom"></Line> 
           <Line Cursor="SizeWE" MouseDown="p_OnSizeW" X1="0" X2="0" StrokeThickness="4" Y1="0" Y2="{TemplateBinding ActualHeight}" Stroke="Transparent" HorizontalAlignment="Left"></Line> 
           <Line Cursor="SizeWE" MouseDown="p_OnSizeE" X1="{TemplateBinding ActualWidth}" X2="{TemplateBinding ActualWidth}" StrokeThickness="4" Y1="0" Y2="{TemplateBinding ActualHeight}" Stroke="Transparent" HorizontalAlignment="Right"></Line> 
           <Rectangle Cursor="SizeNWSE" MouseDown="p_OnSizeNW" Width="5" Height="5" Fill="Transparent" VerticalAlignment="Top" HorizontalAlignment="Left" /> 
           <Rectangle Cursor="SizeNESW" MouseDown="p_OnSizeNE" Width="5" Height="5" Fill="Transparent" VerticalAlignment="Top" HorizontalAlignment="Right" /> 
           <Rectangle Cursor="SizeNESW" MouseDown="p_OnSizeSW" Width="5" Height="5" Fill="Transparent" VerticalAlignment="Bottom" HorizontalAlignment="Left" /> 
           <Rectangle Cursor="SizeNWSE" MouseDown="p_OnSizeSE" Width="5" Height="5" Fill="Transparent" VerticalAlignment="Bottom" HorizontalAlignment="Right" /> 
          </Grid> 
         </Grid> 
        </Border> 

        <ControlTemplate.Triggers> 
         <Trigger Property="ResizeMode" Value="CanMinimize"> 
          <Setter TargetName="ResizeDummies" Property="Visibility" Value="Collapsed"></Setter> 
         </Trigger> 
         <Trigger Property="ResizeMode" Value="NoResize"> 
          <Setter TargetName="ResizeDummies" Property="Visibility" Value="Collapsed"></Setter> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

DropShadowedWindowStyle.xaml.cs:

namespace DropShadowedWindow 
{ 
    public partial class DropShadowedWindowStyle 
    { 
     #region Helper Functions 

      /// <summary> 
      /// Return WinApi window handler from WPF window 
      /// </summary> 
      /// <param name="w"></param> 
      /// <returns></returns> 
      protected static IntPtr p_GetHW(Window w) 
      { 
       var helper = new WindowInteropHelper(w); 
       return helper.Handle; 
      } 

      /// <summary> 
      /// Get templated parent window, if it exists 
      /// </summary> 
      /// <param name="sender"></param> 
      protected Window p_GetTemplatedWindow(object sender) 
      { 
       var element = sender as FrameworkElement; 
       if (element != null) 
       { 
        var w = element.TemplatedParent as Window; 
        if (w != null) return w; 
       } 
       return null; 
      } 


     #endregion Helper Functions 

     #region Window Event Hanlders 

      protected enum SizingAction 
      { 
       North = 3, 
       South = 6, 
       East = 2, 
       West = 1, 
       NorthEast = 5, 
       NorthWest = 4, 
       SouthEast = 8, 
       SouthWest = 7 
      } 

      protected void p_OnSizeS(object sender, MouseButtonEventArgs e) { p_OnSize(sender, SizingAction.South); } 
      protected void p_OnSizeN(object sender, MouseButtonEventArgs e) { p_OnSize(sender, SizingAction.North); } 
      protected void p_OnSizeE(object sender, MouseButtonEventArgs e) { p_OnSize(sender, SizingAction.East); } 
      protected void p_OnSizeW(object sender, MouseButtonEventArgs e) { p_OnSize(sender, SizingAction.West); } 
      protected void p_OnSizeNW(object sender, MouseButtonEventArgs e) { p_OnSize(sender, SizingAction.NorthWest); } 
      protected void p_OnSizeNE(object sender, MouseButtonEventArgs e) { p_OnSize(sender, SizingAction.NorthEast); } 
      protected void p_OnSizeSE(object sender, MouseButtonEventArgs e) { p_OnSize(sender, SizingAction.SouthEast); } 
      protected void p_OnSizeSW(object sender, MouseButtonEventArgs e) { p_OnSize(sender, SizingAction.SouthWest); } 


      /// <summary> 
      /// Switch to resize mode by dragging corners 
      /// </summary> 
      /// <param name="sender"></param> 
      /// <param name="action"></param> 
      protected void p_OnSize(object sender, SizingAction action) 
      { 
       if (Mouse.LeftButton == MouseButtonState.Pressed) 
       { 
        var w = p_GetTemplatedWindow(sender); 
        if (w != null && w.WindowState == WindowState.Normal) p_DragSize(p_GetHW(w), action); 
       } 
      } 


     #endregion Window Event Hanlders 

     #region P/Invoke 

      const int WmSyscommand = 0x112; 
      const int ScSize = 0xF000; 

      [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")] 
      private static extern IntPtr p_SendMessage(IntPtr h_wnd, uint msg, IntPtr w_param, IntPtr l_param); 

      /// <summary> 
      /// Activate resize mode 
      /// </summary> 
      /// <param name="handle"></param> 
      /// <param name="sizing_action"></param> 
      private void p_DragSize(IntPtr handle, SizingAction sizing_action) 
      { 
       p_SendMessage(handle, WmSyscommand, (IntPtr)(ScSize + sizing_action), IntPtr.Zero); 
       p_SendMessage(handle, 514, IntPtr.Zero, IntPtr.Zero); 
      } 

     #endregion 
    } 
} 

注:這個例子不包括一些內容,移動,關閉,最大化和最小化窗口。你可以看到在這個項目做出來https://github.com/D-Key/whosh或本文http://www.codeproject.com/Articles/140267/Create-Custom-Windows-in-WPF-with-Ease

您還可以在這裏看到另一種方法:http://social.msdn.microsoft.com/Forums/vstudio/en-US/02fb62be-4550-4036-8a72-fe53e43a6414/showing-resizegrip-on-a-window-with-a-shadow