Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi canvas probleme, oder so (https://www.delphipraxis.net/98271-canvas-probleme-oder-so.html)

cherry 24. Aug 2007 08:55


canvas probleme, oder so
 
hi

ich habe ein kleines Problem mit meiner Komponente...
und zwar habe ich folgenden bug entdeckt, und weiss nicht an was es liegt, vielleicht könnt ihr mir weiterhelfen.
Die ganze Komponente findet ihr in unsererOpen Source Library.

Das Problem:

Wenn ich ein Icon in mein Button zeichne soll er in die mitte kommen. In den meisten Konstellationen funktioniert das auch einwandfrei, habe ich aber ein icon 16*16 auf einer Canvas 22*22, ist das Bild, gerade nachdem ich mein Programm starte nicht in der mitte. Sobald ich dann mit der Maus darüberfahre, geht es in die mitte und wird von diesem Moment an immer korrekt angezeigt. Bis ich das Programm wieder neu starte... mit Bildern und Icons ab 32*32 habe ich dieses Problem nie!

hier die Routinen die das Bild zeichnen, vielleicht fällt euch ja etwas auf, PS: ich verwende nur ein Bild, also
PictureUseOnlyOne := true!

Delphi-Quellcode:
procedure TEButton.DrawPicture;
begin
 if (FPicture <> nil) then
   Canvas.Draw((Width - FPicture.Graphic.Width) div 2,(Height - FPicture.Graphic.Height) div 2 ,FPicture.Graphic);
end;

procedure TEButton.DrawPictureOver;
begin
 if (FPictureUseOnlyOne) then
 begin
  if (FPicture <> nil) then
   Canvas.Draw((Width - FPicture.Graphic.Width) div 2,(Height - FPicture.Graphic.Height) div 2 ,FPicture.Graphic);
 end
 else
 begin
  if (FPictureOver <> nil) then
  Canvas.Draw((Width - FPictureOver.Graphic.Width) div 2,(Height - FPictureOver.Graphic.Height) div 2 ,FPictureOver.Graphic);
 end;
end;

procedure TEButton.DrawPictureDown;
begin
 if (FPictureUseOnlyOne) then
 begin
  if (FPicture <> nil) then
   Canvas.Draw((Width - FPicture.Graphic.Width) div 2,(Height - FPicture.Graphic.Height) div 2 ,FPicture.Graphic);
 end
 else
 begin
  if (FPictureDown <> nil) then
   Canvas.Draw((Width - FPictureDown.Graphic.Width) div 2,(Height - FPictureDown.Graphic.Height) div 2 ,FPictureDown.Graphic);
 end;
end;

sirius 24. Aug 2007 09:08

Re: canvas probleme, oder so
 
Beim ersten mal Zeichnen ist FPicture.Width und FPicture.Height = 32, warum auch immer.

cherry 24. Aug 2007 09:12

Re: canvas probleme, oder so
 
tatsache?
wie hast du das rausbekommen? hast du mein beispiel nachkonstruiert und die Komponente runtergeladen?

cherry 24. Aug 2007 09:33

Re: canvas probleme, oder so
 
ich hab dasselbe icon in ein jpg umgewandelt. -> Das Problem besteht nur bei Icons!
Ich denke es liegt vielleicht daran das Standard Icons 32*32 sind, und er beim ersten ausrechnen
der canvas koordinaten die standard grössen statt der realen grösse verwendet.

Aber wie kann ich dieses Problem nur lösen??

sirius 24. Aug 2007 10:03

Re: canvas probleme, oder so
 
Zitat:

Zitat von cherry
tatsache?
wie hast du das rausbekommen? hast du mein beispiel nachkonstruiert und die Komponente runtergeladen?

Jep


Zitat:

Zitat von cherry
ich hab dasselbe icon in ein jpg umgewandelt. -> Das Problem besteht nur bei Icons!
Ich denke es liegt vielleicht daran das Standard Icons 32*32 sind, und er beim ersten ausrechnen
der canvas koordinaten die standard grössen statt der realen grösse verwendet.

Jep

Er nimmt zu Anfang die Standardgrößen des Systems (MSDN-Library durchsuchengetsystemmetrics)
Das Zuweisen eines Icons bewirkt ja nur ein Hin- und Herschieben von einem Stream (urspr. FileStream der Icondatei). Der Header (beim Icon) wird nur ausgewertet, wenn das Icon das erste mal gezeichnet wird. Dies geschieht über die Methode TIcon.Handleneeded --> ReadIcon. Deswegen sind nach dem ersten Draw die Angaben richtig.
Demnach musst du dir nur ersatzweise das Handle besorgen "Button.Picture.Icon.Handle" oder den Stream selber auswerten ( Byte 7 und 8 )


Edit: "8 Klammer zu" wer denkt schon jedes mal daran 8)

cherry 24. Aug 2007 14:12

Re: canvas probleme, oder so
 
danke für deine bestätigung... ich habe jetzt schon einiges probiert, aber ich kriegs nicht hin.
das arbeiten mit handle ist mir völlig fremd...

