चूंकि माउस ड्रैग ऑपरेशन के दौरान कैप्चर किया जाता है, इसलिए OnEndDrag
हैंडलर में ड्रैग ऑपरेशन समाप्त होने पर पता लगाने में कोई समस्या नहीं है, भले ही यह एप्लिकेशन के किसी भी रूप से बाहर हो। आप बता सकते हैं कि ड्रॉप को स्वीकार किया गया है या नहीं, 'लक्ष्य' ऑब्जेक्ट का परीक्षण करके और यदि ड्रॉप स्वीकार नहीं किया गया है, तो आप बता सकते हैं कि यह माउस स्थिति का परीक्षण करके एप्लिकेशन के बाहर है या नहीं।
हालांकि इस दृष्टिकोण के साथ अभी भी एक समस्या है। आप यह नहीं बता सकते कि ड्रैग को 'Esc' कुंजी दबाकर रद्द कर दिया गया है या नहीं। ड्रैग कर्सर को फॉर्म के बाहर 'स्वीकृत' पर सेट करने में सक्षम नहीं होने की समस्या भी है, क्योंकि कोई नियंत्रण OnDragOver
वहां नहीं कहा जाएगा।
आप अपनी रचना के ड्रैग ऑब्जेक्ट का उपयोग करके ड्रैग ऑपरेशन के व्यवहार को बदलकर इन समस्याओं को दूर कर सकते हैं। नीचे एक उदाहरण है:
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.
स्रोत
2012-10-18 22:49:51
किसी भी मदद के लिए इस लिंक पर है, [खींचें/एक आवेदन के अंदर और एक और आवेदन करने के लिए ड्रॉप] (http://stackoverflow.com/q/198488/576719)? –
@LURD: मैंने ऐसा भी सोचा, और लगभग इसे एक डुप्लिकेट कहा जाता है, जब तक कि मैंने प्रश्न को दोबारा पढ़ नहीं लिया और "एक नई विंडो बनाने के लिए" देखा। यह "एक और आवेदन" नहीं है; यह आपके स्वयं के एप्लिकेशन में एक नई विंडो बना रहा है जब इसके बाहर कुछ गिरा दिया जाता है। मैं इसके बजाय उठाया। :-) यह एक अच्छा सवाल प्रतीत होता है। –
@ केनहाइट, आप सही हैं। क्रोम पर बस इस सुविधा की कोशिश की। –