Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Move eines TImage (https://www.delphipraxis.net/175518-move-eines-timage.html)

Satyr 27. Jun 2013 18:30

Move eines TImage
 
Guten Abend,

ich werkel gerade an einem kleinem Programm das aus mehreren Bildern eine Art Collage erstellt. Vom Grundgerüst recht einfach.
Eine PaintBox, darauf ein gleichgroßes TImage als optionaler Hintergrund. Darauf erzeuge ich dann wieder TImages mit beliebigen Bildinhalten. Das Canvas der PaintBox wird zum Schluss abgespeichert und ich habe das Bild.
Klappt bis dahin auch wunderbar.
Jetzt wollte ich einbauen das man die oberen TImages verschieben kann.
Erst ein einfaches Drag&Drop versucht, welches aber nicht so funktioniert hat wie es sollte. Das Drop war nicht 100% auf den richtigen Koordinaten und der Mauszeiger nicht das TImage.
Also versuche ich momentan schlicht die Komponente zu bewegen. Mit folgendem Code:

Delphi-Quellcode:
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 SetCapture(TWinControl(Sender).Handle);
 GetCursorPos(oldPos);
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
const
  minWidth = 20;
  minHeight = 20;
var
  newPos: TPoint;
  frmPoint : TPoint;
begin
    with TImage(Sender) do
    begin
        GetCursorPos(newPos);
        //Screen.Cursor := crSize;
        Left := Left - oldPos.X + newPos.X;
        Top := Top - oldPos.Y + newPos.Y;
        oldPos := newPos;
    end;
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    Screen.Cursor := crDefault;
    ReleaseCapture;
end;
Das Problem ist, ich kann es nicht mal versuchen zu testen. Sobald der Mauszeiger über dem betreffenden TImage ist, verschwindet dieses. Komplett. Nichts mehr da.
Ich verstehe einfach nicht wieso.

Jemand eine Idee?

Gruß,
Andreas

MrMooed 27. Jun 2013 20:01

AW: Move eines TImage
 
Zitat:

Zitat von Satyr (Beitrag 1219885)
Delphi-Quellcode:
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
const
  minWidth = 20;
  minHeight = 20;
var
  newPos: TPoint;
  frmPoint : TPoint;
begin
    with TImage(Sender) do
    begin
        GetCursorPos(newPos);
        //Screen.Cursor := crSize;
        Left := Left - oldPos.X + newPos.X; // <--- 
        Top := Top - oldPos.Y + newPos.Y;  // <--- 
        oldPos := newPos;
    end;
end;

Wenn, wie du sagst, der Fehler auftritt, sobald du mit der Maus über dem TImage bist, vermute ich dass es die MouseMove Methode ist die Probleme bereitet. Weißt du deiner Variable oldPos denn irgend eine Anfangsposition zu ? Vielleicht greift er sonst auf eine Stelle zu die gerade im Speicher lag - und dein TImage landet im Nirvana

Satyr 27. Jun 2013 20:10

AW: Move eines TImage
 
Ich habs grade noch mal durchgeguckt. Das wirds sein, das hab ich tatsächlich vergessen. Müsste in den MouseDown, oder?

MrMooed 27. Jun 2013 21:10

AW: Move eines TImage
 
im MouseDown weißt du ihm ja schon die Position zu.
Delphi-Quellcode:
 GetCursorPos(oldPos)
Aber den Wert hat er noch nicht wenn du bloß mit der Maus auf dem Image bist - allerdings noch nicht geklickt hast.
Du könntest einfach in deiner OnMouseMove Methode überprüfen ob eine Taste gedrückt wurde:

Delphi-Quellcode:
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
const
  minWidth = 20;
  minHeight = 20;
var
  newPos: TPoint;
  frmPoint : TPoint;
begin
  if ssLeft in Shift // würde die Linke Taste gedrückt? (oder welche auch immer du drücken möchtest)
    then with TImage(Sender) do
           begin
             GetCursorPos(newPos);
             //Screen.Cursor := crSize;
             Left := Left - oldPos.X + newPos.X;
             Top := Top - oldPos.Y + newPos.Y;
             oldPos := newPos;
           end;
end;

Medium 27. Jun 2013 21:16

AW: Move eines TImage
 
Da die nächste Frage vermutlich wird: "Wie speicher ich mehrere Images in einer Datei ab?": Gar nicht, der Ansatz ist dafür ungeeignet. (Man könnte einen Screenshot des Formulars machen und auf die Grenzen der Images zurecht schneiden, aber das ist zum schütteln.)

Der richtige(re) weg wäre das Weglassen von TImage, und statt dessen alles auf einer Paintbox zu malen. Die Einzelbilder sollte man sich in eigenen kleinen Klassen bereit halten, die zum einen ein TBitmap mit dem Bild, zum Anderen die X- und Y-Koordinaten (und ggf. Skalierung) beinhaltet. Dazu noch eine kleine Manager-Klasse, die das Selektieren und Bewegen von den Bildern kapselt, und das Ergebnis auf einen beliebigen Canvas blitten kann (zum Zeichnen auf die Paintbox oder ein TBitmap zum speichern z.B.), und schon wird die Nummer deutlich sauberer und handlicher.

Satyr 27. Jun 2013 21:26

AW: Move eines TImage
 
Zitat:

Zitat von MrMooed (Beitrag 1219893)
im MouseDown weißt du ihm ja schon die Position zu.
Delphi-Quellcode:
 GetCursorPos(oldPos)
Aber den Wert hat er noch nicht wenn du bloß mit der Maus auf dem Image bist - allerdings noch nicht geklickt hast.
Du könntest einfach in deiner OnMouseMove Methode überprüfen ob eine Taste gedrückt wurde:

Delphi-Quellcode:
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
const
  minWidth = 20;
  minHeight = 20;
var
  newPos: TPoint;
  frmPoint : TPoint;
begin
  if ssLeft in Shift // würde die Linke Taste gedrückt? (oder welche auch immer du drücken möchtest)
    then with TImage(Sender) do
           begin
             GetCursorPos(newPos);
             //Screen.Cursor := crSize;
             Left := Left - oldPos.X + newPos.X;
             Top := Top - oldPos.Y + newPos.Y;
             oldPos := newPos;
           end;
end;

Danke, das hat mir geholfen. Zwar nicht 1:1 übernommen aber es hat die Richtung gezeigt.
Ich habe mir ein Boolean erstellt und speicher darin ob grade ein Drag stattfindet oder nicht.
Damit geht es perfekt *s*.

@Medium
Das es nicht 100% die sauberste Lösung ist wie ich das mache, ist mir klar. Aber es ist die schnellste. Das wird kein großes Programm, da reicht es quick und leicht dirty. Ich speicher einfach das Canvas der PaintBox ab und habe mein Bild... inkl. aller darüber liegenden Bildern.
Nur wie genau ich die dynamisch erzeugten Bilder bewege weiß ich noch nicht genau. Aber eventuell ist die dynamische Erzeugung nicht nötig. Das muss ich noch abklären.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:43 Uhr.

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