Einzelnen Beitrag anzeigen

oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#22

Re: Komponente im Raster verschieben

  Alt 30. Aug 2007, 09:00
Hi Leute,

also das mit dem Verschieben zur Laufzeit hat mir einige Kopfschmerzen bereitet. Das lag zum einen daran, dass man erst mal verstehen muß was wann sich ändert und dann muss man es auch noch schaffen seine Gehirnwindungen zu entknoten und einen machbaren ansatz finden.

Hier jetzt mein Ergebnis. Wenn jemand Verbesserungsvorschläge hat, her damit.

noch mal die Aufgabenstellung zum Verständnis:
- Das Control soll zur Laufzeit in einem Raster der Weite X verschoben werden können.
- Das Verschieben erfolgt mittels:
Delphi-Quellcode:
  //Fängt alle Mausereignisse ab
  ReleaseCapture;
  // verschiebt das Control (hängt am Mauszeiger)
  TWinControl(self).Perform(WM_SYSCOMMAND, $F012, 0);
in der vererbten MouseDown Methode.
- Das Control soll nicht erst nach dem Droppen einrasten, sondern fortlaufend während des movens.

Umsetzung:
Delphi-Quellcode:
  TBaseCustomControl = class(TCustomControl)
  private
    FGrid: Boolean; // Gitter zum einrasten an
    FGridWidth: Integer; // Pixelweite des Gitters
    FOldScreenRect : TRect; // letzte Größe des ClientRect beim moven
    MoveOffsetX, MoveOffsetY : Integer; // komulierte X-, Y-Offsets beim moven
    procedure WMSizing(var AMsg: TMessage); message WM_SIZING;
    procedure WMMoving(var AMsg: TMessage); message WM_MOVING;
....
  public
    property Grid : Boolean read FGrid write FGrid;
    property GridWidth : Integer read FGridWidth write FGridWidth;
...

procedure TBaseCustomControl.WMMoving(var AMsg: TMessage);
var ARect : PRect;
begin
  // am Gitter ausrichten
  if Grid then begin
    ARect := PRect(AMsg.lParam);

    // Startwert für Left setzen und auf Raster korrigieren
    if (FOldScreenRect.Left = 0) or
      ((FOldScreenRect.Left mod FGridWidth) > 0) then
      FOldScreenRect.Left := ARect.Left div FGridWidth * FGridWidth;

    // Startwert für Right setzen und auf Raster korrigieren
    if (FOldScreenRect.Right = 0) or
      ((FOldScreenRect.Right mod FGridWidth) > 0) then
      FOldScreenRect.Right := ARect.Right div FGridWidth * FGridWidth;

    // Startwert für Top setzen und auf Raster korrigieren
    if (FOldScreenRect.Top = 0) or
      ((FOldScreenRect.Top mod FGridWidth) > 0) then
      FOldScreenRect.Top := ARect.Top div FGridWidth * FGridWidth;

    // Startwert für Bottom setzen und auf Raster korrigieren
    if (FOldScreenRect.Bottom = 0) or
      ((FOldScreenRect.Bottom mod FGridWidth) > 0) then
      FOldScreenRect.Bottom := ARect.Bottom div FGridWidth * FGridWidth;

    Dec(MoveOffsetX, (ARect.Left - FOldScreenRect.Left));
    Dec(MoveOffsetY, (ARect.Top - FOldScreenRect.Top));
    // in X-Richtung verschieben
    if Abs(MoveOffsetX) > FGridWidth then begin
      // über das Raster hinaus
      Dec(ARect.Left, (FGridWidth*MoveOffsetX div Abs(MoveOffsetX)));
      Dec(ARect.Right, (FGridWidth*MoveOffsetX div Abs(MoveOffsetX)));
      MoveOffsetX := 0;
    end else begin
      ARect.Left := FOldScreenRect.Left;
      ARect.Right := FOldScreenRect.Right;
    end;
    // in Y-Richtung verschieben
    if Abs(MoveOffsetY) > FGridWidth then begin
      // über das Raster hinaus
      Dec(ARect.Top, (FGridWidth*MoveOffsetY div Abs(MoveOffsetY)));
      Dec(ARect.Bottom, (FGridWidth*MoveOffsetY div Abs(MoveOffsetY)));
      MoveOffsetY := 0;
    end else begin
      ARect.Top := FOldScreenRect.Top;
      ARect.Bottom := FOldScreenRect.Bottom;
    end;
    FOldScreenRect := ARect^;
  end;
end;
Jo, so klappt es bei mir erst mal sauber.

Gruß oki
42
  Mit Zitat antworten Zitat