Seite 1 von 2

Timer Problem

Verfasst: 14.08.2007 15:45
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:

Verfasst: 14.08.2007 17:07
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.

Verfasst: 14.08.2007 17:13
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
);

Verfasst: 14.08.2007 17:15
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.

Verfasst: 14.08.2007 18:16
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.

Verfasst: 14.08.2007 18:20
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.

Verfasst: 14.08.2007 18:25
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?

Verfasst: 14.08.2007 22:06
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:

Verfasst: 14.08.2007 22:39
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!

Verfasst: 14.08.2007 22:46
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