Sven's CA-Visual Objects - Seite

23.11.2012

eMail

eMail

Übersicht | Vorheriger | Nächster

Dispatcher für Control's und Window's:

Beim Schreiben eigener Dispatch()-Methoden ist folgendes zu beachten:

Es sind zwei verschiedene Arten von Dispatchern zu unterscheiden.
Alle Klassen die von der Klasse Control erben
und alle Klassen die von der Klasse Window erben.
Die Unterschiede beschränken sich auf die Behandlung der Rückgabewerte an Windows.

  1. Dispatcher der Basisklasse Control:
    1. Nach der eigenen Event-Behandlung soll der original-Dispatcher (die original WindowProcedure) des Control's ausgeführt werden.
      In diesem Fall kann man entweder RETURN SUPER:Dispatch(oEvent) aufrufen oder man beendet die Methode Dispatch() mit der Anweisung RETURN 0L, wenn klar ist, dass ein Aufruf von RETURN SUPER:Dispatch(oEvent) unnötig ist. Wird RETURN SUPER:Dispatch(oEvent) verwendet, ist darauf zu achten, das SELF:EventReturnValue entweder nicht zugewiesen wird oder auf den Wert 0l gesetzt wird.
    2. Nach der eigenenen Event-Behandlung ist diese vollständig abgeschlossen und es soll ein Rückgabewert an Windows übergeben werden.
      Der RückgabeWert wird in der EXPORT Variable SELF:EventReturnValue gespeichert und die Methode Dispatch() wird mit der Anweisung RETURN 1L verlassen.

    Ein Hinweis zu den Standard-Control Eventhändlern, wie Control:Expose(), Control:Resize() etc. . Wird in diesen Methoden der SELF:EventReturnValue nicht zugewiesen oder auf einen Wert von 0l gesetzt, so wird am Ende dieser Methoden immer noch einmal der Standard Eventhandler (die original WindowProcedure) des Control's aufgerufen. Wird hingegen SELF:EventReturnValue auf z.B. 1l (bzw. ungleich 0l) gesetzt, so wird der Standard Eventhandler (die original WindowProcedure) des Control's nicht mehr aufgerufen, allerdings wird dann dieser Wert 1l aus SELF:EventReturnValue an Windows als Rückgabewert übergeben, was leider für Windows in den allermeisten Fällen bedeutet, dass der Event nicht verarbeitet wurde (- was ja nun eigentlich nicht stimmt -). Wenn man von diesem Verhalten abweichen will oder muss, so muss man auf jeden Fall einen eigenen Dispatcher schreiben, der die entsprechende Event-Message direkt verarbeitet. Im Falle von Expose ist die z.B. die Nachricht (Message) WM_PAINT.

  2. Dispatcher der Basisklasse Window:

    Hier sind zwei Fensterarten zu unterscheiden:

    1. DialogWindows. Dies sind die Klassen DialogWindow und alle Klassen die von DialogWindow erben, wie: ModelessDialog, __DDIMP und __FormDialogWindow (das Surface eines DataWindows). Bei diesen Windows wird die Methode Dispatch nicht von der Fensterprozedur (WindowProcedure) aufgerufen, sondern von der DialogProcedure des DialogWindows. Das bedeutet, dass der Wert der über RETURN der Dispatch-Methode zurückgegeben wird eine Rückmeldung für die DialogProcedure ist, während der Wert von SELF:EventReturnValue immer an die Fensterprozedur (WindowProcedure) über die Anweisung SetWindowLong(hwnd, DWL_MSGRESULT, oDialogWindow:EventReturnValue) übergeben wird. Daraus ergibt sich folgendes:
      1. Nach der eigenen Event-Behandlung soll der original-Dispatcher (die original WindowProcedure) des Control's ausgeführt werden.
        In diesem Fall kann man entweder RETURN SUPER:Dispatch(oEvent) aufrufen oder man beendet die Methode Dispatch() mit der Anweisung RETURN 0L, wenn klar ist, dass ein Aufruf von RETURN SUPER:Dispatch(oEvent) unnötig ist.
      2. Nach der eigenenen Event-Behandlung ist diese vollständig abgeschlossen und es soll ein Rückgabewert an Windows übergeben werden.
        Der RückgabeWert wird in der EXPORT Variable SELF:EventReturnValue gespeichert und die Methode Dispatch() wird mit der Anweisung RETURN 1L verlassen.

       

    2. Alle anderen Windows wie, ShellWindow, TopAppWindow, __DocApp (MDIClientWindow) und __WndApp. __DocApp und  __WndApp sind Hilfsklassen der Klasse ChildAppWindow. Ihre Events landen normalerweise in diesem ChildAppWindow.
      1. Nach der eigenen Event-Behandlung soll der original-Dispatcher (die original WindowProcedure) des Control's ausgeführt werden.
        In diesem Fall kann man entweder RETURN SUPER:Dispatch(oEvent) aufrufen oder man beendet die Methode Dispatch() mit der Anweisung SELF:Default(oEvent) gefolgt von der Anweisung RETURN SELF:EventReturnValue, wenn klar ist, dass ein Aufruf von RETURN SUPER:Dispatch(oEvent) unnötig ist.
      2. Nach der eigenenen Event-Behandlung ist diese vollständig abgeschlossen und es soll ein Rückgabewert an Windows übergeben werden.
        Der RückgabeWert wird in der EXPORT Variable SELF:EventReturnValue gespeichert und die Methode Dispatch() wird mit der Anweisung RETURN SELF:EventReturnValue verlassen oder man übergibt die ReturnWert direkt über RETURN ReturnValue an Windows.
      3. Vor der eigenen Event-Behandlung soll der original-Dispatcher (die original WindowProcedure) des Control's ausgeführt werden.
        In diesem Fall wird zuerst SELF:Default(oEvent) aufgerufen. Der Standard RückgabeWert ist dann nach dem Aufruf in der EXPORT Variablen SELF:EventReturnValue gespeichert. Dann folgt die eigenene Event-Behandlung. Diese wird dann mit RETURN SELF:EventReturnValue abgeschlossen. Soll ein anderer als der Standard RückgabeWert an Windows übergeben werden, so ist SELF:EventReturnValue vorher entsprechen zu setzen.

Generell ist noch folgendes für die Parameter Behandlung von Dispatch wichtig. Da der Parameter oEvent immer vom Typ USUAL, ist muss unbedingt dieser Wert einer typisierten LOCAL Variablen zugewiesen werden um unerwünschte Typkonvertierungen zu vermeiden, die dadurch entstehen, dass die Event-Instance-Variablen dann LateBound über IVARGET() bzw. SEND() abgefragt werden und die Ergebnisse erst einmal USUAL sind. Eine Dispatch Methode sollte also immer folgendermaßen beginnen:

METHOD Dispatch( uEvent ) CLASS MyControl
   LOCAL oEvent := uEvent AS Event

Das Gleiche gilt übrigens für jede Art von Methode, die als Parameter eine Event-Klasse übergeben bekommt.

METHOD Expose( uExposeEvent ) CLASS MyControl
   LOCAL oExposeEvent := uExposeEvent AS ExposeEvent

 

Home | Kontakt | Impressum | ©2012 Ingenieur-Büro Dipl. Ing. Sven Ebert