跟进消息






2.56/5 (5投票s)
用于显示各种消息的用户定义控件。
引言
我喜欢让用户随时了解情况。我知道我可能在这里有点出格,但嘿,我就是这么叛逆。
我们处理了很多系统,对吧?电子邮件、服务器、消息队列、servlet、Web服务等等。而且,我们越来越多地将这些集成到我们编写的应用程序中。有些应用程序可能需要所有这些,甚至更多。如果某个部分出现故障,可能会给用户带来不便。例如,考虑这种情况:作为您应用程序的一部分,用户从消息队列接收消息,使用您的应用程序处理数据,然后将结果数据发布到远程Web服务,同时,通过电子邮件通知下一个部门,该部门将收到数据已完成的通知。
我们在应用程序中加入了异常处理来处理这种情况,对吧?那么用户呢?如果他们尝试将某些内容提交到远程Web服务,却发现公司Web连接已断开,这对他们来说是很令人沮丧的。或者,如果他们尝试发送通知电子邮件,却发现邮件服务器因维护而关闭。最好提前告知他们,这样他们就可以做好准备。毕竟,我们希望用户满意,对吧?(我就是那种多愁善感的人。)
控件
在我们的环境中,系统专家们通过创建一个网页来通知整个组织任何当前发生的问题、任何计划中的停机时间以及他们认为需要传达的任何特殊情况。问题是,你必须打开浏览器,导航到该页面,然后刷新页面才能获得当前状态。
我在我的应用程序中包含了这个OSNotify
控件,用于显示系统状态或其他任何我想让用户关注的消息。它的工作原理如下:
该控件包含一个OSMessage
类,该类定义了几个属性:Key
、Index
、Text
、Importance
、Link
和Ignore
。它还有一个集合类OSMessages
,可以传递给控件进行显示。消息可以标记为三个重要性级别:LOW
、MEDIUM
和HIGH
,每个级别都会显示不同的用户定义图标。Ignore
属性可用于跳过用户不再想看到的消息。
许多属性控制消息的显示;下面将对此进行描述:
BorderStyle
、BackColor
、ForeColor
- 您知道这些是什么。ChangeInterval
、ScrollSize
- 结合使用,设置滚动速度。LowPriorityIcon
、MediumPriorityIcon
、HighPriorityIcon
- 不言自明。MessageDisplayType
-osStatic
或osRightToLeft
。如果为osStatic
,消息将在ChangeInterval
事件超时时更改;如果为RightToLeft
,消息将在ChangeInterval
事件超时时向左滚动ScrollSize
(像素)数量。MessageIsLink
- 如果为true,将导航到OSMessage.Link
属性中标识的文档。PauseOnMouseOver
- 如果为true,则鼠标悬停在控件上时停止滚动,以便用户可以阅读消息。
控件的方法将在下面描述。
DisplayMessages
- 接受一个您在控件外部构建的OSMessages
集合,并按顺序显示这些消息,前提是消息未被忽略。DisplayMessage
- 接受一个OSMessage
对象。这是您在不提供消息集合的情况下手动显示消息的方式;本质上,开发人员可以控制消息的显示。NextMessage
- 立即转到下一条未被忽略的消息。StopDisplay
- 停止滚动。
如果提供了集合,则在显示完最后一条消息后,它会重新从开头开始。我将在这里更新消息,以便用户获得最新信息。
代码
我不会在此处显示所有代码,只显示一些有趣的部分。这是我的Paint
事件:
Private Sub OSNotifier_Paint(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
'use some double-buffering techniques
Dim bmp As New Bitmap(Me.Width, Me.Height, _
Imaging.PixelFormat.Format24bppRgb)
Dim g As Graphics = Graphics.FromImage(bmp)
'repaint background
g.FillRectangle(New SolidBrush(_BackColor), 0, 0, _bmp.Width, bmp.Height)
'this is where our graphic will go
Dim PicRectangle As New Rectangle(3, 3, Me.Height - 6, Me.Height - 6)
g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
'draw border
Select Case Me._BorderStyle
Case BorderStyle.Fixed3D
Dim p1 As New Pen(SystemColors.ControlLightLight, 1)
Dim P2 As New Pen(SystemColors.ControlDark, 1)
Dim P3 As New Pen(SystemColors.ControlDarkDark, 1)
g.DrawRectangle(p1, New Rectangle(0, 0, Me.Width - 1, Me.Height - 1))
g.DrawRectangle(P2, New Rectangle(0, 0, Me.Width, Me.Height))
g.DrawRectangle(P3, New Rectangle(1, 1, Me.Width - 2, Me.Height - 2))
Case BorderStyle.FixedSingle
Dim p1 As New Pen(SystemColors.ControlLightLight, 1)
g.DrawRectangle(p1, New Rectangle(0, 0, Me.Width - 1, Me.Height - 1))
Case Else
'Console.WriteLine("no border")
End Select
If Me.DesignMode Then
'draw graphic is it exists
If Not IsNothing(Me._LowPriorityIcon) Then
g.DrawIcon(Me._LowPriorityIcon, PicRectangle)
ElseIf Not IsNothing(Me._MediumPriorityIcon) Then
g.DrawIcon(Me._MediumPriorityIcon, PicRectangle)
ElseIf Not IsNothing(Me._HighPriorityIcon) Then
g.DrawIcon(Me._HighPriorityIcon, PicRectangle)
End If
'persist the bitmap to the control
e.Graphics.DrawImage(bmp, 0, 0)
Else
'only draw the graphic if we have a message
If Not IsNothing(_CurrentMessage) Then
Select Case _CurrentMessage.Importance
Case OSMessage.MessageImportanceConstants.osIMPORT_LOW
If Not IsNothing(Me._LowPriorityIcon) Then
g.DrawIcon(Me._LowPriorityIcon, PicRectangle)
End If
Case OSMessage.MessageImportanceConstants.osIMPORT_MEDIUM
If Not IsNothing(Me._MediumPriorityIcon) Then
g.DrawIcon(Me._MediumPriorityIcon, PicRectangle)
End If
Case OSMessage.MessageImportanceConstants.osIMPORT_HIGH
If Not IsNothing(Me._HighPriorityIcon) Then
g.DrawIcon(Me._HighPriorityIcon, PicRectangle)
End If
Case Else
If Me._MessageDisplayType = MessageDisplayTypeConstants.osStatic Then
Me._CurrentLeftPosition = 3
End If
End Select
'persist the bitmap to the control
e.Graphics.DrawImage(bmp, 0, 0)
'create new bitmap for the text area
bmp = New Bitmap(Me.pnlTextArea.Width, Me.pnlTextArea.Height, _
Imaging.PixelFormat.Format24bppRgb)
g = Graphics.FromImage(bmp) 'Me.pnlTextArea.CreateGraphics
g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
'determine the left position
If Me._MessageDisplayType = MessageDisplayTypeConstants.osFromRightToLeft Then
Me._CurrentLeftPosition -= _ScrollSize
Else
Me._CurrentLeftPosition = 3
End If
If Me._CurrentLeftPosition + g.MeasureString(_CurrentMessage.Text, _
Me.pnlTextArea.Font).Width < 0 Then
If Me._DisplayingMultipleMessages Then
Me._CurrentMessage = GetNextMessage()
RaiseEvent MessageChange(Me._CurrentMessage)
End If
Me._CurrentLeftPosition = Me.pnlTextArea.Width
End If
g.FillRectangle(New SolidBrush(_BackColor), -1, -1, _
bmp.Width + 1, bmp.Height + 1)
If Not IsNothing(Me._CurrentMessage) Then
Dim dTop As Double = (Me.pnlTextArea.Height - _
g.MeasureString(Me._CurrentMessage.Text, _
Me.pnlTextArea.Font).Height) / 2
Dim newPoint As New PointF(Me._CurrentLeftPosition, dTop)
g.DrawString(Me._CurrentMessage.Text, Me.pnlTextArea.Font, _
New SolidBrush(_ForeColor), newPoint)
Me.pnlTextArea.CreateGraphics.DrawImage(bmp, 0, 0)
End If
Else
'persist the bitmap to the control
e.Graphics.DrawImage(bmp, 0, 0)
End If
End If
End Sub
请注意图形的双缓冲。 .NET在为您的用户控件设置以下样式时,在双缓冲方面做得很好,这些设置在我InitializeComponent
方法中。
Me.SetStyle(ControlStyles.UserPaint, True)
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.DoubleBuffer, True)
我发现,尽管绘制中断时间很短(每20毫秒中断一次看起来不错),但我仍然遇到了一些闪烁,因此我采用了旧的双缓冲技术(创建位图然后将其绘制到图形对象),这效果非常好。
希望您喜欢这个控件!