我在WinformHost中有一个按钮,我想用鼠标将它移动到WindowsFormsHost中的任何位置。我已经完成了如下操作。但当鼠标移到按钮上时,它会闪烁。请帮助更正。
<Grid x:Name="myGrid" Background="Transparent" Height="400" Width="700">
<WindowsFormsHost Height="200" HorizontalAlignment="Left" Margin="10,108,0,0" Name="windowsFormsHost1" VerticalAlignment="Top" Width="200" Background="PaleVioletRed">
<wf:FlowLayoutPanel Name="FlowPanel" BackColor="Red" Dock="Fill">
<wf:Panel.Controls>
<wf:Button x:Name="Btn1" MouseMove="Btn1_MouseMove" MouseDown="Btn1_MouseDown" Width="120" Height="120" Text="BTN1" BackColor="yellow"></wf:Button>
<wf:Button x:Name="Btn2" Width="120" Height="120" Text="BTN2" BackColor="Red"></wf:Button>
</wf:Panel.Controls>
</wf:FlowLayoutPanel>
</WindowsFormsHost>
</Grid>
private System.Drawing.Point MouseDownLocation;
private void Btn1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
btn1.Left = e.X + btn1.Left - MouseDownLocation.X;
btn1.Top = e.Y + btn1.Top - MouseDownLocation.Y;
}
}
private void Btn1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
MouseDownLocation = e.Location;
}
}
重新发布我的评论作为因果报应的答案:
- WinForms和WPF有非常不同的布局系统:WinForms继承了VB6的"一切都是绝对定位的"概念,只使用
X
、Y
、Width
和Height
,这非常简单,但意味着表单需要有固定的大小或需要手动编码来处理调整大小的事件,这是一个需要实现的PITA。- WinForms确实为非常基本的布局添加了
Anchor
和Dock
属性 - 在.NET Framework 2.0中,WinForms添加了
FlowLayoutPanel
和TableLayoutPanel
,这也起到了帮助作用 FlowLayoutPanel
和TableLayoutPanel
为您处理元素的绝对定位,这意味着您不能直接设置控件的坐标(或者更确切地说,设置坐标只是将控件相对于其包含的面板或单元格进行定位(
- WinForms确实为非常基本的布局添加了
- 然而,WPF使用了一个完全不同的布局系统,它根本不使用绝对定位(只能在WPF
<Canvas>
元素内设置坐标(,相反,它有各种各样的内置布局控件,如StackPanel
、DockPanel
、WrapPanel
等,这比WinForm的aneamic布局控件灵活得多。- WPF和XAML被设计为同时支持应用程序UI和"文档"(还记得微软命运多舛的PDF竞争对手"XPS"吗?它是基于XAML的布局模型(,这就是为什么它比WinForms的模型灵活得多
- 然而,WPF有一些主要的程序员工效学问题,比如被设计为每个
Panel
单元格只允许一个子控件(其想法是,您应该使用另一个<Panel>
作为布局控件的子控件,然后将子控件添加到其中——但在使用了WinForm无处不在的ControlsCollection
之后,这一点一开始非常违背直觉(
- 所以我的观点是,WPF和WinForms有着根本不同的布局模型,所以不要在WinForms中使用WPF技术,反之亦然——这就是为什么WinForms的
FlowLayoutPanel
不像你想象的那样工作——如果你认为它的工作方式与WPF的WrapPanel
类似的话 - 由于WinForm的
FlowLayoutPanel
"控制"其子控件的位置和大小,这意味着在每个子控件上设置Left
和Top
(可能还有Width
和Height
,具体取决于Dock
和Anchor
设置(是徒劳的,因为它们将被FlowLayoutPanel
覆盖 - 因此,如果您想绝对设置WinForms控件的位置,那么根本不要使用
FlowLayoutPanel
,只需将控件直接添加到父控件的ControlsCollection
中,然后设置坐标和大小即可 WindowsFormsHost
是一个WPF控件,而不是WinForms控件,因此它只能有一个WinForms控件作为其内容(.Child
属性(。使用WinFormsPanel
控件可以获得一个简单的WinForms控件集合,这些控件的位置和大小可以手动设置
如此:
<Grid
x:Name="myGrid"
Background="Transparent"
Height="400"
Width="700"
>
<WindowsFormsHost
Height="200"
HorizontalAlignment="Left"
Margin="10,108,0,0"
Name="windowsFormsHost1"
VerticalAlignment="Top"
Width="200"
Background="PaleVioletRed"
>
<wf:Panel
Name="FlowPanel"
BackColor="Red"
Dock="Fill"
>
<wf:Panel.Controls>
<wf:Button
x:Name="Btn1"
MouseMove="Btn1_MouseMove"
MouseDown="Btn1_MouseDown"
Width="120"
Height="120"
Text="BTN1"
BackColor="yellow"
/>
<wf:Button
x:Name="Btn2"
Width="120"
Height="120"
Text="BTN2"
BackColor="Red
/>
</wf:Panel.Controls>
</wf:Panel>
</WindowsFormsHost>
</Grid>