2015-09-04 140 views
2

我有一個透明表單,它覆蓋了c#.NET winforms應用程序中的桌面。通過將BackColor設置爲明亮的橙色,然後將TransparencyKey設置爲相同的明亮橙色來完成透明度。Winforms:如何在透明表單上獲取透明控件的鼠標事件

到目前爲止,這個工作很好,它創建一個透明的形式。然後,我想在透明窗體上創建一個控件,在桌面上的項目周圍繪製一個矩形。所以基本上你可以想象一個帶有矩形邊框的透明按鈕。要做到這一點我現在延長控制和設置這樣父窗體的內部控制,這也是透明的:

public class CustomControl : Control 
{ 
    public CustomControl(Size size, Point point) 
    { 
     SetStyle(ControlStyles.SupportsTransparentBackColor, true); 
     this.BackColor = Color.Transparent; 
     this.Size = size; 
     this.Location = point; 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     base.OnPaint(e); 
     Pen pen = new Pen(Color.Red, 2f); 
     e.Graphics.DrawRectangle(pen, this.ClientRectangle); 
    } 
} 

這造成我在尋找的效果是有控制用固體透明窗體中的不透明矩形邊框,您可以通過控件和窗體看到桌面(請參見左下方的圖像)。

enter image description here

的問題是,所述控制的所述透明區域不接收任何鼠標事件。實際上,它基本上不存在。例如,當鼠標移過觸發鼠標懸停,鼠標輸入和鼠標離開事件的控件的紅色矩形邊框,並將光標更改爲您爲該控件設置的任何內容(如this.Cursor)。一旦鼠標位於控件的透明部分,這些事情都不會觸發。

我該如何保持它們現在的狀態與控件的外觀相似,但仍然在透明區域接收鼠標事件。特別是我想收到鼠標懸停並有控制Cursor值得尊重。請注意,如果我將控件的BackColor設置爲Color.Transparent以外的其他值,則鼠標事件可以正常工作。

謝謝!

更新

基於漢斯發表評論我想補充一點,我們已經實現了上述並且它通常工作(即透明區域不響應鼠標事件)。出現這個問題的原因是因爲我最近用所有的Windows 8.1更新和最新的ATI圖形驅動程序重建了我的機器,之後上述設置不再有效(控件上的透明區域不再接收任何鼠標事件並且不再接收任何意圖目的不是控制的一部分)在我的同事的機器上,它幾乎總是有效,儘管我們偶爾會注意到它不起作用,但我們永遠無法重現這個問題。

我的設想是我們做了錯誤的事情導致透明區域不響應鼠標事件。然而,根據漢斯的評論,上面的代碼看起來好像永遠不會起作用,而且它工作的唯一原因是由於Aero中的錯誤。

我們的透明鍵的確切顏色是rgb(255, 128, 0)。另外,我們注意到,透明窗體上的任何標籤控件看起來都很糟糕(根據Han的評論)。

更新2

根據韓寒的關於航空透明度錯誤,我有以下問題更新額外的評論。

  1. 有沒有關於這個bug的任何信息來解釋錯誤是什麼?
  2. 控件的透明區域的預期行爲(假設沒有錯誤)是什麼?鼠標事件(例如鼠標懸停)是否在透明區域上工作?下面

最終的答案(即通常工作)

的回答禮確實提供了一些我的電腦,我的工作。但是,我的主要桌面繼續頑固地拒絕合作。即使在使用相同版本的Windows和.NET的計算機之間複製精確項目時,也存在問題。問題出現時,透明區域不會觸發鼠標事件,也不會被視爲控件的一部分。

另外,我注意到Reza注意到同樣的事情,那就是某些TransparencyKey顏色沒有起作用。雖然我不知道這個bug的任何細節,但我不得不同意Hans的觀點,即WinForms的透明性存在缺陷,如果有人從頭開始,我會去WPF路由併爲將來的麻煩保存。

