WPF無邊框透明窗體的縮放

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章