AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Zoom mit Mausrad

Offene Frage von "himitsu"
Ein Thema von e-gon · begonnen am 12. Sep 2025 · letzter Beitrag vom 12. Sep 2025
Antwort Antwort
e-gon

Registriert seit: 7. Jul 2003
Ort: Stuttgart
165 Beiträge
 
Delphi 6 Enterprise
 
#1

Zoom mit Mausrad

  Alt Heute, 10:40
Hallo zusammen,

ich bräuchte mal Eure Hilfe beim Zoomen. Irgendwie sehe ich den Wald vor lauter Bäumen nicht mehr...

Der Aufbau des Programms ist simpel:
Auf TForm eine TScrollBox (namens SBSpielplan), darin ein TPanel (PSpielplan), darauf noch ein TImage (IMGSpielplan) und neben der ScrollBox eine TComboBox (CBPlanZoom).

Via CTRL-Taste und Mausrad soll nun in oder aus dem Panel hinen-/herausgezoomt werden, wobei der Bildausschnitt unter dem Cursor an genau derselben Stelle bleiben soll.

Der Code dazu sieht folgendermaßen aus:
Delphi-Quellcode:
implementation

var
  PlanZoomFaktor: Double;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  PlanResize(100);
  IMGSpielplan.Align:= alClient;
  IMGSpielplan.Picture.Bitmap.LoadFromFile('D:\Spielplan.bmp');

  PSpielplan.Top:= 0;
  PSpielplan.Left:= 0;
  PSpielplan.Width:= IMGSpielplan.Picture.Bitmap.Width;
  PSpielplan.Height:= IMGSpielplan.Picture.Bitmap.Height;
end;

procedure TForm1.PlanResize(Size: Integer);
begin
  if Size<10 then Size:= 10;

  CBPlanZoom.Text:= IntToStr(Size)+'%';
  CBPlanZoom.Tag:= Size;
  PlanZoomFaktor:= Size/100;

  // Größe des Panels anpassen
  PSpielplan.Width:= Round(IMGSpielplan.Picture.Bitmap.Width*PlanZoomFaktor);
  PSpielplan.Height:= Round(IMGSpielplan.Picture.Bitmap.Height*PlanZoomFaktor);
end;

procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var ZoomFaktorAlt: Extended;
     PointPanel,PointMouse: TPoint;
     e: Extended;
begin
  if (Shift=[ssCtrl]) and
     PtInRect(PSpielplan.ClientRect,PSpielplan.ScreenToClient(Mouse.CursorPos)) then begin
    // alter Zoomfaktor sichern
    ZoomFaktorAlt:= PlanZoomFaktor;

    // Cursor-Positionen ermitteln
    PointMouse:= Mouse.CursorPos;
    PointPanel:= PSpielplan.ScreenToClient(PointMouse);

    // Absolutwert von PointMouse berechnen
    Dec(PointMouse.X,SBSpielplan.Left);
    Dec(PointMouse.Y,SBSpielplan.Top);

    // Mouserad auswerten
    if WheelDelta<>0 then begin
      if WheelDelta>0 then PlanResize(CBPlanZoom.Tag+10)
      else PlanResize(CBPlanZoom.Tag-10);

      // Änderungsfaktor und neue Panelposition berechnen
      e:= PlanZoomFaktor/ZoomFaktorAlt;
      PointPanel.X:= Round(PointPanel.X*e);
      PointPanel.Y:= Round(PointPanel.Y*e);

      // Scrollbalken an Mouseposition anpasen
      SBSpielplan.HorzScrollBar.Position:= PointPanel.X-PointMouse.X;
      SBSpielplan.VertScrollBar.Position:= PointPanel.Y-PointMouse.Y;
    end;

    Handled:= True;
  end;
end;

end.
Das Zoomen funktioniert auch soweit, nur bleibt der Bildausschnitt unter dem Cursor nach dem Zoomen (egal ob vergrößern oder verkleinern) einfach nicht unter dem Cursor sondern ist immer nach rechts unten verschoben. Allerdings finde ich den Fehler einfach nicht.

Kann mir da jemand von Euch helfen? Was ist mein Denkfehler?

Gruß
e-gon
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.745 Beiträge
 
Delphi 12 Athens
 
#2

AW: Zoom mit Mausrad

  Alt Heute, 12:16
Erstmal MousePos anstatt Mouse.CursorPos
da muß dann auch kein ScreenToClient genutzt werden, da die Position bereits passt.

Dieses MousePos mit dem alten Zoomfaktor und dem neuen Zoomfaktor verrechnen (Ergebnis in neue Variable)
und dann hast du über die Differenz von MousePos und NeuerMousePos den Wert, um welchen das Image verschoben werden muß.

