Modifier taille bitmap [Résolu]

Signaler
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
-
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
-
Bonjour,


dans mon appli, je charge une carte au format bitmap dans un paintbox.


Cependant, la procédure StretchDraw :


Paintbox1.canvas.StretchDraw(PaintBox1.ClientRect,BmpM); étire bien la
carte mais dès que je dessine sur cette carte, les positions sont aussi
étirées: plus je m'éloigne de la position (0,0), plus l'image que je déplace
s'éloigne de la souris alors qu'elle devrait être dessous.


J'ai opté pour la solution de redimensionner mon image avec paint, puis
de la charger sur mon appli. Cette solution n'étant que temporaire, je souhaiterias redimensionner cette image avec mon appli comme le permet paint


merci


Seb

21 réponses

Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
1
Voici mon code :



procedure TForm1.FormCreate(Sender: TObject);

Var

i : integer;

begin

.....

BmpM := tbitmap.create;

BmpM.LoadFromFile('C:\...carte_dept31__.bmp'); // chargement de la carte dans OrigBmp

end;



procedure TForm1.PaintBox1Paint(Sender: TObject);

begin

Paintbox1.canvas.draw(0,0,BmpM); // c'est bmpm qui est à jour

end;



procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

Var

i : integer;

p : tpoint;

begin

courant := 0; // pas de curseur actif

p.x := X; p.y := Y;

// Si clic dans curseur existant (ptInRect est une fonction GDI Windows)

// For i := 1 to maxcur do if ptinrect(cc[i].rr, p) then courant := i;

For i := 1 to maxcur

do if ptinrect(cc[i].rr, p)

then begin // on a cliqué sur un rectangle de site

courant := i;

if (
waitforsecondsite and new_link_en_cours) // l'appli attend qu'on clique
sur un autre triangle pour relier les deux

then begin


PaintBox1.Canvas.Pen.Color:=clBlue;


PaintBox1.Canvas.Pen.Style:= psSolid;


CC[courant].bond[site_initial_bond]:=True;


CC[site_initial_bond].bond[courant]:=True;


PaintBox1.Canvas.Polyline([cc[site_initial_bond ].centre,cc[courant
].centre ]); // trace une ligne entre deux
"triangles"


PaintBox1.Canvas.Pen.Color:=clBlack;


waitforsecondsite:=not waitforsecondsite;

exit;

end;

if (
not waitforsecondsite and new_link_en_cours) // l'appli attend qu'on
clique sur le 1er triangle du lien

then begin


site_initial_bond:=courant;


waitforsecondsite:=not waitforsecondsite;

exit;

end;

if ( not new_link_en_cours) //

then
begin // on est peut être en train de déplacer un site donc il faut
effacer les liaisons

//rien pour l'instant



end;

end;

end;



procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

begin



IF ((courant = 0) or new_link_en_cours ) then exit;

IF cc[courant].drawing then

begin

// les nouvelles positions son mémorisées sous forme de rectangle

// ce principe permet de déformer l'objet en plus de le déplacer

cc[courant].rr := rect( x-c1,
y-c2, x+c1, y+c2); // nouvelle position du rectangle

// c1 et c2 sont les longueurs de la base et de la hauteur du triangle

dessinecurseur(courant); // procedure qui dessine un triangle (ou curseur)

Rafraichir_Liaisons; // procedure qui redessine tous les liens entre triangles tracés auparavant

end;

end;



procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

if courant=0 then exit;

dessinecurseur(courant);

Rafraichir_Liaisons;// procedure qui efface puis trace les liaisons

courant:=0;

CC[courant].drawing:=false;

end;



pour info : CC[x] est de type :

type TSite = record // caractéristiques d'un cuseur

drawing : boolean; // en cours de déplacement

rr : trect; // rectangle position courante

rro : trect; // ancien ancienne position

colo : tcolor; // couleur

centre : Tpoint; // centre du triangle

end;



voilà, bonne lecture ...
Messages postés
1023
Date d'inscription
dimanche 1 août 2004
Statut
Membre
Dernière intervention
17 août 2008
2
Bon alors là, ça coince.

