Timer Problem

Anfängerfragen zum Programmieren mit PureBasic.
pede
Beiträge: 90
Registriert: 08.07.2007 20:37
Wohnort: brixen / Italien

Timer Problem

Beitrag von pede »

Grüetzi

Nachdem ich mir jetz auch ein bisschen die Timerfunktionen angesehen habe stellten sich mir einige Fragen, ich hab mehrere kurze Codes geschrieben, um meine Probleme zu verdeutlichen...

Code 1: (aus diesem Forum)

Code: Alles auswählen

If OpenWindow(0, #PB_Ignore, 0, 200, 200, "Test") 

  SetTimer_(WindowID(0), 0, 5000, 0) 
  
  Repeat 
    Select WaitWindowEvent() 
      
      Case #PB_Event_CloseWindow 
        Break 
        
      Case #WM_TIMER 
        Debug "Schon wieder 5 Sekunden um" 
        
    
    EndSelect 
  ForEver 
EndIf 

KillTimer_(WindowID(0), 0)
macht das was ich erwarte!

Code 2:

Code: Alles auswählen

Procedure MSGREQ()
    MessageRequester("Timer", "Die Zeit ist vorbei")
EndProcedure

ende = 0
hwnd = OpenWindow(0, 100, 100, 500, 500, "Timer")
SetTimer_(hWnd, 10, 5000, @MSGREQ())

Repeat
    event = WaitWindowEvent()
    Select event
        Case #PB_Event_CloseWindow
            Ende = 1
           
    EndSelect

Until ende = 1
KillTimer_(hWnd, 10)
macht auch das was ich erwarte

(beide -> Benachrichtigung nach 5 Sekunden)

Code 3:

Code: Alles auswählen

If OpenWindow(0, #PB_Ignore, 0, 200, 200, "Test") 

  SetTimer_(WindowID(0), 0, 5000, 0) 
  
  Repeat 
    Select WaitWindowEvent() 
      
      Case #PB_Event_CloseWindow 
        Break 
        
      Case #WM_TIMER 
        i = i+1
        Messagerequester(Str(i), "5 Sekunden sind um!") 
        
    
    EndSelect 
  ForEver 
EndIf 

KillTimer_(WindowID(0), 0)
tut nicht mehr was ich will
soll heißen, sobald ich eine Messagebox weggeklickt hab, kommt sofort die nächste (mit erhöhtem i) --> WM_TIMER wird zu oft aufgerufen, why?

Code4:

Code: Alles auswählen

Procedure MSGREQ()
    MessageRequester("Timer", "Die Zeit ist vorbei")
EndProcedure

ende = 0
hwnd = OpenWindow(0, 100, 100, 500, 500, "Timer")
SetTimer_(hWnd, 10, 5000, @MSGREQ())

Repeat
    event = WaitWindowEvent()
    Select event
        Case #PB_Event_CloseWindow
            Ende = 1
        Case #WM_TIMER 
        i=i+1
        MessageRequester(Str(i), "5 Sekunden sind um!") 
           
    EndSelect

Until ende = 1
KillTimer_(hWnd, 10)
ist eig. nur ne Spielerei, verhält sich trotzdem komisch in Meinen Augen...
---> es erscheint eine messagebox(von WM_TIMER)
klick ich sie weg, kommt sofort die nächste, nach 5 Sekunden kommt die richtige MSGBOX(@MSGREQ())
Frage: Wieso wird immer noch eine WM_TIMER message aufgerufen (bzw. so viele Timermessages)


Code 5:

Code: Alles auswählen

Procedure MSGREQ()
    MessageRequester("Timer", "Die Zeit ist vorbei")
EndProcedure

ende = 0
hwnd = OpenWindow(0, 100, 100, 500, 500, "Timer")
SetTimer_(hWnd, 10, 5000, @MSGREQ())

Repeat
    event = WaitWindowEvent()
    Select event
        Case #PB_Event_CloseWindow
            Ende = 1
        Case #WM_TIMER 
        Beep_(440, 500)
           
    EndSelect

Until ende = 1
KillTimer_(hWnd, 10)
bei Starten des Programms: 1 beep
nach 5 Sekunde MSGBOX (@MSGREQ())
nach wegklicken 2 Beeps
nach 5 Sekunde MSGBOX (@MSGREQ())
nach wegklicken 2 Beeps
usw...

Frage: wieso werden genau 2 Timermessages aufgerufen

I am confused :freak:
"oh... ein Sarkasmus-Detektor... ein wirklich nützliches Gerät" .. dit.. dit.. ditditdit.. *bumm*
Benutzeravatar
roherter
Beiträge: 1407
Registriert: 10.04.2005 18:58
Kontaktdaten:

Beitrag von roherter »

Auszug aus dem API-Guide zu SetTimer:

Code: Alles auswählen

· hWnd
Identifies the window to be associated with the timer. This window must be owned by the calling thread. If this parameter is NULL, no window is associated with the timer and the nIDEvent parameter is ignored.

· nIDEvent
Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this parameter is ignored.

· uElapse
Specifies the time-out value, in milliseconds.

· lpTimerFunc
Points to the function to be notified when the time-out value elapses. For more information about the function, see TimerProc.
If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application queue. The hwnd member of the message’s MSG structure contains the value of the hWnd parameter.
Leider in Englisch.

Das wichtigste ist der Letzte Punkt.

Points to the function to be notified when the time-out value elapses.

Soll heißen da wird die funktion aufgerufen zb. so:@timerproc()

Ich hoffe das hilft ein wenig.
Purebasic 5.0 32bit und 64 bit

I'm back from hell
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Außerdem hat die Timerproc einen bestimmten Aufbau:

Code: Alles auswählen

VOID CALLBACK TimerProc(
    HWND hwnd,
    UINT uMsg,
    UINT_PTR idEvent,
    DWORD dwTime
);
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Timerprocedure hat immer 4 Parameter, egal ob Du die Werte brauchst.
(siehe Posting von roherter)

Timerprocedure + #WM_TIMER im eventloop ist quatsch.

Mit Timerprocedure ist genauer als mit #WM_TIMER im Eventloop

Modale Dialoge, wie z.B. MessageRequester gehören nicht in eine
Timerprocedure.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
pede
Beiträge: 90
Registriert: 08.07.2007 20:37
Wohnort: brixen / Italien

Beitrag von pede »

Ich glaub ihr habt mich falsch verstanden...

Das Problem is nicht dass ichs nicht schaff das zu erreichen was ich brauch, sondern dass ich einfach ein paar Sachen nicht versteh...
Timerprocedure + #WM_TIMER im eventloop ist quatsch.
Auszug aus MSDN:
lpTimerFunc
[in] Pointer to the function to be notified when the time-out value elapses. For more information about the function, see TimerProc. If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application queue. The hwnd member of the message's MSG structure contains the value of the hWnd parameter.
Das heißt für mich, dass falls lpTimerFunc NICHT NULL ist, keine WM_TIMER message gesendet wird...
Modale Dialoge, wie z.B. MessageRequester gehören nicht in eine
Timerprocedure.
und wieso? dass es nicht funtkioniert seh ich ja, aber wieso das so ist nicht!

wieder MSDN:
Pointer to the function to be notified when the time-out value elapses
Wenn ich nicht irgendetwas genaueres wissen will, sobald eine Message gesendet wurde, brauch ich doch keine TimerProc mit den 4 Parametern.
"oh... ein Sarkasmus-Detektor... ein wirklich nützliches Gerät" .. dit.. dit.. ditditdit.. *bumm*
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

ts-soft hat geschrieben:Timerprocedure hat immer 4 Parameter, egal ob Du die Werte brauchst.
(siehe Posting von roherter).
Zufall. Außerdem bezog er sich auf den Befehl SetTimer_() nicht auf die lpTimerFunc Prozedur. Die Prozedur MSGREQ() enthält keinen einzigen Parameter.
Das heißt für mich, dass falls lpTimerFunc NICHT NULL ist, keine WM_TIMER message gesendet wird...
Nein. Wenn lpTimerFunc NULL ist wird es als Windows Message gesendet wenn ja dann wird das Timer Event explizit in einer seperaten Prozedur bearbeitet anstatt in einem generellen Fenster Callback.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

@pede
Der MessageRequester blockiert die Anwendung. Wie soll das funktionieren.

Die Timerproc ist ein Callback mit 4 parametern, Windows sendet nunmal 4
parameter, wenn Du sie nicht abholst, bleiben sie aufn Stack, bis das
Programm oder der Computer abstürzt.

@Fluid Byte
Weiß nicht was Du mir sagen möchtest?
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
pede
Beiträge: 90
Registriert: 08.07.2007 20:37
Wohnort: brixen / Italien

Beitrag von pede »

Der MessageRequester blockiert die Anwendung. Wie soll das funktionieren
aber nachdem die MessageReq. beendet wurde läuft die Anwendung doch normal weiter?
Ob der Timer angehalten wird oder nicht ist sogar auch egal, das erklärt nämlich immer noch nicht das auftreten der vielen messageboxen (siehe Code3...

auch dass die Procedure aufgerufen wird UND eine WM_TIMER Nachricht gesendet wird, kommt mir komisch vor... (siehe Code 4 + 5)

und dass bei Code5 genau 2x eine WM_TIMER Nachricht gesendet wird
ersetzt man das BEEP_() durch Messagerequester() so werden viele Nachrichten gesendet...

Wie gesagt, ich bekomm schon das hin was ich will, aber wieso sich die Funktion so komisch verhält leuchtet mir nicht ganz ein... :cry:
"oh... ein Sarkasmus-Detektor... ein wirklich nützliches Gerät" .. dit.. dit.. ditditdit.. *bumm*
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Ich kapier nicht wo dein Problem ist. Was ist hier dran auszusetzen:

Code: Alles auswählen

Procedure TimerProc(hwnd,uMsg,idEvent,dwTime)
	Static MsgInc
	
	MessageRequester("blah","blah #" + Str(MsgInc),64)
EndProcedure

OpenWindow(0,0,0,320,240,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)

SetTimer_(WindowID(0),0,2000,@TimerProc())

While WaitWindowEvent() ! 16 : Wend
Fertig ist die Laube!
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Die Nachrichten landen im Messagebuffer, wo Dein Programm sie
nacheinander abholt. Wenn das Timerereignis bereits 2x aufgetreten ist,
bevor es abgeholt wurde, dann kommts eben kurz hintereinander.
Timerereignisse haben unter Windows auch eine geringe Priorität, so das sie
auch mal wegbleiben. Wers genauer braucht sollte HighResTimer nutzen.
Aber auch dort gibts keine Garantien.

Verstehe also das Problem genauso wenig wie Fluid Byte
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten