【问题标题】:Alpha-blended splash screen renders garbage in XP but works in Win7Alpha 混合启动画面在 XP 中呈现垃圾,但在 Win7 中有效
【发布时间】:2011-11-08 01:52:51
【问题描述】:

我有一个无边框表单,其中包含以下代码:

public partial class Splash : Form
{
    bool painted = false;

    public Splash()
    {
        InitializeComponent();

        Opacity = 0;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        //
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        if (painted)
            return;

        Graphics gfx = e.Graphics;
        gfx.CopyFromScreen(new Point(Bounds.Left, Bounds.Top),
                           Point.Empty, Bounds.Size);
        gfx.DrawImage(Properties.Resources.Splash, e.ClipRectangle);

        Opacity = 100;
        painted = true;
    }
}

这在我的 Windows 7 机器上运行良好,但在 Windows XP 中它显示垃圾(可能是帧缓冲区中的任何未对齐内容)而不是启动图像。有时我可以在垃圾中辨认出高度扭曲的旧资源管理器窗口等残余物。

奇怪的是,我在不同的程序中运行相同的代码,该程序具有相同的 24 位 PNG,并且在 XP 机器上运行良好。

知道为什么会发生这种情况吗?


解决办法:

bool painted = false; 行之后添加Bitmap b;,并将OnPaintBackground 更改为:

protected override void OnPaintBackground(PaintEventArgs e)
{
    if (!painted)
    {
        b = new Bitmap(Width, Height);
        Graphics g = Graphics.FromImage(b);

        g.CopyFromScreen(new Point(Bounds.Left, Bounds.Top),
                         Point.Empty, Bounds.Size);
        g.DrawImage(Properties.Resources.Splash, e.ClipRectangle);

        Opacity = 100;
        painted = true;

        g.Dispose();
    }

    Graphics gfx = e.Graphics;
    gfx.DrawImage(b, new Point(0, 0));
    gfx.Dispose();
}

【问题讨论】:

  • 只是一种预感,但尝试注释掉“if (painted) return;”行
  • @MerickOWA 如果我注释掉那一行,那么它将一遍又一遍地CopyFromScreen,并且 alpha 混合将从所有图层中完全消失。
  • 在 If 块中处理完图形对象后,不要忘记调用 g.Dispose()。否则你会泄露一个图形句柄。在这种情况下可能不是一个大问题,因为它只发生一次,但这是一个好习惯。

标签: c# winforms splash-screen


【解决方案1】:

我想这是因为你画了一次之后没有刷新表格。 Win XP不存储windows的任何图形内容,他只是通知他们自己绘制。你的OnPaintOnPaintBackground 函数应该总是刷新窗口。 我不明白您为什么不使用BackgroundImage 属性以及Opacity。您可以将图像设置为拉伸、缩放等。您要显示效果吗?

【讨论】:

  • 我重新编写了 OnPaintBackground,以便在它第一次运行时,它会执行 CopyFromScreen 并将其存储在 Bitmap 中。随后的绘画只是重新绘制图像。这似乎可行,但我很困惑为什么这个确切的代码可以在同一台计算机上与我的其他程序一起正常工作,但这个程序有这个问题。
  • @Ozzah 我认为你很幸运。此消息被多次发送,并且必须在操作系统要求时绘制。有很多事情会导致这种情况发生,比如后台运行的其他程序或操作系统工作方式的差异。
【解决方案2】:

您是否考虑过使用 .BorderStyle 设置为 None 并设置 .TransparencyKey 的表单?它应该模仿您尝试获得的效果,而无需使用 CopyFromScreen 调用。

基于 cmets 编辑

我找到了一些示例源代码,可以执行您想要的每像素 alpha 混合,但它要复杂得多并且涉及 pInvoke。作为参考,您可以在此处找到它。 http://www.codeproject.com/KB/GDI-plus/perpxalpha_sharp.aspx

【讨论】:

  • 正如我所说,我已经在使用无边界表单了。 TransparencyKey 不支持完整的 alpha 混合。我有一个带有 24 位 PNG 的部分透明飞溅。就像我说的,上面的代码可以在 XP 上使用我以前的程序而不是这个程序。
  • 啊,有道理。如果我记得有另一种支持 alpha 遮罩的窗口堆肥方法,我会看看能不能找到它。
  • 我找到了我正在寻找的代码,但它实际上比您使用的代码复杂得多。如果您仍然感兴趣,可以在这里找到示例的源代码codeproject.com/KB/GDI-plus/perpxalpha_sharp.aspx
【解决方案3】:

我认为Win7存储窗口的图形内容并自动重绘它们。当窗口没有响应时,您可以看到不同之处——在 WinXP 中他不会被刷新,而在 Win7 中他看起来没问题。还有当您将鼠标悬停在任务栏上时的窗口预览,以及出现表单时的“表单增长”效果。 我在一个单独的答案中写了这个,因为我不知道如何在这个网站上添加评论......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 1970-01-01
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多