Problem beim codegesteuerten Anzeigen von verschiedenen Bildern

  • Ich habe in der Menüzeile 2 Trigger, die mir nach Klick jeweils ein Bild (Bitmap) anzeigen. Ich beliebig zwischen den Bildern hin- und herwechseln. Ein 3. Button soll die beiden Bilder nun einmalig nacheinander anzeigen, mit einer kleinen Pause (TimerSleep) dazwischen. In der von Trigger 3 aufgerufenen Methode werden nacheinander die zu den Triggern 1 und 2 gehörenden Methoden aufgerufen. Ergebnis: Es erscheint immer nur das 2. Bild. Wenn ich die Pause vergrössere, erscheint das 2. Bild entsprechend verzögert. Wo liegt mein Denkfehler?

    Wilfried

  • Hallo!

    Ich würde auf einen Tippfehler im Code tippen (irgendwo wird das falsche Bild, bzw. der falsche Trigger aufgerufen).
    Sonst könnte man noch einen GrInvalRect, bzw. GrInvalRectDWord einbauen, nachdem das erste Bild geladen wurde...

    Jörg

    There are two rules in life:
    1. Never give out all of the information.

  • Ich habe an den Methoden, die einzeln vom zugehörigen Trigger aufgerufen werden, ja nichts verändert. Der Unterschied besteht nur darin, dass sie jetzt von einem Trigger nacheinander aufgerufen werden. Wenn ich den Aufruf der 2. Methode auskommentiere, dann erscheint das 1. Bild. Es scheint so zu sein, dass nur angezeigt wird, was zuletzt gezeichnet wird.

    Wilfried

  • @object GenTriggerClass Start = {
    GI_visMoniker = 'S', "Start";
    GTI_actionMsg = MSG_STARTE_UHR;
    GTI_destination = process;
    HINT_SEEK_MENU_BAR;
    }
    @object GenTriggerClass Bild1 = {
    GI_visMoniker = '1', "Bild1";
    GTI_actionMsg = MSG_BITMAP1_DRAW_TO_DYNAMIC_BITMAP;
    GTI_destination = process;
    HINT_SEEK_MENU_BAR;
    }
    @object GenTriggerClass Bild2 = {
    GI_visMoniker = '2', "Bild2";
    GTI_actionMsg = MSG_BITMAP2_DRAW_TO_DYNAMIC_BITMAP;
    GTI_destination = process;
    HINT_SEEK_MENU_BAR;
    }

    @method BitmapProcessClass, MSG_STARTE_UHR
    {
    @call self::MSG_BITMAP1_DRAW_TO_DYNAMIC_BITMAP();
    TimerSleep(100);
    @call self::MSG_BITMAP2_DRAW_TO_DYNAMIC_BITMAP();
    }
    @method BitmapProcessClass, MSG_BITMAP1_DRAW_TO_DYNAMIC_BITMAP
    {
    VMFileHandle vmfBitmap;
    VMBlockHandle vmbBitmap;
    GStateHandle gsBitmap;
    Bitmap *ptrDoggyBmp;

    @call Doggy::MSG_DOGGY_GET_HUGE_BITMAP_INFO(&vmfBitmap, &vmbBitmap, &gsBitmap);

    MemLock(OptrToHandle(@doggyBmp));
    ptrDoggyBmp = LMemDeref(@doggyBmp);
    GrClearBitmap(gsBitmap); //Ki
    GrDrawBitmap(gsBitmap, 5, 5, ptrDoggyBmp, 0);
    MemUnlock(OptrToHandle(@doggyBmp));

    GrDrawVLine(gsBitmap, 29, 29, (DOGGY_HEIGHT-10));

    @send Doggy::MSG_VIS_INVALIDATE();
    }
    @method BitmapProcessClass, MSG_BITMAP2_DRAW_TO_DYNAMIC_BITMAP
    {
    ...
    GrDrawHLine(gsBitmap, 29, 29, (DOGGY_WIDTH-10));
    ...
    }

    Klick auf Trigger Bild1->Bild1 erscheint, Klick auf Trigger Bild2-> Bild2 erscheint. Beliebig wiederholbar.
    Klick auf Trigger Start-> Bild 2 erscheint nach einer kleinen Pause.
    Tatsächlich sichtbar wird das Bild durch MSG_VIS_DRAW. Diese Methode sollte ja eigentlich durch @send Doggy::MSG_VIS_INVALIDATE() aufgerufen werden. Wenn ich mit Swat einen Stop in MSG_VIS_DRAW setze und dann im Einzelschrittmodus weitergehe, wird mir das bestätigt. Bei Klick auf Trigger Start erfolgt der Stop aber erst mit der 2. Methode.

    Wilfried

  • Hmmm... blockiert das MSG_STARTE_UHR vielleicht den UI-Thread?
    Kannst Du mal aus dem @send Doggy::MSG_VIS_INVALIDATE(); ein @call Doggy::MSG_VIS_INVALIDATE(); machen, damit "TimerSleep" erst dann startet, wenn das MSG_VIS_INVALIDATE durch ist?

    There are two rules in life:
    1. Never give out all of the information.

  • Versuch doch mal testweise, den Rumpf der Beide DRAW_ Handler in je eine Routine zu packen. Und dann rufst du in Start_uhr die routinen.
    Bauchschmerzen habe ich bei der Zeile @call Doggy::.......
    Es kann sein, dass sich hier Threads blockieren.
    Ich müsste noch mal in das Beispiel sehen, fand das aber damals nicht so toll.


    @method BitmapProcessClass, MSG_BITMAP1_DRAW_TO_DYNAMIC_BITMAP
    {
    DrawBitmap1(...);

    }
    @method BitmapProcessClass, MSG_STARTE_UHR{
    DrawBitmap1(...);
    TimerSleep(100);
    DrawBitmap2(...);

    }Gruß
    Rainer

    Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.

  • Also irgendwie so:

    //globale Variable:
    word timerid;

    //neue Methode
    @method BitmapProcessClass, MSG_STARTE_UHR
    {
    @call self::MSG_BITMAP1_DRAW_TO_DYNAMIC_BITMAP();
    TimerStart(TIMER_EVENT_ONE_SHOT, oself, 100, MSG_BITMAP2_DRAW_TO_DYNAMIC_BITMAP, 0, &timerid);
    }

    There are two rules in life:
    1. Never give out all of the information.

  • @Jörg,
    nein, vom "Prinzip" her muss es so gehen, wie Wilfried es will.

    Wilfried
    Ich erinnere mich, das sich meine ersten Gehversuche zum Thema Bitmap auch mit diesem Beipiel begonnen habe. Aber das Beispiel ist einfach nur grottig. Vielleicht ist es gut, wenn man Objektorientiert mit VisObjekten und (einfachen) Bitmaps arbeiten will.

    Ich häng mal was dran.
    1. eine modifizierte Doggy-Bitmap variante und 2. ein BMP-Game, das genau das macht, was du willst - aber natürlich viel komplexer ist.

    Gruß


    Rainer
    P.S.
    erstezt doch mal dein MSG_VIS_INVALIDATE durch
    @call Doggy::MSG_VIS_MARK_INVALID(VOF_GEOMETRY_INVALID | VOF_IMAGE_INVALID, VUM_NOW);

  • Hallo Rainer,

    zuerst mal vielen Dank für deine Mühe!

    Dein BMPGAMSR ist mir tatsächlich viel zu komplex, um es gleich zu verstehen, dein modifiziertes Doggy-Bitmap dagegen habe ich verstanden :) .

    Trotzdem wollte ich wissen, warum meine Version nicht wie gewünscht funktioniert. Ich habe mit Swat herausgefunden, dass @call Doggy::MSG_VIS_INVALIDATE erst zur Wirkung kommt, wenn alle Methoden abgeschlossen sind. Dann wird der letzte Stand der Bitmap angezeigt. Keine Ahnung, warum das so ist.

    In deiner Version bin ich auf @call Doggy::MSG_VIS_REDRAW_ENTIRE_OBJECT gestoßen und habe @call Doggy::MSG_VIS_INVALIDATE damit ersetzt. Und siehe da: Jetzt funktioniert meine Version wie gewünscht! :) :)


    Wilfried

    Ergänzung: MSG_VIS_MARK_INVALID(VOF_GEOMETRY_INVALID | VOF_IMAGE_INVALID, VUM_NOW) wirkt auch nicht.

  • Hallo Wilfried,
    ich hab keine Ahnung, warm deins nicht geht. Meine Vermutung ist, dass MSG_VIS_INVALIDATE nur das Objekt als "geändert" markiert, aber kein "visual update" (neuzeichnen) auslöst. Das passiert offensichtlich erst, wenn "alles fertig" ist. Der ganze Mechanismus ist so komplex, dass ich ihn konzeptionell nicht verstanden habe. Deswegen habe ich einfache Wege gesucht, Bitmaps darzustellen und schließlich auch gefunden.
    Wenn ich eine Uhr via Bitmap programmieren wollte, würde ich auf keinen Fall ein VisObject nehmen, sondern das VisContent selbst die Bitmap darstellen lassen, z.B. via MSG_VIS_REDRAW_ENTIRE_OBJECT. Damit vereinfachst du vieles.
    Gruß
    Rainer

    Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.