|
-
Nov 2nd, 2001, 10:34 AM
#1
Thread Starter
Junior Member
How do I get rid of flicker?
Hello,
Please excuse a dumb, self taught (poorly) VB programmer who devises applications for educational use.
Here's my problem: I have a form on which I have drawn a graphic, at design time, using the line tool.
By using various buttons + slider the user is able to change the gradient of one of the lines and/or shift it to the right or the left. I've no problem with any of this.
But as the line is shifted to right/left and crosses other lines I get some very annoying and distracting flickering. It's as if each time the line moves incrementally all the other lines are redrawn. Is there some coding that I can use to prevent this?
-
Nov 2nd, 2001, 10:35 AM
#2
PowerPoster
Remaining quiet down here !!!
BRAD HAS GIVEN ME THE ULTIMATIVE. I have chosen to stay....
-
Nov 2nd, 2001, 10:41 AM
#3
Thread Starter
Junior Member
Thanks for this James. But ......................
would be grateful if you could point me just that little bit further.
-
Nov 2nd, 2001, 10:55 AM
#4
Thread Starter
Junior Member
I've added
Public Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long
to the module for the application
and called it up by LockWindowUpdate (1) at the beginning of the loop that moves the line
but this does nothing for me.
Any further help would be much appreciated.
-
Nov 2nd, 2001, 10:58 AM
#5
PowerPoster
wELL
Call LockWindowUpdate (me.hwnd)
To release pass the zero - LockWindowUpdate(0).
Sorry for now being more specific before..
Remaining quiet down here !!!
BRAD HAS GIVEN ME THE ULTIMATIVE. I have chosen to stay....
-
Nov 2nd, 2001, 11:36 AM
#6
Thread Starter
Junior Member
James,
I'm making progress (with your help) but:
where do I put the code LockWindowUpdate (me.hwnd) ?
Putting it into Form Load locked my whole screen.
Putting it before the loop to move the line does nothing.
The code that I have is (you can probably pick holes in this)
Private Sub Timer1_Timer()
If ShiftLeft = True Then
If Step < 400 And Line1.X1 > 1500 Then
Select Case Step
Case Step
Y1 = Y1 + 2 * XCoefficient
X2 = X2 - 8
Line1.Y1 = Y1
Line1.Y2 = Y2
Line1.X1 = X1
Line1.X2 = X2
End Select
Step = Step + 1
End If
Else
If Step < 400 And Line1.X2 < 11000 Then
Select Case Step
Case Step
Y1 = Y1 - 2 * XCoefficient
X2 = X2 + 8
Line1.Y1 = Y1
Line1.X2 = X2
End Select
Step = Step + 1
End If
End If
End Sub
At what point do I lock the window?
-
Nov 2nd, 2001, 11:41 AM
#7
PowerPoster
Well
I've never tries this without locking the whole form
2 suggestions :
1) Try locking form at the point you set the Line x y values in you select case areas.
2) If you are drwaing in a picturebox or other container, try, in the same areas, LOCKWINDOWUPDATE(YOURPICTUREBOX or DRAWING IMAGE.hwnd) Do not know if this will work.
I am now one to pick apart code unless asked to do so...
Remaining quiet down here !!!
BRAD HAS GIVEN ME THE ULTIMATIVE. I have chosen to stay....
-
Nov 2nd, 2001, 11:58 AM
#8
Thread Starter
Junior Member
James,
Have tried your suggestion (1).
LockWindowUpdate (me.hwnd) certainly locks the form but when used at this point does not stop the flicker.
The graphic is drawn on the form and not within a container.
Cannot continue conversation - am now off home for dinner plus watch some rugby.
Maybe speak to you over the weekend.
Thanks for your interest.
-
Nov 2nd, 2001, 11:59 AM
#9
PowerPoster
Well
We will keep trying at your liesure.
Enjoy your weekend.
Remaining quiet down here !!!
BRAD HAS GIVEN ME THE ULTIMATIVE. I have chosen to stay....
-
Nov 2nd, 2001, 01:55 PM
#10
Thread Starter
Junior Member
I've taken the liberty of attaching a file to show the problem and action taken (as yet unsuccessful)
-
Nov 2nd, 2001, 08:03 PM
#11
PowerPoster
Hi
The problem is that labels and lines are drawn directly on the form and so each time u move a line over these they have to be redrawn. You have lots of lines and labels and so u get flicker.
A better way is to use a picture box and directly draw your labels and lines. This greatly reduces resources also.
I have thrown together a quick sample that doesnt include all the functionality that u wanted but will be a good base for your additions.
Regards
Stuart
VB Code:
'Form: 1 Picture box (large), 3 command buttons (1 to 3) and
'1 timer - Timer1
Option Explicit
Dim fCounter As Long
Dim fString As String
Dim fStrHeight As Single
Dim fStrWidth As Single
Dim fGradient As Double
Dim fB As Double
Dim fStep As Double
Private Sub Form_Load()
Command1.Caption = "Up"
Command2.Caption = "Down"
Command3.Caption = "Stop"
Timer1.Interval = 100
'1000 for chart and 200 for borders
Picture1.Scale (-200, -200)-(1200, 1200)
With Picture1
'X & Y axis line
.ForeColor = vbRed
.DrawWidth = 2
Picture1.Line (0, 0)-(0, 1000)
Picture1.Line (0, 1000)-(1000, 1000)
'Tick marks & labels
For fCounter = 0 To 1000 Step 100
Picture1.Line (-20, fCounter)-(0, fCounter) 'Y Tick
Picture1.Line (fCounter, 1000)-(fCounter, 1020) 'X Tick
fString = CStr(1000 - fCounter)
fStrHeight = .TextHeight(fString) 'height of label
fStrWidth = .TextWidth(fString) 'width of label
'Y labels
.CurrentX = -40 - fStrWidth
.CurrentY = fCounter - fStrHeight \ 2
Picture1.Print fString;
'Y labels
.CurrentX = 1000 - fCounter - fStrWidth \ 2
.CurrentY = 1030
Picture1.Print fString;
Next
'Bordering Lines
'base these on ur formulae nb (1000 - value)
.ForeColor = vbBlack
.DrawWidth = 1
Picture1.Line (0, 200)-(600, 1000)
Picture1.Line (0, 500)-(900, 1000)
End With
'Movable Line
With Line1
.X1 = 0
.Y1 = 700
.X2 = 400
.Y2 = 1000
fGradient = -(1000 - .Y1) / .X2
fB = 1000 - .Y1
End With
End Sub
Private Sub Command1_Click()
'Move up
fStep = 20
Timer1.Enabled = True
End Sub
Private Sub Command2_Click()
'Move down
fStep = -20
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
With Line1
.X2 = .X2 + fStep
.Y1 = 1000 + fGradient * .X2
End With
End Sub
Private Sub Command3_Click()
Timer1.Enabled = False
End Sub
-
Nov 4th, 2001, 06:23 AM
#12
Thread Starter
Junior Member
Thanks for your help.
I appreciate that you now expect me to fill in the gaps, but there is one problem. On executing the code it stumbles at
'Movable Line
With Line1
with error message “variable not defined”
which I suppose is only reasonable given that it’s not.
Can I declare a line? I clearly need some way of doing this, so that the line has a handle and can then be moved. This was no problem when drawing the line using the line control which is why I went straight to this on my first attempt.
On declaring
Dim Line1 as ………..
I’m offered a set of alternatives including Line. Can I do this?
When I tried it, the code execution no longer stumbled at
With Line 1
but instead at the next line.
I’m not sure what this is telling me. Any help would be greatly appreciated.
There’s another point on which I can’t find an answer in my VB books. Suppose I want to draw/colour a polygon. Say I know its corners relative to the scales in the picture box. It seems that I can’t write what I would like – i.e.
Picture1.polgon ….. and give the corners.
Is there a way of doing this?
Peter
-
Nov 4th, 2001, 07:51 AM
#13
PowerPoster
Hi
Sorry Peter, Line1 was a line control that you put on the form inside the picture box at design time. Is the same line control that u had used in ur version of the program.
Re: the polygon u can do a search on polygon fill and see API code to do that
Regards
Stuart
-
Nov 4th, 2001, 12:51 PM
#14
PowerPoster
Well
Did you get it fuctioning?
Remaining quiet down here !!!
BRAD HAS GIVEN ME THE ULTIMATIVE. I have chosen to stay....
-
Nov 4th, 2001, 01:28 PM
#15
Thread Starter
Junior Member
Thanks to everyone. It was only after I posted the message this morning that I realised that Line1 meant what it usually means. Mea maxima maxima culpa - too many drinks last night!!!
I now have the application working as I want it.
I'll look at the API re polygons.
-
Nov 7th, 2001, 09:57 AM
#16
Thread Starter
Junior Member
Me again I'm afraid. Have searched the API and the following seem to be relevant:
Public Declare Function CreatePolygonRgn Lib "gdi32" (lpPoint As POINTAPI, ByVal nCount As Long, ByVal nPolyFillMode As Long) As Long
Public Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long
Public Declare Function FillRgn Lib "gdi32" (ByVal hdc As Long, ByVal hRgn As Long, ByVal hBrush As Long) As Long
Public Type POINTAPI
x As Long
y As Long
End Type
For the function Polygon, I assume that ByVal nCount As Long simply wants the number of corners, lpPoint As POINTAPI wants a list of the points and ByVal hdc As Long wants an identifier?
So I tried the following code:
Dim A As POINTAPI
Dim B As POINTAPI
Dim C As POINTAPI
Dim Polygon1 As Long
Private Sub Form_Load()
Picture1.Scale (-200, -200)-(1200, 1200)
With Picture1
A.x = 0
A.y = 0
B.x = 0
B.y = 1000
C.x = 1000
C.y = 0
Polygon1 = Polygon(Me.hdc, A - B - C, 3)
End With
End Sub
This stumbled on the A - B - C. Type mismatch error.
So I tried
Polygon1 = Polygon(1, A, B, C, 3)
as the function call, with the same result.
So how do I separate the points or am I completely up a gum tree?
Are there books that cover the API, since Win32API.txt gives no help other than listing the functions etc available?
Another point worries me. Applications that I write need to run on all platforms from Win98 Second Edition (I rule out the first) up to Win XP. So whatever functions I call up from the API must be accessible from all these platforms.
-
Nov 8th, 2001, 08:13 AM
#17
PowerPoster
Hi again
I see u have had no luck on other threads with the polygon api. I had to stretch my little brain to remember all of that algebra / geometry stuff about lines etc and so u can forgive me if i duffed it up. Also it is 12 midnight!! 
Anyway, this code works and u can adjust to your heart's content
Regards
Stuart
VB Code:
Option Explicit
Dim fCounter As Long
Dim fString As String
Dim fStrHeight As Single
Dim fStrWidth As Single
Dim fGradient As Double
Dim fB As Double
Dim fStep As Double
'Coordinates of lines to work out intersecting points
Private Type LineType
X1(1) As Double
Y1(1) As Double
X2(1) As Double
Y2(1) As Double
End Type
Dim MyLine As LineType
'Intersecting points
Dim XInt As Double
Dim YInt As Double
'Polygon api coords
Private Type apiCoords
x As Long
y As Long
End Type
Dim PolyPoints(1 To 4) As POINTAPI
Dim lPolyRgn As Long
Dim lBrush As Long
Dim lRet As Long
Private Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As apiCoords, ByVal nCount As Long) As Long
Private Sub Form_Load()
Command1.Caption = "Up"
Command2.Caption = "Down"
Command3.Caption = "Stop"
Timer1.Interval = 100
'1000 for chart and 200 for borders
Picture1.Scale (-200, -200)-(1200, 1200)
With Picture1
.ForeColor = vbRed
.DrawWidth = 2
'Tick marks & labels
'------------------------------------------------------------
For fCounter = 0 To 1000 Step 100
Picture1.Line (-20, fCounter)-(0, fCounter) 'Y Tick
Picture1.Line (fCounter, 1000)-(fCounter, 1020) 'X Tick
fString = CStr(1000 - fCounter)
fStrHeight = .TextHeight(fString) 'height of label
fStrWidth = .TextWidth(fString) 'width of label
'Y labels
.CurrentX = -40 - fStrWidth
.CurrentY = fCounter - fStrHeight \ 2
Picture1.Print fString;
'Y labels
.CurrentX = 1000 - fCounter - fStrWidth \ 2
.CurrentY = 1030
Picture1.Print fString;
Next
.ForeColor = vbBlack
.DrawWidth = 1
End With
'Draw lines and find intersecting points
'------------------------------------------------------------
With MyLine
.X1(0) = 0: .Y1(0) = 700: .X2(0) = 600: .Y2(0) = 0
Picture1.Line (.X1(0), 1000 - .Y1(0))-(.X2(0), 1000 - .Y2(0))
.X1(1) = 0: .Y1(1) = 500: .X2(1) = 900: .Y2(1) = 0
Picture1.Line (.X1(1), 1000 - .Y1(1))-(.X2(1), 1000 - .Y2(1))
XInt = (.Y1(0) - .Y1(1)) / ((.Y1(0) / .X2(0)) - (.Y1(1) / .X2(1)))
YInt = -.Y1(0) / .X2(0) * XInt + .Y1(0)
End With
'Polygon dimensions
'------------------------------------------------------------
PolyPoints(1) = Rescale(0, MyLine.Y1(1))
PolyPoints(2) = Rescale(0, 0)
PolyPoints(3) = Rescale(MyLine.X2(0), 0)
PolyPoints(4) = Rescale(XInt, YInt)
'API calls to fill polygon
'------------------------------------------------------------
lPolyRgn = CreatePolygonRgn(PolyPoints(1), 4, ALTERNATE)
lBrush = CreateSolidBrush(RGB(230, 230, 230)) 'Pick any colour
If Not lBrush = 0 Then
lRet = FillRgn(Picture1.hdc, lPolyRgn, lBrush)
lRet = DeleteObject(lBrush)
End If
lRet = DeleteObject(lPolyRgn)
'Moved axis drawing here to make sure shows up as thick line
'------------------------------------------------------------
With Picture1
.ForeColor = vbRed
.DrawWidth = 2
Picture1.Line (0, 0)-(0, 1000)
Picture1.Line (0, 1000)-(1000, 1000)
End With
'Movable Line
'------------------------------------------------------------
With Line1
.X1 = 0
.Y1 = 700
.X2 = 400
.Y2 = 1000
fGradient = -(1000 - .Y1) / .X2
fB = 1000 - .Y1
End With
End Sub
Private Function Rescale(ByVal XCoord As Long, ByVal YCoord As Long) As POINTAPI
'Function to rescale coordinates to suit scaling
With Picture1
Rescale.x = (XCoord + 200) / Screen.TwipsPerPixelX * .Width / .ScaleWidth
Rescale.y = (1200 - YCoord) / Screen.TwipsPerPixelY * .Height / .ScaleHeight
End With
End Function
Private Sub Command1_Click()
'Move up
fStep = 20
Timer1.Enabled = True
End Sub
Private Sub Command2_Click()
'Move down
fStep = -20
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
With Line1
.X2 = .X2 + fStep
.Y1 = 1000 + fGradient * .X2
End With
End Sub
Private Sub Command3_Click()
Timer1.Enabled = False
End Sub
-
Nov 9th, 2001, 03:47 AM
#18
Thread Starter
Junior Member
Many thanks for your help
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|