Komponenten bewegen



  • bcb beischpiel: wenn man eine in bcb eine komponente zur entwicklungszeit auf der form verschiebt, wird zuerst nur ein frame gezeichnet. dieser frame wird dann mit der maus bewegt und erst, wenn die maustaste los gelassen wird, ändert die komp ihre koordinaten. das gleiche passiert auch beim ändern der grösse mit der maus.

    und genau das möchte ich auch in meiner anwendung erreichen.

    hat jemand einen einsaz?
    wie bekomme ich so einen rechteck?



  • Du musst auf dem Canvas (Device Context) der Form malen mit einer XOR-Operation.



  • bei deinem vorschlag gibt es ein kleines problemchen

    beim malen auf der form, wird mein frame von untergeordneten komponenten (panels, edits, etc.) verdeckt. also es wird nur auf freien stellen der form gezeichnet



  • Hast du das schon ausprobiert? Hast du auch GetWindowDC() ausprobiert?



  • habe gerade das mit GetDC() selbst gebastelt. ist echt klasse geworden 🙂

    quellcode ist etwas umfangreich, aber bei interesse werde hier ausstellen.

    [ Dieser Beitrag wurde am 26.03.2003 um 03:20 Uhr von Xqgene editiert. ]



  • Original erstellt von Xqgene:
    **quellcode ist etwas umfangreich, aber bei interesse werde hier ausstellen.
    **

    Ja, würde mich interessieren. Wollte sowas selbst immer schonmal machen, bin aber nie dazu gekommen. Wär echt super. 🙂



  • also. ich habe eine komp von TCustomPanel abgeleitet und die funktionalität da rein gepackt. zum testen einfach ein neues projekt erstellen und .cpp und .h mit meinem code überschreiben. ist unter bcb6 gemacht worden (anpassungen für bcb1-5 ???)

    die unit1.h

    //---------------------------------------------------------------------------
    
    #ifndef Unit1H
    #define Unit1H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <ExtCtrls.hpp>
    
    #define SM_NONE         0
    #define SM_LEFT         1
    #define SM_RIGHT        2
    #define SM_UP           4
    #define SM_DOWN         8
    #define SM_MOVE         128
    
    //---------------------------------------------------------------------------
    class TPan : public TCustomPanel
    {
    private:
      int         FSizeMode;
      TRect     FOldRect;
      TPoint    FOldMousePos;
      TRect     FPRegion;
    
      HDC HScreenDC;
      HGDIOBJ HObj;
    protected:
      virtual void __fastcall Paint(void);
      DYNAMIC void __fastcall MouseMove(Classes::TShiftState Shift, int X, int Y);
      DYNAMIC void __fastcall MouseDown(TMouseButton Button,
                                        Classes::TShiftState Shift, int X, int Y);
      DYNAMIC void __fastcall MouseUp(TMouseButton Button,
                                        Classes::TShiftState Shift, int X, int Y);
    public:
      __fastcall TPan(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    
    class TForm1 : public TForm
    {
    __published:    // Von der IDE verwaltete Komponenten
      void __fastcall FormCreate(TObject *Sender);
    private:    // Anwender-Deklarationen
    public:     // Anwender-Deklarationen
      __fastcall TForm1(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif
    

    die unit1.cpp

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    
    void DrawFrame(HDC hdc, TRect Rect, TRect Region);
    
    __fastcall TPan::TPan(TComponent* Owner) : TCustomPanel(Owner)
    {
      Top = 100;
      Left = 100;
      FSizeMode = SM_NONE;
    }
    
    void __fastcall TPan::MouseDown(TMouseButton Button,
      Classes::TShiftState Shift, int X, int Y)
    {
        if (Button != mbLeft) return;   // nur mit links ;-)
    
        FOldMousePos = TPoint(X, Y);
    
      if (Y >= Height - 2) FSizeMode |= SM_DOWN;
      else if (Y <= 2)        FSizeMode |= SM_UP;
    
      if (X >= Width - 2)  FSizeMode |= SM_RIGHT;
      else if (X <= 2)        FSizeMode |= SM_LEFT;
    
      if (FSizeMode == SM_NONE) FSizeMode = SM_MOVE;
    
      HScreenDC = GetDC(0);        // screen dc holen
      HPEN HPen = CreatePen(PS_SOLID, 2, ColorToRGB(clBlack)); // pen erstellen
      HObj = SelectObject(HScreenDC, HPen);                          // pen aktivieren
      SetROP2(HScreenDC, R2_NOTXORPEN);                        // XOR Modus setzen
    
      TPoint p = ClientToScreen(TPoint(0, 0));
      FOldRect = TRect(p.x, p.y, p.x + Width, p.y + Height);
    
      // Rect in dem gezeichnent werden darf berechnen
      FPRegion = ((TControl*)Parent)->ClientRect;
      TPoint p1, p2;
      p1 = ((TControl*)Parent)->ClientToScreen(TPoint(FPRegion.Left, FPRegion.Top));
      p2 = ((TControl*)Parent)->ClientToScreen(TPoint(FPRegion.Right, FPRegion.Bottom));
      FPRegion.Left = p1.x; FPRegion.Top = p1.y;
      FPRegion.Right = p2.x; FPRegion.Bottom = p2.y;
    
      // markierungsrect zeichnen (XOR)
      DrawFrame(HScreenDC, FOldRect, FPRegion);
    }
    
    void __fastcall TPan::MouseUp(TMouseButton Button,
      Classes::TShiftState Shift, int X, int Y)
    {
      if (FSizeMode != SM_NONE)
      {
        // alten rect ausblenden (XOR)
        DrawFrame(HScreenDC, FOldRect, FPRegion);
        // aufräumen
        HGDIOBJ HObjOld = SelectObject(HScreenDC, HObj);    // original object widerherstellen
        DeleteObject(HObjOld);                                                      // pen-object löschen
        ReleaseDC(0, HScreenDC);                          // Screen freigeben
    
        FSizeMode = SM_NONE;
    
        // neue koordinaten/grösse zuweisen
        // swap
        int a;
        if (FOldRect.Left > FOldRect.Right) { a=FOldRect.Left; FOldRect.Left=FOldRect.Right; FOldRect.Right=a; }
        if (FOldRect.Top > FOldRect.Bottom) { a=FOldRect.Top; FOldRect.Top=FOldRect.Bottom; FOldRect.Bottom=a; }
        TPoint NewPos = ((TControl*)Parent)->ScreenToClient(TPoint(FOldRect.left, FOldRect.top));
        SetBounds(NewPos.x, NewPos.y, FOldRect.Width(), FOldRect.Height());
      }
    }
    
    void __fastcall TPan::MouseMove(Classes::TShiftState Shift, int X, int Y)
    {
      if (FSizeMode != SM_NONE)
      {
        // alten rect ausblenden (XOR)
        DrawFrame(HScreenDC, FOldRect, FPRegion);
    
        // neuen rect zeichnen (XOR)
        if (FSizeMode != SM_MOVE) // bei gröseänderng
        {
          if (FSizeMode & SM_DOWN)  FOldRect.bottom = FOldRect.top + Y;
          if (FSizeMode & SM_RIGHT) FOldRect.right  = FOldRect.left + X;
          if (FSizeMode & SM_UP)        FOldRect.top        = FOldRect.bottom + Y - Height;
          if (FSizeMode & SM_LEFT)  FOldRect.left   = FOldRect.right + X - Width;
        }
        else // beim verschieben
        {
            OffsetRect(FOldRect, X - FOldMousePos.x, Y - FOldMousePos.y);
          FOldMousePos.x = X, FOldMousePos.y = Y;
        }
    
        DrawFrame(HScreenDC, FOldRect, FPRegion);
      }
      else
        if ((Y <= 2 && X <= 2) || (Y >= Height - 2 && X >= Width - 2)) Cursor = crSizeNWSE;
        else
        if ((Y <= 2 && X >= Width - 2) || (Y >= Height - 2 && X <= 2)) Cursor = crSizeNESW;
        else
        if ((Y >= Height - 2) || (Y <= 2)) Cursor = crSizeNS;
        else
        if ((X >= Width - 2) || (X <= 2)) Cursor = crSizeWE;
        else Cursor = crDefault;
    }
    
    void __fastcall TPan::Paint()
    {
        TCustomPanel::Paint();
    }
    //---------------------------------------------------------------------------
    
    void DrawFrame(HDC hdc, TRect Rect, TRect Region)
    {
        TPoint pp;
    
      // swap
      int a;
      if (Rect.Left > Rect.Right) { a=Rect.Left; Rect.Left=Rect.Right; Rect.Right=a; }
      if (Rect.Top > Rect.Bottom) { a=Rect.Top; Rect.Top=Rect.Bottom; Rect.Bottom=a; }
    
      if ((Rect.Left > Region.Right) ||
            (Rect.Top > Region.Bottom) ||
          (Rect.Right < Region.Left) ||
            (Rect.Bottom < Region.Top))
        return;
    
      bool l=true, r=true, t=true, b=true;
    
      if (Rect.Left < Region.Left) { l=false; Rect.Left = Region.Left; }
      if (Rect.Top < Region.Top) { t=false; Rect.Top = Region.Top; }
      if (Rect.Right > Region.Right) { r=false; Rect.Right = Region.Right; }
      if (Rect.Bottom > Region.Bottom) { b=false; Rect.Bottom = Region.Bottom; }
    
      if (t)
      {
        MoveToEx(hdc, Rect.left, Rect.top, &pp);
        LineTo(hdc, Rect.right, Rect.top);
      }
      else   MoveToEx(hdc, Rect.right, Rect.top, &pp);
    
      if (r) LineTo(hdc, Rect.right, Rect.bottom );
      else   MoveToEx(hdc, Rect.right, Rect.bottom, &pp);
    
      if (b) LineTo(hdc, Rect.left, Rect.bottom );
      else   MoveToEx(hdc, Rect.left, Rect.bottom, &pp);
    
      if (l) LineTo(hdc, Rect.left, Rect.top );
    }
    
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
      : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
      TPan* p = new TPan(this);
      p->Parent = this;
    }
    //---------------------------------------------------------------------------
    

    [ Dieser Beitrag wurde am 26.03.2003 um 07:53 Uhr von Xqgene editiert. ]


Anmelden zum Antworten