简体   繁体   English

通过透明的Windows窗体防止鼠标单击

[英]Preventing mouse clicks through a transparent Windows Form

I'm making a little tool for drawing onto the screen with the mouse after a 'pen' button is toggled in a floating sidebar. 在浮动侧边栏中切换“笔”按钮后,我正在制作一个用鼠标在屏幕上绘图的小工具。

I have done this (please don't laugh) by having a top-most windows form with its background as its transparency key cover the whole screen. 我做了这个(请不要笑)通过最顶层的窗体形式及其背景,因为它的透明度键覆盖整个屏幕。 I need to make the mouse not click through the form onto the stuff below when I"m in drawing mode. I tried following this: Windows form with a transparent background that cannot be clicked through How to disable click through on transparent control? 当我处于绘图模式时,我需要让鼠标不要点击表格到下面的东西。我试过这样: Windows窗体的透明背景无法点击 如何禁用点击透明控件?

which successfully stops the mouse but also un-maximises the form and drags it around with the mouse (using HTCAPTION IntPtr(2) this is) I tried using some of the other values listed on MSDN, but with no luck. 它成功地停止了鼠标,但也没有最大化窗体并用鼠标拖动它(使用HTCAPTION IntPtr(2)这是)我尝试使用MSDN上列出的一些其他值,但没有运气。

I'm way out of my depth, any help greatly appreciated (newbie friendly please!) 我离开了我的深度,任何帮助都非常感谢(请新手友好!)

PS I'm using this right now.. 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);
        }

UPDATE: Now solved the problem by approaching it in another way entirely. 更新:现在完全以另一种方式解决问题。 It doesn't look like WndProc will work so I simply created a blank form over the whole screen the showed my main form (form.Show(this)) from within that. 它看起来不像WndProc会工作,所以我只是在整个屏幕上创建了一个空白表单,从中显示了我的主要表单(form.Show(this))。 Then adjust the opacity of the blank form which sits underneath from 0% to 1% to allow/ prevent clicking through. 然后调整位于下方的空白表单的不透明度从0%到1%以允许/防止点击。 Works! 作品! Thanks to all answers, taught me a lot. 感谢所有的答案,教会了我很多。

Actually, no need to laugh—it sounds to me like you're doing this the correct way already. 实际上,没有必要笑 - 这对我来说听起来就像你正在以正确的方式做到这一点。 Since you don't own the desktop, you shouldn't draw directly on it. 由于您不拥有桌面,因此不应直接在桌面上绘制。 Instead, you need to simulate it by overlaying a transparent form that you do own, and then drawing on that. 相反,你需要通过叠加,你自己一个透明的形式,再画上模拟它。 Because you own the transparent overlay form, it's no problem to draw on it. 因为您拥有透明覆盖表单,所以在它上面绘制没有问题。

But beyond that, it sounds like you're just trying values randomly without a clear understanding of what they actually do. 但除此之外,听起来你只是在没有清楚地了解他们实际做什么的情况下随意尝试价值。 That's like throwing darts with your eyes closed. 这就像闭上眼睛一样投掷飞镖。 You won't have a very high hit count. 你不会有很高的命中率。

Let's start by understanding what your code does. 让我们首先了解您的代码所做的事情。 The magic value 0x84 corresponds to the WM_NCHITTEST message, which is sent by Windows to a window to determine how mouse clicks on that window should be handled. 魔术值0x84对应于WM_NCHITTEST消息,该消息由Windows发送到窗口以确定应如何处理该窗口上的鼠标点击。 In response to that message, you reply with one of the HT* values, given in the linked documentation. 在回复该消息时,您将回复链接文档中给出的HT*值之一。 Each of those values has a particular meaning, also explained in the documentation. 这些值中的每一个都具有特定含义,也在文档中进行了解释。 For example: 例如:

  • HTCAPTION (which has a value of 2) means that the clicked portion of the window should be treated as the window's caption/title bar. HTCAPTION (其值为2)表示窗口的单击部分应被视为窗口的标题/标题栏。 You know from using Windows that you can drag windows around on the screen using the title bar, so it makes sense that returning HTCAPTION in response to mouse clicks would allow your window to be draggable. 您知道使用Windows可以使用标题栏在屏幕上拖动窗口,因此返回HTCAPTION以响应鼠标单击将允许您的窗口可拖动。 You'll see this used on borderless forms (ie, those with no title bar) to allow them to be movable. 您会看到这在无边框表格(即没有标题栏的表格)上使用,以允许它们移动。

  • HTTRANSPARENT (which has a value of -1) is another available value. HTTRANSPARENT (值为-1)是另一个可用值。 This one's pretty simple. 这一个很简单。 It just makes your window look transparent. 它只是让你的窗口看起来透明。 It's like saying "don't mind me, there's no window here!" 这就像说“不要介意我,这里没有窗户!” Mouse clicks are simply passed on to the window that lies below yours in the Z order as if you weren't there. 鼠标点击只是简单地传递到Z顺序下面的窗口,就好像你不在那里一样。

  • HTCLIENT (a value of 1) is the default result when the click occurs anywhere on the window's client area. 当单击发生在窗口客户区的任何位置时, HTCLIENT (值为1)是默认结果。 You would return this (or simply call the default window procedure) when you want everything to work normally. 当您希望一切正常工作时,您将返回此(或只是调用默认窗口过程)。 Click events that return this value would go on to be processed normally by the framework, raising either the form's Click event, or getting passed on to child controls located on the form. 返回此值的单击事件将继续由框架正常处理,引发窗体的Click事件,或者传递给位于窗体上的子控件。

So, when you're not drawing, you probably want to return HTTRANSPARENT . 因此,当您没有绘图时,您可能想要返回HTTRANSPARENT When you are drawing, you probably want to return HTCLIENT so that your drawing code can see the mouse events and draw the result. 绘制,你可能要返回HTCLIENT让你的绘图代码可以看到鼠标事件并绘制结果。

Fixing your code, then: 修复你的代码,然后:

// 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);
}

You might just want to set the visibility of your window to like 5% or so and leave the transparent key deactivated. 您可能只想将窗口的可见性设置为大约5%左右,并保持透明密钥停用。

you basically won't notice it and jet it's there :D 你基本上不会注意到它并将它喷射到那里:D

hope this helps 希望这可以帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM