2012-11-29 13 views
12

खींचते समय TTreeView चयन गड़बड़ मैं TTreeView पर ड्रैग-एंड-ड्रॉप कार्यक्षमता को कार्यान्वित कर रहा हूं। इसके बारे में एक OnStartDrag घटना पर, मैं अपने व्युत्पन्न वर्ग की DragOcject बना रहा हूं:एक नोड

TTreeDragControlObject = class(TDragObject) 
    private 
    FDragImages: TDragImageList; 
    FText: String; 
    protected 
    function GetDragImages: TDragImageList; override; 
    end; 

procedure TfrmMain.tvTreeStartDrag(Sender: TObject; 
    var DragObject: TDragObject); 
begin 
    DragObject := TTreeDragControlObject.Create; 
    TTreeDragControlObject(DragObject).FText := tvTree.Selected.Text; 
end; 

और ये मेरे ओवरराइड मेरी DragObcject की GetDragImages समारोह है:

function TTreeDragControlObject.GetDragImages: TDragImageList; 
var 
    Bmp: TBitmap; 
begin 
    if FDragImages = nil then 
    begin 
    FDragImages := TDragImageList.Create(nil); 
    Bmp := TBitmap.Create; 
    try 
     Bmp.Width := Bmp.Canvas.TextWidth(FText) + 25; 
     Bmp.Height := Bmp.Canvas.TextHeight(FText); 

     Bmp.Canvas.TextOut(25, 0, FText); 

     FDragImages.Width := Bmp.Width; 
     FDragImages.Height := Bmp.Height; 
     FDragImages.SetDragImage(FDragImages.Add(Bmp, nil), 0, 0); 
    finally 
     Bmp.Free; 
    end; 
    end; 

    Result := FDragImages; 
end; 

सब कुछ ठीक छोड़कर यह एक ही कार्य करता है गड़बड़ पेंटिंग पेड़ नोड पर खींचते समय:

The node glitch

मैं इस व्यवहार से कैसे बच सकता हूं?

+1

ठीक है, मैं स्टंप हो गया हूं। यह TListBox के साथ नहीं होता है, TTreeView पेंट कोड में एक बग प्रतीत होता है। मैं सुझाव दे सकता हूं कि एक तृतीय पक्ष TreeView नियंत्रण की तलाश है। – Blorgbeard

+1

गड़बड़ क्या है? आप किस व्यवहार से बचने की कोशिश कर रहे हैं? –

+0

@TOndrej कृपया मेरी पोस्ट की आखिरी छवि पर एक नज़र डालें। बनाया गया बिटमैप के पीछे चयन कर्सर चाल के बाद रहता है। – JustMe

उत्तर

7

@ शॉन और @ बम्मी के उत्तरों के आधार पर मैं पूरे कोड और निष्कर्षों को पोस्ट करूंगा जो डी 5 में मेरे लिए काम करते थे।

WinXP XPManifest पर आवश्यक नहीं है - Hide/ShowDragImage आवश्यक है।

Win7 XPManifest पर आवश्यक है। Hide/ShowDragImage आवश्यक नहीं है।

निष्कर्ष - दोनों XPManifest और HideDragImage और ShowDragImage का उपयोग टीवी सुनिश्चित करने के लिए XP/Win7 पर दोनों काम करेंगे।


type 
    TTreeDragControlObject = class(TDragControlObject) 
    private 
    FDragImages: TDragImageList; 
    FText: String; 
    protected 
    function GetDragImages: TDragImageList; override; 
    public 
    destructor Destroy; override; 
    procedure HideDragImage; override; 
    procedure ShowDragImage; override; 
    property DragText: string read FText write FText; 
    end; 

    TForm1 = class(TForm) 
    TreeView1: TTreeView; 
    procedure TreeView1StartDrag(Sender: TObject; var DragObject: TDragObject); 
    procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); 
    procedure TreeView1EndDrag(Sender, Target: TObject; X, Y: Integer); 
    private 
    FDragObject: TTreeDragControlObject; 
    public 
    end; 

... 

{ TTreeDragControlObject} 
destructor TTreeDragControlObject.Destroy; 
begin 
    FDragImages.Free; 
    inherited; 
end; 

procedure TTreeDragControlObject.HideDragImage; 
begin 
    GetDragImages.HideDragImage; 
end; 

procedure TTreeDragControlObject.ShowDragImage; 
begin 
    GetDragImages.ShowDragImage; 
end; 

function TTreeDragControlObject.GetDragImages: TDragImageList; 
var 
    Bmp: TBitmap; 
begin 
    if FDragImages = nil then 
    begin 
    FDragImages := TDragImageList.Create(nil); 
    Bmp := TBitmap.Create; 
    try 
     Bmp.Width := Bmp.Canvas.TextWidth(FText) + 25; 
     Bmp.Height := Bmp.Canvas.TextHeight(FText); 
     Bmp.Canvas.TextOut(25, 0, FText); 
     FDragImages.Width := Bmp.Width; 
     FDragImages.Height := Bmp.Height; 
     FDragImages.SetDragImage(FDragImages.Add(Bmp, nil), 0, 0); 
    finally 
     Bmp.Free; 
    end; 
    end; 
    Result := FDragImages; 
