I am looking for a sample of a transparent window (C# Winforms) that I can click-through.
I have found a similar question here, but that does not work the way I want. I want to be able to have controls (Buttons, Treeview, etc) that are clickable and are on top of a transparent window, where its transparent areas are click-through.
EDIT: Sorry for the incomplete post. Think this time I made myself a bit clearer.
I have tried using WS_EX_LAYERED to make the window click-through and it didnt work, then I added WS_EX_TRANSPARENT and it became click-through. Even non keyed colors and non-alpha zero colors became click-trhough. OK. In this MSDN article it says it would be this way:
... if the layered window has the WS_EX_TRANSPARENT extended window style, the shape of the layered window will be ignored and the mouse events will be passed to other windows underneath the layered window.
The problem is with what says a bit before that:
Hit testing of a layered window is based on the shape and transparency of the window. This means that the areas of the window that are color-keyed or whose alpha value is zero will let the mouse messages through.
I dont know what I may have been doing wrong, but simply overriding CreateParams and setting WS_EX_LAYERED does not make the form click-through.
Follows my code:
public class ControlLayer : Form
{
public ControlLayer()
{
this.Visible = true;
this.TopMost = true; // make the form always on top
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; // hidden border
this.WindowState = FormWindowState.Maximized; // maximized
this.MinimizeBox = this.MaximizeBox = false; // not allowed to be minimized
this.MinimumSize = this.MaximumSize = this.Size; // not allowed to be resized
this.TransparencyKey = this.BackColor = Color.Red; // the color key to transparent, choose a color that you don't use
Button button = new Button()
{
Text = "Test",
BackColor = Color.White,
ForeColor = Color.Black,
Location = new Point(250, 50),
Size = new Size(75, 23),
};
button.Click += (sender, e) => MessageBox.Show("click");
this.Controls.Add(button);
// Extend aero glass style on form init
OnResize(null);
}
protected override void OnResize(EventArgs e)
{
int[] margins = new int[] { 0, 0, Width, Height };
// Extend aero glass style to whole form
DwmExtendFrameIntoClientArea(this.Handle, ref margins);
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
// Set the form click-through
cp.ExStyle |= 0x80000 /* WS_EX_LAYERED */ | 0x20 /* WS_EX_TRANSPARENT */;
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// do nothing here to stop window normal background painting
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(Color.Red);
e.Graphics.DrawEllipse(Pens.Orange, 10, 10, 100, 100);
e.Graphics.FillEllipse(Brushes.Orange, 110, 10, 100, 100);
e.Graphics.DrawRectangle(Pens.White, 0, 0, this.Size.Width-1, this.Size.Height-1);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
MessageBox.Show("layered");
}
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("dwmapi.dll")]
static extern void DwmExtendFrameIntoClientArea(IntPtr hWnd, ref int[] pMargins);
}
I would like to receive mousedown notifications when I click the filled orange ellipse, receive click notifications from the button, and do not receive notifications when I click the inside of the other ellipse. If you test the form the way it is, it should let the mouse through. If you change CreateParams by removing the | 0X20 (WS_EX_TRANSPARENT) it does not let the mouse events through. My understanding of the microsoft article about Layered Windows is that it should let mouse events through where it has color keyed and alpha value zero.
So, any thoughts?