c# - 检测按钮是否在绘制的矩形框内
问题描述
我有一个带有矩形框的画布,用于选取框,我的 uniformgrid 包含动态生成的按钮。
选框选择工具现在正在工作,即我可以看到它被绘制在统一网格上,并且我已经根据示例代码获得了 mousedown 位置和 mouseup 位置:
我的 XAML 是这样的:
<Grid Name="mainGrid" DockPanel.Dock="Top" Width="800" Height="400">
<Rectangle x:Name="selectionBox" Visibility="Collapsed" Stroke="White" StrokeThickness="4" StrokeDashArray="2,1"/>
<UniformGrid DockPanel.Dock="Top" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="uniformGrid" Grid.Row="1" Width="{Binding Width, ElementName=mainGrid}" Height="{Binding Height, ElementName=mainGrid}"
Rows="{Binding RowCount}"
Columns="{Binding ColumnCount}" MouseDown="UniformGrid_MouseDown" MouseUp="UniformGrid_MouseUp" MouseMove="UniformGrid_MouseMove" Background="Transparent">
</UniformGrid>
<Canvas Name="buttonCanvas">
</Canvas>
</Grid>
问题是,我不确定如何检查我的按钮(它们是 UniformGrid 的子项)是否包含/部分包含在此矩形中。
解决方案
这是对您链接的解决方案的扩展。
以下是一种方法,它将确定给定按钮在给定MouseUp
位置MouseDown
内。在该示例中,有一个名为 的成员变量mouseDownPos
和一个名为 的局部变量mouseUpPos
,它们分别注册了这些变量。因此,在Grid_MouseUp
事件处理程序中,我将添加以下代码来获取Button
您的所有控件Canvas
,迭代它们中的每一个并将它们传递给一个方法以查看它是否在所述区域内。
private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
{
// Release the mouse capture and stop tracking it.
mouseDown = false;
theGrid.ReleaseMouseCapture();
// Hide the drag selection box.
selectionBox.Visibility = Visibility.Collapsed;
Point mouseUpPos = e.GetPosition(theGrid);
// TODO:
//
// The mouse has been released, check to see if any of the items
// in the other canvas are contained within mouseDownPos and
// mouseUpPos, for any that are, select them!
//
var buttons = canvasButtons.Children.OfType<System.Windows.Controls.Button>();
foreach (var button in buttons)
{
var isInSelection = IsInsideSelection(mouseDownPos, mouseUpPos, button);
}
}
这IsInsideSelection()
是我编写的一个函数,它询问矩形的鼠标上下位置以及Button
控件。
private bool IsInsideSelection(Point mouseDown, Point mouseUp, System.Windows.Controls.Button button)
{
// This grabs the coordinates of the button, relative to the main window.
// If you would like it relative to something else, like your canvas or the grid, you'd have to pass appropriate control to the `TransformToAncestor()` function.
var buttonPos = button.TransformToAncestor(mainWin).Transform(new Point(0, 0));
// Bottom right corner coordinates of the button control.
var btnBottomRight = new Point(buttonPos.X + button.Width, buttonPos.Y + button.Height);
// If button X and Y (which is the top left corner of the button)
// are outside the mouse down position, it's not inside the rectangle
if (buttonPos.X < mouseDown.X || buttonPos.Y < mouseDown.Y)
return false;
// If X and Y of button bottom right corner is outside mouse up coordinates,
// then the control is again outside the rectangle
if (btnBottomRight.X > mouseUp.X || btnBottomRight.Y > mouseUp.Y)
return false;
// Everything else, control is inside
return true;
}
笔记:
- 这会获取按钮相对于主窗口的坐标。如果你希望它相对于其他东西,比如你的画布或网格,你必须将适当的控制传递给
TransformToAncestor()
函数。
编辑
仅当矩形是从左到右绘制时,上述函数才有效。要处理从右到左的情况,您可以上下切换鼠标位置,如下所示:
private bool IsInsideSelection(Point mouseDown, Point mouseUp, System.Windows.Controls.Button button)
{
if (mouseUp.X < mouseDown.X)
{
var temp = mouseUp;
mouseUp = mouseDown;
mouseDown = temp;
}
var buttonPos = button.TransformToAncestor(mainWin).Transform(new Point(0, 0));
var btnBottomRight = new Point(buttonPos.X + button.Width, buttonPos.Y + button.Height);
if (buttonPos.X < mouseDown.X || buttonPos.Y < mouseDown.Y)
return false;
if (btnBottomRight.X > mouseUp.X || btnBottomRight.Y > mouseUp.Y)
return false;
return true;
}
编辑2:
以下是XAML
我的测试应用程序,我在UniformGrid
这里使用 a 来控制控件。请注意,在检索按钮时,您必须使用名称UniformGrid
来执行此操作,在本例中为“unfGrid”。
<Window ...
Name="mainWin"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="600" Width="600">
<Grid x:Name="theGrid"
MouseDown="Grid_MouseDown"
MouseUp="Grid_MouseUp"
MouseMove="Grid_MouseMove"
Background="Transparent">
<UniformGrid Name="unfGrid" Grid.Row="0">
<Button Name="Btn1" Content="Button1" Grid.Row="0"
Width="100" Height="24"/>
<Button Name="Btn2" Content="Button2" Grid.Row="1"
Width="100" Height="24"/>
<Button Name="Btn3" Content="Button3" Grid.Row="2"
Width="100" Height="24"/>
<!-- This canvas contains elements that are to be selected -->
</UniformGrid>
<Canvas Grid.Row="0">
<!-- This canvas is overlaid over the previous canvas and is used to
place the rectangle that implements the drag selection box. -->
<Rectangle
x:Name="selectionBox"
Visibility="Collapsed"
Stroke="Black"
StrokeThickness="1"/>
</Canvas>
</Grid>
</Window>
推荐阅读
- r - 将字符串保存在数据框中(行和列)
- string - 在对象的属性中找到最大值
- javascript - 如何使用 JS 禁用多个输入?
- typo3 - 在自己的viewhelper中使用外国模型作为参数
- node.js - Nodejs async-await 疑惑
- python - 我可以链接列表的索引吗?
- r - 将 geom_boxplot 定位到图的顶部
- javascript - 如何使用 javascript 附加一个 li 和链接元素
- python - 无法在 Python 中导入已安装的包
- nginx - 在 Kubernetes 中找不到具有 OAuth2 身份验证 404 页面的 Nginx Ingress