Marking 狀態管理
BeginMark:建立新 PenMarkInfo 物件,尚未加入文件,Marking 回傳 true。
EndMark:若新簽名包含至少一筆筆跡則加入文件,否則捨棄,Marking 回傳 false。
OnMouseDown 事件處理核心邏輯
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (this.Marking)
{
myCurrentLine = new PointArrayList();
LastPoint = new Point(e.X, e.Y);
}
else
{
// 座標修正 (考慮 AutoScrollPosition)
int x = e.X - this.AutoScrollPosition.X;
int y = e.Y - this.AutoScrollPosition.Y;
// 命中測試:距離平方 < 13 視為命中
foreach (PenMarkInfo info in myDocument)
foreach (PointArrayList line in info.Lines)
foreach (Point p in line)
{
double r = (p.X - x)*(p.X - x) + (p.Y - y)*(p.Y - y);
if (r < 13)
{
Rectangle rect = info.Bounds;
if (myCurrentInfo != null)
rect = Rectangle.Union(rect, myCurrentInfo.Bounds);
rect.Offset(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);
myCurrentInfo = info;
this.Invalidate(rect); // 宣告局部無效需重繪
goto EndElse;
}
}
EndElse: ;
}
}
Invalidate 機制
Invalidate(Rectangle):宣告局部區域無效,後續 OnPaint 的 ClipRectangle 即為此矩形,優化重繪範圍。
Invalidate() (無參數):宣告整個控制項需重繪。
演算法重點
- 使用距離平方避免
Math.Sqrt 運算。
goto 跳出多層迴圈 (可改用布林旗標或方法抽離)。
- 命中後合併舊/新邊界並轉換回客戶區座標再
Invalidate。