wär toll wenn du mir ein bisschen auf die Sprünge helfen könntest.. :roll:

sirius 24. Aug 2007 15:12

Re: canvas probleme, oder so
 
Mit dem Handle ist nur ein Trick
Du musst mit dem Handle nix machen. Einfach nur das Handle verlangen und dann wegschmeissen. Denn wenn du das Handle verlangst und das Icon ist grad neu geladen (ergo: er hat weder ein Handle noch die richtigen Angaben zu Höhe und Breite) dann besorgt er sich ein Handle und nebenbei schaut er noch nach, wie groß eigentlich das Icon ist. Das ist quasi von hinten durch die Brust ins Auge.

du musst also vorm ersten abfragen der Abmaße mal das Handle verlangen. Machs doch im OnChangeereignis:
Delphi-Quellcode:
procedure TEButton.PictureChanged(Sender:Tobject);
begin
  if (FPicture<>nil) and (FPicture.Graphic.ClassName='TIcon')
    then FPicture.Icon.handle; //nur verlangen, du brauchst dir das Handle nicht zu merken
   //stell dir einfach vor durch diese Methode verlangst du vom Objekt mal in den Icon-Header zu schauen
end;
Im Constructor:
Delphi-Quellcode:
FGradientDown:=gdTopToBottom;
FPicture:=TPicture.Create;
Fpicture.OnChange:=Picturechanged; //neue Zeile
FPictureOver:=TPicture.Create;
Das musst du wahrscheinlich auch noch für die anderen beiden TPicture machen.

Das scheint ein Fehler in der Implementierung von TPicture bzw TIcon zu sein. Man geht einfach nicht davon aus, dass jemand die Abmaße braucht bevor das Bild gezeichnet wird.

cherry 24. Aug 2007 16:07

Re: canvas probleme, oder so
 
vielen Dank für deine Hilfe...
Es hat auf den ersten Bilck geklappt. Muss den Code noch vervollständigen...
ich schick dann am Montag noch den Code, wie ich es jetzt gemacht habe..

liebe grüsse und ein schönes wochenende

enemyleft

cherry 31. Aug 2007 13:31

Re: canvas probleme, oder so
 
So, ich hab das bei mir jetzt so implementiert. Ist das unschön? oder kann man das so lassen?

Delphi-Quellcode:
// Das Handle wird nicht benötigt.
// Durch diese Methode verlangt man vom Objekt mal in den Icon-Header zu
// schauen ansonsten könnte man die reale Icongrösse nicht erruieren bevor
// es das erste mal gezeichnet wird.

procedure TEButton.DrawPicture;
begin
  if (FPicture <> nil) then
  begin
    if (FPicture.Graphic is TIcon) then FPicture.Icon.handle;
    Canvas.Draw((Width - FPicture.Width) div 2,(Height - FPicture.Height) div 2 ,FPicture.Graphic);
  end;
end;

procedure TEButton.DrawPictureOver;
begin
 if (FPictureUseOnlyOne) then
 begin
  if (FPicture <> nil) then
  begin
   if (FPicture.Graphic is TIcon) then FPicture.Icon.handle;
   Canvas.Draw((Width - FPicture.Width) div 2,(Height - FPicture.Height) div 2 ,FPicture.Graphic);
  end;
 end
 else
 begin
  if (FPictureOver <> nil) then
  begin
   if (FPictureOver.Graphic is TIcon) then FPictureOver.Icon.handle;
   Canvas.Draw((Width - FPictureOver.Width) div 2,(Height - FPictureOver.Height) div 2 ,FPictureOver.Graphic);
  end;
 end;
end;

procedure TEButton.DrawPictureDown;
begin
 if (FPictureUseOnlyOne) then
 begin
  if (FPicture <> nil) then
  begin
   if (FPicture.Graphic is TIcon) then FPicture.Icon.handle;
   Canvas.Draw((Width - FPicture.Width) div 2,(Height - FPicture.Height) div 2 ,FPicture.Graphic);
  end;
 end
 else
 begin
  if (FPictureDown <> nil) then
  begin
   if (FPictureDown.Graphic is TIcon) then FPicture.Icon.handle;
   Canvas.Draw((Width - FPictureDown.Width) div 2,(Height - FPictureDown.Height) div 2 ,FPictureDown.Graphic);
  end;
 end;
end;

end.

shmia 31. Aug 2007 13:54

Re: canvas probleme, oder so
 
Zitat:

Zitat von cherry
Ist das unschön? oder kann man das so lassen?

Na ja, programmiert nach dem Motto "blos nicht Code Teile wiederverwenden, lieber Copy & Paste"
Delphi-Quellcode:
procedure TEButton.DrawPictureOver;
begin
 if (FPictureUseOnlyOne) then
 begin
 (*
   if (FPicture <> nil) then
   begin
    if (FPicture.Graphic is TIcon) then FPicture.Icon.handle;
    Canvas.Draw((Width - FPicture.Width) div 2,(Height - FPicture.Height) div 2 ,FPicture.Graphic);
   end; *)
   DrawPicture; // das ist doch das Gleiche
 end


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:48 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz