上一篇,我们实现了同一窗体间的拖放,并且显示鼠标跟随效果,今天,我们来实现不同窗体之间的拖放,因为不是用一个窗体,而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的拖放(一)已经有说明,有什么不明白就看文章一吧。
本文代码下载