Bild-Viewer Probleme



  • Kannst das ja mal etwas genauer sagen!? 😕

    Koennte interessant werden 🙂



  • Jau, das wär mal interessant, @WebFritzi. Soll man das Bild in ein .dib umwandeln? Da müßte man sicher den passenden Filter organisieren? Aber KA. Hab manchmal den Eindruck, daß einige Spiele so ein offscreen-format nutzen. Screenshot geling, aber es ist nicht brauchbar. Total dunkel, da geht auch mit Gamma-Korrektur nix.

    @DerAltenburger, ich hab deine Idee noch nicht wirklich verstanden. Wenn ich von dem gestretchten FImage ins gleichgroße FPaint drawe, erwarte ich, daß es in Originalgröße angezeigt wird, der Rest im FPaint wird mit der Default-Brush gefüllt. Hab es aber noch nicht probiert.

    Kompliziert würde es aber ggf. ohnehin. Beim Copy/Paste wird ja noch ein Image eingesetzt. Die Auswahl ist dann verschiebbar. Und das alles mit einer Klassenkompo organisieren? ... Bin ohnehin noch nicht aktiv dran. Ich kann zwar nicht alle Schritte vorplanen, dazu fehlt noch total die Erfahrung. Aber zumindest die Grundplanung muß Hand und Fuß haben...



  • Hi Omega

    Der Trick ist: das Bild aus FImage wird mit StretchDraw in FPaint gebracht.
    Dabei wird die Groesse dauerhaft angepasst. FPaint kann dann 1:1 angezeigt werden!!! FPaint enthaelt auch nicht unbeding das ganze Bild (Braucht ja nur soviel, wie Scrollbox zeigen kann. Das Timingproblem beim malen giebt's ja nur, wenn TImage, in der gemalt wird, nicht Originalgroesse zeigt. Ist ja auch nur beim Malen mit der Maus.

    ich poste mal 'n Stueck Code fuer die Klasse TImagePaintScroller
    (2. Variante!!!):

    //Ergaenzung fuer Headerdatei
    //Klasse zum Anzeigen von Bildern und Zeichnen in einer Scrollbox
    //mit separater Skizzierflaeche
    class PACKAGE TImagePaintScroller2 : public TImagePaintScroller
    {
    private:
    protected:
      TImage *FPaint;                            //separate Zeichenfläche
    DYNAMIC void __fastcall MouseDown(TMouseButton Button, Classes::TShiftState Shift, int X, int Y);
    DYNAMIC void __fastcall MouseUp(TMouseButton Button, Classes::TShiftState Shift, int X, int Y);
    DYNAMIC void __fastcall MouseMove(Classes::TShiftState Shift, int X, int Y);
    public:
                   __fastcall TImagePaintScroller2(TComponent* Owner);
                   __fastcall ~TImagePaintScroller2(void);
    __published:
    };
    //Ergaenzung fuer Headerdatei Ende
    
    //Ergaenzung fuer Unitdatei
    // ValidCtrCheck wird benutzt, um sicherzustellen, daß die erzeugten Komponenten keine
    // rein virtuellen Funktionen haben.
    static inline void ValidCtrCheck(TImagePaintScroller2 *)
    {
            new TImagePaintScroller2(NULL);
    }
    //Constructor fuer ImageScrollbox2
    //---------------------------------------------------------------------------
    __fastcall TImagePaintScroller2::TImagePaintScroller2(TComponent* Owner)
             : TImagePaintScroller(Owner)
    { FPaint=new TImage(this);                   //Bildanzeige erzeugen
      FPaint->Parent=this;                       //sonst keine Anzeige!!!
      FPaint->Visible=false;                     //soll Anzeige nicht verdecken
      FPaint->Stretch=true;
      FPaint->AutoSize=false;
      FPaint->Align=alNone;//Client;
    }
    //---------------------------------------------------------------------------
    //Destructor fuer ImageScrollbox2
    __fastcall TImagePaintScroller2::~TImagePaintScroller2(void)
    { delete FPaint;
    }
    //---------------------------------------------------------------------------
    void __fastcall TImagePaintScroller2::MouseDown(TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
    {
      TImagePaintScroller::MouseDown(Button,Shift,X,Y);
      if (Button==mbLeft)
      {
        FPaint->Width=FImage->Width;
        FPaint->Height=FImage->Height;
        FPaint->Top=FImage->Top;
        FPaint->Left=FImage->Left;
        FPaint->Picture->Bitmap->Width=FPaint->Width;
        FPaint->Picture->Bitmap->Height=FPaint->Height;
        FPaint->Canvas->Brush->Style=bsSolid;
        FPaint->Canvas->Brush->Color=clWhite;
        FPaint->Canvas->FillRect(Rect(0,0,FPaint->Width,FPaint->Height));
    //  Hier Bild in richtiger Groesse aus FImage einpassen!!!
        FPaint->Canvas->StretchDraw(FPaint->ClientRect,FImage->Picture->Graphic);
        FPaint->Visible=true;
        FImage->Visible=false;
      }
    }
    //---------------------------------------------------------------------------
    void __fastcall TImagePaintScroller2::MouseUp(TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
    { TImagePaintScroller::MouseUp(Button,Shift,X,Y);
      if (Button==mbLeft)
      {
        FImage->Visible=true;
        FPaint->Visible=false;
      }
    }
    //---------------------------------------------------------------------------
    void __fastcall TImagePaintScroller2::MouseMove(Classes::TShiftState Shift, int X, int Y)
    {
      FPaint->Canvas->MoveTo(float(PenPos.x) * Dimension->ImageZoom,float(PenPos.y) * Dimension->ImageZoom);
      TImagePaintScroller::MouseMove(Shift,X,Y);
      if (FPenDown)
      {
        FPaint->Canvas->LineTo(X+HorzScrollBar->Position,Y+VertScrollBar->Position);
      }
    }
    //Ergaenzung fuer Unitdatei Ende
    

    😉 bringt aber nur was, wenn im Haupprogramm die neue Klasse benutzt wird :p 😃

    Das mit dem Planen ist wichtig: nicht ueberstuertzen, was in 'ner Komponente drin ist, wird immer weitervererbt. Das wird man schwer los!!!
    Es muss / sollte auch nicht alles da rein!

    Aber: Du kannst in eine (neue) Komponente beliige andere einbauen (dynamisch). 😉 😕

    [ Dieser Beitrag wurde am 28.02.2003 um 20:10 Uhr von DerAltenburger editiert. ]



  • Ah ja. FillRect für ein neues Bild, nicht nur für FPaint. Hier braucht FImage bereits 2 Wege - oder BildLaden überschreibt einfach das FillRect. FPaint bezieht die Skrollbalken mit ein. Da bin ich jetzt auf die Praxis gespannt. Den Code werd ich in Ruhe einbauen, nicht nur abschreiben. Übersicht gewinnen/behalten ist das wichtigste. Ich schau auch immer wieder den Urcode durch. Steht noch nicht viel drin, und trotzdem... (1/4 Jahr Turbo C++, fast nur Resourcen-Workshop, 1/2 Jahr BCB3, 4 Jahre andere Bereiche, nichts "höheres" als HTML, seit ein paar Wochen wieder am Ball... also im Prinzip noch ein sehr früher Zeitpunkt, um in den Klassenkampf einzusteigen. Aber der Forderfaktor macht Spaß. 😉 )

    Ich hab hier allerdings schon eine Situation, die den Klassenbereich deutlich sprengen dürfte. MouseDown --> MouseUp im Image verwalten doch schon einiges an externen Aufgaben. Das gehört nicht in eine Klasse. Eine Klasse soll einbindbar sein, ohne daß in der App etwas besonders eingerichtet sein muß. Bereits die Notwendigkeit, bestimmte Objecte/ObjectNamen verwenden zu müssen, halte ich für nicht gut.

    Also ganz nette Überlegungen. Ob ich bei einem derart zentralen Teil nicht doch besser eine Kompo bau? Dann kann ich auch die Events verknüpfen usw. Ich glaub, ich soll mal ein Beispiel bringen, damit die Aufgabenstellungen deutlicher werden. Hier ist das Malen im Code nicht mehr geragt, das ist Anwendungsprogrammierung für den praktischen Einsatz.

    void __fastcall TPixi::ImageMouseMove(TObject *Sender,
                TShiftState Shift, int X, int Y)
    { 
        if (NewDlg->Visible == false)
            Edit1->SetFocus();
        if (MarkBase->Visible)
        {
            Screen->Cursor = crCross;
            Drawing = false;
        }
        if(Drawing)
        {
            Image->Canvas->Pen->Mode = pmNotXor;        // XOR-Modus zum Zeichnen/Löschen verwenden.
            Image->Canvas->MoveTo(Origin.x, Origin.y);  // Stift auf Ausgangspunkt zurücksetzen.
            if (MarkBtn->Down)
                MarkImageMouseMove(Sender,Shift,X,Y);
            else if (ClearBtn->Down)
                PenBmpMouseMove(Sender,Shift,X,Y);
            else if (LineBtn->Down)
                LineBmpMouseMove(Sender,Shift,X,Y);
            else if (CircleBtn->Down || FillCircleBtn->Down)
                CircleImageMouseMove(Sender,Shift,X,Y);
            else if (RoundRectBtn->Down || FillRoundRectBtn->Down)
                RoundRectBmpMouseMove(Sender,Shift,X,Y);
            else if (PenBtn->Down)
                PenBmpMouseMove(Sender,Shift,X,Y);
            else if (FillRectBtn->Down || RectBtn->Down)
                RectImageMouseMove(Sender,Shift,X,Y);
            MovePt = Point(X,Y);
            Image->Canvas->Pen->Mode = pmCopy;
     }
     status = 2;
     //StatusImageMouseMove(Sender,Shift,X,Y);
    }
    

    Also auch die Statusanzeige ist betroffen. Ins MouseUp ist dann noch der Wechsel des Screen->Sursor bei Verwendung der Pipette geregelt. Insgesamt wird der Klassenrahmen IMHO deutlich gesprengt. Das ist es, was mir momentan die größte Sorge bereitet. Vielleicht geht eine Schnittstellenregelung. Das bedeutet aber, daß beim Einbinden der Klasse in der App eine bestimmte Function je Maus-Event vorhanden sein muß...



  • Original erstellt von <Omega-X>:
    Das gehört nicht in eine Klasse. Eine Klasse soll einbindbar sein, ohne daß in der App etwas besonders eingerichtet sein muß. Bereits die Notwendigkeit, bestimmte Objecte/ObjectNamen verwenden zu müssen, halte ich für nicht gut. Also ganz nette Überlegungen. Ob ich bei einem derart zentralen Teil nicht doch besser eine Kompo bau?

    Eine Komponente ist eine Klasse!

    P.S.: Dein Beitrag liest sich wie ein Tagebuch-Eintrag. 😃

    [ Dieser Beitrag wurde am 01.03.2003 um 00:32 Uhr von WebFritzi editiert. ]



  • Oh ja, eine Kompo ist eine Klasse. :p Genau gesagt, der visuelle Part fehlt mir bei diesem Weg.

    Ein Tagebuch paßt eigentlich nicht in eine Werkstatt. Im Kopf sind sie besser aufgehoben. 😃 Ich frag mich ganz einfach ernsthaft, ob eine komplexe Aufgabenstellung in eine Klasse gehört. Allenfalls genau so viel, wie auch wiederverwendbar sein wird...

    ...

    Hmmm... FImage ist ein TImage und kann richtig malen, mein TImage in der Anwendung kann es nicht richtig? Da is was faul! In der Tat, es geht. Mein Fehler, dem Point(X,Y) kann man nicht an zentraler Stelle Berechnungen zuweisen. Nicht mal innerhalb einer Function nützt es was. Bei jeder Operation muß gerechnet werden (neue Bedingung). *Ufff*, 100 m Kabel ist 'ne verdammt lange Leitung. 🙄



  • Ich verstehe wirklich nicht, wieso du es fast nie auf die Reihe bekommst, deine Fragen allgemein verständlich zu formulieren. Dein letzter Beitrag ist für mich von vorne bis hinten unverständlich!



  • Ist es zu abstrakt? Vielleicht auch ungewohnt? Das muß sich doch ändern lassen.

    Bei der Klasse/Kompo vermiß ich hier im Beispiel die Handhabbarkeit im Objectinspector, verschieben können, die EventHandler gemeinsam durch verschiedene Kompos verwenden lassen. Für mich sieht es so aus, als ob die Aufgabenstellung zu komplex ist, um sie auf diesem Weg aufzubauen. Es geht sicher, dürfte aber hohen Aufwand erfordern.

    Der untere Teil wollte einfach sagen, daß ich jetzt endlich rausgefunden hab, warum ich im gezoomten TImage nicht malen konnte. Ich hatte die Umrechnungen nur zentral durchgeführt. Ich muß es aber in jeder Anweisung tun.



  • Hi Omega

    Du scheinst noch Probleme mit OOP- Philosophie zu haben. 😉

    Das ist normal!!!

    Dein wahrscheinlicher Fehler: Du denkst nicht abstrakt genug!!! 😕

    Du musst bei Komponentenerstellung sehr stark abstrahieren! Dich auch mal vom Gesamtprojekt (kurzzeitig) trennen koennen!? 😕

    Im Prinzip:

    1. Was soll das Programm im Ganzen bringen (voellig EGAL wie)
    2. Welche Komponenten gibt es / Was koennen die / kann ich das brauchen?
    3. Auswahl der geeigneten Komponenten.
    Z.B.: Bild Anzeigen / Zeichnen / Zoomen = TImage
    4. Fuer die Teilfunktion des Programmes, wo keine Kompo perfekt ist:
    welche kann Teile am besten, wie kann ich die 'erweitern'
    Z.B.: TImage kann Anzeigen
    TImage kann malen
    TImage kann 'zoomen' ( Stretch) = nicht perfekt, anzupassen
    TImage kann nicht Scrollen (bei grossen Bildern!
    Z.B.: TScrollBox kann Inhalt bei Bedarf Scrollen (automatisch) = sehr gut
    TScroller kann nichts anderes ???
    Das war der Punkt, den wir amm Anfang hatten. Darauf setzte meine Idee auf.
    5. Ne Klasse machen die alles kann
    a) Rollbalken an ein TImage machen ? (keine Ahnung wie das sinnvoll geht)
    b) TImage in TScrollbox
    - kann Anzeigen, Zeichnen, Zoomen, Scrollen
    voila.
    Also b)
    6. Was stoert:
    a)Klasse kapselt TImage - kein Zugriff von Aussen
    -> TImage public machen (hab' ich der Einfachheit halber gemacht!)oder
    -> Methoden schreiben, fuer alle denkbaren Zugriffe : Das ist jetzt Dein
    Teil!
    b)Klasse kann 'drinnen' malen mit Maus;aber Mause reagiert nur automatisch
    in Klasse?
    -> in Mouse?????- Routinen die StandardRoutinen mit aufrufen - dann
    kann 'aussen' mit OnMouse????? Methoden in Hauptmodul reagiert werden!
    c)Das automatische Zeichnen (war zur Demonstration von mir gedacht!!!) soll
    nicht immer erfolgen!
    -> Boolean variable in privat setzen, die Zeichnen erlaubt / verbietet!
    -> property dazu, die Steuerung von Aussen erlaubt.
    -> Mouse????? Routinen so anpassen, dass
    if (AutoDraw==true)
    ..... bisherige malfunktion...
    else
    ..... was anderes oder nichts!...
    7. In Hauptmodul:
    fuer OnMouse????? Routinen schreiben, was passieren soll / Methoden rufen
    (Die noch zu schreiben waeren siehe 6.)
    8. Die Klasse fuer Objektinspektor sichtbar machen:
    -> Halt Modul ergaenzen um Registrierungscode, in NEUE KOMPONENTE
    voila : Das Ding ist in der Palette!!!
    9. Aus Palette in Testprog ziehen,
    OnMouse?????- Zeugs angeben......
    Groesse / Align ... einstellen ...
    Wenn noch was fehlt das ganze wieder von vorn!!!

    Tip: Wenn 'ne Kompo nicht alles kann, nicht immer gleich die Kompo aendern /ergaenzen!!!
    Manchmal besse: Ne neue Kompo ABLEITEN und der alles beibringen - Das sollte hier demonstriert werden!!!

    Das Demo sollte keine perfekte Sache sein!!! Hat zu viele Fehler!!!???
    (z.b: Absturz, wenn in leeres Image gemalt wird, Maus bewegt)

    Ich hoffe das war jetzt nicht zu durcheinander! 🕶
    Verdau das 'mal.

    Wenn Du noch was interessantes hast, kann's ja weitergehen. Sonst: Meld Dich mal wenns fertig ist (Mich wuerd' 'mal interessieren was Du genau machst?) 😃

    PS: DerAltenburger@aol.com



  • Hi DerAltenburger

    Logo hab ich die Philosophie der OOP noch nicht wirklich verstanden. Der Thread von @Junix in der FAQ hatte sie aber schon etwas näher gebracht. Alles weitere braucht Praxis. Dein Lehrgang paßt also edel in die Reihe. Ich glaub, nicht nur ich bin dir sehr dankbar dafür. - Stimmt, im abstrakten Denken bin ich ziemlich schwach. Das macht etliche Bereiche recht schwer zugänglich...

    Macht gar nix, daß das Beispiel einige kleine Schwachpunkte enthält. Ganz im Gegenteil. Die weiterführende Aufgabenstellung ergibt sich daraus von ganz allein.

    ZB. stimmt der Parameter nicht, wenn bei höherer Vergrößerung über FImage/FPaint hinausgemalt wird. Die Situation gilt es, zu entschärfen.

    Die Stiftzeichnung klappt in dieser Stufe noch nicht richtig. Die Umrechnung haut noch nicht richtig hin. Außerhalb der gezeichneten Linie bleiben Fragmente zurück.

    Ein ähnliches Prob hab ich aber bereits nur im Image/FImage beim Zeichnen von ungefüllten RoundRect und Rect. Da bleiben innen Aufbaufragmente und die Spur der Mausführung zurück. Wieder Zurückgehen beim Aufziehen einer Draw-Figur hinterläßt Reste. Muß jetzt seh'n, daß ich die Fehler find und korrigier. So ganz systematisch darf die Umrechnung der Koordinaten wohl nicht sein.

    Wenn's fertig ist? Das wird dauern. Ich bau ein Paint-Programm. Priorität hat ein sinnvolles Handling. Raumaufteilung und viel Tastakombi. Eine große gut durchgestufte Farbauswahl. Erst mal die Standard-DrawTools, nach und nach spezielleres, soweit es gelingt. Heller, Dunkler, Invertieren sind schon drin.

    Mit FloodFillAll hab ich noch Probs im gestretchten Image. BrushCopy verlangt nach dem Einkopieren eines externen Bildes. Damit paßt sich die Picture->Grafik an, Image zeigt nur noch einen Teil des Bildes. Da es bei 100% klappt, muß eine indirekte Lösung gefunden werden.

    Ein weiteres Feature wäre, Image transparent, eine stretchbare Vorlage zum Abmalen drunter verschieben können. Nach oben käme Ebenenzeichnen dazu. Bei transparentem Arbeiten lassen sich dann mehrere Ebenen gemeinsam capturen - oder ggf. andere Wege über Transparentfarben usw. In weiter Ferne wäre dann zB. noch die Umriß-Markierung und entsprechendes Copy/Paste. Also insgesamt wird das ein längerfristiges Projekt. Da kann auch immer wieder anderes dazwischen laufen. Das erste Ziel ist natürlich mal die erste Praxistauglichkeit im Standardumfang.

    Dank dir noch mal sehr. Das PS hab ich notiert - will natürlich nicht mit jeder kleinen Frage bomben. :p



  • Dann viel Spass 😉

    Bis ....


Anmelden zum Antworten