65.9K
CodeProject 正在变化。 阅读更多。
Home

跟进消息

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.56/5 (5投票s)

2004年10月5日

CPOL

4分钟阅读

viewsIcon

36301

downloadIcon

94

用于显示各种消息的用户定义控件。

Sample screenshot

引言

我喜欢让用户随时了解情况。我知道我可能在这里有点出格,但嘿,我就是这么叛逆。

我们处理了很多系统,对吧?电子邮件、服务器、消息队列、servlet、Web服务等等。而且,我们越来越多地将这些集成到我们编写的应用程序中。有些应用程序可能需要所有这些,甚至更多。如果某个部分出现故障,可能会给用户带来不便。例如,考虑这种情况:作为您应用程序的一部分,用户从消息队列接收消息,使用您的应用程序处理数据,然后将结果数据发布到远程Web服务,同时,通过电子邮件通知下一个部门,该部门将收到数据已完成的通知。

我们在应用程序中加入了异常处理来处理这种情况,对吧?那么用户呢?如果他们尝试将某些内容提交到远程Web服务,却发现公司Web连接已断开,这对他们来说是很令人沮丧的。或者,如果他们尝试发送通知电子邮件,却发现邮件服务器因维护而关闭。最好提前告知他们,这样他们就可以做好准备。毕竟,我们希望用户满意,对吧?(我就是那种多愁善感的人。)

控件

在我们的环境中,系统专家们通过创建一个网页来通知整个组织任何当前发生的问题、任何计划中的停机时间以及他们认为需要传达的任何特殊情况。问题是,你必须打开浏览器,导航到该页面,然后刷新页面才能获得当前状态。

我在我的应用程序中包含了这个OSNotify控件,用于显示系统状态或其他任何我想让用户关注的消息。它的工作原理如下:

该控件包含一个OSMessage类,该类定义了几个属性:KeyIndexTextImportanceLinkIgnore。它还有一个集合类OSMessages,可以传递给控件进行显示。消息可以标记为三个重要性级别:LOWMEDIUMHIGH,每个级别都会显示不同的用户定义图标。Ignore属性可用于跳过用户不再想看到的消息。

许多属性控制消息的显示;下面将对此进行描述:

  • BorderStyleBackColorForeColor - 您知道这些是什么。
  • ChangeIntervalScrollSize - 结合使用,设置滚动速度。
  • LowPriorityIconMediumPriorityIconHighPriorityIcon - 不言自明。
  • MessageDisplayType - osStaticosRightToLeft。如果为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毫秒中断一次看起来不错),但我仍然遇到了一些闪烁,因此我采用了旧的双缓冲技术(创建位图然后将其绘制到图形对象),这效果非常好。

希望您喜欢这个控件!

© . All rights reserved.