Controls provide a paint event that is called at the end of their own paint
cycles. Handling this event and painting on the Graphics object provided
will ensure that whatever you paint is correctly timed to coincide with the
message driven architecture of Windows.
You can force the control to paint itself by calling the Invalidate method,
this initiates a paint cycle which will then kick off the Paint event where
you can do your own drawing.
For your own requirements you're a bit stuck because PictureBox doesn't do
internal double buffering and so invalidating the control at a rate that
would enable animation such as you require would also cause unacceptable
flickering. I don't think you'll get a good result with a transition engine
that writes over the contents of a PictureBox. PictureBox is a fairly
useless and much misused control anyway.
I would suggest creating a custom control to display an image and do the
transitions. Below my signature is a control I wrote for WellFormed that
does transitions. You may be able to modify that code to suit your purposes.
--
Bob Powell [MVP]
Visual C#, System.Drawing
Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/gdiplus_faq.htm
The GDI+ FAQ RSS feed:
http://www.bobpowell.net/faqfeed.xml
Windows Forms Tips and Tricks RSS:
http://www.bobpowell.net/tipstricks.xml
Bob's Blog:
http://bobpowelldotnet.blogspot.com/atom.xml
----------------------------------------------------------------------------
------------------
Imports System
Imports System.ComponentModel
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging
Imports System.Threading
Imports System.Windows.Forms
Namespace WellFormed
'/ <summary>
'/ Summary description for ImageTransitionControl.
'/ </summary>
Public Class ImageTransitionControl
Inherits Control
Private t As System.Threading.Timer
Public Enum TransitionTypes
Fade
BarnDoor
Slide
Spin
Checker
Blinds
Iris
Spiral
End Enum 'TransitionTypes
Private _transitionType As TransitionTypes = TransitionTypes.Fade
Public Property TransitionType() As TransitionTypes
Get
Return _transitionType
End Get
Set(ByVal Value As TransitionTypes)
_transitionType = value
End Set
End Property
Private _nHDivs As Integer = 3
Public Property HorizontalDivisions() As Integer
Get
Return _nHDivs
End Get
Set(ByVal Value As Integer)
If value = 0 Then
value = 3
End If
_nHDivs = value
End Set
End Property
Private _nVDivs As Integer = 3
Public Property VerticalDivisions() As Integer
Get
Return _nVDivs
End Get
Set(ByVal Value As Integer)
If value = 0 Then
value = 3
End If
_nVDivs = value
End Set
End Property
Private _imageA As Image
Public Property ImageA() As Image
Get
Return _imageA
End Get
Set(ByVal Value As Image)
_imageA = value
End Set
End Property
Private _imageB As Image
Public Property ImageB() As Image
Get
Return _imageB
End Get
Set(ByVal Value As Image)
_imageB = value
End Set
End Property
Public Sub New()
SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.DoubleBuffer Or
ControlStyles.UserPaint Or ControlStyles.ResizeRedraw, True)
End Sub 'New
'Variables used in the timing system
Private _transitionTime As New TimeSpan(0, 0, 0, 1, 0)
Private _currentPercentage As Single = 0
Private _running As Boolean = False
Public Property TransitionTime() As Single
Get
Return CSng(_transitionTime.TotalSeconds)
End Get
Set(ByVal Value As Single)
_transitionTime = New TimeSpan(0, 0, 0, 0, CInt(1000 * value))
End Set
End Property
'The moment at which the transition begins
Private _startTime As DateTime
'Called to start the transition off
Public Sub Go()
t = New System.Threading.Timer(New TimerCallback(AddressOf Tick), Nothing,
40, 40)
Me._currentPercentage = 0
_running = True
_startTime = DateTime.Now
Invalidate()
End Sub 'Go
'Services the tick event and re-calculates the percentage done
Sub Tick(ByVal state As Object)
Dim ts As TimeSpan = DateTime.Now.Subtract(Me._startTime)
_currentPercentage = CSng(100.0F / Me._transitionTime.TotalSeconds *
ts.TotalSeconds)
If _currentPercentage > 100 Then
_currentPercentage = 100
End If
Invalidate()
End Sub 'Tick
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
If _imageA Is Nothing OrElse _imageB Is Nothing Then
Return
End If
Dim pth As GraphicsPath = Nothing
If _currentPercentage < 100 Then
e.Graphics.DrawImage(_imageA, Me.ClientRectangle, 0, 0, _imageA.Width,
_imageA.Height, GraphicsUnit.Pixel)
End If
Select Case Me.TransitionType
Case TransitionTypes.Fade
If (True) Then
'This transition fades one image over the other
Dim ia As New ImageAttributes
Dim cm As New ColorMatrix
cm.Matrix33 = 1.0F / 255 * (255 * _currentPercentage / 100)
ia.SetColorMatrix(cm)
e.Graphics.DrawImage(_imageB, Me.ClientRectangle, 0, 0, _imageB.Width,
_imageB.Height, GraphicsUnit.Pixel, ia)
ia.Dispose()
End If
Case TransitionTypes.BarnDoor
'has the effect of a barn door closing over the image
e.Graphics.DrawImage(_imageB, New Rectangle(0, 0, CInt(Me.Width *
_currentPercentage / 200), Me.Height), 0, 0, CInt(_imageB.Width / 2),
_imageB.Height, GraphicsUnit.Pixel)
e.Graphics.DrawImage(_imageB, New Rectangle(CInt(Me.Width - Me.Width *
_currentPercentage / 200), 0, CInt(Me.ClientRectangle.Width *
_currentPercentage / 200), Me.ClientRectangle.Height), CInt(_imageB.Width /
2), 0, CInt(_imageB.Width / 2), _imageB.Height, GraphicsUnit.Pixel)
Case TransitionTypes.Iris
'use a path
pth = New GraphicsPath
'calculate the width and height of the ellipse
Dim w As Integer = CInt(Me.Width * 1.414F * _currentPercentage / 200)
Dim h As Integer = CInt(Me.Height * 1.414F * _currentPercentage / 200)
pth.AddEllipse(CInt(Me.Width / 2 - w), CInt(Me.Height / 2 - h), CInt(2 * w),
CInt(2 * h))
'use the path as a clipping region
e.Graphics.SetClip(pth, CombineMode.Replace)
'Draw the image
e.Graphics.DrawImage(_imageB, ClientRectangle, 0, 0, _imageB.Width,
_imageB.Height, GraphicsUnit.Pixel)
pth.Dispose()
Case TransitionTypes.Checker
pth = New GraphicsPath
Dim cw As Integer = CInt(Me.Width * _currentPercentage / 100) / _nHDivs
Dim ch As Integer = Me.Height / _nVDivs
Dim row As Integer = 0
Dim y As Integer
For y = 0 To (Me.Height) - ch Step ch
Dim x As Integer
For x = 0 To (Me.Width) - (Me.Width / _nHDivs) Step Me.Width / _nHDivs
Dim rc As New Rectangle(x, y, cw, ch)
If (row And 1) = 1 Then
rc.Offset(Me.Width / (2 * _nVDivs), 0)
End If
pth.AddRectangle(rc)
If _currentPercentage >= 50 AndAlso (row And 1) = 1 AndAlso x = 0 Then
rc.Offset(-(Me.Width / _nHDivs), 0)
pth.AddRectangle(rc)
End If
Next x
row += 1
Next y
Dim r As New [Region](pth)
e.Graphics.SetClip(r, CombineMode.Replace)
e.Graphics.DrawImage(_imageB, ClientRectangle, 0, 0, _imageB.Width,
_imageB.Height, GraphicsUnit.Pixel)
r.Dispose()
pth.Dispose()
Case TransitionTypes.Slide
Dim mx As New Matrix(1, 0, 0, 1, Me.Width * _currentPercentage / 100 -
Me.Width, 0)
e.Graphics.Transform = mx
e.Graphics.DrawImage(_imageB, ClientRectangle, 0, 0, _imageB.Width,
_imageB.Height, GraphicsUnit.Pixel)
Case TransitionTypes.Spin
' calculate the degrees of spin
Dim degrees As Single = 360 * _currentPercentage / 100
'and the origin (center of the client area
Dim ofsX As Single = Me.Width / 2
Dim ofsY As Single = Me.Height / 2
'calculate the scale at which the image will be drawn
Dim Scale As Single = 1 * _currentPercentage / 100
'catering for zero's which will cause an exception
If Scale = 0 Then
Scale = 0.0001F
End If 'create a matrix with the scale and origin
Dim rm As New Matrix(Scale, 0, 0, Scale, ofsX, ofsY)
'do the spin
rm.Rotate(degrees, MatrixOrder.Prepend)
'use the matrix
e.Graphics.Transform = rm
'draw the image
e.Graphics.DrawImage(_imageB, New Rectangle(-Width / 2, -Height / 2, Width,
Height), 0, 0, _imageB.Width, _imageB.Height, GraphicsUnit.Pixel)
rm.Dispose()
Case TransitionTypes.Spiral
If _currentPercentage < 100 Then
Dim percentageAngle As Double = _nHDivs * (Math.PI * 2) / 100
Dim percentageDistance As Double = Math.Max(Width, Height) / 100
pth = New GraphicsPath(FillMode.Winding)
Dim cx As Single = Width / 2
Dim cy As Single = Height / 2
Dim pc1 As Double = _currentPercentage - 100
Dim pc2 As Double = _currentPercentage
If pc1 < 0 Then
pc1 = 0
End If
Dim a As Double = percentageAngle * pc2
Dim last As New PointF(CSng(cx + pc1 * percentageDistance * Math.Cos(a)),
CSng(cy + pc1 * percentageDistance * Math.Sin(a)))
a = percentageAngle * pc1
While pc1 <= pc2
Dim thisPoint As New PointF(CSng(cx + pc1 * percentageDistance *
Math.Cos(a)), CSng(cy + pc1 * percentageDistance * Math.Sin(a)))
pth.AddLine(last, thisPoint)
last = thisPoint
pc1+=0.1
a+=percentageAngle/10
End While
pth.CloseFigure()
e.Graphics.SetClip(pth, CombineMode.Replace)
pth.Dispose()
End If
e.Graphics.DrawImage(_imageB, ClientRectangle, 0, 0, _imageB.Width,
_imageB.Height, GraphicsUnit.Pixel)
Case TransitionTypes.Blinds
Dim y As Integer
For y = 0 To _nHDivs - 1
Dim src As New Rectangle(0, y * (_imageB.Height / _nHDivs), _imageB.Width,
_imageB.Height / _nHDivs)
Dim drc As New Rectangle(0, y * (Height / _nHDivs), Width, CInt(Height /
_nHDivs * _currentPercentage / 100))
drc.Offset(0, Height / (_nHDivs * 2) - drc.Height / 2)
e.Graphics.DrawImage(_imageB, drc, src, GraphicsUnit.Pixel)
Next y
End Select
If _currentPercentage = 100 Then
_running = False
If Not (t Is Nothing) Then
t.Dispose()
End If
t = Nothing
End If
MyBase.OnPaint(e)
End Sub 'OnPaint
End Class 'ImageTransitionControl
End Namespace 'WellFormed
----------------------------------------------------------------------------
------------------
"rut" <ru*@discussions.microsoft.com> wrote in message
news:20**********************************@microsof t.com...
If I have a picturebox with a background image and I want to
1. Display text atop of the background and
2. Have transistions between text; ie, when the text changes, the screen
can fade out/in or have a windowblind type transition,etc.
How do you create transitions in a picture box in conjunction with
displaying text?
(Using vb.net.