Based on my previous question (
I wish it to have transparent background, i.e. to not draw the gray border on top of the black background.
Can I do it with my TransparentButton class, without major changes (like drawing the text and background, and border manually)?
CodePudding user response:
Why are you setting WS_EX_TRANSPARENT
in CreateParams
? When I need a transparent background, I don't use WinAPI constants. WinForms was created to simplify the usage, and the solution I know is to set the BackgroundColor
of your button to Color.Transparent
.
Yes, it just sets the background color same as the parent's background color, but it works.
CodePudding user response:
This edited TransparentButton
improves on my previous answer. It no longer requires an override to OnPaint
and uses no custom drawing whatsoever. What I missed the first time is to simply set the Button.BackgroundImage
to the camouflage bitmap.
Requirements:
- Create a button with transparent background.
- Do it without drawing the background manually in
OnPaint
. - Keep the
Button.FlatStyle
asFlatStyle.Standard
. - Do not disturb the rounded edges of the standard button.
class TransparentButton : Button
{
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
Refresh();
}
public void SetParentForm(Form form)
{
_parentForm= form;
Refresh();
}
Form? _parentForm = null;
public new void Refresh()
{
if (!(DesignMode || _parentForm == null))
{
// Hide this button before drawing
Visible = false;
// Draw the full container
var tmp = (Bitmap)new Bitmap(_parentForm.Width, _parentForm.Height);
_parentForm.DrawToBitmap(tmp, new Rectangle(0, 0, _parentForm.Width, _parentForm.Height));
var ptScreen = _parentForm.PointToScreen(_parentForm.ClientRectangle.Location);
var ptOffset = new Point(
ptScreen.X - _parentForm.Location.X,
ptScreen.Y - _parentForm.Location.Y);
var clipBounds = new Rectangle(Location.X ptOffset.X, Location.Y ptOffset.Y, Width, Height);
BackgroundImage = tmp.Clone(
clipBounds,
System.Drawing.Imaging.PixelFormat.DontCare);
// Show this button.
Visible = true;
}
}
Design Mode Example
Main form BackgroundImage
to main form with a Stretch
layout. Then overlay a TableLayoutPanel
whose job it is to keep the button scaled correctly as the form resizes. TransparentButton
is now placed in one of the cells.
Test
Here's the code I used to test this answer:
public partial class MainForm : Form
{
public MainForm() => InitializeComponent();
protected override void onl oad(EventArgs e)
{
base.OnLoad(e);
buttonTransparent.FlatStyle= FlatStyle.Standard;
buttonTransparent.SetParentForm(this);
buttonTransparent.ForeColor= Color.White;
buttonTransparent.Click = onClickTransparent;
}
private void onClickTransparent(object? sender, EventArgs e) =>
MessageBox.Show("Clicked!");
protected override CreateParams CreateParams
{
get
{
const int WS_EX_COMPOSITED = 0x02000000;
// https://stackoverflow.com/a/36352503/5438626
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_COMPOSITED;
return cp;
}
}
}