不得不在類似的情況下處理winforms透明度,我發現的第一件事是:它不支持半透明(以一種簡單的方式)。
我最終深入研究了window styles(最重要的一個是WS_EX_LAYERED),並推出了我自己的控制。
大部分這方面的東西,我發現通過大量的谷歌搜索,並嘗試和錯誤...
讓我們去爲它:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public partial class ShaderControl : UserControl
{
//we will need all these imports, see their documentation on what they do exactly
[DllImport("user32")]
private static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32")]
private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32", EntryPoint = "SetWindowLong", SetLastError = true)]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32", EntryPoint = "SetLayeredWindowAttributes")]
private static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
[DllImport("user32", EntryPoint = "GetWindowLong", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
//we're going to give the window these constans as parameters
private const int WS_EX_TOOLWINDOW = 0x80; //make it a toolwindow
private const int WS_EX_NOACTIVATE = 0x8000000; //make it non-activating
private const int WS_EX_TOPMOST = 0x8; //make it the topmost window
//and we need these ones later on, too to achieve semi-transparency
private const int GWL_EXSTYLE = -20;
private const int WS_EX_LAYERED = 0x80000;
private const int LWA_ALPHA = 0x2;
private double opacity = 0.8; //between 0 and 1
public ShaderControl()
{
InitializeComponent();
}
protected override CreateParams CreateParams
{
//here we create the window parameters
//this will be called once when the window is created
get
{
CreateParams p = base.CreateParams;
p.ExStyle |= (WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
return p;
}
}
public new void Show()
{
//here we make the window a child of the desktop
if (this.Handle == IntPtr.Zero)
{
base.CreateControl();
}
SetParent(base.Handle, IntPtr.Zero);
ShowWindow(base.Handle, 1);
}
protected sealed override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (this.Visible)
{
//every time the window gets shown we have to update the window attributes
//the important thing here is the WS_EX_LAYERED attribute, this makes it possible to achieve semi-transparency
int wl = GetWindowLong(this.Handle, GWL_EXSTYLE);
wl = wl | WS_EX_LAYERED;
SetWindowLong(this.Handle, GWL_EXSTYLE, wl);
SetLayeredWindowAttributes(this.Handle, 0, (byte)(opacity * 255), LWA_ALPHA);
}
}
public double Opacity
{
get
{
return opacity;
}
set
{
//when the opacity changes we have to renew the window attributes
opacity = value > 0d ? Math.Min(1d, value) : Math.Max(0d, value);
SetLayeredWindowAttributes(this.Handle, 0, (byte)(opacity * 255), LWA_ALPHA);
}
}
}
現在所有的留給你的是設置ShaderControl.Opacity
的值0和1之間,適合您的需求和 - 最重要的 - 給這個控制正確的大小和位置!
延伸閱讀:
vbaccelerator.com - Floating Control
codeproject.com - Microsoft WORD 2007 Style Semi transparent Minibar
Topmost form, clicking "through" possible?
關於'A'值改變(100'')的東西像什麼'20'? –
@HighCore讓面板更輕但不透明(這是它後面的控件不可見),alpha是0-256的比例,所以即使是100我也應該大部分看透。 – asutherland
「BackColor屬性不支持透明顏色,除非System.Windows.Forms.ControlStyles的SupportsTransparentBackColor值設置爲true。」 - http://msdn.microsoft.com/en-us/library/system.windows.forms.control.backcolor(v=vs.110).aspx – mao47