Loop i VB6 & andra problem
Loop i VB6 & andra problem
Hej.
Sitter hemma och småpysslar med ett litet program i Visual Basic 6 och har stött på et problem.
Det jag vill göra är att när jag trycker på en knapp så ska en variabel räknas upp var tiondels sekund i en loop tills man trycker på en stoppknapp, hur löser man detta?
Variabeln är döpt enligt följande:
Dim linepos as Integer
Altså den heter linepos och har värdet 0 från början, sen ska den stega upp med ett angivet värde t.ex. +10 var tiondels sekund.
Hur löser jag det och får det hyffsat exakt?
Sitter hemma och småpysslar med ett litet program i Visual Basic 6 och har stött på et problem.
Det jag vill göra är att när jag trycker på en knapp så ska en variabel räknas upp var tiondels sekund i en loop tills man trycker på en stoppknapp, hur löser man detta?
Variabeln är döpt enligt följande:
Dim linepos as Integer
Altså den heter linepos och har värdet 0 från början, sen ska den stega upp med ett angivet värde t.ex. +10 var tiondels sekund.
Hur löser jag det och får det hyffsat exakt?
Senast redigerad av Cenorpa 17 februari 2006, 11:24:54, redigerad totalt 3 gånger.
Dåså då ska du få det 
Du skapar en timer (den syns inte i runtime) på panelen.
Dubbelklicka på den så får du "eventet" som händer varje gång den aktiveras.
Sen kodar du som följer där du vill att timern ska starta.
Observera att det övre blocket kanske inte ska stå ihop med det nedre utan kanske i initialize e.dyl där du känner för att ha det.
Lycka till!

Du skapar en timer (den syns inte i runtime) på panelen.
Dubbelklicka på den så får du "eventet" som händer varje gång den aktiveras.
Sen kodar du som följer där du vill att timern ska starta.
Kod: Markera allt
Dim linepos as Integer
linepos = 0 ' Startvärde för linepos
Timer1.Interval = 100 ' (ms) Sätter intervallet med vilken timern ska aktiveras.
Timer1.Enabled = True ' Startar timern
Private Sub Timer1_Timer() ' detta event händer nu var 100'e millisekund.
linepos = linepos + 1 'ökar på variabeln linepos med 1
End Sub
Lycka till!
Nja, det skulle jag inte lita på. 
Ett betydligt säkrare alternativ är att gör en loop i koden och läsa av Timer-variabeln. "Timer" är en sekundräknare med flyttal och 2 decimaler = 10ms precision.
Exemplet förutsätter att "quit" och "n" är globaler och "quit" sätts till True när Stop-knappen trycks in.
"n" är tiden som räknas upp.
Mvh
speakman

Ett betydligt säkrare alternativ är att gör en loop i koden och läsa av Timer-variabeln. "Timer" är en sekundräknare med flyttal och 2 decimaler = 10ms precision.
Kod: Markera allt
Dim quit As Boolean
Dim n As Long
Dim t As Double
quit = False
t = Int(Timer * 10)
Do
If Int(Timer * 10) <> t Then
n = n + 1
End If
If quit Then Exit Do
DoEvents
Loop
"n" är tiden som räknas upp.
Mvh
speakman
Speakman: Helt rätt den stämmer inte 100% över långa tidsperioder men för att få det smidigt får vi kombinera våra exempel.
Hade lite för lite att göra så jag gjorde allt
Bara att ladda ner HÄR. Antigen ta spara mål som eller öppna direkt.
En "känd" bugg är att om man trycker flera gånger på stoppknappen blir totaltiden "fel" fast egentligen blir den inte det, svårt att förklara
Koden är som följer:
Är det såhär kod ska se ut eller? 
Mycket nöje!
Hade lite för lite att göra så jag gjorde allt

En "känd" bugg är att om man trycker flera gånger på stoppknappen blir totaltiden "fel" fast egentligen blir den inte det, svårt att förklara

Koden är som följer:
Kod: Markera allt
Dim StartTime, TotalTime
' Körs varje gång BTN_Start_Click nedtryckes
Private Sub BTN_Start_Click()
' StartTime sätts till timer (för att lagra starttiden)
StartTime = Timer
' Startar Timer1
Timer1.Enabled = True
End Sub
' Körs varje gång BTN_Start_Click nedtryckes
Private Sub BTN_Stop_Click()
' Här räknas totaltiden ut (formatnumber formatterar talet så att det ALLTID har två decimaler
TotalTime = FormatNumber(Round(Timer - StartTime, 2), 2)
' Stoppar Timer1
Timer1.Enabled = False
' Sätter LBL_Time till den uträknade tiden en sista gång
LBL_Time.Caption = FormatNumber(Round((TotalTime), 1), 1) & " sekunder"
' Skickar en MsgBox med sluttiden med 2 decimaler.
MsgBox ("Tiden från start till stopp var " & Chr(13) & TotalTime & " sekunder.")
End Sub
' Körs var 100'e millisekund
Private Sub Timer1_Timer()
' Sätter LBL_Time till den uträknade tiden
LBL_Time.Caption = FormatNumber(Round((Timer - StartTime), 1), 1) & " sekunder"
End Sub
' Körs varje gång programmet startas
Private Sub Form_Load()
' Sätter intervallet(ms) med vilken timern ska aktiveras.
Timer1.Interval = 100
' Stoppar Timer1
Timer1.Enabled = False
End Sub

