长话短说,我正在尝试编写一些类似于Growl的弹出式通知(应该出现在系统托盘旁边,并根据需要堆叠)。
我可以处理实例化/位置等,但我想添加非矩形toast的功能。我还希望具有Alpha透明度,因此在toast表单上使用半透明背景PNG将与其后面的桌面或窗口混合。
所以...先说显而易见的:
Form.TransparencyKey对我的需求不足,因为我想在某些地方获得50/50前景/背景,在其他地方获得0/100,在另一些地方获得100/0等等。
我的初始方法是覆盖OnBackgroundPaint()方法,注释掉对MyBase.OnBackgroundPaint的调用,并使用事件参数中的图形对象向表单绘制我想要的内容。
这似乎起初是有效的-目前,我只是为了测试而绘制一些矩形,因此PNG可能会出现新的困难,但我还没有到达那里。
我无法完成的是更新图形-第一次渲染表单时,它显示为我所期望的完美状态(没有边框,只有一些浮动在桌面上的矩形)。如果我将窗口移动到透明窗口后面,透明窗口不会更新/重新绘制。
我认为我需要调用Me.Invalidate()来强制重新绘制,但不确定何时应进行调用-我如何知道在我后面的窗口已更改其内容?
我错了吗?
非常感谢。
编辑:我尝试在计时器中放置一个Me.Invalidate(),只是为了测试重绘发生的方式-似乎它确实触发了重绘,但重绘发生在现有表单背景的上方-即,最初50%不透明的区域现在变成了75%不透明(50% +之前存在的50%)。
因此,在几次Invalidate()之后,我的表单显示为黑色框-我需要在重新绘制之前清除表单的背景,但Graphics.Clear(Color)似乎只是使用指定的颜色进行填充-显然,对于这个问题的目的,Colors.Transparent并不真正意味着透明-它似乎是在渲染窗口时使用的技巧“显示控件下面的内容”,但当我们处理表单本身时,它不起作用。
如果有人想要轻松复制,请参考下面的表单代码:
我可以处理实例化/位置等,但我想添加非矩形toast的功能。我还希望具有Alpha透明度,因此在toast表单上使用半透明背景PNG将与其后面的桌面或窗口混合。
所以...先说显而易见的:
Form.TransparencyKey对我的需求不足,因为我想在某些地方获得50/50前景/背景,在其他地方获得0/100,在另一些地方获得100/0等等。
我的初始方法是覆盖OnBackgroundPaint()方法,注释掉对MyBase.OnBackgroundPaint的调用,并使用事件参数中的图形对象向表单绘制我想要的内容。
这似乎起初是有效的-目前,我只是为了测试而绘制一些矩形,因此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