关于Winforms:如何在保持控件可见的同时向C#表单添加透明度?

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

UPDATE: I took a break from messing with the transparency stuff for a few days. I started messing with it again tonight. I got a new result using Hans Passant's solution:
new result
http://img3.imageshack.us/img3/4265/icontransp.jpg

Passant's solution does solve the issue of the transparent background gradient. However, I'm still running into the problem with the transparent colors in my icon blending with the form's BackColor. You can see the fuchsia around various parts of the icon in the above image.

原始内容:

我已经在这个地方呆了几个小时了,运气还不太好。我搞砸了Control.Region,Form.TransparencyKey,Form.Opacity和其他一些具有时髦效果的随机对象。

最近,我一直在尝试自定义桌面,并决定与Application Docks混为一谈。在了解了Mac扩展坞和一些第三方Windows实施方案后,我决定自己构建一个。

最终,我想继续使用Win32 API。现在,我只想使用尽可能多的C#和.Net框架功能来工作。

我希望在此应用程序中可以做一些事情:

  • 显示带有渐变背景的表单/菜单。
  • 在保持图标不透明的同时,使窗体/菜单具有透明度。
  • 显示包含透明背景的图标。
  • 菜单和图标应能够接收与鼠标相关的事件(悬停,离开,单击,拖动,拖放以及其他一些事件)。

这是我要拍摄的效果:
Desired Effect
http://img207.imageshack.us/img207/5716/desired.jpg

此图像显示了我要实现的视觉效果。这是我为名为Rainmeter的程序制作的皮肤。该图像在皮肤后面显示了Notepad ++,并在编辑器中打开了一些皮肤文件。菜单是透明的,但图标仍然不透明。

我的方法:

在我看来,使用Form充当菜单似乎是合乎逻辑的首选。我对事件有基本的了解。我不太确定如何创建自己的点击事件,因此使用表格可以使事件的处理变得更加容易。我考虑了一些图标的选择。我决定将PictureBoxes用于图标,因为它们可以保存图像并接收事件。

一旦完成菜单所有结构逻辑的代码,我便开始尝试使用它来获得所需的视觉效果。 Form.Opacity影响了表单上所有内容的透明度。由于我希望图标完全不透明,因此我独自保留了此属性。我尝试将BackColor设置为Color.Transparent,但这给出了一个错误。我玩了一些组合...
Combination Effects
http://img204.imageshack.us/img204/757/effectsi.jpg

我用Drawing2D.LinearGradientBrush将渐变绘制到位图中。然后将此位图放置为Form.BackgroundImage或PictureBox.Image。如果使用了PictureBox,则将其大小设置为可覆盖整个Form,然后发送到背面。

我注意到某些Form.BackgroundColor将与我图标的轮廓混合在一起。图标的边缘具有透明性,外观更平滑。由于图标拾取了Form的BackgroundColor,因此我认为将图标加载到表单后,PictureBoxes正在创建新图像。然后,当图像的半透明部分应与表单后面的任何颜色合并时,它们将与Form的BackgroundColor合并。

effect with white desktop
http://img838.imageshack.us/img838/8299/whitedesktop.jpg

在此图像中,即使窗体的紫红色颜色现在已完全透明,您仍可以看到图标中存在的紫红色。我忘了指出,在每种情况下都使用相同的绿色到黄色渐变,Alpha值为150。在渐变看起来不是绿色的图像中,这是因为透明色与紫红色背景混合在一起。

我不太确定该怎么办。我觉得如果我能以某种方式使Form完全透明,我就能得到我想要的东西。我还以为我可能会比较幸运,只画图标而不是使用PictureBoxes。然后,问题将是设置图标以接收鼠标事件。 (我从未做过自己的事件,并且我认为它将涉及一些Win32 API调用。)

我还能对PictureBox进行其他操作以获得我想要的效果吗?无论哪种情况,对于我想要达到的总体效果,我都欢迎任何想法或建议。


这在Winforms中很容易做到。 您需要的是两种形式的三明治。 最下面的应该提供透明的渐变背景,最上面的应该绘制图标并处理鼠标单击。 一些示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        this.TopMost = true;
        this.FormBorderStyle = FormBorderStyle.None;
        this.TransparencyKey = this.BackColor = Color.Fuchsia;
        this.Opacity = 0.3;
        var overlay = new Form();
        overlay.FormBorderStyle = FormBorderStyle.None;
        overlay.TransparencyKey = overlay.BackColor = Color.Fuchsia;
        overlay.StartPosition = FormStartPosition.Manual;
        overlay.Location = this.Location;
        overlay.MouseDown += HandleIconClick;
        this.Resize += delegate { overlay.Size = this.Size; };
        this.LocationChanged += delegate { overlay.Location = this.Location; };
        overlay.Paint += PaintIcons;
        this.Paint += PaintBackground;
        this.Load += delegate { overlay.Show(this); };
    }
    private void PaintBackground(object sender, PaintEventArgs e) {
        var rc = new Rectangle(0, 0, this.ClientSize.Width, this.ClientSize.Height);
        using (var br = new LinearGradientBrush(rc, Color.Gainsboro, Color.Yellow, 0f)) {
            e.Graphics.FillRectangle(br, rc);
        }
    }
    private void PaintIcons(object sender, PaintEventArgs e) {
        e.Graphics.DrawIcon(Properties.Resources.ExampleIcon1, 50, 30);
        // etc...
    }
    void HandleIconClick(object sender, MouseEventArgs e) {
        // TODO
    }
}

我选择的颜色和图标有点像这样:

enter image description here


好的,我在所有这些内容中都有所迷失,但是从原始段落的描述中,我将确保背景矩形不是图片框的可视父级。 使用Panel.Zindex使它们具有重叠的同级,并在图片框的前面。

然后,您可以更改矩形的不透明度,而不会影响图标。 还要确保图标源图像文件具有透明背景。

我认为应该可以。