最後,我們根據漢斯的一些答案完成了一項工作,這些答案需要使用計時器來檢查鼠標位置並嵌套兩個窗體(一個窗體爲不透明集)以便能夠管理鼠標光標。這個解決方案已經在我們所有的系統上運行過了,並且希望能夠繼續下去,直到我們轉向WPF。我接受了Reza的答案,因爲它似乎在大多數地方都有效,但請注意它可能不適用於你,而且爲什麼沒有押韻或理由。

有關我們實施的兩種解決方法的詳細信息,請參閱Hans提供的以下問題和解答。

MouseHover and MouseLeave Events controlling

How can I add transparency to a c# form while keeping controls visible?

+0

看看這個SO帖子:http://stackoverflow.com/questions/14432230/transparency-and-mouse-events-winforms。 Hans Passant建議每隔50ms檢查鼠標指針是否在邊界內。 – Christoph

+1

謝謝你的迴應。我實際上實現了漢斯解決方案,它確實工作,雖然我無法使用此方法爲控件正確設置遊標,因爲透明區域未被視爲控件的一部分。希望我可能錯過了更明顯的東西。 – Sarus

+0

使用'SetWindowsHookEx'添加全局鼠標偵聽器。然後監聽WM_MOUSE消息。 – Loathing

回答

2

重要

請考慮設置形式的BackgroundColor以紅色和TransparencyKey以紅色和透明控制的BackGroundColor爲透明,也將努力!

我看到的奇怪之處在於,該方法不適用於例如洋紅色,但適用於紅色和藍色。


我想你應該創建透明的控制是這樣的:

透明控制代碼

public class TransparentControl : Control 
{ 
    public TransparentControl() 
    { 
     this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); 
    } 

    private const int WS_EX_TRANSPARENT = 0x20; 
    protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT; 
      return cp; 
     } 
    } 
} 

而對於鼠標事件和渲染邊框當鼠標進入,這裏是我做過的樣品使用.Net 4.5Windows 8.1

創建一個Form並將我們使用上面的代碼創建的TransparentControl放在上面,然後處理MouseEnterMouseLeaveMouseLeavePaint事件並在鼠標處於控制範圍內時繪製邊框並處理事件並顯示消息。

表單代碼

private bool drawBorder; 
private void transparentControl1_MouseLeave(object sender, EventArgs e) 
{ 
    drawBorder = false; 
    transparentControl1.Invalidate(); 
} 

private void transparentControl1_MouseEnter(object sender, EventArgs e) 
{ 
    drawBorder = true; 
    transparentControl1.Invalidate(); 
} 

private void transparentControl1_Paint(object sender, PaintEventArgs e) 
{ 
    if(drawBorder) 
    { 
     using (var pen = new Pen(this.ForeColor, 5)) 
     { 
      e.Graphics.DrawRectangle(pen, 0, 0, this.transparentControl1.Width - 1, this.transparentControl1.Height - 1); 
     } 
    } 
} 

private void transparentControl1_Click(object sender, EventArgs e) 
{ 
    MessageBox.Show("Clicked"); 
} 

截圖

enter image description here

鼠標光標是在控制的區域,這樣的黑色邊框被畫。

重要提示

如果繪製邊框的顏色一樣form'a透明按鍵,邊框將不顯示。

+0

謝謝你的帖子。在我的情況下,我正在繪製帶邊框的控件來啓動(所以不需要drawBorder邏輯)。但是,鼠標事件僅在邊框本身上觸發,而不是控件的透明部分。例如,如果將鼠標懸停在文件夾圖標上,則不會觸發MouseHover事件,但如果將鼠標懸停在邊框上,則會觸發MouseHover事件。你的樣品是否有同樣的問題?我試圖用你的邏輯,但仍然遇到了同樣的問題。 – Sarus

+0

你能夠整體分享你的測試嗎?我似乎無法弄清楚我們的兩個應用程序可能有什麼區別。 – Sarus

+0

謝謝你的提議。我給你發了封郵件。 – Sarus