TdhMarchingAnts - 一个 .NET 组件,用于在附加控件的客户端区域选择(和绘制)矩形并返回坐标
本文介绍了一个 .NET 组件,该组件可以在附加控件的表面上绘制用户鼠标活动确定的“橡皮筋矩形”(选择完成后被“行军蚁”替换),并通过事件返回矩形坐标。
请注意: 下载文件较大的原因是演示项目中包含的图片。编译后的 DLL 库只有 44 KB。
引言
作为我的项目图像处理子系统的一个小部分,我需要一种方法来允许用户选择他们正在处理的图像集上的标识区域。然后,每个单独图像的此区域将在放大时显示(与作为缩略图显示的全图/裁剪图相比)。
虽然我的需求非常具体——我想知道在 `PictureBox` 控件表面上选择的矩形的坐标——但我决定编写一个更通用的类,它可以绘制矩形在任何继承自 `System.Windows.Forms.Control` 的对象上,并将矩形坐标返回给调用程序。
我编写的用于实现此目标的类是:`TdhMarchingAnts_NativeWindow`。可以通过直接通过代码实例化来使用此类。
我还编写了一个组件类 `TdhMarchingAnts`,作为 `TdhMarchingAnts_NativeWindow` 的开发环境“包装器”。
演示程序使用/测试了这两个类。
使用类 -- 代码
要使用我编写的 `TdhMarchingAnts` 类,请在您的项目中添加对类库 'TDHMarchingAnts.dll' 的引用。此库中使用的命名空间是
using TDHControls.TDHMarchingAnts;
`TdhMarchingAnts` 组件的 'Windows Form Designer generated code' 的示例是
private void InitializeComponent()
{
this.tdhAnts
= new TDHControls.TDHMarchingAnts.TdhMarchingAnts(this.components);
//
// tdhAnts
//
this.tdhAnts.AntAttachedControl = this.pnlDemo;
this.tdhAnts.AntBackColor = System.Drawing.Color.Black; // default: .White
this.tdhAnts.AntForeColor = System.Drawing.Color.White; // default: .Red
this.tdhAnts.AntsActive = true; // Note: this is 'false' by default
this.tdhAnts.RegionDeselectEvent += new
TDHControls.TDHMarchingAnts.RegionDeselectEventHandler(
this.tdhAnts_RegionDeselectEvent);
this.tdhAnts.RegionSelectEvent += new
TDHControls.TDHMarchingAnts.RegionSelectEventHandler(
this.tdhAnts_RegionSelectEvent);
}
独立于 `TdhMarchingAnts` 组件实例化 `TdhMarchingAnts_NativeWindow` 类的示例代码是
private TDHControls.TDHMarchingAnts.TdhMarchingAnts_NativeWindow native_PicBox;
private TDHControls.TDHMarchingAnts.TdhMarchingAnts_NativeWindow native_Panel;
{
this.native_PicBox
= new TDHControls.TDHMarchingAnts.TdhMarchingAnts_NativeWindow(this.pbxImage);
this.native_PicBox.AntsActive = true; // Note: this is 'false' by default
this.native_PicBox.RegionSelectEvent += new
TDHControls.TDHMarchingAnts.RegionSelectEventHandler(
this._PicBox_RegionSelectEvent);
this.native_PicBox.RegionDeselectEvent += new
TDHControls.TDHMarchingAnts.RegionDeselectEventHandler(
this._PicBox_RegionDeselectEvent);
// The Constructor also accepts the "left-Ant" fore- and back- colors
this.native_Panel
= new TDHControls.TDHMarchingAnts.TdhMarchingAnts_NativeWindow
(this.pnlForSomething, Color.Blue, Color.Yellow);
}
使用类 -- 代码(事件处理器)
`TdhMarchingAnts_NativeWindow` 类和 `TdhMarchingAnts` 组件最多会引发六个事件(即,每个鼠标按钮三个)。
假设适当的布尔属性为 `true
`,则当用户在“单击并拖动”后释放左键(或右键)时,将引发 `_RegionSelectEvent()` 事件(以及相应的 `_RightRegionSelectEvent()` 事件)。
假设适当的布尔属性为 `true
`,则当用户单击左键(或右键)时,将引发 `_ClickEvent()` 和 `_RegionDeselectEvent()` 事件(以及相应的 `_RightClickEvent()` 和 `_RightRegionDeselectEvent()` 事件)。因此,`_ClickEvent()`(或 `_RightClickEvent()`)可能单独引发,也可能与 `_RegionDeselectEvent()`(或 `_RightRegionDeselectEvent()`)结合引发。
事件处理器方法的签名如下
private void _ClickEvent(object sender, System.Drawing.Point ClickedPoint)
{
// do something (assuming you care about this event)
}
private void _RegionDeselectEvent(object sender, System.Drawing.Point ClickedPoint)
{
// do something (assuming you care about this event)
}
private void _RegionSelectEvent(object sender, System.Drawing.Rectangle SelectedRect)
{
// do something (surely you do care about this event!)
}
private void _RightClickEvent(object sender, System.Drawing.Point ClickedPoint)
{
// do something (assuming you care about this event)
}
private void _RightRegionDeselectEvent(object sender,
System.Drawing.Point ClickedPoint)
{
// do something (assuming you care about this event)
}
private void _RightRegionSelectEvent(object sender,
System.Drawing.Rectangle SelectedRect)
{
// do something (surely you do care about this event!)
}
请注意:从 1.0.004 版本开始,所有事件处理器方法的签名都已更改(如果这造成不便,我深表歉意)。事件处理器参数列表最初应包含“`object sender
”`。
使用类 -- 界面
从 1.0.002 版本开始,`TdhMarchingAnts` 类可以与鼠标左键或右键(或两者)一起使用。“默认”按钮是左键:也就是说,先前命名的属性、方法和事件也为鼠标左键活动定义;为鼠标右键活动定义的相应属性、方法和事件前面有“Right_”(用于属性和方法)或“Right”(用于事件)。
`TdhMarchingAnts` 组件和 `TdhMarchingAnts_NativeWindow` 类具有基本相同的公共接口。
仅限于 `TdhMarchingAnts` 组件类的公共(静态)方法是
public static System.Drawing.Point ReallyEmptyPoint()
- 此方法返回一个 `System.Drawing.Point` 对象,其 .X 和 .Y 属性设置为 -1。public static bool IsReallyEmptyPoint(System.Drawing.Point pt)
- 如果 `System.Drawing.Point` 对象 'pt
' 的 .X 和 .Y 属性均等于 -1,则此方法返回 'true
',否则返回 'false
'。public static System.Drawing.Rectangle ReallyEmptyRectangle()
- 此方法返回一个 `System.Drawing.Rectangle` 对象,其 .X、.Y、.Width 和 .Height 属性均设置为 -1。public static bool IsReallyEmptyRectangle(System.Drawing.Rectangle rec)
- 如果 `System.Drawing.Point` 对象 'rec
' 的 .X、.Y、.Width 和 .Height 属性均等于 -1,则此方法返回 'true
',否则返回 'false
'。
两个类的“全局”属性是
AntAttachedControl
- (抱歉,属性名称如此,但我希望它在字母顺序上排在第一位,以便自动生成代码首先设置它。)此属性用于将 `TdhMarchingAnts_NativeWindow` 实例附加到特定控件。Enabled
- 此布尔值决定类整体是否已启用/活动,从而响应用户的鼠标活动。
两个类的“左键”属性、方法和事件处理器签名是
AntsActive
- 此布尔值决定类是否响应用户鼠标左键选择和取消选择活动。AntBackColor
- 由鼠标左键选择活动确定的“蚂蚁”路径的 `System.Drawing.Color`。AntForeColor
- 由鼠标左键选择活动确定的“蚂蚁”(本身)的 `System.Drawing.Color`。AntsMarch
- 此布尔值决定由鼠标左键选择活动确定的“蚂蚁”是否会动画。SelectedPointTL
- 此属性返回一个 `System.Drawing.Point`,表示所选区域的左上角坐标。如果尚未选择区域,则 .X 和 .Y 值为 -1。SelectedPointBR
- 此属性返回一个 `System.Drawing.Point`,表示所选区域的右下角坐标。如果尚未选择区域,则 .X 和 .Y 值为 -1。SelectedRect
- 此属性返回一个 `System.Drawing.Rectangle`,表示所选区域。如果尚未选择区域,则 .Width 和 .Height 值为 -1。
注意: 此属性的默认值是 'false
'。必须将其设置为 'true
' 才能激活类以进行左键选择和取消选择活动。
注意: 通常,先设置 `AntBackColor`,然后再设置 `AntForeColor`。当设置 `AntBackColor` 时,类会自动将 `AntForeColor` 设置为(希望是理想的)对比色。
注意: 要让类绘制实线,请将 `AntForeColor` 设置为 `AntBackColor` 之前设置的相同值。(或者,可以通过 `ExterminateAnts()` 方法完成此操作。)
public void EraseAntPath()
- 此方法删除所选区域的视觉表示,但保留矩形坐标本身。public void ForgetAntPath()
- 此方法删除所选区域的视觉表示*并*处理矩形坐标。public void ExterminateAnts()
- 此方法将 `AntForeColor` 设置为 `AntBackColor` 的当前值——即,它将绘制的矩形更改为实线。public void SetAntPath(System.Drawing.Rectangle PathRect)
- 此方法在附加控件上绘制一个具有给定矩形坐标的矩形。
注意: 此方法将生成一个 'RegionSelectEvent
',就好像用户已选择由矩形表示的区域一样。
public delegate void ClickEventHandler(object sender, System.Drawing.Point ClickedPoint)
- [如果 (.Enabled=true
)] 当用户在附加到 `TdhMarchingAnts` 组件的控件上单击鼠标左键时,将发生此事件。public delegate void RegionDeselectEventHandler(object sender, System.Drawing.Point ClickedPoint)
- [如果 (.Enabled=true
) 且 (.AntsActive=true
) 且当前已选择一个区域] 当用户在附加到 `TdhMarchingAnts` 组件的控件上单击鼠标左键时,将发生此事件。public delegate void RegionSelectEventHandler(object sender, System.Drawing.Rectangle SelectedRect)
- [如果 (.Enabled=true
) 且 (.AntsActive=true
)] 当用户在“单击并拖动”后释放鼠标左键时,将引发此事件。
注意: 在这种情况下,将同时引发 `ClickEvent` 和 `RegionDeselectEvent` 事件。
两个类的“右键”属性、方法和事件处理器签名是
Right_AntsActive
- 此布尔值决定类是否响应用户鼠标右键选择和取消选择活动。Right_AntBackColor
- 由鼠标右键选择活动确定的“蚂蚁”路径的 `System.Drawing.Color`。Right_AntForeColor
- 由鼠标右键选择活动确定的“蚂蚁”(本身)的 `System.Drawing.Color`。Right_AntsMarch
- 此布尔值决定由鼠标右键选择活动确定的“蚂蚁”是否会动画。Right_SelectedPointTL
- 此属性返回一个 `System.Drawing.Point`,表示所选区域的左上角坐标。如果尚未选择区域,则 .X 和 .Y 值为 -1。Right_SelectedPointBR
- 此属性返回一个 `System.Drawing.Point`,表示所选区域的右下角坐标。如果尚未选择区域,则 .X 和 .Y 值为 -1。Right_SelectedRect
- 此属性返回一个 `System.Drawing.Rectangle`,表示所选区域。如果尚未选择区域,则 .Width 和 .Height 值为 -1。
注意: 此属性的默认值是 'false
'。必须将其设置为 'true
' 才能激活类以进行右键选择和取消选择活动。
注意: 通常,先设置 `AntBackColor`,然后再设置 `AntForeColor`。当设置 `AntBackColor` 时,类会自动将 `AntForeColor` 设置为(希望是理想的)对比色。
注意: 要让类绘制实线,请将 `AntForeColor` 设置为 `AntBackColor` 之前设置的相同值。(或者,可以通过 `ExterminateAnts()` 方法完成此操作。)
public void Right_EraseAntPath()
- 此方法删除所选区域的视觉表示,但保留矩形坐标本身。public void Right_ForgetAntPath()
- 此方法删除所选区域的视觉表示*并*处理矩形坐标。public void Right_ExterminateAnts()
- 此方法将 `Right_AntForeColor` 设置为 `Right_AntBackColor` 的当前值——即,它将绘制的矩形更改为实线。public void Right_SetAntPath(System.Drawing.Rectangle PathRect)
- 此方法在附加控件上绘制一个具有给定矩形坐标的矩形。
注意: 此方法将生成一个 'RightRegionSelectEvent
',就好像用户已选择由矩形表示的区域一样。
public delegate void RightClickEventHandler(object sender, System.Drawing.Point ClickedPoint)
- [如果 (.Enabled=true
)] 当用户在附加到 `TdhMarchingAnts` 组件的控件上单击鼠标右键时,将发生此事件。public delegate void RightRegionDeselectEventHandler(object sender, System.Drawing.Point ClickedPoint)
- [如果 (.Enabled=true
) 且 (.Right_AntsActive=true
) 且当前已选择一个区域] 当用户在附加到 `TdhMarchingAnts` 组件的控件上单击鼠标右键时,将发生此事件。public delegate void RightRegionSelectEventHandler(object sender, System.Drawing.Rectangle SelectedRect)
- [如果 (.Enabled=true
) 且 (.Right_AntsActive=true
)] 当用户在“单击并拖动”后释放鼠标右键时,将引发此事件。
注意: 在这种情况下,将同时引发 `RightClickEvent` 和 `RightRegionDeselectEvent` 事件。
历史
- 2006 年 12 月 8 日:提交 `TdhMarchingAnts` ver. 1.0.001 至 The Code Project。
- 2006 年 12 月 12 日:ver. 1.0.002。
ClickEvent(object sender, System.Drawing.Point ClickedPoint)
RightClickEvent(object sender, System.Drawing.Point ClickedPoint)
RightRegionSelectEvent(object sender, System.Drawing.Rectangle SelectedRect)
RightRegionDeselectEvent(object sender, System.Drawing.Point ClickedPoint)
- 2006 年 12 月 13 日:ver. 1.0.003
- 将以下方法从 `TdhMarchingAnts_NativeWindow` 类移至 `TdhMarchingAnts` 类(并将其设为 '
public
') public static System.Drawing.Point ReallyEmptyPoint()
public static bool IsReallyEmptyPoint(System.Drawing.Point pt)
public static System.Drawing.Rectangle ReallyEmptyRectangle()
public static bool IsReallyEmptyRectangle(System.Drawing.Rectangle rec)
- 2006 年 12 月 15 日:ver. 1.0.004
- `TdhMarchingAnts_NativeWindow.InvalidateAntPaths()` 方法中的逻辑缺陷已得到纠正。由于 `this._parentControl.Invalidate(true);` 语句在 `InvalidateAntPaths()` 方法开始时引发的 `this._parentControl.Paint()` 事件中存在一个时序问题,尝试调用 `.DrawAntPath()` 方法来重绘“AntPath(s)”是徒劳的。这是因为 `this._parentControl.Paint()` 事件倾向于在 `.DrawAntPath()` 之后发生。
- 但严重的逻辑缺陷(与徒劳无功的尝试不同)在于,由于该调用 `.DrawAntPath()` 方法的参数列表,在右键单击后(再次)引发了“
RegionSelectEvent
”。 - 在所有 `TDHMarchingAnts.TdhMarchingAnts` 事件处理器的参数列表中添加了 '
object sender
'。 - 2007 年 1 月 8 日:ver. 1.0.006
- 添加了逻辑来拦截禁用“行军蚁”(包括释放 `Path`)时发生的时序问题。显然,可能已经安排了一个计时器滴答事件,当该方法执行时,由于 `Path` 被设置为 `
null
`,将导致未处理的异常。 - 2007 年 1 月 11 日:ver. 1.0.007
- 在设置 [
this._parentControl.Cursor = cursorOriginal;
] 之前,添加了一个检查条件 [this._parentControl.Visible
]。当“_parentControl
”不可见时,设置“_parentControl
”的光标会导致 VS2005 出现异常。
添加了以下事件(以及相应的属性和方法)
在 `TdhMarchingAnts` 类中创建了以下新的公共方法