end; 

{ TForm1 } 
procedure TForm1.TreeView1StartDrag(Sender: TObject; var DragObject: TDragObject); 
begin 
    FDragObject := TTreeDragControlObject.Create(TTreeView(Sender)); 
    FDragObject.DragText := TTreeView(Sender).Selected.Text; 
    DragObject := FDragObject; 
end; 

procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; 
    State: TDragState; var Accept: Boolean); 
begin 
    Accept := Source is TTreeDragControlObject; 
end; 

procedure TForm1.TreeView1EndDrag(Sender, Target: TObject; X, Y: Integer); 
begin 
    FDragObject.Free; 
end; 

ध्यान दें कि अपने कोड में FDragImages और var DragObject दोनों स्मृति लीक कर रहे हैं। मैं TDragObject के बजाय TDragControlObject का उपयोग करने का सुझाव दूंगा (क्या आपकी tvTreeEndDrag आग अभी भी है? - यह मेरे लिए आग नहीं आई)

+0

हाँ kobik तुम सही हो -।। मैं वांछित परिणाम प्राप्त करने के लिए उन दो तरीकों गठबंधन करने के लिए :) अंत खींचें सफलतापूर्वक फायरिंग कर रहा है – JustMe

+1

@kobik: अच्छा जवाब। –

4

TXPManifest का उपयोग करके इस बग को डी 7 में ठीक करता है।

विंडोज, संदेश, SysUtils, प्रकार, वर्ग, ग्राफिक्स, नियंत्रण, फार्म, संवाद, XPMan, ComCtrls उपयोग करता है;

अतिरिक्त:

procedure Win7UpdateFix(Form: TForm; CharCode: Word); 
var i: Integer; 
begin 
    if Assigned(Form) and (Win32MajorVersion >= 6) and (Win32Platform = VER_PLATFORM_WIN32_NT) then //Vista, Win7 
    begin 
    case CharCode of 
     VK_MENU, VK_TAB: //Alt or Tab 
     begin 
     for i := 0 to Form.ComponentCount-1 do 
     begin 
      if Form.Components[i] is TWinControl then 
      begin 
      //COntrols that disappear - Buttons, Radio buttons, Checkboxes 
      if (Form.Components[i] is TButton) 
      or (Form.Components[i] is TRadioButton) 
      or (Form.Components[i] is TCheckBox) then 
       TWinControl(Form.Components[i]).Invalidate; 
      end; 
     end; 
     end; 
    end; 
    end; 
end; 

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; 
    Shift: TShiftState); 
begin 
    if key=VK_MENU then 
    begin 
     Win7UpdateFix(Self,key) 
    end; 
end; 
+0

हाँ, लेकिन यह भी नियंत्रण है और कैप्शन में – JustMe

+0

:-(ALT कुंजी क्लिक करने के बाद गायब हो जाने की है कि कारण बनता है मैं कोड का एक टुकड़ा है, जो मदद कर सकता है जोड़ा, शायद जवाब के लिए अनुकूलित किया जाना – bummi

4

यह वही व्यवहार डेल्फी 2010 में पाया जाता है और TXPManifest नहीं ठीक होता है। सह-घटनाओं से मैंने हाल ही में और स्वतंत्र रूप से डेल्फी 2010 आवेदन में इसी समस्या को पार किया। समाधान HideDragImage()/ShowDragImage() तो जैसे तरीकों ...

TTreeDragControlObject = class(TDragObject) 
private 
    FDragImages: TDragImageList; 
    FText: String; 
protected 
    function GetDragImages: TDragImageList; override; 
public 
    procedure HideDragImage; override; 
    procedure ShowDragImage; override; 
end; 

... और फिर लागू करने के लिए है ...

procedure TTreeDragControlObject.HideDragImage; 
begin 
    FDragImages.HideDragImage 
end; 

procedure TTreeDragControlObject.ShowDragImage; 
begin 
    FDragImages.ShowDragImage 
end; 

इस के conseequence है कि खिड़कियों एपीआई फ़ंक्शन ImageList_DragShowNolock() ड्रैग छवि पेंट करने से पहले और बाद में कहा जाता है (विंडोज़ संदेश TVM_SELECTITEM(TVGN_DROPHILITE) के माध्यम से)। इस समारोह के बिना, ड्रैग छवि ठीक से चित्रित नहीं है। ImageList_DragShowNolock (झूठी/सही) को सीमित करने की आवश्यकता टीवीएम_SELECTITEM + TVGN_DROPHILITE एक खराब दस्तावेज सुविधा है, और यदि अन्य मंचों का न्याय करना है, तो शिकायत का एक आम कारण है।

+0

धन्यवाद है। दुर्भाग्य से यह दृष्टिकोण :-( – JustMe

+0

+1 आपका समाधान D5 में भी मेरे लिए काम किया (के साथ और XPManifest के बिना) D7 में काम नहीं कर रहा । – kobik

+4

ऊपर XP पर काम किया लेकिन Win7 मशीन पर काम किया नहीं था -। XPManifest यह ठीक हो जोड़ने – kobik

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