如何使我的表单透明,但我在上面绘制的内容不透明?

12

我尝试将表单的不透明度设置为50%,然后在其上绘制字符串。似乎我在其上绘制的字符串也具有50%的不透明度。如何绘制非透明字符串,但让表单背景透出50%?

如果可能的话,我也愿意在WPF中实现此操作,但我需要明确的说明或示例项目,因为我以前从未这样做过。

澄清一下,我希望表单背景是黑色的,不透明度为80%,透出底部内容的50%,然后我想在其上绘制文本等并使其看起来100%不透明。

7个回答

19

在WPF中,这非常容易实现:

  1. 在窗口上设置WindowStyle="None"(注意:这是必需的,您不能同时具有透明度和标准窗口Chrome)
  2. 在窗口上设置AllowsTransparency="True"
  3. 使用具有透明度的刷子,例如Background="#AAFFFFFF",为窗口设置背景

以下是一个快速示例:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Height="300" Width="300" AllowsTransparency="True" Background="#AAFFFFFF" WindowStyle="None">
<Grid>
    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20" FontWeight="Bold">Hello World!</TextBlock>
</Grid>

显然,由于您已禁用了标准的Windows窗口装饰,您需要提供自己的按钮来关闭/最小化/最大化/拖动窗口。您可以自己很容易地实现这个功能,或者您可以考虑购买 Blendables 这样的工具,它附带了一个“无边框窗口”控件,您可以使用。


4

这不是一样的,它的意思是当你绘制任何颜色时,它将显示为透明,也就是0%不透明(或完全透明,这取决于你是个半杯满的人还是半杯空的人)。它不允许你将其设置为50%透明。 - esac
好的。感谢更新。你说得对,当然。TransparencyKey只有在你想要让它100%透明时才起作用。(我个人倾向于看到杯子半满而不是半空。) - David

1

我想到的一个解决方法是使用两个重叠的窗口。将底部窗口渲染为50%的不透明度,然后在另一个重叠的窗口上绘制文本。如果您正在执行标签类型显示,这可能很简单,但如果您需要大量用户输入,则可能会变得复杂,并且可能需要通过“主”或“底部”窗口进行过滤。

所以,我让它工作了,但有点棘手。两个窗口的解决方案似乎很有前途,直到我发现当您甚至隐式地引用.Net或Win32时,它会做一些奇怪的自动父级控制。可能与消息被泵送的方式有关。主父级控件持有应用程序消息泵和猜测是隐式的父级控件......

我尝试了许多解决方法,但下面的计时器效果最好。无论如何,这可能是更好地解决它的线索......


// 主窗口或透明窗口。请注意,它只是设置并运行计时器。
using System;
using System.Windows.Forms;
namespace TransparencyPlusNottransparentTest
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
        }

    private void timer1_Tick(object sender, EventArgs e)
    {
        Program.ShowNontransparency();
    }
}

}

// 这是“顶部”或不透明的窗口。请注意,它在透明背景上进行所有者绘制。设计时设置也没有边框等。 using System.Drawing; using System.Windows.Forms;

namespace TransparencyPlusNottransparentTest { public partial class FormTop : Form { public FormTop() { InitializeComponent(); BackColor = Color.Firebrick; TransparencyKey = Color.Firebrick; }

    private void FormTop_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawString("Hello Whirrled!", new Font("Tahoma", 14f), Brushes.Black, 10f, 10f );
    }
}

}

// 这个程序的控制。它实例化了两个窗口, // 将主窗口设置为主应用程序窗口,并托管公共 // hacky 方法来强制非透明窗口显示在顶部 // 并偏移,以免遮挡主窗口的顶部。 using System; using System.Drawing; using System.Windows.Forms;

namespace TransparencyPlusNottransparentTest { static class Program { private static FormMain _formMain; private static FormTop _formTop; private const int XY_OFFSET = 30;

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        _formTop = new FormTop();
        _formTop.Show(null);

        _formMain = new FormMain();

        Application.Run(_formMain);
    }

    public static void ShowNontransparency()
    {
        _formTop.Location = 
            new Point(
            _formMain.Location.X + XY_OFFSET, 
            _formMain.Location.Y + XY_OFFSET);

        _formTop.BringToFront();
    }
}

}


0
在 ControlStyles 枚举 MSDN 中有一个名为 SupportsTransparentBackColor 的值。在您的窗体构造函数中运行以下代码:
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);

那么你可以将背景颜色设置为Color.Transparent。

希望这可以帮到你。


嗯,这听起来像是我想要的,但是我得到了一个灰色的框,似乎我在其上绘制的任何内容都没有显示出来。我尝试使用Color.Transparent和this.BackColor = Color.FromArgb(180, 0, 0, 0);。 - esac
1
我认为这不会起作用,来自MSDN:如果为true,则控件接受具有小于255的alpha分量的BackColor以模拟透明度。仅当UserPaint位设置为true且父控件派生自Control时,才会模拟透明度。我猜想由于主窗体没有父级控件,因此它未通过最后一个测试。 - esac
啊,抱歉。我没有注意到。我认为你的理论是正确的。 - Alastair Pitts

0
使用TransparencyKey将窗口渲染为透明。创建一个背景颜色与您想要的透明度相同的空面板。
然后在单独的容器/面板中创建所有子项(它本身是上面创建的半透明面板的兄弟),并且不呈现任何背景。
这样应该可以实现半透明背景但可见控件的效果。

我刚试过了一下,透明容器里面出现了不透明的背景,并且正好是我设置透明键的那个颜色。例如,我将透明键设置为粉色,然后在上面放置一个80%不透明度的黑色背景面板,结果看到的是一个带有粉色/黑色不透明背景。 - esac
尝试将 TransparencyKey / 窗体背景设置为透明。 - Richard Szalay
这又回到了下面的同样问题。除非我可以设置'SupportsTransparentBackColor',否则不支持Color.Transparent,而这只有在父控件是Control时才允许。对于主窗体,没有父控件: SetStyle(ControlStyles.SupportsTransparentBackColor, true); this.TransparencyKey = Color.Transparent; this.BackColor = Color.Transparent; - esac

0
在WinForms中,MSDN说:
透明度属性使您能够为窗体及其控件指定透明度级别。当此属性设置为小于100%(1.00)的值时,整个窗体(包括边框)都会变得更加透明。
因此,您设置不透明度的窗体的任何子控件都将更改其不透明度。如果您想在单个控件上实现不同级别的不透明度,则必须切换到WPF。

0

我假设这是一个WinForms项目,尽管你说过你愿意尝试WPF。

让我换个思路:有没有什么特别的原因你不能只是“假装”一下呢?比如,在PhotoShop Elements或Paint Shop Pro中制作一个位图,将其设置为WinForm的整个背景,然后在该位图上直接“绘制”控件将放置在其上的部分透明区域?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接