Allgemeines zur Message-Queue unter Windows
Windows setzt jede Aktion des Benutzers in eine Nachricht um
und speichert diese in einer Nachrichtenwarteschlange
Jede Anwendung muß diese Nachrichtenwarteschlange zyklisch
abfragen.
Windows ermittelt für jede Nachricht den zugehörigen Empfänger in
Abhängigkeit von der Sichtbarkeit.
Wird von einem Programm ein Fenster erstellt, so wird für
dieses von Windows eine Message-Queue (Nachrichtenwarteschlange) angelegt.
Das ist eine Speicherstruktur ähnlich einer Liste von Arbeitsschritten.
In diese Liste werden alle das Fenster und seine Unterfenster betreffenden auftretenden
Ereignisse, wie z.B. Mausveränderungen (Position, Bewegungen, Clicks, ...),
Fensterveränderungen (Ort, Größe, Position, ...) u.v.a. eingefügt.
Was ganz vorne steht, kann als nächstes vom WindowCallback
verarbeitet werden, der Rest wartet bis er ganz vorne auf der Liste ist.
Dabei werden die Ereignisse aber nicht einfach nur ‚hinten angefügt’, sondern
aufgrund verschiedener Prioritäten teilweise bevorzugt behandelt.
Zudem gibt es noch Echtzeit-Ereignisse, die rennen gleich an
der ganzen Schlange vorbei und regeln ganz vorne ihre Angelegenheit bis sie
fertig sind, während die anderen warten.
Event handling
Es gibt zwei Funktionen, mit welchen ein Ereignis abgefragt werden kann.
Diese sind WindowEvent und WaitEvent, wobei der einzige Unterschied
darin besteht, das WaitEvent darauf wartet bis etwas geschieht und
erst dann einen Wert ausgibt, während WindowEvent
bei jedem Aufruf entweder das Event, oder solange nichts passiert ist,
den Wert '0' zurück gibt.
WindowEvent sollte vermieden werden, da das
Programm auch wenn es nicht benutzt wird die CPU stark belastet.
Do 'warte auf "Fenster schließen"
Loop Until WaitEvent = EventClose
Vom Programm aus muss immer wieder überprüft werden, ob in
der Message-Queue neue Anweisungen für das Fenster vorliegen, so dass darauf
entsprechend reagiert werden kann.
Dies geschieht unter Windows normalerweise über eine
Callback-Prozedur (eine von außen meist häufig wiederkehrend aufgerufene
Prozedur). Dem WindowCallback.
Windows9 bietet da aber zusätzlich mit WaitEvent und WindowEvent zwei bequeme Alternativen.
Diese beiden Funktionen verwalten intern den
WindowCallback eigenständig und kümmern sich dabei um einen Teil der Ereignisse selbst.
Nach ‚Außen’ - als Rückgabewert an das
Programm - schicken sie nur solche Ereignisse, die in den meisten Fällen vom
Programmierer behandelt werden wollen (spezielle Ereignisse werden also von WindowEvent
nicht an das Programm weitergegeben, z.B. für diese muss ein eigener WindowCallback verwendet
werden.).
Dies erlaubt dem Programmierer sofortige Konzentration auf die
individuellen Nutzereingaben über Menüs, Gadgets, etc., lässt sich aber trotzdem
mit Wissen der Message-Konstanten und/oder einem eigenen Window-Callback beliebig erweitern.
Timer
Eine Möglichkeit regelmäßig wiederkehrende Aufgaben zu erledigen sind Timer.
Hier ein Beispiel zur Anzeige der Uhrzeit, die über einen Timer jede Sekunde erneuert wird.
#Include Once "window9.bi"
Var hwnd = OpenWindow("Nr. 4b",30,30,300,150) 'Fenster erstellen
TextGadget(11,50,20,200,55,Time,SS_CENTER Or SS_SUNKEN) 'Textfeld
SetGadgetFont(11,Cast(Integer,LoadFont("arial",36))) 'große Zahlen
Dim As Integer Timer1
SetTimer(hwnd, Timer1, 1000, NULL) 'Timer initialisieren
Do
Var event=WindowEvent()
If event=EventClose Then 'Fenster geschlossen?
KillTimer(hwnd, Timer1) 'Timer löschen
End
EndIf
If event=EventTimer Then 'Timer Ereignis?
SetGadgetText(11,Time) 'dann neu schreiben
EndIf
Loop
|
|
In diesem Beispiel wird der Timer einmal pro Sekunde, solange das Fenster aktiv ist, aufgerufen.
Sobald der Timer abgelaufen ist liefert WindowEvent einen Rückgabewert vom Typ EventTimer.
Der Timer wird nun erneut mit dem Wert von 1000ms gestartet bis er durch KillTimer beendet wird.
EventGadget
Um mehrere verschiedene Gadgets benutzen zu können benötigt man den EventGadget().
Sollte man wie es in größeren Programmen üblich ist mehrere Gadgets auf
einem Fenster haben bietet es sich an diese auch über ein Select / Case zu verwalten.
#Include Once "window9.bi"
Var hwnd = OpenWindow("Nr. 3",30,30,480,320,WS_VISIBLE Or WS_SYSMENU)
WindowColor(hwnd, BGR(200,200,200))
CenterWindow(hwnd)
ButtonGadget(1,30,250,100,20,"&Hilfe")
ButtonGadget(2,190,250,100,20,"&Info")
ButtonGadget(3,350,250,100,20,"&Ende")
Do
Var event=WindowEvent()
If event=EventClose Then End
If event=EventGadget Then
Select Case EventNumber
Case 1 : MessBox("Hilfe","Dies ist die Hilfe!")
Case 2 : MessBox("Info", "Dies ist ein Info!")
Case 3 : MessBox("Ende", "Dies ist das Ende!") : End
End Select
EndIf
Loop |
|
EventPaint
Wird das Fenster verschoben, überdeckt oder der Zeichenbereich sonst gestört, muß es neu
gezeichnet werden. Genau das wird durch EvenPaint ausgelöst.
#Include Once "window9.bi"
Var hwnd=OpenWindow("Nr. 5",100,100,300,300)
CenterWindow(hwnd)
Do
Var event=WindowEvent()
If event=EventClose Then End
If event=EventPaint Then
WindowStartDraw(hwnd)
'LineDraw (Startpunkt x, y, Endpunkt x, y,Strichstärke,Farbe,Style)
LineDraw(65, 65,200,200,10,&h0000ff)
LineDraw(65,200,200, 65,10,&hff0000)
StopDraw
EndIf
Loop |
|
alle Events
Auf dieser Übersicht finden sich alle Events, die in Window9 mit WaitEvent abgefangen
werden können.
Bezeichnung |
ID |
EventSize |
&h005 |
EventActivate |
&h006 |
EventPaint |
&h00F |
EventClose |
&h010 |
EventKeyDown |
&h100 |
EventKeyUp |
&h101 |
EventTimer |
&h113 |
EventMouseMove |
&h200 |
EventLBDown |
&h201 |
EventLBUp |
&h202 |
EventRBDown |
&h204 |
EventRBUp |
&h205 |
EventMBDown |
&h207 |
EventMBUp |
&h208 |
EventMouseWheel |
&h20A |
EventGadget |
&h401 |
EventMenu |
&h402 |