Seite 1 von 1

Benutzerhinweis anzeigen

Verfasst: 06.12.2006 01:13
von Tracker
Hi @ all!
Ich habe ein Problem, bei dem ich einfach nicht weiterkomme.
Ich würde bei meinem Programm gerne einen Benutzerhinweis "Bitte etwas Geduld..." anzeigen, während im Hintergrund Daten entpackt werden.
Der Benutzerhinweis soll das Entpacken aber nicht verlangsamen.
Ich habe das Forum und das Codearchiv durchforstet, aber leider kein passendes Beispiel gefunden.

Folgendes habe ich gescripted:

Code: Alles auswählen

;Benutzerhinweis anzeigen, während das Programm im Hintergrund weiterarbeitet
If OpenWindow(0, 200, 200, 300, 100, #PB_Window_BorderLess| #PB_Window_ScreenCentered,"")
   If CreateGadgetList(WindowID())
      TextGadget(1,0,30,300,20,"Daten werden entpackt!", #PB_Text_Center)
      TextGadget(2,0,50,300,20,"Bitte etwas Geduld ...", #PB_Text_Center)
   EndIf
  
   SetTimer_(WindowID(),1,100,0)  ;100 ms Wartezeit zum Gadgetaufbau
   Repeat 
      EventID = WindowEvent()
      If EventID = #WM_TIMER And EventwParam()=1  ;1=TimerID
         Quit=1
         KillTimer_(WindowID(),1)
      EndIf
      Until Quit=1

      ;Simulation der Entpackroutine (hier 10 Sekunden)
      Delay(10000)
      
      CloseWindow(0)
EndIf
End
Das funktioniert aber nicht richtig, weil der SplashScreen während der 10 Sekunden in denen ein Unterprogramm ablaufen soll keinen Refresh erhält.
Wenn man ein anderes Fenster darüberbewegt, verschwindet zuerst der Text und anschließend wird der komplette Fensterinhalt zerstört.

Kann mir bitte jemand erklären, wie ich mein Beispiel umschreiben muss, damit der Benutzerhinweis erhalten bleibt?

Verfasst: 06.12.2006 01:21
von mk-soft
Alle Proceduren die viel zeit benötigen in ein Thread starten. Achtung mehrfachstart verhindern.

Verfasst: 06.12.2006 01:30
von Tracker
Und wie müsste ich das tun, damit mein Benutzerhinweis nicht zerstört wird, wenn ich andere Fenster darüberbewege?
Mein Programm habe ich noch mit PureBasic 3.94 erstellt und ich kenne mich nicht besonders gut mit Window-Programmierung aus.

Verfasst: 06.12.2006 08:07
von ZeHa
Das mit den Threads mußt Du Dir so vorstellen, als würdest Du zwei separate Programme laufen haben, die sich gegenseitig nicht in die Quere kommen (okay, das kann schon passieren :mrgreen: aber darum geht's jetzt nicht).

Das heißt, Deine Loading- und Entpackfunktionen laufen in Thread 1 ab, dem Du eine hohe Priorität zuweist, weil die ja am wichtigsten sind. Dein Hinweis-Fenster kannst Du in einem 2. Thread anzeigen, und dort kannst Du auch ohne Probleme die Window-Events abfragen usw., wodurch sich das Fenster "ganz normal" anfühlt und nicht kaputt geht sobald sich ein anderes Fenster darüberschiebt.

Im Endeffekt laufen diese beiden Threads dann gleichzeitig, sodaß selbst während dem Entpacken Dein Fenster immer wieder refreshed wird. Das kannst Du natürlich auch erstmal mit Deinem 10-Sekunden-Delay testen.

Wie man Threads erstellt und startet, kannst Du in der Hilfe nachlesen.

Verfasst: 06.12.2006 08:28
von Morty
Moin,

also ich versuche bei sowas die Threads immer zu umgehen. Ich mache einfach eine Procedure, in der ein Fenster mit "Always on top" geöffnet wird. Und wenn die Berechnungen fertig sind schliesse ich das einfach wieder.

Skizze:

Code: Alles auswählen

procedure warten(mode.l)
  if mode=#true
    openwindow(...)
    ;und noch die Gadgets etc
  else
    closewindow(...)
  endif
endprocedure
Vorm Berechnen dann:

Code: Alles auswählen

warten(#true)
aufrufen, danach:

Code: Alles auswählen

warten(#false)
Man kann es auch soweit treiben, dass man auf das Fenster ein ProgressBarGadget setzt und dieses in seiner Berechnungsphase einfach mit aktuallisiert.

Gruss,
Morty

Verfasst: 06.12.2006 10:25
von Kaeru Gaman
@Morty

aber dann werden in deinem fenster keine events abgefragt,
und du hast ein unverschiebbares Sanduhren-Heim auf dem desktop rumliegen.

die sicherheits von Threads ist in PB4 wesentlich verbessert worden.
es gibt nun keinen grund mehr, vor ihnen zurückzuschrecken.

Trau Dich! *Fishermen's rüberrreich*

Verfasst: 06.12.2006 10:43
von Morty
@Kaeru Gaman
Danke für die Fishermens.

Kam vllt. etwas falsch rüber, aber ich benutze durchaus auch Threads. Ich wollte hier nur eine andere Methode zeigen, wie man's auch machen könnte...aber nicht muss.
Das meine Variante ein paar Nachteile hat (keine Events, etc.) ist leider so, aber für so eine 10-12 sekündiges Warten ist es denke ich ausreichend.

Ansonsten kann ich meinen Vorredner nur zustimmen, versuch Dich ein bissl an Threads und setze diese bei längeren Berechnungen (usw.) ein.

Gruss, Morty

Ach ja, und allen einen frohen Niklaus (wer drauf steht :wink: )

Verfasst: 06.12.2006 21:55
von Tracker
Vielen Dank für eure Tipps!
Die Verwendung eines eigenen Threads für den Benutzerhinweis hat mein Problem gelöst.
Jetzt wird der SplashScreen mit dem Benutzerhinweis nicht mehr zerstört.
Auch die CPU wird laut Taskmanager kaum beansprucht.
Das stark vereinfachte Beispiel funktioniert bereits ab Windows 95A.

Code: Alles auswählen

;Entpackvorgang starten und gleichzeitig Benutzerhinweis in einem anderen Thread anzeigen
Procedure BenutzerhinweisAnzeigen(interval.l)
   If OpenWindow(0, 200, 200, 300, 100, #PB_Window_BorderLess| #PB_Window_ScreenCentered,"")
      If CreateGadgetList(WindowID())
         TextGadget(1,0,30,300,20,"Daten werden entpackt!", #PB_Text_Center)
          TextGadget(2,0,50,300,20,"Bitte etwas Geduld ...", #PB_Text_Center)
      EndIf
  
      While(1)
         EventID = WaitWindowEvent()
      Wend
      
      CloseWindow(0)
   EndIf
EndProcedure

If OpenConsole()
   ThreadId.l = CreateThread(@BenutzerhinweisAnzeigen(), 1)
   If ThreadId
      ;Simulation von 5 Sekunden Hintergrundarbeiten 
      Print("Entpackroutine starten ...")
      Delay(5000)
      KillThread(ThreadId)
   EndIf
EndIf
End
Wenn ich mir überlege, wie lange ich mich erfolglos damit herumgeärgert habe.
Einfach unglaublich!
Ich hätte gleich im Forum nachfragen sollen.
Vielen Dank nochmal! :allright: