WPF中的無邊框透明可縮放窗體
阿新 • • 發佈:2019-01-08
WPF中的無邊框透明窗體,由於沒有邊並且透明,窗體無法進行縮放操作,今天來講解如何解決這個問題。
先說一下思路,我們先手為該窗體新增4個邊,4個角用於縮放操作,然後再為他們寫事件,完成拖放操作。
xaml程式碼:
<Windowx:Class="WpfResizeWindow.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"Height="300"Width="300"WindowStyle="None" AllowsTransparency="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="4"/>
<RowDefinition/>
<RowDefinition Height="4"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinitionWidth="4"/>
<ColumnDefinition/>
<ColumnDefinitionWidth="4" />
</Grid.ColumnDefinitions>
<RectangleName="ResizeTopLeft"Fill="Black"Grid.Row="0"Grid.Column="0"MouseMove="ResizePressed"MouseDown="ResizePressed"/>
<RectangleName="ResizeTop"Fill="Black"Grid.Row="0"Grid.Column="1"MouseMove="ResizePressed"MouseDown="ResizePressed"/>
<RectangleName="ResizeTopRight" Fill="Black"Grid.Row="0"Grid.Column="2"MouseMove="ResizePressed"MouseDown="ResizePressed"/>
<RectangleName="ResizeLeft"Fill="Black"Grid.Row="1"Grid.Column="0"MouseMove="ResizePressed"MouseDown="ResizePressed"/>
<RectangleName="ResizeRight"Fill="Black"Grid.Row="1"Grid.Column="3"MouseMove="ResizePressed"MouseDown="ResizePressed"/>
<RectangleName="ResizeBottomLeft"Fill="Black"Grid.Row="3"Grid.Column="0"MouseMove="ResizePressed"MouseDown="ResizePressed"/>
<RectangleName="ResizeBottom"Fill="Black"Grid.Row="3"Grid.Column="1"MouseMove="ResizePressed"MouseDown="ResizePressed"/>
<RectangleName="ResizeBottomRight"Fill="Black"Grid.Row="3"Grid.Column="2"MouseMove="ResizePressed"MouseDown="ResizePressed"/>
</Grid>
</Window>
cs程式碼:
public partial class Window1 : Window
{
privateconst intWM_SYSCOMMAND = 0x112;
privateHwndSource _HwndSource;
privateDictionary<ResizeDirection, Cursor> cursors = newDictionary<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}
};
privateenum ResizeDirection
{
Left = 1,
Right = 2,
Top = 3,
TopLeft = 4,
TopRight = 5,
Bottom = 6,
BottomLeft = 7,
BottomRight = 8,
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
privatestatic externIntPtr SendMessage(IntPtr hWnd, uintMsg, IntPtr wParam, IntPtr lParam);
publicWindow1()
{
InitializeComponent();
this.SourceInitialized +=delegate(objectsender, EventArgs e)
{
this._HwndSource = PresentationSource.FromVisual((Visual)sender)as HwndSource;
};
this.MouseMove += new MouseEventHandler(Window_MouseMove);
}
voidWindow_MouseMove(objectsender, MouseEventArgs e)
{
if (Mouse.LeftButton != MouseButtonState.Pressed)
{
FrameworkElement element = e.OriginalSource asFrameworkElement;
if (element != null && !element.Name.Contains("Resize"))
this.Cursor = Cursors.Arrow;
}
}
privatevoid ResizePressed(objectsender, MouseEventArgs e)
{
FrameworkElement element = sender asFrameworkElement;
ResizeDirection direction = (ResizeDirection)Enum.Parse(typeof(ResizeDirection), element.Name.Replace("Resize",""));
this.Cursor = cursors[direction];
if (e.LeftButton == MouseButtonState.Pressed)
ResizeWindow(direction);
}
privatevoid ResizeWindow(ResizeDirection direction)
{
SendMessage(_HwndSource.Handle, WM_SYSCOMMAND, (IntPtr)(61440 + direction), IntPtr.Zero);
}
}
從程式碼可以看出,先註冊4個邊和4個角的MouseMove和MouseDown事件,滑鼠移動到拖放內容上時,判斷滑鼠懸停在那個邊上,改變滑鼠指標變成相應物件,判斷滑鼠是否按下,如果按下了,則傳送Win32訊息,進行拖放操作,從程式碼中可以看出來最終的拖放還是使用Win32 api來實現,因為,如果完全用wpf的事件進行拖放的話,實在是太慢了。