Mycket nöje!
Hmm skulle verkligen en VB6 timer dra sig så mycket på 5 minuter?
Jag tycker det låter helt otroligt, nu har jag aldrig mätt på det, men skrivit div servrar med minut och sekundevent. Och dessa har snurrat i bra många fler minuter än 5 (altså borde en halv sekunds dragning i tiden märkas rätt tydligt)
Däremot kan ju eventen komma lite fördröjt om maskinen är hårt belastad.
Men det kommer du aldrig ifrån i ett så högnivå os som windows..
Speakmans do while loop har ju samma problem, säg att "DoEvents" tar en halvsekund... då får du ju inget event "i tid" endå.. (Den loopen ger väll förövrig en 100% cpu belastning hela tiden med, vilket i mina ögon är lite fulkodningvarning på)
Jag tycker det låter helt otroligt, nu har jag aldrig mätt på det, men skrivit div servrar med minut och sekundevent. Och dessa har snurrat i bra många fler minuter än 5 (altså borde en halv sekunds dragning i tiden märkas rätt tydligt)
Däremot kan ju eventen komma lite fördröjt om maskinen är hårt belastad.
Men det kommer du aldrig ifrån i ett så högnivå os som windows..
Speakmans do while loop har ju samma problem, säg att "DoEvents" tar en halvsekund... då får du ju inget event "i tid" endå.. (Den loopen ger väll förövrig en 100% cpu belastning hela tiden med, vilket i mina ögon är lite fulkodningvarning på)
AndLi: Den är tyvärr inte så exakt antar att det har med prollen att göra också ju mer belastad den är desto längre tar det för koden i timern att exekveras.
Jag testade med en räknare parallelt med den riktiga tiden och den drog sig en del. Men frågan är ju hur EXAKT man måste ha det. Syslar man tex med dragracing är det ju en sak. Springer man runt ett motionsspår en annan.
Cenorpa: Du behöver bara ladda hem den jag gjorde ovan. Som du ser är det kommenterat så att du ska slippa fundera över allt. Kolla igenom och testa.
Funktionen med text beskrivet är detta.
1. Du trycker på start.
2. timern startas och starttiden sparas i en variabel.
3. varje 100 dels sekund uppdateras skärmen så man ser hur lång tid som just nu är gången.
4. Trycker du på stop subtraheras nuvarande tid mot starttid och man får därmed exekveringstiden
Jag testade med en räknare parallelt med den riktiga tiden och den drog sig en del. Men frågan är ju hur EXAKT man måste ha det. Syslar man tex med dragracing är det ju en sak. Springer man runt ett motionsspår en annan.
Cenorpa: Du behöver bara ladda hem den jag gjorde ovan. Som du ser är det kommenterat så att du ska slippa fundera över allt. Kolla igenom och testa.
Funktionen med text beskrivet är detta.
1. Du trycker på start.
2. timern startas och starttiden sparas i en variabel.
3. varje 100 dels sekund uppdateras skärmen så man ser hur lång tid som just nu är gången.
4. Trycker du på stop subtraheras nuvarande tid mot starttid och man får därmed exekveringstiden
AndLi: Varför skulle min version fela i tiden? Den går ju på systemklockan, och missar den ett par ms första varvet, så tas det ju igen nästkommande varv. Enda missen som KAN uppstå är om den inte kör loopen på längre än 100ms, men hur stora är oddsen för det? 
Sedan vad det gäller CPU, så är hela poängen med DoEvents att den INTE ska ta 100% CPU (utan överlåta till andra processer). Det är iaf enda möjligheten i VB.
Mvh
speakman

Sedan vad det gäller CPU, så är hela poängen med DoEvents att den INTE ska ta 100% CPU (utan överlåta till andra processer). Det är iaf enda möjligheten i VB.
Mvh
speakman
Jag rättar: Det är enda möjligheten i VB för tidskritiska applikationer.
Fast jag syftade även på att lämna ifrån sig CPU'n, eftersom ingen tidsangiven överlämning finns i VB (som Sleep i C), och ett anrop till Sleep genom Declare Function skapar ännu större belastning (total låsning, 100 %CPU).
Mvh
speakman
Fast jag syftade även på att lämna ifrån sig CPU'n, eftersom ingen tidsangiven överlämning finns i VB (som Sleep i C), och ett anrop till Sleep genom Declare Function skapar ännu större belastning (total låsning, 100 %CPU).
Mvh
speakman
Re: Loop i VB6
Här är ett förslag som blir betydligt mer exakt än med timers.Cenorpa skrev:...Det jag vill göra är att när jag trycker på en knapp så ska en variabel räknas upp var tiondels sekund i en loop tills man trycker på en stoppknapp, hur löser man detta?
Hur löser jag det och får det hyffsat exakt?
Det använder en multimediatimer istället.

Huvuddelen av programmet:
Sub TightLoop()
Randomize
Dim Nu As Long, Nxt As Long
Dim Incr As Long ' Värde att öka räknaren med
Static Value As Long ' Det aktuella värdet
Incr = Val(Me.txtStep.Text) ' Lägg till ev. felhantering...
Nu = GetTickCount()
Nxt = Nu + 100 ' Nästa event om 100 ms
Running = True ' Aktivera loopen
While Running ' Main loop
Nu = GetTickCount()
If Nu >= Nxt Then ' Nu är det dags!
Value = Value + Incr
Me.txtResult.Text = Value
Nxt = Nu + 100
End If
DoEvents
Sleep 50 'ms Förhindrar loopen från att ta all CPU.
Wend
End Sub
Du kan hämta hela programmet här: http://www.meter.se/elektronikforumet/TimerSample.zip
HTH