IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

D�faire ou refaire ce qui figure sur un Canvas


Sujet :

C++Builder

  1. #1
    Membre confirm�
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    69
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 69
    Par d�faut D�faire ou refaire ce qui figure sur un Canvas
    Bonjour � tous!
    Je voudrais savoir s'il existait une fonction qui servirait � d�faire o� refaire ce que l'on a dessin� sur un canvas.
    Par exemple:
    -pour un composant TEdit on fait Edit1->Undo();
    -pour un TMemo un on envoit un message Windows WM_UNDO:
    SendMessage(Memo->Handle,WM_UNDO,0,0);
    mais pour le Canvas je n'ai rien trouv�.
    Merci de m'aider
    Bon courage � tous!

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 412
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 412
    Par d�faut
    Salut !

    Avec ma version BCB3 Pro, �a n'existe pas.
    En fait, il faut le mettre en place soi-m�me en obj�tisant les actions.
    Par exemple, si � un instant T on a effectu� un CopyRect il faudrait pour bien faire m�moriser le contenu du rectangle source dans un bitmap afin de le r�tatblir en cas d'undo.

    Pour des situations beaucoup plus critiques (dessin par accumulation de primitives etc...) on aurait int�r�t � modiliser les objets graphiques de mani�re � jongler avec deux listes (l'une dont les objets sont dessin�s et l'autre qui contient les objets temporairement retir�s pour ensuite ou �ventuellement autoriser un redo).

    A plus !

  3. #3
    Membre confirm�
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    69
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 69
    Par d�faut
    Merci henderson de m'avoir r�pondu mais j'avoue que �a me parrait compliqu� surtout que je ne suis qu'une d�butante en programmation orient�e objet.
    N'y aurait-il pas une solution plus abordable?

  4. #4
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 412
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 412
    Par d�faut
    Salut !

    La solution abordable est au bout de tes doigts : la POO !

    D�faire quoi au juste ?

    A plus !

  5. #5
    Membre confirm�
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    69
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 69
    Par d�faut
    Lors d'un click sur le canvas d'un TImage, un bitmap en forme de r�ctangle se dessine � l'emplacement du click de la souris. Apr�s plusieurs clicks j'aimerais faire un Undo. Et le probl�me est justement l�..
    Merci!

  6. #6
    Membre confirm�
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    69
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 69
    Par d�faut
    Alors..Personne n'a jamais eu affaire � ce probl�me?
    ok si pas de solution rapide, comment pourrais-je le faire en programmant?

  7. #7
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 412
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 412
    Par d�faut
    Salut !

    Voici un exemple tr�s minimaliste qui montre comment obj�tiser des actions.
    Ici je n'ai d�velopp� qu'une seule action qui consiste � dessiner un bitmap quelconque � un endroit quelconque.

    La classe jAction d�rive de TComponent pour ne pas avoir � d�truire ces objets manuellement; c'est leur propri�taire (d�riv� de TComponent lui aussi) qui s'en chargera lors de sa propre destruction.
    Comme on peut le voir, cette classe va permettre de m�moriser :
    - un bitmap (celui que l'on va incruster)
    - une position
    - un canvas, en tant que support de l'incrustation

    L'objet dispose �galement d'une m�thode Do qui va pr�cis�ment r�aliser l'incrustation.

    En plus, on dispose d'une m�thode HasFocus pour d�tecter si l'objet graphique c'est � dire le r�sultat de la copie du bitmap, est sous le curseur.
    On pourra donc s�lectionner une action (via le r�sultat graphique) ce qui sera pratique pour sa suppression.

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    class jAction : public TComponent
    {
    private :
     
    public :
     
    Graphics::TBitmap *Bitmap; //simple pointeur
    TCanvas *Canvas; //simple pointeur
    TPoint Pos;
     
        //On initialise dès la construction
        __fastcall jAction(TComponent *AOwner,
                           Graphics::TBitmap *B,
                           TCanvas *C,
                           TPoint P);
        __fastcall ~jAction();
        bool __fastcall HasFocus(TRect R);
        void __fastcall Do();
    };

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    __fastcall jAction::jAction(TComponent *AOwner, Graphics::TBitmap *B, TCanvas *C, TPoint P)
        : TComponent(AOwner)
    {
    Bitmap = B;
    Canvas = C;
    Pos = P;
    }
     
    __fastcall jAction::~jAction()
    {
    }
     
    void __fastcall jAction::Do()
    {
    Canvas->Draw(Pos.x, Pos.y, Bitmap);
    }
     
    bool __fastcall jAction::HasFocus(TRect R)
    {
    // Je montre en détail mais ça se simplifie...
    int left = Pos.x;
    int top = Pos.y;
    int right = left + Bitmap->Width;
    int bottom = top + Bitmap->Height;
    return((left < R.Right) &&
           (right >= R.Left) &&
           (top < R.Bottom) &&
           (bottom >= R.Top));
    }

    J'ai volontairement pris comme support du dessin une classe d�riv�e de TCustomControl..., c'est juste pour l'exemple !

    On va donner � ce jPaintBox de quoi :
    - m�moriser une image de fond
    - m�moriser les actions
    - remonter la s�quence des op�rations
    - s�lectionner/supprimer ou ajouter une action


    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    class jPaintBox : public TCustomControl
    {
    private :
     
    int FStep; // pour caler la sequence des actions
    TList *Actions; // la liste des actions (du type jAction)
    Graphics::TBitmap *FImage; //simple pointeur vers une image de fond (bitmap)
     
    protected :
        //méthodes Set pour les propriétés
        void __fastcall SetStep(int Value);
        void __fastcall SetImage(Graphics::TBitmap *Value);
     
    public :
     
    TImage *Target; //Cible (l'image à incruster) que l'utilisateur devra fournir
     
        __fastcall jPaintBox(TComponent *AOwner);
        __fastcall ~jPaintBox();
     
        // pour se peindre lui-même, il suffit de surcharger la méthode Paint
        void __fastcall Paint();
        // pour ajouter une action
        void __fastcall Add(Graphics::TBitmap *I, TPoint P);
        // pour ajouter une action lors du MouseDown sur l'objet
        void __fastcall OnMouseDownAdd(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y);
        // pour aller chercher un objet sous le curseur
        jAction* __fastcall HasFocus(TRect R);
        // la méthode tant espérée
        void __fastcall Undo();
     
        //Les propriétés visibles par l'utilsateur
        //A ce stade... nous sommes les concepteurs du bidule donc ...
        __property Graphics::TBitmap *Image={read=FImage, write=SetImage};
        __property int Step={read=FStep, write=SetStep};
     
    };
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
     
    __fastcall jPaintBox::jPaintBox(TComponent *AOwner)
        : TCustomControl(AOwner)
    {
    if(AOwner->InheritsFrom(__classid(TWinControl))) Parent = (TWinControl*)AOwner;
    Actions = new TList;
    OnMouseDown = OnMouseDownAdd;
    }
     
    __fastcall jPaintBox::~jPaintBox()
    {
    Actions->Clear();
    delete Actions;
    Actions = NULL;
    }
     
    void __fastcall jPaintBox::SetStep(int Value)
    {
    FStep = Value;
    Repaint(); //pour rendre la modification visible immédiatement
    }
     
    void __fastcall jPaintBox::SetImage(Graphics::TBitmap *Value)
    {
    FImage = Value;
    Repaint(); //pour rendre la modification visible immédiatement
    }
     
    void __fastcall jPaintBox::Paint()
    {
    if(Image != NULL)
        {
        Canvas->Draw(0,0,Image);
        }
    else
        {
        Canvas->Brush->Style = bsSolid;
        Canvas->Brush->Color = Brush->Color;
        Canvas->FillRect(Rect(0,0,Width,Height));
        }
    if(Actions != NULL) // par sécurité
        {
        for(int j = 0; (j < Step) && (j < Actions->Count); j++)
            {
            ((jAction*)Actions->Items[j])->Do();
            }
        }
    }
     
    void __fastcall jPaintBox::Add(Graphics::TBitmap *I, TPoint P)
    {
    jAction *Action = new jAction(this, I, Canvas, P);
    Actions->Add(Action);
    Step = Actions->Count; //Step = Count à chaque ajout
    }
     
    void __fastcall jPaintBox::OnMouseDownAdd(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
    {
    // pour faire la distinction entre sélectionner/supprimer et ajouter
    if(Button == mbRight)
        {
        jAction *Action = HasFocus(Rect(X,Y,X,Y));
        if(Action != NULL)
            {
            if (MessageDlg("Supprimer l'action ?", mtConfirmation,
                     TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes)
                {
                Actions->Delete(Actions->IndexOf(Action));
                delete Action; // suppression manuelle ici
                Step = Step - 1; // pour une suppression réaliste
                }
            }
        }
    else
        {
        Add(Target->Picture->Bitmap, Point(X,Y));
        }
    }
     
    /*
    Ici, on va travailler en mode rétro simplement par ce que chaque action est
    dessinée sous la suivante.
    */
     
    jAction* __fastcall jPaintBox::HasFocus(TRect R)
    {
    jAction *Action;
    int max = Actions->Count - 1;
    if(Step < max) max = Step;
    for(int j = max; j >=0; j--)
        {
        Action = (jAction*)Actions->Items[j];
        if(Action->HasFocus(R)) return Action;
        }
    return NULL;
    }
    A ce stade, voici ce que j'ai rajout� pour tester l'ensemble :
    - 4 TImages (Image1...4). Pour ces 4 images, un simple clic sur l'une d'elles
    permet de la m�moriser en tant que cible pour une �ventuelle action.
    L'action est effective d�s que l'on clique sur l'objet PaintBox.
    - 1 TImage (Image5) qui me permet de rajouter un fond pour le PaintBox. Cette image est invisible pour l'utilisateur et le PaintBox vient se positionner au dessus.
    - 1 TScrollBar pour remonter la s�quence des actions.

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    jPaintBox *PaintBox;
     
    //---------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    PaintBox = new jPaintBox(this);
    //REM : Image5 sert pour le fond
    PaintBox->SetBounds(Image5->Left, Image5->Top, Image5->Width, Image5->Height);
    PaintBox->Image = Image5->Picture->Bitmap;
    PaintBox->Target = Image1; // pour éviter un NULL
    }
    //---------------------------------------------
     
    void __fastcall TForm1::Image1Click(TObject *Sender)
    {
    PaintBox->Target = (TImage*)Sender;
    }
    //---------------------------------------------
     
    void __fastcall TForm1::ScrollBar1Change(TObject *Sender)
    {
    PaintBox->Step = ScrollBar1->Position;
    }
    //---------------------------------------------
    Ce que je montre ici, est d�clinable pour les primitives de TCanvas.
    Par contre, dans ce cas, il faudra passer par une classe de base et am�nager les classes d�riv�es de mani�re � ce qu'elles r�alisent l'action.
    Par ailleurs, on peut aussi rajouter d'autres fonctionnalit�s (le Drag, par exemple, est simple � mettre en place).

    A plus !

  8. #8
    Membre confirm�
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    69
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 69
    Par d�faut
    Je vous remercie Henderson pour l'aide que vous m'avez apport�e. J'ai test� votre programme et �a marche vraiment comme je voulais.
    Il y a cependant un petit d�tail, lorsque je reviens en arri�re (Undo) tout se passe comme pr�vu mais quand je veux rajouter une image (dessin), l'image est rajout�e mais au dernier �tat de mon PainBox.
    C'est � dire que si j'avais 3 bitmaps dessin�s et que je reviens � l'�tat o� j'en avais qu'un seul, en ajoutant un autre bitmap, les 2 images supprim�es r�aparraissent et j'ai finalement 4 bitmaps dessin�s.
    Merci encore pour votre effort.
    Bon courage!

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. R�ponses: 5
    Dernier message: 24/05/2013, 13h32
  2. [CV] Projets qui peuvent figurer sur un CV
    Par afrikha dans le forum CV
    R�ponses: 20
    Dernier message: 09/12/2005, 06h34
  3. Qui vient sur developpez.com ?
    Par chess dans le forum Evolutions du club
    R�ponses: 29
    Dernier message: 11/09/2004, 13h31
  4. application qui connecte sur une page web
    Par spoolz dans le forum Entr�e/Sortie
    R�ponses: 6
    Dernier message: 14/04/2004, 09h47
  5. LABEL QUI DISPARAIT SUR UN PICTUREBOX !
    Par Sophie42 dans le forum MFC
    R�ponses: 2
    Dernier message: 13/01/2004, 12h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo