Salut,
je veux créer une zone de selection à la souris dans une Timage, comment faire?
Version imprimable
Salut,
je veux créer une zone de selection à la souris dans une Timage, comment faire?
Salut !
Code:TRect Bnds = Rect(left, top, right, bottom); //à toi de définir left, top...
ou bien à l'aide d'une méthode (ici membre de TForm1)Code:
1
2
3
4 if((X < Bnds.Right) && (X > Bnds.Left) && (Y < Bnds.Bottom) && (Y > Bnds.Top)) { //match }
Code:
1
2 public : void __fastcall InsideBnds(int X, int Y);
Une méthode plus générale (par ex : s'il existe plusiers zones):Code:
1
2
3
4 void __fastcall TForm1::InsideBnds(int X, int Y) { return ((X < Bnds.Right) && (X > Bnds.Left) && (Y < Bnds.Bottom) && (Y > Bnds.Top)); }
Pour terminer, l'interception de deux rectangles :Code:
1
2
3
4
5 void __fastcall TForm1::InsideBnds(int X, int Y, TRect *R) { return ((X < R->Right) && (X > R->Left) && (Y < R->Bottom) && (Y > R->Top)); }
C'est le cas lorsque l'on délimite une zone à l'aide de la souris :
Dans la OnMouseDown : Bnds.Left = X; Bnds.Top = Y;
Dans la OnMouseMove : Bnds.Right = X; Bnds.Bottom = Y;
Dans la OnMouseUp on échange Left et Right si Left > Right, idem pour Top et Bottom si Top > Bottom
La nature des paramètres (TRect R ou TRect *R) est purement anecdotique, un pointeur étant cependant plus simple et plus rapide.Code:
1
2
3
4
5
6
7 void __fastcall TForm1::InsideBnds(TRect S, TRect *R) { return ((S.Left < R->Right) && (S.Right > R->Left) && (S.Top < R->Bottom) && (S.Bottom > R->Top)); }
A plus !
:salut:
merci pour ton aide.
je tiens à te préciser que je suis débutante en programmation C++ Builder, et je n'ai pas bien compris ce que tu as expliqué:bug: . si ce n'est pas trop te demander peux tu détailler un peu plus, me dire par exemple ou je dois mettre chaque code
:merci:
:help:
Salut !
Si tu pouvais donner plus de précisions !
A plus !
Salut,
Je veux savoir ou je dois écrire les codes que tu m’as donné, ou plus précisément toutes les étapes à suivre pour créer la zone de sélection.
A+
Salut,
il existe une source qui fait ce que tu souhaites et qui, je pense doit être détaillé.
Salut,
J'ai essayé de réimplémenter le programme de la source que vous m'avez donné et je n'ai rien obtenu! j'explique le problème avec plus de précisions:
dans le Unit1.cpp j'ai mis:
Dans le unit1.h j'ai mis:Code:
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 //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { DoubleBuffered = true; selection = new TSelectionHandler( Image1->Canvas, Image1->Width, Image1->Height); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { if (selection->DoesSelectionExists()) { TRect selectionRectangle = selection->GetSelection(); Graphics::TBitmap * bitmapSrc = Image1->Picture->Bitmap; Graphics::TBitmap * bitmapDest = new Graphics::TBitmap(); bitmapDest->Height = selectionRectangle.Height(); bitmapDest->Width = selectionRectangle.Width(); TRect dest; dest.top = 0; dest.left = 0; dest.bottom = selectionRectangle.Height(); dest.right = selectionRectangle.Width(); bitmapDest->Canvas->CopyRect(dest, bitmapSrc->Canvas, selectionRectangle); Image2->Picture->Bitmap->Assign(bitmapDest); selection->UnSetSelection(); } } //--------------------------------------------------------------------------- void __fastcall TForm1::Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { selection->SetFirstPoint(X,Y); } //--------------------------------------------------------------------------- void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { selection->SetMousePoint(X,Y); } //--------------------------------------------------------------------------- void __fastcall TForm1::Image1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { selection->SetSecondPoint(); } //---------------------------------------------------------------------------
Ensuite j'ai ajouté File.cpp je l'ai appelé SelectionHandler.h j'ai mis dedans:Code:
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 //--------------------------------------------------------------------------- #ifndef Unit1H #define Unit1H //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <ExtCtrls.hpp> #include <Graphics.hpp> #include "SelectionHandler.h" //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components TImage *Image1; TImage *Image2; TButton *Button1; void __fastcall Button1Click(TObject *Sender); void __fastcall Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y); void __fastcall Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y); void __fastcall Image1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y); private: // User declarations TSelectionHandler * selection; public: // User declarations __fastcall TForm1(TComponent* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif
j'obtiens toujours la liste d'erreurs suivante:Code:
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 //--------------------------------------------------------------------------- #pragma hdrstop #include "SelectionHandler.h" //--------------------------------------------------------------------------- #pragma package(smart_init) //--------------------------------------------------------------------------- TSelectionHandler::TSelectionHandler(TCanvas * canvas, int Width, int Height) { isDragging = false; isSelected = false; this->canvas = canvas; canvasHeight = Height; canvasWidth = Width; selection = TRect(0,0,0,0); } //--------------------------------------------------------------------------- void TSelectionHandler::SetFirstPoint(int X, int Y) { if (isSelected) { DrawSelection(); } isDragging = true; pointClick.x = X; pointClick.y = Y; selection = TRect(pointClick, pointClick); DrawSelection(); } //--------------------------------------------------------------------------- void TSelectionHandler::SetSecondPoint() { if (isDragging) { isDragging = false; isSelected = true; } } //--------------------------------------------------------------------------- void TSelectionHandler::SetMousePoint(int X, int Y) { if (isDragging) { DrawSelection(); if (X < 0) { X = 0; } if (X > canvasWidth) { X = canvasWidth; } if (Y < 0) { Y = 0; } if (Y > canvasHeight) { Y = canvasHeight; } gauche à if (X < pointClick.x) { selection.left = X; selection.right = pointClick.x; } else { selection.left = pointClick.x; selection.right = X; } if (Y < pointClick.y) { selection.top = Y; selection.bottom = pointClick.y; } else { selection.top = pointClick.y; selection.bottom = Y; } DrawSelection(); } } //--------------------------------------------------------------------------- void TSelectionHandler::UnSetSelection() { if (isSelected) { DrawSelection(); isSelected = false; } } //--------------------------------------------------------------------------- TRect TSelectionHandler::GetSelection() { return selection; } //--------------------------------------------------------------------------- void TSelectionHandler::DrawSelection() { canvas->DrawFocusRect(selection); } //--------------------------------------------------------------------------- bool TSelectionHandler::DoesSelectionExists() { return isSelected; }
je ne sais pas ou est l'erreur!! Aidez moi SVPCode:
1
2
3
4
5
6
7
8
9
10
11
12 [C++ Error] Unit1.h(12): E2209 Unable to open include file 'SelectionHandler.h' [C++ Error] Unit1.h(28): E2303 Type name expected [C++ Error] Unit1.h(28): E2139 Declaration missing ; [C++ Error] Unit1.cpp(23): E2451 Undefined symbol 'selection' [C++ Error] Unit1.cpp(23): E2303 Type name expected [C++ Error] Unit1.cpp(23): E2379 Statement missing ; [C++ Error] Unit1.cpp(32): E2451 Undefined symbol 'selection' [C++ Warning] Unit1.cpp(62): W8004 'bitmapSrc' is assigned a value that is never used [C++ Error] Unit1.cpp(70): E2451 Undefined symbol 'selection' [C++ Error] Unit1.cpp(77): E2451 Undefined symbol 'selection' [C++ Error] Unit1.cpp(84): E2451 Undefined symbol 'selection'
Salut !
C'est la première erreur qui déclenche les autres !
Soit donner le chemin complet pour l'inclusion du header (#include "SelectionHandler.h") soit déplacer les fichiers (.cpp et .h) dans le dossier du projet, ce qui serait plus simple.
A plus !
:salut:
j'ai corrigé la première erreur mais cela n'a pas résolu le problème:cry:
toutes ces erreurs restent à corriger:
A+Code:
1
2
3
4
5
6
7
8
9 [C++ Error] Unit1.cpp(24): E2451 Undefined symbol 'selection' [C++ Error] Unit1.cpp(24): E2303 Type name expected [C++ Error] Unit1.cpp(24): E2379 Statement missing ; [C++ Error] Unit1.cpp(34): E2451 Undefined symbol 'selection' [C++ Warning] Unit1.cpp(64): W8004 'bitmapSrc' is assigned a value that is never used [C++ Error] Unit1.cpp(70): E2451 Undefined symbol 'selection' [C++ Error] Unit1.cpp(77): E2451 Undefined symbol 'selection' [C++ Error] Unit1.cpp(84): E2451 Undefined symbol 'selection'
Salut,
Comment ajouter le SelectionHandler.cpp aux classes de mon projet ?
A bientôt
Salut,
tu vas dans Project | Add to Project, cela doit normalement t'ajouter le fichier que tu désires.
salut Bandit boy,
je l'ai fait mais ça n'a rien changé, le problème persiste j'ai toujours la même liste d'erreurs qui s'affiche:aie:
A+
Salut !
Cette fameuse classe SelectionHandler pourrait être ajoutée dans la class de TForm1 (donc en amont de la déclaration de la class TForm1 puisque TForm1 en fait usage) et les méthodes développées dans l'unité de TForm1.
Ca permettrait de supprimer deux fichiers (.cpp et .h de cette classe).
En fait, on gagnerait ici à développer le mécanisme de cette sélection à l'aide des événementielles du TImage *Image1.
Par exemple et j'ai rajouté une petite fonctionnalité pour déplacer ce rectangle :
On commence par rajouter ceci dans la classe de TForm1, dans la partie public :
Les méthodes personalisées :Code:
1
2
3
4
5
6
7
8
9
10 //Propriétés (ce sont les variables qui vont servir pour les mécanismes) bool RectIsVisible; bool SelFlag; bool MoveFlag; TPoint Start; TRect Bnds; //Méthodes qui vont intervenir accessoirement dans le mécanisme bool __fastcall InsideBnds(int X, int Y); void __fastcall DrawBnds(); void __fastcall Swap(int *A, int *B);
Pour ce qui est des méthodes événementielles, elles sont ici affectées à Image1 :Code:
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 bool __fastcall TForm1::InsideBnds(int X, int Y) { //tester si le point (X,Y) est dans le Rectangle Bnds return((X < Bnds.Right) && (X >= Bnds.Left) && (Y < Bnds.Bottom) && (Y >= Bnds.Top)); } void __fastcall TForm1::DrawBnds() { //le Canvas est celui de Image1, ici pour l'exemple TCanvas *C = Image1->Canvas; //Pas de Brush donc C->Brush->Style =bsClear; //Pen solide, noir en mode NOT C->Pen->Style = psSolid; C->Pen->Mode = pmNot; C->Pen->Color = clBlack; //On dessine ou on efface le rectangle de délimitation grâce au NOT C->Rectangle(Bnds.Left, Bnds.Top, Bnds.Right, Bnds.Bottom); //Etat du rectangle après opération RectIsVisible = !RectIsVisible; } void __fastcall TForm1::Swap(int *A, int *B) { //Pour garder la cohérence entre (Left,Top) et (Right,Bottom) //Echange *A et *B si *A > *B if(*A > *B) { int w = *A; *A = *B; *B = w; } }
}Code:
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 void __fastcall TForm1::Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { //Tant qu'à faire, fixer ces opérations sur le bouton gauche if(Button == mbLeft) { if(RectIsVisible && InsideBnds(X,Y)) { //On va déplacer le rectangle existant MoveFlag = true; //Valeurs de départ pour le déplacement Start = Point(X,Y); } else { if(RectIsVisible) DrawBnds(); //S'il est visible on l'efface //On va dessiner le rectangle SelFlag = true; //Initialiser les points (Left,Top) et par défaut (Right,Bottom) Bnds = Rect(X,Y,X,Y); //On le dessine... même si ça semble inutile... DrawBnds(); } } } void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { if(SelFlag) { //effacer DrawBnds(); //Actualiser le point (Right,Bottom) Bnds.Right = X; Bnds.Bottom = Y; //dessiner DrawBnds(); } if(MoveFlag) { //effacer DrawBnds(); //Décalages en X et Y int ofx = X - Start.x; int ofy = Y - Start.y; //Report des décalages Bnds.Left += ofx; Bnds.Right += ofx; Bnds.Top += ofy; Bnds.Bottom += ofy; //Pour une nouvelle saisie (sans quoi... !!!) Start = Point(X,Y); //dessiner DrawBnds(); } } void __fastcall TForm1::Image1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { MoveFlag = false; //fin du processus if(SelFlag) { //fin du processus SelFlag = false; //Assurer que les données du TRect sont cohérentes Swap(&Bnds.Left, &Bnds.Right); Swap(&Bnds.Top, &Bnds.Bottom); }
Je ne sais pas si ça reflète bien ce que tu souhaites faire... en particulier pour le OnClick qui n'a plus lieu d'être...
A plus !
Salut,
ma question va te paraitre un peu bête mais je vais te l'a poser comme même:
que veux tu dire par "Les méthodes personalisées"?
merci pour ton aide.
A+
Salut !
Ce sont les méthodes "utilisateur"... en fait... c'est aussi valable pour un "concepteur" donc je préfère "personnalisé" au lieu de "utilisateur"... donc des méthodes qui ne sont pas mises en place par BCB en tant que "published".
Il suffit d'en déclarer le prototype dans la classe.
Selon les cas, on peut avoir à opter pour différents modes d'accessibilité : private, protected ou public.
A noter que l'on peut déclarer n'importe quel prototype, même ceux qui sont utilisés par BCB dans son contexte published pour les événementielles.
Dans ce cas précis, leur utilisation passe par une initialisation dynamique (en cours d'exécution) lorsque l'on veut les affecter à un événement précis d'un objet quelconque qui sait gérer l'événement.
Dans ce que j'ai montré, l'avantage serait de ne plus utiliser les flags et donc les tests successifs lorsqu'il y a plusieurs tâches possibles pour un même événement.
On y gagne aussi en lisibilité puisque les actions sont développées distinctement à l'aide de méthodes spécifiques.
Par contre on a un peu plus de code (perte de temps pour développer mais gain de temps à l'exécution... même aussi minime soit-il.
Par exemple, j'aurais pu donner à BCB le soin de me définir les 3 événementielles pour Image1 et j'aurais rajouté en public dans la classe de TForm1 :
En gardant tout ce que j'ai donné, sauf les deux booléens (SelFlag et MoveFlag) qui n'ont plus lieu d'être.Code:
1
2
3
4
5
6
7
8
9
10
11 //Méthodes OnMouseMove pour les deux actions void __fastcall WhenSelecting(TObject *Sender, TShiftState Shift, int X, int Y); void __fastcall WhenMoving(TObject *Sender, TShiftState Shift, int X, int Y); //Méthode OnMouseUp pour les deux actions void __fastcall WhenSelectingEnds(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y); void __fastcall WhenMovingEnds(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y);
Le développement aurait été le suivant :
Les méthodes événementielles pour les actions :Code:
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 void __fastcall TForm1::Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { if(Button == mbLeft) { if(RectIsVisible && InsideBnds(X,Y)) { Start = Point(X,Y); //Contexte événementiel pour le déplacement du rectangle Image1->OnMouseMove = WhenMoving; Image1->OnMouseUp = WhenMovingEnds; } else { if(RectIsVisible) DrawBnds(); Bnds = Rect(X,Y,X,Y); DrawBnds(); //Contexte événementiel pour la sélection Image1->OnMouseMove = WhenSelecting; Image1->OnMouseUp = WhenSelectingEnds; } } } void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { // ne fait rien mais pourrait faire... } void __fastcall TForm1::Image1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { // ne fait rien mais pourrait faire... }
Finalement...c'est simple à faire ! Non ?Code:
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 void __fastcall TForm1::WhenSelecting(TObject *Sender, TShiftState Shift, int X, int Y) { DrawBnds(); Bnds.Right = X; Bnds.Bottom = Y; DrawBnds(); } void __fastcall TForm1::WhenMoving(TObject *Sender, TShiftState Shift, int X, int Y) { DrawBnds(); int ofx = X - Start.x; int ofy = Y - Start.y; Bnds.Left += ofx; Bnds.Right += ofx; Bnds.Top += ofy; Bnds.Bottom += ofy; Start = Point(X,Y); DrawBnds(); } void __fastcall TForm1::WhenSelectingEnds(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { //On s'assure de la cohérence (Left,Top) et (Right,Bottom) au niveau du TRect Bnds Swap(&Bnds.Left, &Bnds.Right); Swap(&Bnds.Top, &Bnds.Bottom); //On restaure le contexte initial Image1->OnMouseMove = Image1MouseMove; Image1->OnMouseUp = Image1MouseUp; //S'il y a quelque chose à faire... //.. } void __fastcall TForm1::WhenMovingEnds(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { //On restaure le contexte initial Image1->OnMouseMove = Image1MouseMove; Image1->OnMouseUp = Image1MouseUp; //S'il y a quelque chose à faire... //.. }
A plus !
:merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci: :merci::merci: :merci: :merci::merci: :merci: :merci: :merci:
:lahola: :lahola: :lahola: :lahola: :lahola: :lahola: :lahola: :lahola: :lahola::lahola: