最顶尖的透明窗口

时间:2014-05-06 19:19:48

标签: c# winforms

我正在寻找一个可以点击的透明窗口(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值为零。

那么,有什么想法吗?

0 个答案:

没有答案