• A simple NewsTicker


    By 8 Jan 2014

    Introduction

    When looking around the internet for a clue to implementing a simple scrolling news ticker style panel for an application I have in production, the samples I found all pointed to the use of Graphics.Drawstring, which when turned into a control flickered annoyingly no matter what I tried. The code I will present below in my first ever submission (please be gentle!) provides two ways that I found to overcome this. Please feel free to add/amend and otherwise improve on my examples!

    Also, I should add that there are a lot of omissions in the class, like extra properties that could be implemented and there is virtually no error trapping... I will leave that up to your individual requirements.

    Implementation 1 - Text Rendering

    Having started to code a control against the sample ideas I found and having already implemented double buffering to little effect, I took a look at an alternative way to actually draw the text to the control's surface and came across theTextRenderer class

    The key area of the first implementation is to use a TextRenderer object instead of the aforementionedGraphics.Drawstring call. In the snippet below, Gr is a graphics object defined for the UserControl itself, _news is the actual string to present in the control and the variables X and Y are the starting width and height offset of the string.

    Gr.Clear(Me.BackColor)
    TextRenderer.DrawText(Gr, _news, Me.Font, New Point(CInt(X), CInt(Y)), Me.ForeColor)
    View Code

    The text is moved across the panel by manipulating the value of X in response to a timer Tick event until it is found to be less than zero minus the length of the string itself (ie: it has disappeared off the left side of the control) when it is reset to the starting point, the right side of the control.

    Altering the values of the timer's interval and a step value _speed allows the user to fine-tune the control for least flicker.

    The two central methods in the control respond to the initial setup during MyBase.Load and the timer tick response

    Private Sub SetupWindow()
      Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
      Gr = Me.CreateGraphics()
      X = Me.Width
      Me.BorderStyle = Windows.Forms.BorderStyle.Fixed3D
      Me.Dock = DockStyle.Bottom
      _strSize = Gr.MeasureString(_news, Me.Font)
      If (Me.Height < _strSize.Height + 4) Then Me.Height = CInt(_strSize.Height) + 4
      Timer.Interval = 25
      Timer.Start()
    End Sub
    
    Private Sub UpdateDisplay()
      Dim tHeight As Double = _strSize.Height
      Select Case Me.TextPosition
       Case TextPlacement.Top : Y = 0
        Case TextPlacement.Middle : Y = CSng((Me.Height / 2) - (tHeight / 2))
        Case TextPlacement.Bottom : Y = CSng(Me.Height - tHeight)
      End Select
      Gr.Clear(Me.BackColor)
      TextRenderer.DrawText(Gr, _news, Me.Font, New Point(CInt(X), CInt(Y)), Me.ForeColor)
      If X <= (0 - _strSize.Width) Then
        X = Me.Width
      Else
        X = CSng(X - _speed)
      End If
    End Sub
    View Code

    Implementation 2 - Repositioning a Label

    While I was looking at ways to reduce the flicker in the above code, I considered the possibility of not redrawing the text directly at all but just moving it, so I added a label to my UserControl, set Autosize = True and set its text property to the string to be shown (_news). By manipulating the same X and variables as above, having first set them to the label's width and height offset it was possible to implement the same effect of a scrolling text with (to my mind) even less flickering evident than that noticeable in the first implementation

    lbl.Location = New Point(CInt(X), CInt(Y))
    View Code

    The full listing for implementation two is reproduced here (Note: I am omitting the label insertion in the designer partial class, although this should be placed on the UserControl and named lbl for this code to operate correctly)

    Public Class NewsTicker 
    Inherits System.Windows.Forms.UserControl
    
    Enum TextPlacement
     Top
     Middle
     Bottom
    End Enum
    
    
    Dim X As Single
    Dim Y As Single
    Dim Gr As Graphics
    Dim _news As String = "There is no news to display at this time"
    Dim _strSize As SizeF
    Private _tpos As TextPlacement = TextPlacement.Top
    Private _speed As Double = 1.0
    
    Private Sub NewsTicker_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load
        SetupWindow()
    End Sub
    Private Sub NewsTicker_Resize(sender As Object, e As System.EventArgs) Handles Me.Resize
        SetupWindow()
    End Sub
    Private Sub Timer_Tick(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles Timer.Tick
        UpdateDisplay()
    End Sub
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        lbl.Height = Me.Height - 4
        lbl.Text = _news
        lbl.AutoSize = True
        lbl.Location = New Point(Me.Width, 0)
        Me.Dock = DockStyle.Bottom
        Me.BorderStyle = Windows.Forms.BorderStyle.Fixed3D
        X = Me.Width
        If (Me.Height < lbl.Height + 4) Then Me.Height = CInt(lbl.Height) + 4
        Timer.Interval = 25
        Timer.Start()
    End Sub
    
    Private Sub UpdateDisplay()
        Dim tHeight As Double = lbl.Height
        Select Case Me.TextPosition
            Case TextPlacement.Top : Y = 0
            Case TextPlacement.Middle : Y = CSng((Me.Height / 2) - (tHeight / 2))
            Case TextPlacement.Bottom : Y = CSng(Me.Height - tHeight)
        End Select
        lbl.Location = New Point(CInt(X), CInt(Y))
        If X <= (0 - lbl.Width) Then
            X = Me.Width
        Else
            X = CSng(X - _speed)
        End If
    End Sub
    
    Public Property News As String
        Get
            Return _news
        End Get
        Set(value As String)
            _news = value
            SetupWindow()
        End Set
    End Property
    Public Property TextPosition As TextPlacement
        Get
            Return _tpos
       End Get
       Set(value As TextPlacement)
            _tpos = value
       End Set
       End Property
    
    Public Property Speed As Double
        Get
            Return _speed
        End Get
        Set(value As Double)
            If value < 0.01 Or value > 100 Then
                Throw New ArgumentOutOfRangeException("Speed", _
                  "Cannot be less than 0.01 or greater than 100")
            Else
                _speed = value
                SetupWindow()
            End If
        End Set
    End Property
    End Class
    View Code

    I will upload the full project source as a .ZIP when I can work out why I keep getting an 'Unexpected error' during the upload procedure? - .ZIP now uploaded thanks to the guys at CP!

    History

    • v1.0 - Initial release: 27 December 2013.
    • v1.01 - .ZIP upload issue resolved.

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    http://www.codeproject.com/Articles/702858/A-simple-NewsTicker-Two-implementations

  • 相关阅读:
    Boot-Repair&usb_repair
    Introducing ASLR for FreeBSD
    node.js操作Cookie
    Docker常见仓库MySQL
    Docker常见仓库CentOS
    Docker常见仓库Ubuntu
    Docker常见仓库Node.js
    Docker常见仓库WordPress
    Docker常见仓库Nginx
    Docker命令查询
  • 原文地址:https://www.cnblogs.com/gmth/p/3513386.html
Copyright © 2020-2023  润新知