Da die Maus während einer Ziehoperation erfasst wird, gibt es kein Problem mit der Erkennung, wenn eine Ziehoperation in einem OnEndDrag
-Handler abgeschlossen ist, auch wenn sie sich außerhalb der Form der Anwendung befindet. Sie können feststellen, ob der Drop akzeptiert wird oder nicht, indem Sie das Zielobjekt testen, und wenn der Drop nicht akzeptiert wird, können Sie feststellen, ob es sich außerhalb der Anwendung befindet, indem Sie die Mausposition testen.
Allerdings gibt es immer noch ein Problem mit diesem Ansatz. Sie können nicht feststellen, ob der Ziehvorgang abgebrochen wurde, indem Sie die Taste 'Esc' drücken. Es gibt auch das Problem, den Drag-Cursor außerhalb des Formulars nicht auf 'akzeptiert' setzen zu können, da dort kein Steuerelement OnDragOver
aufgerufen wird.
Sie können dieses Problem beheben, indem Sie das Verhalten der Ziehoperation mithilfe eines Ziehobjekts Ihrer Erstellung ändern. Im Folgenden finden Sie ein Beispiel:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls;
type
TForm1 = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
TabSheet3: TTabSheet;
procedure FormCreate(Sender: TObject);
procedure PageControl1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PageControl1StartDrag(Sender: TObject;
var DragObject: TDragObject);
procedure PageControl1EndDrag(Sender, Target: TObject; X, Y: Integer);
procedure PageControl1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
PageControl1.DragMode := dmManual;
end;
type
TDragFloatSheet = class(TDragControlObjectEx)
private
class var
FDragSheet: TTabSheet;
FDragPos: TPoint;
FCancelled: Boolean;
protected
procedure WndProc(var Msg: TMessage); override;
end;
procedure TDragFloatSheet.WndProc(var Msg: TMessage);
begin
if (Msg.Msg = CN_KEYDOWN) and (Msg.WParam = VK_ESCAPE) then
FCancelled := True;
FDragPos := DragPos;
inherited;
if (Msg.Msg = WM_MOUSEMOVE) and
(not Assigned(FindVCLWindow(SmallPointToPoint(TWMMouse(Msg).Pos)))) then
Winapi.Windows.SetCursor(Screen.Cursors[GetDragCursor(True, 0, 0)]);
end;
//-------------------
procedure TForm1.PageControl1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
TDragFloatSheet.FDragSheet :=
(Sender as TPageControl).Pages[TPageControl(Sender).IndexOfTabAt(X, Y)];
PageControl1.BeginDrag(False);
end;
procedure TForm1.PageControl1StartDrag(Sender: TObject;
var DragObject: TDragObject);
begin
DragObject := TDragFloatSheet.Create(Sender as TPageControl);
end;
procedure TForm1.PageControl1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
var
TargetSheet: TTabSheet;
begin
TargetSheet :=
(Sender as TPageControl).Pages[TPageControl(Sender).IndexOfTabAt(X, Y)];
Accept := Assigned(TargetSheet) and (TargetSheet <> TDragFloatSheet.FDragSheet);
end;
procedure TForm1.PageControl1EndDrag(Sender, Target: TObject; X, Y: Integer);
begin
if Assigned(Target) then begin
// normal processing, f.i. find the target tab as in OnDragOver
// and switch positions with TDragFloatSheet.FDragSheet
end else begin
if not TDragFloatSheet.FCancelled then begin
if not Assigned(FindVCLWindow(TDragFloatSheet.FDragPos)) then begin
// drop TDragFloatSheet.FDragSheet at TDragFloatSheet.FDragPos
end;
end;
end;
end;
end.
Link von irgendeiner Hilfe ist, [Drag/Drop-innerhalb einer Anwendung und auf eine andere Anwendung] (http://stackoverflow.com/q/198488/576719)? –
@LURD: Ich dachte es auch und nannte es fast ein Duplikat, bis ich die Frage erneut las und das "um ein neues Fenster zu erstellen" sah. Das ist nicht "eine andere Anwendung"; Es erstellt ein neues Fenster in Ihrer eigenen Anwendung, wenn etwas außerhalb davon abgelegt wird. Ich habe stattdessen hochgestuft. :-) Es scheint eine gute Frage zu sein. –
@KenWhite, Sie haben Recht. Probieren Sie diese Funktion in Chrome aus. –