2013-04-07 65 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