WPF无边框窗口使用内边距调整大小

时间:2014-01-13 04:01:49

标签: c# wpf

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

wpf designer screenshot

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

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

以下是握​​把设计师:

designer with grip

1 个答案:

答案 0 :(得分: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