繪圖功能封裝在 DrawTools 類別,主視窗僅調用工具方法,**低耦合、高內聚**。
finishingImg:繪製過程中臨時軌跡(滑鼠移動時的預覽)originalImg:已確認的繪圖內容 + 初始背景DrawTools_Graphics (畫布)、DrawColor (顏色)、OriginalImg (底圖)問題:Image.FromFile 鎖定檔案,無法覆蓋存檔 → 「GDI+ 一般性錯誤」
解法:讀取 → 畫到新 Bitmap → **立即 Dispose 原圖** → 後續操作新 Bitmap
private void openPic_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "JPG|*.jpg|Bmp|*.bmp|所有文件|*.*";
if (ofd.ShowDialog() == DialogResult.OK)
{
Bitmap bmpFromFile = new Bitmap(ofd.FileName); // 鎖定檔案
panel2.AutoScrollPosition = new Point(0, 0);
pbImg.Size = bmpFromFile.Size;
reSize.Location = new Point(bmpFromFile.Width, bmpFromFile.Height);
dt.DrawTools_Graphics = pbImg.CreateGraphics();
// 關鍵:畫到新 Bitmap 並釋放原圖
Bitmap bmp = new Bitmap(pbImg.Width, pbImg.Height);
Graphics g = Graphics.FromImage(bmp);
g.FillRectangle(new SolidBrush(pbImg.BackColor),
new Rectangle(0, 0, pbImg.Width, pbImg.Height));
g.DrawImage(bmpFromFile, 0, 0, bmpFromFile.Width, bmpFromFile.Height);
g.Dispose();
bmpFromFile.Dispose(); // 釋放檔案鎖定!
g = pbImg.CreateGraphics();
g.DrawImage(bmp, 0, 0);
g.Dispose();
dt.OriginalImg = bmp;
bmp.Dispose();
sFileName = ofd.FileName; // 記錄路徑供存檔覆蓋
ofd.Dispose();
}
}

完整工程代碼可下載參考(原文提供下載連結)。