在C#中单击具有透明背景的表单

时间:2014-05-04 18:34:41

标签: c# transparency

我一直在研究RAD Studio,如果背景是完全透明的话,这会自动执行,但似乎在Visual Studio中并不那么简单。我已经阅读了函数GetWindowLong()和SetWindowLong()的文章和问题,但是当我尝试自己使用它们时,我得到错误“当前上下文中不存在名称xxx”。 我试过的是:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            int initialStyle = GetWindowLong(this.Handle, -20);
            SetWindowLong(this.Handle, -20, initialStyle | 0x80000 | 0x20);
        }
    }
}

那么我需要包含一些文件以使其正常工作,还是我必须将该功能放在其他位置?我也很想知道为什么它在RAD Studio和Visula Studio中表现得如此不同。

3 个答案:

答案 0 :(得分:1)

您使用的方法在标准.NET库中找不到,您需要通过user32.dll调用它们。

[DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]
private static extern IntPtr GetWindowLong32(HandleRef hWnd, int nIndex);

[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Auto)]
private static extern IntPtr GetWindowLongPtr64(HandleRef hWnd, int nIndex);

[DllImport("user32.dll", SetLastError = true)]
static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, UInt32 dwNewLong);

public static IntPtr GetWindowLong(HandleRef hWnd, int nIndex)
{
    if (IntPtr.Size == 4) return GetWindowLong32(hWnd, nIndex);
    else return GetWindowLongPtr64(hWnd, nIndex);
}

以这种方式调用它们现在可以正常工作:

uint initialStyle = GetWindowLong(this.Handle, -20);
SetWindowLong(this.Handle, -20, initialStyle | 0x80000 | 0x20);

确保您使用的是System.Runtime.InteropServices

编辑:我发现并修改了另一个问题中的一些代码(我会添加链接,如果我能找到它,我关闭了标签但找不到它),并想出了这个:

[DllImport(“user32.dll”,CharSet = CharSet.Auto,CallingConvention = CallingConvention.StdCall)]         public static extern void mouse_event(int dwFlags,int dx,int dy,int cButtons,int dwExtraInfo);         private const int MOUSEEVENTF_LEFTDOWN = 0x02;         private const int MOUSEEVENTF_LEFTUP = 0x04;

    public enum GWL
    {
        ExStyle = -20,
        HINSTANCE = -6,
        ID = -12,
        STYLE = -16,
        USERDATA = -21,
        WNDPROC = -4
    }

    public enum WS_EX
    {
        Transparent = 0x20,
        Layered = 0x80000
    }

    public enum LWA
    {
        ColorKey = 0x1,
        Alpha = 0x2
    }

    [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
    public static extern int GetWindowLong(IntPtr hWnd, GWL nIndex);

    [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
    public static extern int SetWindowLong(IntPtr hWnd, GWL nIndex, int dwNewLong);

    [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
    public static extern bool SetLayeredWindowAttributes(IntPtr hWnd, int crKey, byte alpha, LWA dwFlags);

    private void Form1_Click(object sender, EventArgs e)
    {
        base.OnShown(e);

        int originalStyle = GetWindowLong(this.Handle, GWL.ExStyle);
        int wl = GetWindowLong(this.Handle, GWL.ExStyle);
        wl = wl | 0x80000 | 0x20;

        SetWindowLong(this.Handle, GWL.ExStyle, wl);

        int X = Cursor.Position.X;
        int Y = Cursor.Position.Y;

        mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
        System.Threading.Thread.Sleep(50);

        SetWindowLong(this.Handle, GWL.ExStyle, originalStyle);

        TopMost = true;
    }

我不是如何做到这一点的专家,我不确定我是否喜欢这个解决方案,但它确实有效。

请务必使用以下代码订阅该活动:this.Click += Form1_Click;

答案 1 :(得分:1)

假设表格名称为form1

将这些属性设置为以下。

form1.BackColor = Control;
form1.TransparencyKey = Control;

现在您可以轻松点击表单的透明区域。希望这是你想要的。

答案 2 :(得分:0)

Shujaat Siddiqui的答案适用于点击透明度。它不会隐藏表格的标题,也不会隐藏它的边界。

要执行此操作,您可以设置Opacity=0d 选择FormBorderStyle=none以及Text=""ControlBox=false;

您也可以考虑在窗口区域切割孔,以便精确控制点击通过的位置和不通过的位置。

在所有这些情况下,您还必须计划控制表格的位置和大小。

但是,只要你不进行半透明的背景,一切都可以做到。