.net - VB.Net WinForms 表单 OnPaint() 透明度刷新

标签 .net vb.net winforms gdi+

长话短说,我正在尝试编写一些 toast 样式的弹出通知(类似于 Growl),它们应该出现在系统托盘和适当的堆栈旁边。

我可以处理实例化/位置/等...但我想为非矩形 toast 添加功能。我还希望具有 Alpha 透明度,以便 toast 表单上的半透明背景 PNG 可以与其后面的桌面或窗口混合。

所以......为了让显而易见的事情消失:

Form.TransparencyKey 不足以满足我的需求,因为它是全有或全无的透明效果,我希望在某些地方获得 50/50 前景/背景,在其他地方获得 0/100,在其他地方获得 100/0 等等。

我最初的方法是重写 OnBackgroundPaint() 方法,注释掉对 MyBase.OnBackgroundPaint 的调用,并使用 eventargs 中的图形对象准确地绘制我想要的表单。

这似乎开始工作 - 目前,我只是为了测试目的绘制了一些矩形,所以 PNG 可能会带来新的困难,但我还没有做到。

我无法完成的是更新图形 - 第一次呈现表单时,它完美地显示为我所期望的(没有边框,只有一些矩形漂浮在桌面上)。如果我将窗口移到透明窗口后面,透明窗口不会更新/重新绘制

我相信我需要调用 Me.Invalidate() 来强制重新绘制,但不确定何时应该调用 - 我如何知道我身后的窗口已更改其内容?

我采取了错误的方法吗?

非常感谢

编辑:我尝试将 Me.Invalidate() 放入计时器中,只是为了测试重绘是如何发生的——似乎它确实触发了重绘,但重绘操作覆盖了现有的表单背景——即原本为 50% 的区域不透明现在是 75% 不透明(50% + 之前的 50%)

所以,在几个 Invalidate() 之后,我的表单显示为一个黑框 - 我需要在重新绘制之前清除表单的背景,但 Graphics.Clear(Color) 似乎只是用指定的颜色进行填充- 显然,出于这个问题的目的,Colors.Transparent 并不真正意味着透明 - 这似乎是在渲染窗口以“显示其下方的控制内容”时使用的技巧,当我们处理表单本身

如果有人想轻松复制,我的表单代码如下:

Imports System.Drawing
Public Class TransparentForm

    Private Timer As Timers.Timer

    Private Sub TransparentForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Timer = New Timers.Timer
        AddHandler Timer.Elapsed, AddressOf Timer_Tick
        Timer.Interval = 100
        Timer.Start()
    End Sub

    Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
        ''MyBase.OnPaintBackground(e)
        Console.WriteLine("BackgroundPainted")
        For x = 0 To 9
            e.Graphics.FillRectangle(
                New SolidBrush(Color.FromArgb(CInt(x / 10 * 255), 127, 127, 127)),
                CInt(x * Me.Width / 10),
                0,
                CInt(Me.Width / 10),
                Me.Height
            )
        Next
    End Sub

    Sub Timer_Tick(ByVal sender As Object, ByVal e As EventArgs)
        Me.Invalidate()
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        Console.WriteLine("Painted")
    End Sub

    Protected Overrides Sub OnInvalidated(ByVal e As System.Windows.Forms.InvalidateEventArgs)
        MyBase.OnInvalidated(e)
        Console.WriteLine("Invalidated")
    End Sub

End Class

最佳答案

有一篇 CodeProject 文章展示了如何使用 png 作为表单的“皮肤”。显然,这支持部分透明而不是 Form.TransparencyKey 提供的 50/50 方法。 .

这是link到 codeproject 文章。我正在尝试在 VB 中上传项目,并会在完成后立即更新此答案。

编辑

这是link到我上面引用的 CodeProject 文章的 VB.NET 版本。
http://www20.zippyshare.com/v/86701716/file.html

我将尝试查看您的代码,看看可以做些什么来帮助您解决问题。

关于.net - VB.Net WinForms 表单 OnPaint() 透明度刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3476950/

相关文章:

.net - 从具有不同类型的 HttpWebResponse GetResponseStream 反序列化 XML

c# - 在 C# 和 IronPython 之间传递 pickle 字符串

c# - 如果给定短路径,应用程序无法从应用程序配置中读取

mysql - Vb.net 和 MySQL 问题

.net - 在 .net 中解析 xml 的正则表达式

.net - 为什么使用 TransactionScope 和 MSDTC 的 VS 数据库单元测试失败?

c# - 如何检查文本框内容中是否有空格?

c# - 保留最后 N 个项目并从 ListBox 中删除其他项目

c# - 将多行数据导出到 csv 中的同一单元格

java - .NET 相当于内部类型数组的 java.util.Arrays.hashCode() 函数?