Magnetisches "ansnappen" von Forms
-
Aufgrund dessen, dass hier im Forum so viele Fragen zum "Snapping" aufgetaucht sind habe ich mich mal selber etwas mit dem Thema beschäftigt.
Im folgenden Beispiel werden 2 Forms verwendet, wobei Form 2 diejenige ist die magnetisch an Form1 ansnappt:
*.h
//--------------------------------------------------------------------------- #ifndef Unit2H #define Unit2H //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #define NICHTGEDOCKT 0 #define UNTEN 1 #define OBEN 2 #define RECHTS 3 #define LINKS 4 //--------------------------------------------------------------------------- class TForm2 : public TForm { __published: // Von der IDE verwaltete Komponenten void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y); void __fastcall FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y); private: // Anwender-Deklarationen int LastX, LastY; //letzte Mausposition HWND hwnd_Form1; //Handle auf Form1 TRect Form1Rect; //Form1-Größeneigenschaften int MagneticDist; //magnetischer Abstand int Docked; //Zustandsvariable für Dock-Art public: // Anwender-Deklarationen __fastcall TForm2(TComponent* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TForm2 *Form2; //--------------------------------------------------------------------------- #endif
*.cpp
#include <vcl.h> #pragma hdrstop #include "Unit2.h" #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm2 *Form2; //--------------------------------------------------------------------------- __fastcall TForm2::TForm2(TComponent* Owner) : TForm(Owner) { MagneticDist = 50; Docked = NICHTGEDOCKT; } //--------------------------------------------------------------------------- void __fastcall TForm2::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { TPoint P; if (Shift.Contains(ssLeft)) { P = Mouse->CursorPos; // Verschiebemöglichkeiten entsprechend des Dockstatus switch (Docked) { case OBEN: Form2->Left = P.x - LastX; break; case UNTEN: Form2->Left = P.x - LastX; break; case LINKS: Form2->Top = P.y - LastY;; break; case RECHTS: Form2->Top = P.y - LastY; break; case NICHTGEDOCKT: Form2->Top = P.y - LastY; Form2->Left = P.x - LastX; break; } if (hwnd_Form1) { // von oben if (abs(Form1Rect.Top - (Form2->Top + Form2->Height)) < MagneticDist) { if (((Form2->Left + Form2->Width) >= Form1Rect.Left) && (Form2->Left <= Form1Rect.Right)) { Form2->Top = Form1Rect.Top-Form2->Height; P.x = Form2->Left + LastX; P.y = Form2->Top + LastY; Mouse->CursorPos = P; Docked = OBEN; return; } } // von unten if (abs(Form1Rect.Bottom - Form2->Top) < MagneticDist) { if (((Form2->Left + Form2->Width) >= Form1Rect.Left) && (Form2->Left <= Form1Rect.Right)) { Form2->Top = Form1Rect.Bottom; P.x = Form2->Left + LastX; P.y = Form2->Top + LastY; Mouse->CursorPos = P; Docked = UNTEN; return; } } // von links if (abs(Form1Rect.Left - (Form2->Left + Form2->Width)) < MagneticDist) { if (((Form2->Top + Form2->Height) >= Form1Rect.Top) && (Form2->Top <= Form1Rect.Bottom)) { Form2->Left = Form1Rect.Left-Form2->Width; P.x = Form2->Left + LastX; P.y = Form2->Top + LastY; Mouse->CursorPos = P; Docked = LINKS; return; } } // von rechts if (abs(Form1Rect.Right - Form2->Left) < MagneticDist) { if (((Form2->Top + Form2->Height) >= Form1Rect.Top) && (Form2->Top <= Form1Rect.Bottom)) { Form2->Left = Form1Rect.Right; P.x = Form2->Left + LastX; P.y = Form2->Top + LastY; Mouse->CursorPos = P; Docked = RECHTS; return; } } // Ansonsten ist nichts passiert Docked = NICHTGEDOCKT; } } } //--------------------------------------------------------------------------- void __fastcall TForm2::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { // Variablen initialisieren LastX = X; LastY = Y; hwnd_Form1 = FindWindow("TForm1", NULL); //Form1 suchen if (hwnd_Form1) GetWindowRect(hwnd_Form1, &Form1Rect); //Fensterkoordinaten bestimmen }
Das Problem hierbei ist noch, das man wenn Form2 an Form1 angesnappt ist es nur noch schwer über Eck wieder losbekommt. Wenn jemand eine Lösung dazu weis ...
[ Dieser Beitrag wurde am 19.02.2003 um 16:37 Uhr von F98 editiert. ]
-
Eine Lösung, die mir jetzt noch schnell eingefallen ist, ist die MagneticDist nach dem Andocken auf 0 zu setzen.