Du bekommst hier bereits die Position als Parameter rein,
aber selbst wenn nicht, dann die Position einmal zu Beginn in eine Variable.

Mit Live-Daten zu arbeiten (Mouse.CursorPos) ist extrem ungünstig.
Wenn du die Maus verschiebst, während noch berechnet wird, dann stimmen die Folgeberechnungen natürlich nicht mehr.

Die aktuelle Position ist auch nicht nötig.
Es müsste doch ein HorzScrollBar.ScrollBy geben ... da einfach nur die Differenz rein.



PS: Nicht auf Picture.Bitmap zugreifen, sondern Picture.LoadFromFile, Picture.Width usw.
Dann hast du zukünftig auch die Möglichkeit beim Load z.B. ein PNG, JPEG oder sonstwas zu laden.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
e-gon

Registriert seit: 7. Jul 2003
Ort: Stuttgart
165 Beiträge
 
Delphi 6 Enterprise
 
#3

AW: Zoom mit Mausrad

  Alt Heute, 12:48
Hallo himitsu,

vielen Dank für die schnelle Antwort.

Wenn ich Dich richtig verstanden habe, sollte mein Code jetzt so aussehen:
Delphi-Quellcode:
procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var ZoomFaktorAlt: Extended;
     Point,PointMouse: TPoint;
     e: Extended;
begin
  PointMouse:= Mouse.CursorPos;

  if (Shift=[ssCtrl]) and
     PtInRect(PSpielplan.ClientRect,PSpielplan.ScreenToClient(PointMouse)) then begin
    // alter Zoomfaktor sichern
    ZoomFaktorAlt:= PlanZoomFaktor;

    // Mouserad auswerten
    if WheelDelta<>0 then begin
      if WheelDelta>0 then PlanResize(CBPlanZoom.Tag+10)
      else PlanResize(CBPlanZoom.Tag-10);

      // Änderungsfaktor berechnen und auf Panelposition anwenden
      e:= PlanZoomFaktor/ZoomFaktorAlt;
      Point.X:= MousePos.X-Round(MousePos.X*e);
      Point.Y:= MousePos.Y-Round(MousePos.Y*e);

      // Scrollbalken an Mouseposition anpasen
      SBSpielplan.HorzScrollBar.Position:= SBSpielplan.HorzScrollBar.Position+Point.X;
      SBSpielplan.VertScrollBar.Position:= SBSpielplan.VertScrollBar.Position+Point.Y;
    end;

    Handled:= True;
  end;
end;
Jetzt springt der Bildausschnitt unter dem Cursor aber immer noch. Bei Hineinscrollen nach rechts unten, beim Herausscrollen nach links oben.

Oder habe ich da was falsch verstanden?

PS: Danke für den Hinweis!

Gruß
e-gon
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.745 Beiträge
 
Delphi 12 Athens
 
#4

AW: Zoom mit Mausrad

  Alt Heute, 13:11
ich glaub so in etwa
Delphi-Quellcode:
                                                                                          vvvvvvvv
procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
  ZoomFaktorAlt: Extended;
  NewMousePos, Difference: TPoint;
begin
  if (Shift = [ssCtrl]) {and PtInRect(PSpielplan.ClientRect, PSpielplan.ParentToClient(MousePos))} then begin
    if WheelDelta <> 0 then begin
      ZoomFaktorAlt := PlanZoomFaktor;
      if WheelDelta > 0 then
        PlanResize(CBPlanZoom.Tag + 10)
      else
        PlanResize(CBPlanZoom.Tag - 10);

      // Mausposition in neuen Zoomfaktor umrechnen, die Verschiebung bestimmen und dann um das verschieben
      NewMousePos.X := Round(NewMousePos.X / ZoomFaktorAlt * PlanZoomFaktor);
      NewMousePos.Y := Round(NewMousePos.Y / ZoomFaktorAlt * PlanZoomFaktor);
      Difference := NewMousePos.Subtract(MousePos); // oder andersrum rechnen? MousePos.Subtract(NewMousePos)
      SBSpielplan.ScrollBy(Difference.X, Difference.Y); // klar, man könnte auch Position:=Position+OffsetBzwDifferenz rechnen, oder Position:=Position-Alt+Neu, aber das kann die Komponente ja übernehmen
    end;
    Handled:= True;
  end;
end;
Liegt das TImage eigentlich auf Pos 0:0?
Wenn nicht, dann muß dieses Offest vorher von MousePos abgezogen werden, da das Zommen ja erst ab dieser Stelle beginnt (ParentToClient)

hmmm, wieso gibt es nur Add/Substract, aber kein MulDiv, im, bzw. für TPoint und TRect
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (Heute um 13:24 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:39 Uhr.
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