@ Shining : ZeroMemory remet la memoire indéxée à zero (#0) mais ne libère pas la mémoire. C'est comme si tu faisait FillChar(CC, SizeOf(CC), 0). Je ne crios pas que ce soit ce que Sébastien recherche.

@ Sébastien : C'est pas Finalize(CC[I]) mais Finalize(CC[I].Bond)
En gros, cela donne :
{ Libération des éléments des tableaux "bond". }
for I : = 0 to High(CC) do
Finalize(CC[I].Bond);
{ Libération du tableau CC. }
Finalize(CC);

Si tu ne te plantes pas ......
tu ne pousseras jamais
Messages postés
1023
Date d'inscription
dimanche 1 août 2004
Statut
Membre
Dernière intervention
17 août 2008
2
Alors, c'est toujours un problème quand on dessine sur un TPaintBox.
Enfin, avec un peu de méthode, on y arrive.
Tout d'abord, tu aurais du poster ce que tu as mis dans l'évenement OnPaint de ton PaintBox, ça aurait pu nous aider.

Ensuite, normalement, quand tu dessine sur un PaintBox, au prochain dessin, tu dois tout redessiner. tu devrais peut être passer pa un bimap temporaire avant de dessiner sur ton PaintBox.

A + pour un bout de code (met aussi l'évent OnMouveMove, OnMouseDown et OnMouseUp, mieux vaut plus que pas assez)

++

Si tu ne te plantes pas ......
tu ne pousseras jamais
Messages postés
1023
Date d'inscription
dimanche 1 août 2004
Statut
Membre
Dernière intervention
17 août 2008
2
Pour ton problème, je ne vois pas trop du fait que tu places des triangles sur ta carte (correspondants à des sites) que tu peux déplacer et aussi relier entre eux.

En plus, tu oublies de préciser que CC[x] contient aussi un array of Boolean à ce que je vois. Mais ça, c'est pas grave.

Le truc, c'est que tes procédures DessineCurseur() et Rafraichir_Liaisons() dessinent-elles directement dans le PaintBox ou alors dans le BmpM ??

Alors là, ça coince pour moi. Désolé.

Si tu ne te plantes pas ......
tu ne pousseras jamais
Messages postés
40
Date d'inscription
mercredi 2 novembre 2005
Statut
Membre
Dernière intervention
19 juin 2006
1
Salut Seb,

Et si tu redimensionnais ton BMP avant, aurais-tu le même problème ?
Pour redimensionner un BMP, tu as plein d'exemples dans le forum.
Tu peux prendre le source de Pilot All posté dans les sources du site ou sur www.abadiane.net et voir dans l'unité UTools.pas la fonction ImageResizeToBMP

Abadiane
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
1
Réponse à florenth :

je dessines dans le bmpm :

bmpm.canvas.polygon([point(p1, r.top ),


point( r.right -round(c1/2) , r.bottom -round(c2/2)),


point(r.left +round(c1/2), r.bottom -round(c2/2)),


point(p1, r.top )]);



réponse à Abadiane : je consulte le site
Messages postés
1023
Date d'inscription
dimanche 1 août 2004
Statut
Membre
Dernière intervention
17 août 2008
2
Ah, si tu dessines dans le BmpM, c'est normal que ça marche pas.
Car si ta souris est sur le pixel 100,100 de ton PaintBox, comme l'image qui est dedans est agrandie, cela correspond peut être au point 30,30 du BmpM. En gros, il faut appliquer le facteur de redimentionnement horisontal et vertical (calculé par la méthode StrctchDraw) et l'appliquer aux coordonées du curseur.

Bre, quel bazar.

Alors que si, dès le départ, tu as BmpM de la même taille que ton PaintBox, là, plus de problèmes.
Tu dois alors modifier ta procédure FormCrate comme suit :
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
BmpTemp: TBitmap;
begin
//
BmpTemp : = TBitmap.Create;
BmpTemp.LoadFromFile('C:\...carte_dept31__.bmp');
BmpM := TBitmap.Create;
BmpM.Width := PaintBox.Width;
BmpM.Height := PaintBox.Height;
BmpM.Canvas.StretchDraw(BmpM.Canvas.ClipRect, BmpTemp);
BmpTemp.Free;
end ;<hr size ="2" width= "100%">et ta procédure PaintBoxPaint comme ça :
begin
PaintBox.Canvas.Draw(0, 0, BmpM);
end;
<hr size ="2" width="100%">
Si ça ne marche pas, dis nous ce qui cloche avec un maximum de détails.
++

Si tu ne te plantes pas ......
tu ne pousseras jamais
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
1
merci florenth, ça marche impeccable mais lorsque je quitte l'appli,
j'ai violation d'accès ..; puis plein de messagedlg :' runtime error
216 at 00405E86'

ça te parle ?
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
1
Seb, 23 ans, Toulouse
débutant en delphi
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
1
l'erreur intervient si on a créé au moins un site (dessiner un triangle)

si on ouvre et on quitte, ça ne fait pas l'erreur
Messages postés
1023
Date d'inscription
dimanche 1 août 2004
Statut
Membre
Dernière intervention
17 août 2008
2
La runtime error 216 est bien connue mais dans ton cas, je ne vois pas.
Voir la FAQ Delphi

Mais là, c'est bizarre.
Tu es sur d'avoir tout bien recopié ?

Si tu ne te plantes pas ......
tu ne pousseras jamais
Messages postés
1023
Date d'inscription
dimanche 1 août 2004
Statut
Membre
Dernière intervention
17 août 2008
2
Ahhhh, ben dans ce cas, si ton tableau CC[x].Bond n'est pas libéré à la fin de l'appli, tu peux avoir ce genre de problèmes.
Vérifie bien tout
++

Si tu ne te plantes pas ......
tu ne pousseras jamais
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
1
"CC[x].Bond n'est pas libéré" => pour libérer, je fais CC[x].Bond.free ?



PS:tu commences surement à comprendre que je suis vraiment débutant et sans formation de base
Messages postés
1023
Date d'inscription
dimanche 1 août 2004
Statut
Membre
Dernière intervention
17 août 2008
2
Ah non, pas tout à fait.
Tu fais simplement
Finalize(CC);
Mais je ne suis pas sur que cela suffise.
Alors je pense qu'il faut aussi ajouter :
for I := 0 to High(CC) do
Finalize(CC[I].Bond);

"tu commences surement à comprendre que je suis vraiment débutant et sans formation de base"
Si tu es autodidacte (comme moi et une bonne partie des gens sur ce forum) c'est tout à fait compréhensible.
On ne sait jamais par quel bout commencer à apprendre et souvent, on commence par le compliqué en négligeant certaines bases essentielles.
Dur, dur d'être un codeur ^^

++

Si tu ne te plantes pas ......
tu ne pousseras jamais
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
1
voici le code qui provoque toujours une violation d'accès et erreur 216 :

"
procedure TForm1.FormDestroy(Sender: TObject);
var
i :integer;
begin
BmpF.free; // destruction des bitmaps
BmpM.free; // quand on ferme la fiche
for I := 0 to High(CC) do
Finalize(CC[I]);
end;
"
si je ne mets pas le finalize et que je ferme l'appli sans avoir rien dessiné, alors pas de problème.
si je mets le finalize et que je ferme l'appli sans avoir rien dessiné, alors violation d'accès ... erreur 216

?
Messages postés
304
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
10 mars 2012

as-tu essayé avec ZeroMemory(@CC, SizeOf(TSite)) au lieu de

for I := 0 to High(CC) do
Finalize(CC[I]); ??

@+
Messages postés
304
Date d'inscription
lundi 30 décembre 2002
Statut
Membre
Dernière intervention
10 mars 2012

juste une petite précision...si CC est un array of TSite et qu'il est créer dynamiquement il faudra muliplié SizeOf(TSite) par la dimension du tableau cela va de soi !!!
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
1
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
1
@florenth : j'ai bien mis cela dans le ondestroy de ma fiche, mais ça provoque toujours EAccessViolation et erreur 216 dès que je déplace un triangle. par contre, no problème si je ne déplace pas de triangle.
DELPHI m'indique que "Finalize(CC[I].Bond);" ne nécessite pas de Initialize/Finalize.
je ne sais pas comment essayer (dois je le faire ?) la proposition de shinning.
Messages postés
51
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
25 juillet 2006
1
le message EAccessviolation indique la dll ntdll.dll. j'ai fait une recherche sur google et sur commentçamarche.net, il est dit que c'est dû à un virus.
qu'en pensez vous ?