SetTimer funktioniert nur einmal - warum?

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Olaf.Renns
Beiträge: 27
Registriert: 26.02.2009 10:11

SetTimer funktioniert nur einmal - warum?

Beitrag von Olaf.Renns »

Hallo,

nach nun etlichen Tools mit PureBasic habe ich nun leider ein kleines Problem, das ich nicht lösen kann, obwohl es sehr einfach erscheint. Bestimmt stehe ich nur wieder auf dem Schlauch. Hier als mein Problem. Ich hab den Code aufs nötige reduziert:

Code: Alles auswählen

#MessageBox_Timeout = -1 
  
Global g_hwndTimedOwner 
Global g_bTimedOut 

Procedure MessageBoxTimer(hwnd, uiMsg, idEvent, dwTime) 
  g_bTimedOut = #True 
  If g_hwndTimedOwner 
    EnableWindow_(g_hwndTimedOwner, #True) 
  EndIf 
  PostQuitMessage_(0) 
EndProcedure 

Procedure TimedMessageBox(hwndOwner, pszMessage.s, pszTitle.s, flags, dwTimeout) 
  Protected idTimer.l, iResult.l 
  g_hwndTimedOwner = #Null 
  g_bTimedOut = #False 
  If hwndOwner And IsWindowEnabled_(hwndOwner) 
    g_hwndTimedOwner = hwndOwner 
  EndIf 
  idTimer.l = SetTimer_(#Null, 0, dwTimeout, @MessageBoxTimer()) 
  iResult.l = MessageBox_(hwndOwner, pszMessage, pszTitle, flags) 
  KillTimer_(#Null, idTimer) 
  If g_bTimedOut 
    PeekMessage_(@msg.MSG, #Null, #WM_QUIT, #WM_QUIT, #PM_REMOVE) 
    iResult = #MessageBox_Timeout 
  EndIf
  ProcedureReturn iResult 
EndProcedure 

Repeat
  uiResult = TimedMessageBox(#Null, "Test", "Test", #MB_OK+#MB_ICONSTOP, 5000)
ForEver
Das Problem ist, das die getimte Messagebox nur einmal erscheint, wenn man die Zeit ablaufen lässt. Danach poppt keine Nachricht mehr auf. Wenn man die Messagebox in der angegebenen Zeit mit "Ok" bestätigt, dann erscheint diese aufgrund der forever-Schleife auch sofort wieder wie es soll. Kann vielleicht jemand helfen?

Edit: Achja, der Grund-Code ist nicht von mir!
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Re: SetTimer funktioniert nur einmal - warum?

Beitrag von edel »

Bei mir scheint es so zu laufen wie es soll, poste doch mal dein OS und PB Version.
Olaf.Renns
Beiträge: 27
Registriert: 26.02.2009 10:11

Re: SetTimer funktioniert nur einmal - warum?

Beitrag von Olaf.Renns »

Hallo edel,

also Version ist 4.30 und OS ist Vista Ultimate und Vista Professional. Bei beiden der gleiche Effekt.
dag
Beiträge: 12
Registriert: 16.06.2009 15:01

Re: SetTimer funktioniert nur einmal - warum?

Beitrag von dag »

Auch wenn das Problem schon ein paar Jahre auf dem Buckel hat...

Ich hatte das gleiche Problem, nach dem Aufruf der TimedMessageboxen waren keine weiteren Boxen, auch Normale vom PB, mehr möglich. Auf msdn wurde berichtet, das die Funktion PostQuitMessage(0) zu zuerst unbemerkten Fehlern führt.
Aber das war noch nicht alles, eine Bemerkung im Kommentarbereich von Timerproc Callback Function brachte mich auf die Spur: TimerProc darf nicht mit hwnd = #Null aufgerufen werden. (Undokumentierter Fehler).

Und genau das Passiert, wenn TimedMessageBox(#Null, ...) und der g_hwndTimedOwner = #Null steht.

Code: Alles auswählen

 
  g_hwndTimedOwner = #Null
  g_bTimedOut = #False
  If hwndOwner And IsWindowEnabled_(hwndOwner)
    g_hwndTimedOwner = hwndOwner
  EndIf 
und

Code: Alles auswählen

Repeat
  uiResult = TimedMessageBox(#Null, "Test", "Test", #MB_OK+#MB_ICONSTOP, 5000)
ForEver
Ich hab also vorher ein Openwindow(0) und dann die TimedMessageBox(WindowID(0),...) aufgerufen. damit wird der g_hwndTimedOwner auch "Not #Null". Dazu den TimerProc mit hwndOwner aufgerufen. PostQuitMessage_ hab ich mit PostMessage_(iResult,#WM_Quit,0,0) ausgetauscht, da ich ja das iResult (=MessageBox) Schliessen will und PostQuitMessage(0) geht immer nur auf Thread und das ist very Bad :)

jetzt sieht der code so aus:

Code: Alles auswählen

Procedure TimedMessageBox(hwndOwner, pszMessage.s, pszTitle.s, flags, dwTimeout)
  Global g_hwndTimedOwner, iResult.l
  Global g_bTimedout, msg.MSG
  Protected idTimer.l, 
  g_hwndTimedOwner = #Null
  g_bTimedout = #False
  If hwndOwner And IsWindowEnabled_(hwndOwner)
    g_hwndTimedOwner = hwndOwner
  EndIf
  idTimer.l = SetTimer_(#Null, 0, dwTimeout, @MessageBoxTimer())
  iResult.l = MessageBox_(hwndOwner, pszMessage, pszTitle, flags)
  KillTimer_(#Null, idTimer)
  If g_bTimedout
    PeekMessage_(@msg.MSG, #Null, #WM_QUIT, #WM_QUIT, #PM_REMOVE)
  EndIf
EndProcedure
Procedure MessageBoxTimer(hwndOwner, uiMsg, idEvent, dwTime)
  g_bTimedout = #True
  PostMessage_(iResult,#WM_QUIT,0,0)
EndProcedure

If OpenWindow(0,0,0,500,250,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
    TimedMessageBox(WindowID(0), "Die erste Nachricht ..geht auch alleine zu", "Das erste",0, 1000)
    MessageRequester("huhu","nur mal test")
EndIf

Bild
Antworten