2013-04-07 95 views
7

我正在制作一个用于在浮动边栏中切换“笔”按钮后用鼠标在屏幕上绘图的小工具。通过透明Windows窗体防止鼠标点击

我已经完成了这个(请不要笑),因为它的背景为最顶级窗体,它的透明度键覆盖整个屏幕。 我需要鼠标不通过形式点击进入下面时,我“米绘图模式我试过的东西下面这样: 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%,以允许/防止点击。作品! 感谢所有的答案,教会了我很多。

回答

5

实际上,没有必要笑,这听起来像你正在做这个正确的方式。由于您不拥有桌面,因此您不应该直接在桌面上绘画。相反,你需要通过覆盖你自己的透明窗体来模拟它,然后绘制它。因为你拥有透明的覆盖表格,所以使用它是没有问题的。

但除此之外,它听起来像你只是随机尝试值而没有清楚地理解他们实际做了什么。这就像你闭着眼睛投掷飞镖。你不会有很高的命中数。

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

  • HTCAPTION(其具有值2)意味着,窗口的点击部应该作为窗口的标题/标题栏进行处理。您知道使用Windows时,您可以使用标题栏在屏幕上拖动窗口,因此返回HTCAPTION以响应鼠标单击可以让您的窗口可拖动。你会看到这个用于无边界形式(即没有标题栏的形式)以允许它们移动。

  • HTTRANSPARENT(其值为-1)是另一个可用值。这个很简单。它只是让你的窗户看起来透明。这就像说:“不介意我,这里没有窗户!”鼠标点击只需按照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); 
} 
+1

测试在Windows 8机器,窗口的透明部分不将消息发送到父窗口时,鼠标点击。 (在记录消息和Spy ++中进行验证)。 – 2013-04-07 13:27:58

+0

@Cody,哇,谢谢你这么清楚和完整的答案!它看起来不错,但我现在看到的是,在绘制点之后,如果再次点击该点,现在是蓝色,不透明,则点击会通过.. – 2013-04-07 14:09:17

+0

在Windows 10上无法正常工作同样的原因约翰提到。 – 2016-02-28 13:44:16

1

你可能只是想设置你的窗口的知名度,像5%左右,并留下停用透明的关键。

,你基本上不会注意到它和喷气它的存在:d

希望这有助于

+0

谢谢@Chronos,但有什么办法可以做到这一点:按钮和更重要的是我用笔模式绘制的东西不是5%可见? – 2013-04-08 03:03:21

+1

我想我低估了这个问题。我现在有一种使用三种形式的解决方案。第一个只是显示gui beeing由于透明度键而大部分隐形。第二个仅控制5%的可见度输入。第三次再次使用透明度键绘制。 Sry我以前没想过这件事。这次测试它是文件以及一个包含所有这些文件的.rar https://drive.google.com/folderview?id=0B-5Qr5swDDp8ZV9CMUVrVHloeWc&usp=sharing – ChronosMOT 2013-04-08 13:43:39

+0

谢谢,我已经想出了一个类似的解决方案两种形式 - 我使用与UI相同的形式,但我没有更新解决方案,因为我还没有完全测试所有目标机器。很高兴看到我像其他人一样思考问题! – 2013-04-09 03:24:49