WPF透明窗体不支持缩放解决方案

方案一

WPF中的无边框透明窗体,由于没有边并且透明,窗体无法进行缩放操作,今天来讲解如何解决这个问题。

先说一下思路,我们先手为该窗体添加4个边,4个角用于缩放操作,然后再为他们写事件,完成拖放操作。

Xaml文件

<Window x:Class="UniversalRobot.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:UniversalRobot"
        mc:Ignorable="d"
        Title="Window2" Height="300" Width="300" WindowStyle="None" AllowsTransparency="True">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="4"/>
            <RowDefinition/>
            <RowDefinition Height="4"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="4"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="4"/>
        </Grid.ColumnDefinitions>
        <Rectangle Name="ResizeTopLeft" Fill="#01000000" Grid.Row="0" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeTop" Fill="#01000000" Grid.Row="0" Grid.Column="1" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeTopRight" Fill="#01000000" Grid.Row="0" Grid.Column="2" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeLeft" Fill="#01000000" Grid.Row="1" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeRight" Fill="#01000000" Grid.Row="1" Grid.Column="3" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeBottomLeft" Fill="#01000000" Grid.Row="3" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeBottom" Fill="#01000000" Grid.Row="3" Grid.Column="1" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeBottomRight" Fill="#01000000" Grid.Row="3" Grid.Column="2" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
    </Grid>
</Window>

  后台代码

namespace UniversalRobot
{
    /// <summary>
    /// Window2.xaml 的交互逻辑
    /// </summary>
    public partial class Window2 : Window
    {
        public Window2()
        {
            InitializeComponent();

            this.SourceInitialized += delegate (object sender, EventArgs e)
            {
                this._HwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
            };

        }


        private const int WM_SYSCOMMAND = 0x112;
        private HwndSource _HwndSource;
        private enum ResizeDirection
        {
            Left = 1,
            Right = 2,
            Top = 3,
            TopLeft = 4,
            TopRight = 5,
            Bottom = 6,
            BottomLeft = 7,
            BottomRight = 8,
        }
        private Dictionary<ResizeDirection, Cursor> cursors = new Dictionary<ResizeDirection, Cursor>
        {
            {ResizeDirection.Top, Cursors.SizeNS},
            {ResizeDirection.Bottom, Cursors.SizeNS},
            {ResizeDirection.Left, Cursors.SizeWE},
            {ResizeDirection.Right, Cursors.SizeWE},
            {ResizeDirection.TopLeft, Cursors.SizeNWSE},
            {ResizeDirection.BottomRight, Cursors.SizeNWSE},
            {ResizeDirection.TopRight, Cursors.SizeNESW},
            {ResizeDirection.BottomLeft, Cursors.SizeNESW}

        };
        private void ResizePressed(object sender, MouseEventArgs e)
        {
            FrameworkElement element = sender as FrameworkElement;
            ResizeDirection direction = (ResizeDirection)Enum.Parse(typeof(ResizeDirection), element.Name.Replace("Resize", ""));

            this.Cursor = cursors[direction];

            if (e.LeftButton == MouseButtonState.Pressed)
                ResizeWindow(direction);
        }
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        private void ResizeWindow(ResizeDirection direction)
        {
            SendMessage(_HwndSource.Handle, WM_SYSCOMMAND, (IntPtr)(61440 + direction), IntPtr.Zero);
        }

    }
}

  从代码可以看出,先注册4个边和4个角的MouseMove和MouseDown事件,鼠标移动到拖放内容上时,判断鼠标悬停在那个边上,改变鼠标指针变成相应对象,判断鼠标是否按下,如果按下了,则发送Win32消息,进行拖放操作,从代码中可以看出来最终的拖放还是使用Win32 api来实现,因为,如果完全用wpf的事件进行拖放的话,实在是太慢了。

 方案二

进一步,把该功能封装到自己的类中。

posted @ 2017-08-01 14:29  JeffreyGoogle  阅读(668)  评论(0编辑  收藏  举报