WPF中的无边框透明窗体,由于没有边并且透明,窗体无法进行缩放操作,今天来讲解如何解决这个问题。
先说一下思路,我们先手为该窗体添加4个边,4个角用于缩放操作,然后再为他们写事件,完成拖放操作。
xaml代码:
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
|
<
Window
x:Class
=
"WpfResizeWindow.Window1"
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代码:
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
|
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的事件进行拖放的话,实在是太慢了。