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的事件進行拖放的話,實在是太慢了。