ControlPaint.DrawReversibleFrame) 無殘影更新。
public class MyRectangle
{
// 主矩形
public int X, Y, Width, Height, MinWidth = 5, MinHeight = 5;
public int DownPointX, DownPointY; // 滑鼠按下起始點
public Rectangle Rect => new Rectangle(X, Y, Width, Height);
// 8 個控制點小矩形
public int LittleRectSize = 4;
public Rectangle LeftTop, LeftMid, LeftBot, RightTop, RightMid, RightBot, TopMid, BotMid;
// 狀態旗標
public bool MoveMode, SizeMode;
public bool OnLeftTop, OnLeftMid, OnLeftBot, OnRightTop, OnRightMid, OnRightBot, OnTopMid, OnBotMid, OnCenter;
public Cursor CurrentCursor { get; private set; } = Cursors.Cross;
...
}
void UpdateHandles()
{
int o = LittleRectSize / 2;
LeftTop = new Rectangle(X - o, Y - o, LittleRectSize, LittleRectSize);
LeftMid = new Rectangle(X - o, Y + Height/2 - o, LittleRectSize, LittleRectSize);
LeftBot = new Rectangle(X - o, Y + Height - o, LittleRectSize, LittleRectSize);
RightTop = new Rectangle(X + Width - o, Y - o, LittleRectSize, LittleRectSize);
RightMid = new Rectangle(X + Width - o, Y + Height/2 - o, LittleRectSize, LittleRectSize);
RightBot = new Rectangle(X + Width - o, Y + Height - o, LittleRectSize, LittleRectSize);
TopMid = new Rectangle(X + Width/2 - o, Y - o, LittleRectSize, LittleRectSize);
BotMid = new Rectangle(X + Width/2 - o, Y + Height - o, LittleRectSize, LittleRectSize);
}
void Draw(Color backColor)
{
UpdateHandles();
ControlPaint.DrawReversibleFrame(Rect, backColor, FrameStyle.Dashed);
foreach (var r in new[]{LeftTop,LeftMid,LeftBot,RightTop,RightMid,RightBot,TopMid,BotMid})
ControlPaint.FillReversibleRectangle(r, Color.White);
}
// 重載:繪製中即時更新
void Draw(MouseEventArgs e, Color backColor)
{
Draw(backColor); // 先抹除舊框
// 計算新寬高
Width = e.X < DownPointX ? DownPointX - e.X : e.X - DownPointX;
Height = e.Y < DownPointY ? DownPointY - e.Y : e.Y - DownPointY;
X = e.X < DownPointX ? e.X : DownPointX;
Y = e.Y < DownPointY ? e.Y : DownPointY;
Draw(backColor); // 再畫新框
}
void CheckMouse(MouseEventArgs e)
{
ResetFlags();
if (LeftTop.Contains(e.Location)) { OnLeftTop = true; CurrentCursor = Cursors.SizeNWSE; }
else if (LeftMid.Contains(e.Location)) { OnLeftMid = true; CurrentCursor = Cursors.SizeWE; }
else if (LeftBot.Contains(e.Location)) { OnLeftBot = true; CurrentCursor = Cursors.SizeNESW; }
else if (RightTop.Contains(e.Location)) { OnRightTop = true; CurrentCursor = Cursors.SizeNESW; }
else if (RightMid.Contains(e.Location)) { OnRightMid = true; CurrentCursor = Cursors.SizeWE; }
else if (RightBot.Contains(e.Location)) { OnRightBot = true; CurrentCursor = Cursors.SizeNWSE; }
else if (TopMid.Contains(e.Location)) { OnTopMid = true; CurrentCursor = Cursors.SizeNS; }
else if (BotMid.Contains(e.Location)) { OnBotMid = true; CurrentCursor = Cursors.SizeNS; }
else if (Rect.Contains(e.Location)) { OnCenter = true; CurrentCursor = Cursors.SizeAll; }
else CurrentCursor = Cursors.Cross;
// 按下時進入對應模式
if (e.Button == MouseButtons.Left)
{
if (OnCenter && !SizeMode) MoveMode = true;
else if (!MoveMode) SizeMode = true;
}
else { MoveMode = SizeMode = false; }
}
void Resize(MouseEventArgs e)
{
if (!SizeMode) return;
if (OnLeftTop) { if (Right - e.X < MinWidth || Bottom - e.Y < MinHeight) return; Width = Right - e.X; Height = Bottom - e.Y; X = e.X; Y = e.Y; }
else if (OnLeftMid) { if (Right - e.X < MinWidth) return; Width = Right - e.X; X = e.X; }
else if (OnLeftBot) { if (Right - e.X < MinWidth || e.Y - Top < MinHeight) return; Width = Right - e.X; Height = e.Y - Top; X = e.X; }
else if (OnRightTop) { if (e.X - Left < MinWidth || Bottom - e.Y < MinHeight) return; Width = e.X - Left; Height = Bottom - e.Y; Y = e.Y; }
else if (OnRightMid) { if (e.X - Left < MinWidth) return; Width = e.X - Left; }
else if (OnRightBot) { if (e.X - Left < MinWidth || e.Y - Top < MinHeight) return; Width = e.X - Left; Height = e.Y - Top; }
else if (OnTopMid) { if (Bottom - e.Y < MinHeight) return; Height = Bottom - e.Y; Y = e.Y; }
else if (OnBotMid) { if (e.Y - Top < MinHeight) return; Height = e.Y - Top; }
}
MyRectangle 將選區幾何、控制點、游標、繪製、互動邏輯全封裝,表單層僅需轉發滑鼠事件並呼叫 Draw/Resize,實現關注點分離。