c# - 通过透明的 Windows 窗体防止鼠标点击

标签 c# winforms

我正在制作一个小工具,用于在 float 侧边栏中切换“笔”按钮后用鼠标在屏幕上绘图。

我已经做到了这一点(请不要笑),方法是让最顶层的窗体及其背景作为透明键覆盖整个屏幕。 当我处于绘图模式时,我需要让鼠标不通过表单点击到下面的东西上。我试过以下操作: Windows form with a transparent background that cannot be clicked through How to disable click through on transparent control?

它成功地停止了鼠标,但也取消了最大化表单并用鼠标拖动它(使用 HTCAPTION IntPtr(2) 这是)我尝试使用 MSDN 上列出的其他一些值,但没有运气。

我无法理解,非常感谢任何帮助(请新手友好!)

PS 我现在正在使用这个..

        //code for allowing clicking through of menus
        protected override void WndProc(ref Message m)
        {              
            if (penMode && m.Msg == 0x84)
            {
                m.Result = new IntPtr(2);    
            }
            else
                base.WndProc(ref m);
        }

更新:现在完全以另一种方式解决了这个问题。它看起来不像 WndProc 会工作,所以我只是在整个屏幕上创建了一个空白表单,从中显示了我的主表单 (form.Show(this))。然后将位于下方的空白表格的不透明度从 0% 调整到 1%,以允许/防止点击。作品! 感谢大家的回答,教会了我很多东西。

最佳答案

实际上,没必要笑——在我看来你已经在以正确的方式做这件事了。由于您不拥有桌面,因此不应直接在其上绘图。相反,您需要通过覆盖您拥有 的透明表单来模拟它,然后在其上绘制。因为你拥有透明叠加窗体,所以在上面绘图是没有问题的。

但除此之外,听起来您只是在随机尝试值,而没有清楚地了解它们的实际作用。这就像闭着眼睛扔飞镖一样。你不会有很高的命中率。

让我们首先了解您的代码的作用。魔法值 0x84 对应于 WM_NCHITTEST 消息,该消息由 Windows 发送到窗口以确定应如何处理鼠标在该窗口上的单击。为响应该消息,您回复了链接文档中给出的 HT* 值之一。这些值中的每一个都有特定的含义,也在文档中进行了解释。例如:

  • HTCAPTION(值为 2)表示窗口的点击部分应被视为窗口的标题/标题栏。通过使用 Windows,您知道可以使用标题栏在屏幕上四处拖动窗口,因此返回 HTCAPTION 以响应鼠标单击将允许您的窗口可拖动是有意义的。您会看到它用于无边框表单(即没有标题栏的表单)以允许它们移动。

  • HTTRANSPARENT(值为 -1)是另一个可用值。这个很简单。它只是让你的窗口看起来透明。这就像在说“别介意我,这里没有 window !”鼠标点击会简单地传递到 Z 顺序中位于您下方的窗口,就好像您不在那里一样。

  • HTCLIENT(值为 1)是在窗口客户区任意位置单击时的默认结果。当您希望一切正常工作时,您将返回此(或简单地调用默认窗口过程)。返回此值的点击事件将继续由框架正常处理,引发表单的 Click 事件,或传递给位于表单上的子控件。

因此,当您 绘图时,您可能想要返回HTTRANSPARENT。当您 绘图时,您可能想要返回 HTCLIENT,以便您的绘图代码可以看到鼠标事件并绘制结果。

修复你的代码,然后:

// Code for allowing clicking through of the form
protected override void WndProc(ref Message m)
{
    const uint WM_NCHITTEST = 0x84;

    const int HTTRANSPARENT = -1;
    const int HTCLIENT      = 1;
    const int HTCAPTION     = 2;
    // ... or define an enum with all the values

    if (m.Msg == WM_NCHITTEST)
    {
        // If it's the message we want, handle it.
        if (penMode)
        {
            // If we're drawing, we want to see mouse events like normal.
            m.Result = new IntPtr(HTCLIENT);
        }
        else
        {
            // Otherwise, we want to pass mouse events on to the desktop,
            // as if we were not even here.
            m.Result = new IntPtr(HTTRANSPARENT);
        }
        return;  // bail out because we've handled the message
    }

    // Otherwise, call the base class implementation for default processing.
    base.WndProc(ref m);
}

关于c# - 通过透明的 Windows 窗体防止鼠标点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15862398/

相关文章:

c# - System.IdentityModel.Tokens 和 Microsoft.IdentityModel.Tokens 之间的冲突

wpf - PreviewKeyDown 未触发 ElementHost 中的 Tab 键和箭头键

MySQL/VB.NET(Winform) - 如何正确使用@var?

c# - 根据鼠标位置设置 WinForms TextBox 的 SelectionStart

c# - 如何在一个按钮中设置两种不同大小的文本,android api > 24

c# - SourceSafe CRC 计算

c# - Visual Studio 2017 使用 C# 7.2 发布 ASP.NET Core 应用程序

c# - X文档 : is it possible to force the load of a malformed XML file?

c# - 线程中的 TopMost 表单?

c# - 将占位符添加到密码 C# winforms 的文本框控件