【问题标题】:WPF borderless window resize with inner-marginsWPF 无边框窗口使用内边距调整大小
【发布时间】:2014-01-13 04:01:49
【问题描述】:

我有一个在设计器中看起来像这样的 WPF 窗口:

在内网格和窗口边缘之间有一个空间区域,因为在这两个元素之间,绘制了一个 DropShadow。

我的问题是我不能使用 WPF 的本机工具来调整窗口大小。如果我将 ResizeMode 设置为 CanResize,则手柄是透明的,因此您实际上无法抓住它们。如果我将 ResizeMode 设置为 CanResizeWithGrip,我可以看到夹点,但它在整个窗口的右下方。有什么办法可以让调整大小的手柄显示内部网格的开始位置而不是表单的外边缘?

这是设计者的把手:

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    您可以通过创建自定义窗口样式来做到这一点。这是实现示例:

    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

    【讨论】:

      猜你喜欢
      • 2013-07-12
      • 2011-09-22
      • 2017-03-25
      • 2013-03-27
      • 2021-06-18
      • 2013-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多