WPF中的拖放(三)

上一篇,我们实现了同一窗体间的拖放,并且显示鼠标跟随效果,今天,我们来实现不同窗体之间的拖放,因为不是用一个窗体,而Adorner(装饰器)只能在父窗体内移动,所以,我们实现不同窗体之间显示鼠标跟随效果,就要再新建一个窗体来显示鼠标跟随的内容。我们先看一下完成后的效果图。

由于要获得鼠标相对屏幕坐标和把拖放窗体的位置带到放置窗体的位置,需要使用Win32 API来完成,我们先创建一个类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static class Win32
{
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public int X;
        public int Y;
        public POINT( int x, int y)
        {
            this .X = x;
            this .Y = y;
        }
    }
    public static Int32 GWL_EXSTYLE = -20;
    public static Int32 WS_EX_LAYERED = 0x00080000;
    public static Int32 WS_EX_TRANSPARENT = 0x00000020;
    [DllImport( "user32.dll" , CharSet = CharSet.Auto)]
    public static extern bool GetCursorPos( out POINT pt);
    [DllImport( "user32.dll" , CharSet = CharSet.Auto)]
    public static extern Int32 GetWindowLong(IntPtr hWnd, Int32 nIndex);
    [DllImport( "user32.dll" , CharSet = CharSet.Auto)]
    public static extern Int32 SetWindowLong(IntPtr hWnd, Int32 nIndex, Int32 newVal);
}

我们通过GetCursorPos()方法获得鼠标坐标,GetWindowLong()、SetWindowLong()方法获得和设置窗体属性。

接下来,我们编写拖拽窗体Window1.xaml.cs,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
public partial class Window1 : Window
{
    //显示拖拽内容的窗体
    private Window _dragdropWindow = null ;
    //实例化Window2用于放置操作
    Window2 win = new Window2();
    public Window1()
    {
        InitializeComponent();
        win.Show();
        this .rectangle1.PreviewMouseMove += new MouseEventHandler(rectangle1_PreviewMouseMove);
    }
    void rectangle1_PreviewMouseMove( object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            this .StartDragWindow(e);
        }
    }
    private void StartDragWindow(MouseEventArgs e)
    {
        QueryContinueDragEventHandler queryhandler = new QueryContinueDragEventHandler(DragSource_QueryContinueDrag);
        this .rectangle1.QueryContinueDrag += queryhandler;
        this .CreateDragDropWindow( this .rectangle1);
        DataObject data = new DataObject( typeof ( string ), "Moved!!!" );
        this ._dragdropWindow.Show();
        DragDropEffects de = DragDrop.DoDragDrop( this .rectangle1, data, DragDropEffects.Move);
        this .DestroyDragDropWindow();
        this .rectangle1.QueryContinueDrag -= queryhandler;
    }
    void DragSource_QueryContinueDrag( object sender, QueryContinueDragEventArgs e)
    {
        this .UpdateWindowLocation();
    }
    /// <summary>
    /// 更新拖拽窗体位置
    /// </summary>
    private void UpdateWindowLocation()
    {
        if ( this ._dragdropWindow != null )
        {
            Win32.POINT p;
            if (!Win32.GetCursorPos( out p))
            {
                return ;
            }
            this ._dragdropWindow.Left = ( double )p.X;
            this ._dragdropWindow.Top = ( double )p.Y;
        }
    }
    /// <summary>
    /// 创建拖拽窗体
    /// </summary>
    /// <param name="dragElement"></param>
    private void CreateDragDropWindow(Visual dragElement)
    {
        this ._dragdropWindow = new Window();
        this ._dragdropWindow.WindowStyle = WindowStyle.None;
        this ._dragdropWindow.Opacity = 0.6;
        this ._dragdropWindow.AllowsTransparency = true ;
        this ._dragdropWindow.AllowDrop = false ;
        this ._dragdropWindow.Background = null ;
        this ._dragdropWindow.IsHitTestVisible = false ;
        this ._dragdropWindow.SizeToContent = SizeToContent.WidthAndHeight;
        this ._dragdropWindow.Topmost = true ;
        this ._dragdropWindow.ShowInTaskbar = false ;
        this ._dragdropWindow.SourceInitialized += new EventHandler(
        delegate ( object sender, EventArgs args)
        {
            PresentationSource windowSource = PresentationSource.FromVisual( this ._dragdropWindow);
            IntPtr handle = ((System.Windows.Interop.HwndSource)windowSource).Handle;
            Int32 styles = Win32.GetWindowLong(handle, Win32.GWL_EXSTYLE);
            Win32.SetWindowLong(handle, Win32.GWL_EXSTYLE, styles | Win32.WS_EX_LAYERED | Win32.WS_EX_TRANSPARENT);
        });
        Rectangle r = new Rectangle();
        r.Width = ((FrameworkElement)dragElement).ActualWidth;
        r.Height = ((FrameworkElement)dragElement).ActualHeight;
        r.Fill = new VisualBrush(dragElement);
        this ._dragdropWindow.Content = r;
        this .UpdateWindowLocation();
    }
    /// <summary>
    /// 销毁托抓窗体
    /// </summary>
    private void DestroyDragDropWindow()
    {
        if ( this ._dragdropWindow != null )
        {
            this ._dragdropWindow.Close();
            this ._dragdropWindow = null ;
        }
    }
}

关键代码在StartDragWindow(MouseEventArgs)这个方法,开始拖拽时,我们先创建_dragdropWindow这个拖拽窗体,并进行相应初始化操作,定义被拖拽物体(这里为矩形)状态发生变化时调用UpdateWindowLocation()方法,更新拖拽窗体位置,拖拽完成后调用DestroyDragDropWindow()方法,销毁拖拽窗体,这一系列过程,达到完成窗体拖拽操作。

最后,我们编写放置窗体Window2.xaml.cs,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public partial class Window2 : Window
{
    public Window2()
    {
        InitializeComponent();
        this .AllowDrop = true ;
        this .DragOver += new DragEventHandler(canvas2_DragOver);
        this .Drop += new DragEventHandler(canvas2_Drop);
    }
    void canvas2_Drop( object sender, DragEventArgs e)
    {
        IDataObject data = e.Data;
        if (data.GetDataPresent( typeof ( string )))
        {
            string msg = data.GetData( typeof ( string )) as string ;
            MessageBox.Show(msg);
        }
    }
    void canvas2_DragOver( object sender, DragEventArgs e)
    {
        if (!e.Data.GetDataPresent( typeof ( string )))
        {
            e.Effects = DragDropEffects.None;
            e.Handled = true ;
        }
    }
}

这里的代码很简单,WPF的拖放(一)已经有说明,有什么不明白就看文章一吧。
本文代码下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值