简体   繁体   English

我如何使我的表格透明,但我画的不是?

[英]How do I make my form transparent, but what I draw on it not?

I tried setting the opacity of my form to 50%, and then drawing a string on it. 我尝试将表单的不透明度设置为50%,然后在其上绘制一个字符串。 It seems that the string I draw on it also has an opacity of 50%. 似乎我在其上绘制的字符串也具有50%的不透明度。 How would I draw a non transparent string , but let the form background show through 50%? 我如何绘制非透明字符串,但让表单背景显示50%?

Would also be willing to do this in WPF if it is possible, but I would need explicit instructions or an example project as I have never done it before. 如果可能的话,也愿意在WPF中这样做,但我需要明确的指示或示例项目,因为我以前从未这样做过。

To clarify, I want the form background to be a black 80% opaque to what is underneath, and then I want to draw text, etc.. on it and have it appear 100% opaque. 为了澄清,我希望表单背景是一个黑色的80%不透明的底部,然后我想在它上面绘制文字等,让它看起来100%不透明。

This is very easily done in WPF: 这在WPF中非常容易完成:

  1. Set WindowStyle="None" on the Window (note: this is required, you cannot have Transparency and the standard windows chrome) 在窗口上设置WindowStyle =“None”(注意:这是必需的,你不能有透明度和标准的windows chrome)
  2. Set AllowsTransparency="True" on the Window 在窗口上设置AllowTransparency =“True”
  3. Set a Background on the Window using a brush with transparency, such as Background="#AAFFFFFF" 使用具有透明度的画笔在窗口上设置背景,例如Background =“#AAFFFFFF”

Here's a quick sample: 这是一个快速示例:

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

Now obviously, since you've disabled the standard Windows chrome, you will need to supply your own button to close/minimize/maximize/drag the window. 现在显然,由于您已禁用标准Windows镶边,因此您需要提供自己的按钮来关闭/最小化/最大化/拖动窗口。 You can do this pretty easily yourself or you could look into purchasing something like Blendables which comes with a "Chromeless Window" control that you could use. 你可以自己很容易地做到这一点,或者你可以考虑购买像Blendables这样的东西,它带有你可以使用的“Chromeless Window”控件。

One workaround that comes to mind is to use two windows overlaid on top of one another. 我想到的一个解决方法是使用两个叠加在一起的窗口。 Render the "bottom" window at 50% opacity and then owner draw your text to a window overlaid on top of the other one. 以50%不透明度渲染“底部”窗口,然后所有者将文本绘制到覆盖在另一个上面的窗口。 If you're doing lable-type displays this might be simple but might get complicated quickly if you need a lot of user input which might then need to get filtered down through to your "main" or "bottom" window. 如果您正在进行标签式显示,这可能很简单但如果您需要大量用户输入可能会很快变得复杂,这可能需要过滤到“主”或“底部”窗口。

So, i got it to work, but it's a little squirrelly. 所以,我让它工作,但它有点松鼠。 The two window solution seemed promissing until i discovered that .Net or Win32 does some weird auto parenting thing when you even implicitly refer to it. 两个窗口解决方案看起来很有希望,直到我发现.Net或Win32甚至隐含地引用它时会做一些奇怪的自动育儿事情。 Probably has to do with the way the messages are pumped though. 可能与消息的抽取方式有关。 The main parent holds the application message pump and int guess is implicitly the parent... 主要父母持有应用程序消息泵和int guess隐含地是父...

i tried a bunch of workarounds but this timer thing below worked the best. 我尝试了一堆变通方法,但下面的这个计时器工作效果最好。 In any case, it might be a clue as to doing it better... 在任何情况下,它可能是一个更好的做法的线索......


// the "main" or transparent window. Notice it just sets and runs the timer
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();
    }
}

}

// the "top" or not transparent window. Notice it does owner draw on // transparent background. The design-time settings are also sans border etc. 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 );
    }
}

}

// The control of this whole spiel. It instantiates both windows, // sets the main as the main app window and hosts the public // hacky method to force the non-transparent window to show up on top // and offset so it doesn't obscure the top of the main window. 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();
    }
}

}

in the ControlStyles enumeration MSDN there is a value called SupportsTransparentBackColor. 在ControlStyles枚举MSDN中有一个名为SupportsTransparentBackColor的值。 In your form contructor run this: 在你的表单构造器中运行:

SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);

then you can set the background color to Color.Transparent. 然后你可以将背景颜色设置为Color.Transparent。

Hope this helps. 希望这可以帮助。

Use TransparencyKey to render the window as transparent. 使用TransparencyKey将窗口渲染为透明。 Create an empty panel with the background color of your and give it the desired opacity. 使用您的背景颜色创建一个空面板,并为其指定所需的不透明度。

Then create all your children in a separate container/panel (itself a sibling to the translucent panel created above), and have it not render a background at all. 然后在一个单独的容器/面板(本身是上面创建的半透明面板的兄弟)中创建所有孩子,并让它根本不渲染背景。

This should give you the effect of a translucent background but visible controls. 这应该给你半透明背景但可见控件的效果。

In winforms, MSDN says this: 在winforms中,MSDN说:

The Opacity property enables you to specify a level of transparency for the form and its controls. 使用“不透明度”属性可以指定窗体及其控件的透明度级别。 When this property is set to a value less than 100 percent (1.00), the entire form, including borders, is made more transparent. 当此属性设置为小于100%(1.00)的值时,整个表单(包括边框)将变得更加透明。

So, any child controls of the form that you set opacity on will have their opacity changed. 因此,您设置不透明度的窗体的任何子控件都将更改其不透明度。 If you want to achieve different levels of opacity on individual controls, you'll have to switch to WPF. 如果要在单个控件上实现不同级别的不透明度,则必须切换到WPF。

I assume that this is a WinForms project, though you said you'd be willing to try WPF. 我假设这是一个WinForms项目,虽然你说你愿意尝试WPF。

Lemme switch to my lateral thinking cap: Any particular reason you couldn't just fake it? Lemme切换到我的横向思维上限:你有什么特别的理由不能伪造它吗? As in, make a bitmap in PhotoShop Elements or Paint Shop Pro or some such that you will set as the entire background of the WinForm, and you simply draw the partially transparent area over which the controls will be placed right on that bitmap? 如在,在PhotoShop Elements或Paint Shop Pro中制作一个位图,或者你将设置为WinForm的整个背景,你只需绘制部分透明区域,控件将放在该位图上?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM