2012-10-18 13 views
6

मैं क्रोम की टैब खींचने की कार्यक्षमता अनुकरण करने की कोशिश कर रहा हूं। मैं चाहता हूं कि उपयोगकर्ता टैब स्ट्रिप में किसी नए स्थान पर एक टैब खींचने में सक्षम हो या उसे एक नई विंडो बनाने के लिए एप्लिकेशन के बाहर छोड़ दें। एप्लिकेशन के भीतर खींचना आसान है, लेकिन जब मैं उपयोगकर्ता को अपने ऐप पर कहीं नहीं छोड़ता तो मुझे कैसे पता चलेगा?अपने आवेदन के बाहर एक ड्रैग ड्रॉप का पता लगाने के लिए कैसे?

संक्षेप में मैं टैब को "फाड़ना" लागू करने के लिए देख रहा हूं।

+0

किसी भी मदद के लिए इस लिंक पर है, [खींचें/एक आवेदन के अंदर और एक और आवेदन करने के लिए ड्रॉप] (http://stackoverflow.com/q/198488/576719)? –

+1

@LURD: मैंने ऐसा भी सोचा, और लगभग इसे एक डुप्लिकेट कहा जाता है, जब तक कि मैंने प्रश्न को दोबारा पढ़ नहीं लिया और "एक नई विंडो बनाने के लिए" देखा। यह "एक और आवेदन" नहीं है; यह आपके स्वयं के एप्लिकेशन में एक नई विंडो बना रहा है जब इसके बाहर कुछ गिरा दिया जाता है। मैं इसके बजाय उठाया। :-) यह एक अच्छा सवाल प्रतीत होता है। –

+0

@ केनहाइट, आप सही हैं। क्रोम पर बस इस सुविधा की कोशिश की। –

उत्तर

7

चूंकि माउस ड्रैग ऑपरेशन के दौरान कैप्चर किया जाता है, इसलिए 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. 
+1

+1। बहुत अच्छी तरह से किया! :-) –

+0

ग्रेट उत्तर सर्टैक। धन्यवाद। – norgepaul

संबंधित मुद्दे