dierdan
asked on
Flicker in Picturebox
G'day,
I want to show this(Rotline.frm) rotating line without the flicker it presently suffers.
I think the PictureBox should be filled with a 'bitblt' routine but I don't know how; I don't want to use 2
Picturebox controls.
Has anybody got any ideas?
Thank you, Dan Dierikx
'_____________Rotline.frm ________________
VERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 3195
ClientLeft = 60
ClientTop = 345
ClientWidth = 4680
LinkTopic = "Form1"
ScaleHeight = 3195
ScaleWidth = 4680
StartUpPosition = 3 'Windows Default
Begin VB.CommandButton Command2
Caption = "&Exit"
Height = 450
Left = 3165
TabIndex = 2
Top = 2625
Width = 1245
End
Begin VB.CommandButton Command1
Caption = "&Start"
Height = 435
Left = 3165
TabIndex = 1
Top = 1080
Width = 1290
End
Begin VB.PictureBox Picture1
AutoRedraw = -1 'True
Height = 2355
Left = 405
ScaleHeight = 2295
ScaleWidth = 2445
TabIndex = 0
Top = 375
Width = 2505
Begin VB.Line Line1
BorderWidth = 5
DrawMode = 9 'Not Mask Pen
X1 = 1125
X2 = 1125
Y1 = 1050
Y2 = 90
End
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Dim LH As Single
Dim Rad As Single
Const PI = 3.1416
Private Sub Command1_Click()
If Command1.Caption = "&Start" Then
Command1.Caption = "&Stop"
For t = 62832 To 0 Step -1
If Command1.Caption = "&Start" Then Exit For
Rad = t / 100
SinRad = Sin(Rad)
CosRad = Cos(Rad)
Line1.X2 = Line1.X1 + (LH * CosRad)
Line1.Y2 = Line1.Y1 - (LH * SinRad)
If t = 0 Then t = 62832
DoEvents
Sleep (10)
Next t
End If
Command1.Caption = "&Start"
End Sub
Private Sub Command2_Click()
Unload Me
End Sub
Private Sub Form_Load()
LH = Sqr((Line1.X2 - Line1.X1) ^ 2 + (Line1.Y2 - Line1.Y1) ^ 2)
End Sub
I want to show this(Rotline.frm) rotating line without the flicker it presently suffers.
I think the PictureBox should be filled with a 'bitblt' routine but I don't know how; I don't want to use 2
Picturebox controls.
Has anybody got any ideas?
Thank you, Dan Dierikx
'_____________Rotline.frm ________________
VERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 3195
ClientLeft = 60
ClientTop = 345
ClientWidth = 4680
LinkTopic = "Form1"
ScaleHeight = 3195
ScaleWidth = 4680
StartUpPosition = 3 'Windows Default
Begin VB.CommandButton Command2
Caption = "&Exit"
Height = 450
Left = 3165
TabIndex = 2
Top = 2625
Width = 1245
End
Begin VB.CommandButton Command1
Caption = "&Start"
Height = 435
Left = 3165
TabIndex = 1
Top = 1080
Width = 1290
End
Begin VB.PictureBox Picture1
AutoRedraw = -1 'True
Height = 2355
Left = 405
ScaleHeight = 2295
ScaleWidth = 2445
TabIndex = 0
Top = 375
Width = 2505
Begin VB.Line Line1
BorderWidth = 5
DrawMode = 9 'Not Mask Pen
X1 = 1125
X2 = 1125
Y1 = 1050
Y2 = 90
End
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Dim LH As Single
Dim Rad As Single
Const PI = 3.1416
Private Sub Command1_Click()
If Command1.Caption = "&Start" Then
Command1.Caption = "&Stop"
For t = 62832 To 0 Step -1
If Command1.Caption = "&Start" Then Exit For
Rad = t / 100
SinRad = Sin(Rad)
CosRad = Cos(Rad)
Line1.X2 = Line1.X1 + (LH * CosRad)
Line1.Y2 = Line1.Y1 - (LH * SinRad)
If t = 0 Then t = 62832
DoEvents
Sleep (10)
Next t
End If
Command1.Caption = "&Start"
End Sub
Private Sub Command2_Click()
Unload Me
End Sub
Private Sub Form_Load()
LH = Sqr((Line1.X2 - Line1.X1) ^ 2 + (Line1.Y2 - Line1.Y1) ^ 2)
End Sub
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you rspahitz for your solution.
My project however requires 16 lines which are manipulated with Vscrolls to make up an animated figure.
I would prefer to use Line Controls for ease of programming. The Control Lines are just 'rearranged' during animation whereas each drawn line needs to be erased and redrawn.
I could make an array of line 'joins', x1y1.....x16y16 and rearrange the relative angles of the lines but need to figure out how to erase the previous position of the line.
You have answered my original question but I would welcome further comments from you or anyone following this.
My project however requires 16 lines which are manipulated with Vscrolls to make up an animated figure.
I would prefer to use Line Controls for ease of programming. The Control Lines are just 'rearranged' during animation whereas each drawn line needs to be erased and redrawn.
I could make an array of line 'joins', x1y1.....x16y16 and rearrange the relative angles of the lines but need to figure out how to erase the previous position of the line.
You have answered my original question but I would welcome further comments from you or anyone following this.
I know that if you XOR things, they tend to "reverse" themselves. That would seem to be a good strategy here, but I'm not sure how you can XOR a line.
This could end up getting more complex by creating your own line method which draws each pixel by XORing the current color, but then it will probably be slower than using the line control:
Private Sub DrawLine(X1 as single, Y1 as single, X2 as single, Y2 as single, RGBColor as long, optional EraseLine as boolean = False)
Dim X as single
Dim Y as Single
' determine pixel X,Y location for next item in the line
...
if EraseLine then
PSet(X,Y), Point(X,Y) XOR vbWhite ' I think this is right...
else
PSet(X,Y), RGBColor
endif
end sub
Other than that, using your existing method, the best suggestion I can offer is to investigate "double-buffering" which is one way to handle flickering in animations, which is essentially what you're doing.
This could end up getting more complex by creating your own line method which draws each pixel by XORing the current color, but then it will probably be slower than using the line control:
Private Sub DrawLine(X1 as single, Y1 as single, X2 as single, Y2 as single, RGBColor as long, optional EraseLine as boolean = False)
Dim X as single
Dim Y as Single
' determine pixel X,Y location for next item in the line
...
if EraseLine then
PSet(X,Y), Point(X,Y) XOR vbWhite ' I think this is right...
else
PSet(X,Y), RGBColor
endif
end sub
Other than that, using your existing method, the best suggestion I can offer is to investigate "double-buffering" which is one way to handle flickering in animations, which is essentially what you're doing.
ASKER
I will post another question on 'double buffering' if I find Drawn Lines impractical.
Thanks for your help rspahitz.
Thanks for your help rspahitz.
To draw images, you usually use one of the following:
1) An object that handles drawing through simple properties or methods
2) A drawing area (picturebox or form) with the PSet command (set a pixel)
3) A drawing area with the Line command
4) A drawing area with the Circle command