WPF无边框透明窗体的缩放

2010年3月3日 分类: WPF

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

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

xaml代码:

<Window x:Class="WpfResizeWindow.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" 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="Black" Grid.Row="0" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeTop" Fill="Black" Grid.Row="0" Grid.Column="1" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeTopRight" Fill="Black" Grid.Row="0" Grid.Column="2" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeLeft" Fill="Black" Grid.Row="1" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeRight" Fill="Black" Grid.Row="1" Grid.Column="3" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeBottomLeft" Fill="Black" Grid.Row="3" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeBottom" Fill="Black" Grid.Row="3" Grid.Column="1" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
        <Rectangle Name="ResizeBottomRight" Fill="Black" Grid.Row="3" Grid.Column="2" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
    </Grid>
</Window>

cs代码:

public partial class Window1 : Window
{
    private const int WM_SYSCOMMAND = 0x112;
    private HwndSource _HwndSource;

    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 enum ResizeDirection
    {
        Left = 1,
        Right = 2,
        Top = 3,
        TopLeft = 4,
        TopRight = 5,
        Bottom = 6,
        BottomLeft = 7,
        BottomRight = 8,
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    public Window1()
    {
        InitializeComponent();

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

    void Window_MouseMove(object sender, MouseEventArgs e)
    {
        if (Mouse.LeftButton != MouseButtonState.Pressed)
        {
            FrameworkElement element = e.OriginalSource as FrameworkElement;
            if (element != null && !element.Name.Contains("Resize"))
                this.Cursor = Cursors.Arrow;
        }
    }

    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);
    }

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

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

原创文章,转载请注明: 转载自.NET开发者

本文链接地址: WPF无边框透明窗体的缩放

 

Related posts:

  1. WPF中单击标题行可排序的GridView
  2. WPF 仿QQ无边框窗体(自动隐藏/可缩放/最大化不覆盖任务栏)
  3. WPF中的拖放(三)
  4. WPF中的拖放(一)
  5. Silverlight/WPF中的布局
标签: ,
目前还没有任何评论.

Leave a Comment