8

更新:我花了几天时间来处理透明度的问题。我今晚又开始搞砸了。我使用 Hans Passant 的解决方案得到了一个新结果:http: //img3.imageshack.us/img3/4265/icontransp.jpg新结果

Passant的解决方案确实解决了透明背景渐变的问题。但是,我的图标中的透明颜色与表单的 BackColor 混合仍然存在问题。您可以在上图中看到图标各个部分周围的紫红色。

原创内容:

我已经这样做了几个小时了,我没有太多的运气。我弄乱了 Control.Region、Form.TransparencyKey、Form.Opacity 和其他一些带有一些时髦效果的随机事物。

最近我一直在尝试自定义我的桌面并决定弄乱应用程序坞。在看到 Mac Dock 和一些第三方 Windows 实现所提供的功能后,我决定自己构建。

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

我希望在这个应用程序中能够做一些事情:

  • 显示带有渐变背景的表单/菜单。
  • 允许表单/菜单具有透明度,同时保持图标不透明。
  • 显示包含透明背景的图标。
  • 菜单和图标应该能够接收与鼠标相关的事件(悬停、离开、单击、拖动、拖放等)。

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

这张图片显示了我想要达到的视觉效果。这是我为名为 Rainmeter 的程序制作的皮肤。该图像显示了皮肤后面的 Notepad++,其中一些皮肤文件在编辑器中打开。菜单是透明的,但图标保持不透明。

我的方法:

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

一旦我完成了菜单的所有结构逻辑的代码,我就开始使用它来尝试获得我想要的视觉效果。Form.Opacity 影响表单上所有内容的透明度。因为我希望图标完全不透明,所以我不理会这个属性。我尝试将 BackColor 设置为 Color.Transparent,但这会产生错误。我玩了一些组合... http://img204.imageshack.us/img204/757/effectsi.jpg组合效果

我用 Drawing2D.LinearGradientBrush 将渐变绘制到位图中。然后将此位图作为 Form.BackgroundImage 或 PictureBox.Image 放置。如果使用,PictureBox 的大小将覆盖整个表单并发送到后面。

我注意到一些 Form.BackgroundColor 会与我的图标的轮廓混合在一起。图标沿边缘具有透明度,以使外观更平滑。由于图标正在获取表单的 BackgroundColor,这让我认为当图标加载到表单中时 PictureBoxes 正在创建新图像。当图像的半透明部分应该与表单后面的任何颜色合并时,它们会与表单的 BackgroundColor 合并。

白色桌面效果 http://img838.imageshack.us/img838/8299/whitedesktop.jpg

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

我真的不知道从这里做什么。我觉得如果我能以某种方式使表单完全透明,我就能得到我想要的东西。我还想我可能会更好地绘制图标而不是使用 PictureBoxes。那么问题将是设置图标以接收鼠标事件。(我从来没有自己的事件,我认为它会涉及一些 Win32 API 调用。)

我还能用 PictureBoxes 做些什么来获得我想要的效果吗?无论哪种情况,对于我想要达到的整体效果,我都愿意接受任何想法或建议。

4

2 回答 2

14

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

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
    }
}

看起来像这样,我选择了一些随机的颜色和图标:

在此处输入图像描述

于 2012-04-22T10:46:03.973 回答
0

好的,我有点迷失了,但从原始段落中的描述来看,我会确保背景矩形不是图片框的视觉父级。使用 Panel.Zindex 使它们重叠兄弟姐妹,图片框在前面。

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

我认为应该工作。

于 2012-04-22T10:37:06.900 回答