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的事件进行拖放的话,实在是太慢了。