Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Komponenten während der Laufzeit verschieben (https://www.delphipraxis.net/165658-komponenten-waehrend-der-laufzeit-verschieben.html)

tofse 10. Jan 2012 14:43

Komponenten während der Laufzeit verschieben
 
Hallo zusammen,
ich verwende dieses schöne Skript, um TPanel Komponenten innerhalb einer ScrollBox zu verschieben:
Komponenten während der Laufzeit verschieben

Es gibt bei mir nur einen Schönheitsfehler: wenn man den Mauszeiger bei gedrückter Maustaste sehr schnell bewegt, kann es sein, dass (wie soll ich sagen..) das TPanel nicht mehr "nach kommt". Es bleibt stehen, aber
Code:
TMoveCracker(Sender).MouseCapture
aus dem Skript ist noch immer true. Bewege ich dann den Mauszeiger wieder über das TPanel, kann ich dieses weiter bewegen (auch wenn ich die Maustaste vorher sogar loslasse).

Hat jemand einen Tipp, wie ich das TPanel dazubekomme, auch die schnellen Mausbewegungen mitzumachen ?

Danke
Christof

DeddyH 10. Jan 2012 15:11

AW: Komponenten während der Laufzeit verschieben
 
Geht es um alle Panels auf dem Formular?

[edit] Falls ja, versuch es mal hiermit:
Delphi-Quellcode:
type
  TPanel = class(ExtCtrls.TPanel)
  protected
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  end;
 
  TDeinForm = class(TForm)
    ...
  end;

...

procedure TPanel.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
  inherited;
  if ssLeft in Shift then
    begin
      ReleaseCapture;
      Perform(WM_SYSCOMMAND, $F012, 0);
    end;
end;
Das geht auch mit anderen Komponenten, solange sie von TWinControl abstammen. [/edit]

tofse 11. Jan 2012 08:05

AW: Komponenten während der Laufzeit verschieben
 
Danke, das funktioniert super :-D
Nur...wie kann ich jetzt feststellen, wann das Ziehen der Komponente beendet ist?
Vermutlich wegen dem ReleaseCapture wird die Procedure MouseUp nicht mehr aufgerufen.

Edit: Noch eine 2. Frage: wie kann ich während dem Ziehen des TPanel's auf irgendwas reagieren? Z.B. will ich prüfen, ob das TPanel über einen Punkt bewegt wird. In dem anderen Beispiel hatte ich das alles in der Procedure mousemove. Der Code nach dem Perform wird erst ausgeführt, wenn ich das Element nicht mehr bewege....was irgendwie meine erste Frage beantwortet ;-)

Grüße
Christof

Progman 11. Jan 2012 09:03

AW: Komponenten während der Laufzeit verschieben
 
Zitat:

Zitat von tofse (Beitrag 1145324)
Edit: Noch eine 2. Frage: wie kann ich während dem Ziehen des TPanel's auf irgendwas reagieren? Z.B. will ich prüfen, ob das TPanel über einen Punkt bewegt wird. In dem anderen Beispiel hatte ich das alles in der Procedure mousemove. Der Code nach dem Perform wird erst ausgeführt, wenn ich das Element nicht mehr bewege....was irgendwie meine erste Frage beantwortet ;-)

Grüße
Christof

In ControlMouseMove sollte man solche Prüfungen durchführen.

tofse 11. Jan 2012 09:15

AW: Komponenten während der Laufzeit verschieben
 
Hallo,
also ich habe folgenden gekürzten Code:

In einer Unit:
Code:
....
type
  TTermin = Class(TPanel)
....
Dann im Formular:
Code:
...
T:=TTermin.Create(Form1);
T.OnMouseMove:=Form1.ControlMouseMove;
...
Und diese Prozedur:
Code:
procedure TForm1.ControlMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  if ssLeft in Shift then
  begin
    (Sender as TTermin).Dragging:=true;
    ReleaseCapture;
    (Sender as TControl).Perform(WM_SYSCOMMAND, $F012, 0);
    (Sender as TTermin).color:=clGreen;
  end;
end;
Die letzte Zeile mit der Farbzuweisung ist nur zum Testen und soll mein Verständnisproblem zeigen. Erst wenn ich mit dem Ziehen des Elements fertig bin, wird die Farbe grün zugewiesen. Ich verstehe das so, als ob der Code nach Perform auch erst nach dem Ziehen ausgeführt wird.

Du hast geschrieben:
Zitat:

In ControlMouseMove sollte man solche Prüfungen durchführen.
Ich verstehe nicht, wie ich das machen soll, wenn wie hier im Beispiel grün auch erst nach dem Verschieben zugewiesen wird, und nicht während dem Ziehen.

Danke und Grüße
Christof

Progman 11. Jan 2012 09:56

AW: Komponenten während der Laufzeit verschieben
 
Meine Anmerkung bezog sich auf den Original-Code aus dem Link:
Delphi-Quellcode:
procedure TForm1.ControlMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  if FDragging then
    with Sender as TControl do
    begin
      Left := X - FDownX + Left;
      Top := Y - FDownY + Top;
      //in etwa: if (Left=20 and Top>20) then.....
    end;
end;

tofse 11. Jan 2012 10:01

AW: Komponenten während der Laufzeit verschieben
 
Achso...da hat das auch funktioniert, aber wie beschrieben ist die "Performance" da nicht gerade optimal.
Von daher würde ich gerne schon das hier verwenden...
Code:
ReleaseCapture;
Perform(WM_SYSCOMMAND, $F012, 0);
...muss aber halt unbedingt während dem mousemove ein paar Berechnungen vornehmen. Bis jetzt habe ich es nicht hinbekommen.
Habe inzwischen den Code in onmousedown gesteckt, aber während dem Ziehen wird mousemove leider noch immer nicht aufgerufen.

Christof

Progman 11. Jan 2012 10:39

AW: Komponenten während der Laufzeit verschieben
 
Ja, weil dieses

Delphi-Quellcode:
ReleaseCapture;
Perform(WM_SYSCOMMAND, $F012, 0);
die Wirkungsweise dieser Proceduren unterbricht.
Ich arbeite auch grad an einem Programm, dass diese Routinen nutzt. Allerdings verschiebe ich TImages. Und ich habe kein Hängenbleiben oder irgendwelche Verzögerungen beim Schieben.
Vielleicht ist dein System einfach nur zu träge für sowas?

tofse 11. Jan 2012 11:09

AW: Komponenten während der Laufzeit verschieben
 
Hm, und da gibt es keine Möglichkeit?
Wie gesagt, mit der 2. Variante habe ich beim Ziehen keinerlei Probleme, von daher hat es wohl nichts mit Trägheit zu tun.

Und "hängenbleiben" ist auch vielleicht das falsche Wort, da ruckelt nichts etc. Es ist nur so, dass das Panel manchmal an der Stelle bleibt, wenn ich den Mauszeiger bei gedrückter Taste sehr schnell bewege. Dann ist der Zeiger plötzlich außerhalb vom Panel und sobald ich den Zeiger wieder über das Panel ziehe, kann ich das Panel weiter bewegen. Das ist einfach nicht schön :-(

Du kannst das bei deinem Programm nicht nachvollziehen?

Christof

SirThornberry 11. Jan 2012 12:19

AW: Komponenten während der Laufzeit verschieben
 
@DeddyH: Das ganze würde im MouseDown aber bedeutend mehr Sinn machen oder übersehe ich irgendwas?

tofse 11. Jan 2012 12:20

AW: Komponenten während der Laufzeit verschieben
 
Zitat:

Zitat von SirThornberry (Beitrag 1145381)
@DeddyH: Das ganze würde im MouseDown aber bedeutend mehr Sinn machen oder übersehe ich irgendwas?

Hatte ich schon, aber mousemove wird danach leider nicht mehr aufgerufen :-(

DeddyH 11. Jan 2012 12:21

AW: Komponenten während der Laufzeit verschieben
 
Ich hatte das seinerzeit einmal ins MouseMove verschoben, nur fällt mir gerade der Grund nicht mehr ein.

tofse 11. Jan 2012 15:52

AW: Komponenten während der Laufzeit verschieben
 
Hallo,
erst mal Danke für die Anregungen.
Da ich unbedingt das mousemove benötige, um beim Verschieben des Panels die Koordinaten zu berechnen (wegen Scrollen in einer Scrollbox), bin ich wieder zum ursprünglichen Code zurück, auch wenn ich wegen der beschriebenen Probleme nicht glücklich bin.

Ich habe nun versucht, irgendwie zu tricksen, dass der Mauszeiger auch bei schnellen Bewegungen das Panel nicht verlassen kann. Hierzu wollte ich mouseleave einsetzen. Aber in der beschriebenen Situation wird die Prozedur nicht aufgerufen. Wieso ?

Als zweiten Versuch wollte ich im mousemove die übergebenen X,Y Koordinaten mit der Breite bzw. Höhe des Panels abgleichen, d.h. wenn die = sind, darauf reagieren. Das hat auch nicht funktioniert. Daraufhin habe ich mir während dem Ziehen X und Y im Panel ausgeben lassen (bei mousemove), da habe ich dann gesehen, dass diese sich nach dem ersten mousedown nicht mehr verändern.....:?:


Hat jemand noch einen Tipp, wie ich da vorgehen könnte ?

Vielen vielen Dank
Christof

einbeliebigername 11. Jan 2012 18:51

AW: Komponenten während der Laufzeit verschieben
 
Zitat:

Zitat von tofse (Beitrag 1145438)
Daraufhin habe ich mir während dem Ziehen X und Y im Panel ausgeben lassen (bei mousemove), da habe ich dann gesehen, dass diese sich nach dem ersten mousedown nicht mehr verändern.....:?:

Ich weiß jetzt nicht, wie du die Werte ausgegeben hast. Ein Label z.B. kommt, während das MouseCapture an ist, nicht zum Neuzeichnen, so das sich scheinbar nichts ändert.

Zitat:

Zitat von tofse (Beitrag 1145438)
Hat jemand noch einen Tipp, wie ich da vorgehen könnte ?


Du könntest dir mal mit
Delphi-Quellcode:
OutputDebugString(PChar(Format('ControlMouse...: Sender.MouseCapture= %s', [BoolToStr(TMoveCracker(Sender).MouseCapture, True)])));
den Wert vom MouseCapture ins Ereignisprotokoll schreiben lassen. Jeweils am Anfang und Ende von ...Down, ...Up und ...Move. Vielleicht wird das vom Panel weggenommen. Denn wenn MouseCapture an ist, bekommt nur noch dieses Control die Mausnachrichten, selbst wenn sich die Maus außerhalb der Controls befindet.

Einbeliebigername.

tofse 12. Jan 2012 06:57

AW: Komponenten während der Laufzeit verschieben
 
Hallo,

verstehe ich nicht. Habe den OutputDebugString eingebaut, und nur im mouseup wird true ausgegeben, sonst immer false.
Trotzdem funktioniert ja grundsätzlich das Verschieben :?

Christof

roga 12. Jan 2012 07:50

AW: Komponenten während der Laufzeit verschieben
 
Hallo Christof,

ich füge hier mal einige Codeschnipsel aus meiner Komponente ein, vielleicht kannst Du damit etwas anfangen.

Delphi-Quellcode:
// Benötigte Variable
  FDragging: Boolean;

procedure OnMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  ...
  // Drag wird begonnen
  FDragging := True;
  ReleaseCapture;
  Perform(WM_SysCommand, $F012, 0);
  // Folgende Zeile ist sehr wichtig! Sonst keine Auslösung
  if Assigned(OnMouseUp) then MouseUp(Button, Shift, X, Y);
end;

procedure OnMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if FDragging then
  begin
    ...
  end;
end;

procedure OnMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if FDragging then
  begin
    // Drag wird beendet
    FDragging := False;
    ...
  end;
end;
DoubleBuffered sollte auch aktiviert werden.

Gruß roga

tofse 12. Jan 2012 08:04

AW: Komponenten während der Laufzeit verschieben
 
Wird das bei Dir aufgerufen ?
Zitat:

Zitat von roga (Beitrag 1145525)
Code:
procedure OnMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if FDragging then
  begin
    ...
  end;
end;


roga 12. Jan 2012 09:01

AW: Komponenten während der Laufzeit verschieben
 
Liste der Anhänge anzeigen (Anzahl: 1)
Du hast Recht, in dieser Komponente brauchte ich nur das MouseUp-Ereignis für Korrekturen. Die einfachste Lösung wäre über einen Timer, hänge Dir mal eine Demo und die Source an.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:22 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