【问题标题】:How do I create a fully transparent winform in C# that is interactive?如何在 C# 中创建一个完全透明的交互式 Winform?
【发布时间】:2013-06-16 07:48:49
【问题描述】:

我正在尝试在 C# 中创建一个完全透明的表单,但不允许点击通过它进入下面的其他窗口。 我找到了两种很有希望的方法,但没有达到我想要的结果。

第一种是将背景颜色和透明度键设置为相同的值。这给了我透明的形式,但点击通过。

this.BackColor = Color.Red;
this.TransparencyKey = Color.Red;

我尝试的另一件事是将表单的不透明度设置为 1%。这创造了我想要的效果 - 几乎。我得到了一个 99% 透明的表格,但是表格下面的任何东西都有轻微的颜色变化。由于我正在制作的应用程序旨在用于对颜色敏感的环境(图形设计等),因此即使是颜色的微小变化也是不可接受的。所以我转向你,亲爱的。这个可以吗?

【问题讨论】:

  • 你想做什么?只需在表单上添加一个覆盖层,这样就无法单击或与之交互?
  • @Yuck 我认为他的问题很清楚,他只是想让他的表单完全透明,但用户可以与该表单进行交互,不仅可以单击,还可以执行其他操作,例如鼠标进入、鼠标离开、按键,......我想是的,但至少他希望他完全透明的表单可以点击。
  • 我不明白这个问题..如果您将不透明度设置为 0%,您将看不到它,但是您将如何与之交互?!
  • @Alan 你应该多联想,就像你站在玻璃前,你可能看不到它,但你可以触摸到它。如果你知道它就在你面前,你可能知道如何避免不小心撞到它,这可能会让你受伤。
  • @Yuck 我想制作一个允许您在任何其他窗口上绘图的应用程序。因此,当您单击绘图时,不要按下下方的任何按钮,这一点很重要。

标签: c# winforms


【解决方案1】:

我已经找到了解决办法,也分享给大家。

答案很简单:我设置:this.TransparencyKey = Color.Lime;

然后我使用 1x1px Lime PNG 作为背景图片。这还具有不遮挡表单边框和标题栏的额外好处。我稍后会删除它们,但目前,知道表单的位置很有用。

【讨论】:

  • 这对我不起作用,点击仍然会发生。也许这是一个现在在最近的 C# 中“修复”的错误。然而,这让我无法通过点击来解决透明控件。
【解决方案2】:

我完全偶然地找到了解决方案。

我想通过透明窗口点击并通过使用此 SO 问题中的答案得到它:

C# cursor highlighting/follower

该答案使用 LightGreen 的透明度过滤器,但我认为我可能需要使用该颜色,因此我将其更改为 AliceBlue 并单击停止工作。我切换回 LightGreen,它又开始工作了。

【讨论】:

  • 谢谢你!我遇到了类似的问题,这就是为我解决的问题。
【解决方案3】:

您可以尝试仅在系统范围内捕获鼠标操作(单击、移动)并根据需要处理它们,而不是尝试在透明表单上捕获鼠标操作。

【讨论】:

  • 这并不是 OP 真正想要做的。例如,如果您单击一个透明窗口,您会认为您看到的窗口是被单击的窗口,但事实并非如此。如果使用您的解决方案,您看到的窗口肯定是被点击的窗口。当然,如果您有更多代码来处理这种情况(以及更多问题)。一个完全透明的窗口更有趣。
  • 我已经找到了解决方案,我也与大家分享。答案很简单:我设置:this.TransparencyKey = Color.Lime; 然后我使用 1x1px Lime PNG 作为背景图片。这还具有不遮挡表单边框和标题栏的额外好处。我稍后会删除它们,但目前,知道表单的位置很有用。
  • @Ermir 我体验过使窗口完全透明并且仍然可以点击,但是该窗口是由支持 Aero 的 UI 操作系统(如 Windows 7)呈现的,它可能不适用于其他操作系统,如 Windows经验。
  • @Ermir 将其作为答案发布,以便其他查看此问题的人更容易看到
  • @Ermir 是颜色Lime 唯一有效的吗?其他颜色呢?
【解决方案4】:

这可以通过以下方式完成(假设绘制的表格保持最大化。如果不是,请参阅下面的段落):

  • 截取当前屏幕的屏幕截图。
  • 创建一个表单并将屏幕截图用作背景图片。
  • 从表单中删除表单标题,只需将其设为面板即可。

虽然上述解决方案解决了您想要的问题,但您需要回答以下问题:

  • 用户将如何关闭他正在绘制的表单?

如果表单需要调整大小-移动-复杂版本

但是,如果您想调整此表单的大小(刚刚注意到您使用新的屏幕截图进行了编辑),那么您需要剪切截取的屏幕截图部分并将其显示为表单的背景。但这更进一步:每次调整表单大小或移动表单时都需要这样做。

我个人会采用第一种(更简单的)方法。

【讨论】:

  • 我已经找到了一个比其中任何一个都简单得​​多的解决方案。我无法回答我自己的问题,因为这是一个全新的 SO 帐户。但我已将解决方案发布为对@alex 答案的评论
  • 我认为在这种情况下背景仍然是可点击的。如果没有,确实不错的解决方案!祝你好运!
  • @Ermir 您的解决方案不起作用,表单是透明的,毫不奇怪,但它不是交互式的,我可以点击它后面的所有内容。
【解决方案5】:

你可以设置钩子来捕捉鼠标事件。

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public static extern bool UnhookWindowsHookEx(int idHook);

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

    [StructLayout(LayoutKind.Sequential)]
    public class MouseStruct
    {
        public Point pt;
        public int hwnd;
        public int wHitTestCode;
        public int dwExtraInfo;
    }

    public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam); 

    private int hHook;
    public const int WH_MOUSE_LL = 14;
    public static HookProc hProc;

    public int SetHook()                                        
    {
        hProc = new HookProc(MouseHookProc);
        hHook = SetWindowsHookEx(WH_MOUSE_LL, hProc, IntPtr.Zero, 0);
        return hHook;
    }
    public void UnHook()                                        
    {
        UnhookWindowsHookEx(hHook);
    }
    //callback function, invoked when there is an mouse event
    private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)              
    {
        var MyMouseStruct = (MouseStruct)Marshal.PtrToStructure(lParam, typeof(MouseStruct));
        if (nCode < 0)
        {
            return CallNextHookEx(hHook, nCode, wParam, lParam);    
        }
        else
        {
            switch wParam{
                case (IntPtr)513:
                    //click
                    //do whatever you want
                case (IntPtr)512:
                    //move
                case (IntPtr)514:
                    //release
                default:
            }
            Cursor.Position = MyMouseStruct.pt;
            //stop the event from passed to other windows.
            return 1;
        }
    }

更多详情请访问MSDN

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多