我正在寻找一个可以点击的透明窗口(C#Winforms)样本。
我发现了一个类似的问题here,但这并不是我想要的方式。我希望能够拥有可点击的控件(按钮,Treeview等)并位于透明窗口的顶部,其透明区域是点击式的。
编辑:对不完整的帖子抱歉。想想这次我让自己更清楚一点。我已经尝试使用WS_EX_LAYERED来使窗口点击并且它没有工作,然后我添加了WS_EX_TRANSPARENT并且它变成了点击。即使是非键控颜色和非alpha零颜色也会变得非常轻微。好。在this MSDN文章中,它说会是这样的:
...如果分层窗口具有WS_EX_TRANSPARENT扩展窗口样式,则将忽略分层窗口的形状,并将鼠标事件传递到分层窗口下的其他窗口。
问题在于之前的说法:
分层窗口的命中测试基于窗口的形状和透明度。这意味着窗口中的颜色键区域或其alpha值为零的区域将允许鼠标消息通过。
我不知道我可能做错了什么,但是简单地覆盖CreateParams并设置WS_EX_LAYERED并不会使表单点击。
按照我的代码:
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);
}
当我点击填充的橙色椭圆,从按钮接收点击通知,并且当我点击另一个椭圆的内部时不接收通知时,我想收到mousedown通知。如果你按照它的方式测试表单,它应该让鼠标通过。如果通过删除|来更改CreateParams 0X20(WS_EX_TRANSPARENT)它不会让鼠标事件通过。我对有关分层Windows的微软文章的理解是它应该让鼠标事件通过颜色键入的位置和alpha值为零。
那么,有什么想法吗?