Imageプロパティに設定した画像に透過色が設定されている場合、BackColorをColor.TransparentとすればPictureBoxの背景を透過させることはできます。しかしそこに何らかのコントロールが表示されていると、それはPictureBoxの親コントロールの背景色で塗りつぶされてしまいます。この問題はそのコントロールの外観をPictureBoxの背景として描画することで、コントロールが見えているようにすることで解決できます。
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
using (Bitmap bitmap = new Bitmap(Parent.Width, Parent.Height))
{
ControlCollection parentControls = Parent.Controls;
int ownIndex = parentControls.GetChildIndex(this);
// このコントロールの背面にあるコントロールを取得する
IEnumerable<Control> controls = parentControls.Cast<Control>()
.Where(control => ownIndex < parentControls.GetChildIndex(control) // このコントロールより背面に配置されている
&& control.Bounds.IntersectsWith(Bounds)) // このコントロールの領域と交差する
.OrderByDescending(control => parentControls.GetChildIndex(control)); // コントロールのインデックスの降順に並べ替えることで、重なる順を維持する
// 背面にあるコントロールの画像を、Bitmapへ描画する
foreach (Control control in controls)
{
control.DrawToBitmap(bitmap, control.Bounds);
}
// コントロールの背景として描画する
e.Graphics.DrawImage(bitmap, -Left, -Top);
}
}
c# - Show Transparent Loading Spinner above other Controls - Stack Overflow
前述の方法ではコントロールが見えているように表示しているだけのため、そのコントロールをクリックしても実際にはPictureBoxがクリックされます。この問題はPictureBoxにWM_NCHITTESTメッセージが送られたときに、HTTRANSPARENTを返すことで解決できます。
protected override void WndProc(ref Message m)
{
const int WM_NCHITTEST = 0x0084;
const int HTTRANSPARENT = -1;
if (m.Msg == WM_NCHITTEST)
{
m.Result = new IntPtr(HTTRANSPARENT);
}
else
{
base.WndProc(ref m);
}
}
Click through transparency for Visual C# Window Forms? - Stack Overflow
WM_NCHITTEST message (Winuser.h) - Win32 apps | Microsoft Learn