Control.Region 屬性決定控制項的可見/可點擊區域GraphicsPath 描述不規則形狀GraphicsPath
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
public static class BitmapRegion
{
public static void CreateControlRegion(Control control, Bitmap bitmap)
{
if (control == null || bitmap == null) return;
control.Width = bitmap.Width;
control.Height = bitmap.Height;
if (control is Form form)
{
form.Width += 15; // 補償邊框
form.Height += 35;
form.FormBorderStyle = FormBorderStyle.None;
form.BackgroundImage = bitmap;
form.Region = new Region(CalculateGraphicsPath(bitmap));
}
else if (control is Button btn)
{
btn.Text = "";
btn.Cursor = Cursors.Hand;
btn.BackgroundImage = bitmap;
btn.Region = new Region(CalculateGraphicsPath(bitmap));
}
// 可擴充支援 Panel、PictureBox 等
}
private static GraphicsPath CalculateGraphicsPath(Bitmap bitmap)
{
var path = new GraphicsPath();
Color transparentColor = bitmap.GetPixel(0, 0); // 左上角為透明色
for (int y = 0; y < bitmap.Height; y++)
{
int xOpaqueStart = 0;
for (int x = 0; x < bitmap.Width; x++)
{
if (bitmap.GetPixel(x, y) != transparentColor)
{
xOpaqueStart = x;
int xNext = x;
// 尋找連續不透明區段結束
while (xNext < bitmap.Width && bitmap.GetPixel(xNext, y) != transparentColor)
xNext++;
// 加入矩形區段 (高度=1)
path.AddRectangle(new Rectangle(xOpaqueStart, y, xNext - xOpaqueStart, 1));
x = xNext; // 跳過已處理區段
}
}
}
return path;
}
}
public class MainForm : Form
{
private readonly Bitmap _bg = new Bitmap(typeof(MainForm), "Resources.back.png");
public MainForm()
{
InitializeComponent();
BitmapRegion.CreateControlRegion(this, _bg);
}
// 拖曳移動視窗 (無標題列時必要)
private Point _lastPos;
private bool _dragging;
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_lastPos = e.Location;
_dragging = true;
}
base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (_dragging)
{
Location = new Point(
Location.X + e.X - _lastPos.X,
Location.Y + e.Y - _lastPos.Y);
}
base.OnMouseMove(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
_dragging = false;
base.OnMouseUp(e);
}
}
public class MainForm : Form
{
private Button _btn;
private Bitmap _btnNormal, _btnHover;
public MainForm()
{
_btn = new Button { Location = new Point(100, 100) };
_btnNormal = new Bitmap(typeof(MainForm), "Resources.btn_normal.png");
_btnHover = new Bitmap(typeof(MainForm), "Resources.btn_hover.png");
Controls.Add(_btn);
BitmapRegion.CreateControlRegion(_btn, _btnNormal);
_btn.MouseEnter += (s, e) => BitmapRegion.CreateControlRegion(_btn, _btnHover);
_btn.MouseLeave += (s, e) => BitmapRegion.CreateControlRegion(_btn, _btnNormal);
_btn.Click += (s, e) => MessageBox.Show("不規則按鈕被點擊!");
}
}
GraphicsPath,避免重複 GetPixel 掃描。GetPixel 極慢,改用 Bitmap.LockBits 直接存取記憶體。Region 物件直接切換。Region 自動處理點擊測試,只有在不透明區域點擊才會觸發 Click 事件,透明區域點擊會穿透給父容器。
FormBorderStyle.None 後失去標題列,需自行實作移動/最小化/關閉。AutoScaleMode 或使用向量圖 (SVG/WMF)。