2011-12-23 42 views
5

Ứng dụng của tôi được biên dịch với Delphi 2007 đã kéo và thả giữa các lưới và nó hoạt động tốt nhất trong thời gian. Nhưng đôi khi một cách ngẫu nhiên tôi bị vi phạm Truy cập. Tôi gỡ lỗi nó để Controls.pas phương pháp DragTo trong VCL.Lỗi trong Delphi VCL Kéo và thả?

Nó bắt đầu như thế này:

begin 
    if (ActiveDrag <> dopNone) or (Abs(DragStartPos.X - Pos.X) >= DragThreshold) or 
    (Abs(DragStartPos.Y - Pos.Y) >= DragThreshold) then 
    begin 
    Target := DragFindTarget(Pos, TargetHandle, DragControl.DragKind, DragControl); 

Trường hợp ngoại lệ xảy ra trên hàng cuối cùng vì DragControl là con số không. DragControl là một biến toàn cục kiểu TControl. Tôi đã cố gắng vá phương thức này bằng một lệnh gán và gọi CancelDrag nếu DragControl = nil, nhưng điều đó cũng không thành công vì DragObject cũng là không.

procedure CancelDrag; 
begin 
if DragObject <> nil then DragDone(False); 
DragControl := nil; 
end; 

Để tìm hiểu lý do tại sao DragControl là nil tôi đã kiểm tra DragInitControl. Có 2 dòng mà chỉ cần thoát nếu DragControl là 0.

procedure DragInitControl(Control: TControl; Immediate: Boolean; Threshold: Integer); 
var 
    DragObject: TDragObject; 
    StartPos: TPoint; 
begin 
    DragControl := Control; 
    try 
    DragObject := nil; 
    DragInternalObject := False;  
    if Control.FDragKind = dkDrag then 
    begin 
     Control.DoStartDrag(DragObject); 
     if DragControl = nil then Exit; 
     if DragObject = nil then 
     begin 
     DragObject := TDragControlObjectEx.Create(Control); 
     DragInternalObject := True; 
     end 
    end 
    else 
    begin 
     Control.DoStartDock(DragObject); 
     if DragControl = nil then Exit; 
     if DragObject = nil then 
     begin 
     DragObject := TDragDockObjectEx.Create(Control); 
     DragInternalObject := True;   
     end; 
     with TDragDockObject(DragObject) do 
     begin 
     if Control is TWinControl then 
      GetWindowRect(TWinControl(Control).Handle, FDockRect) 
     else 
     begin 
      if (Control.Parent = nil) and not (Control is TWinControl) then 
      begin 
      GetCursorPos(StartPos); 
      FDockRect.TopLeft := StartPos; 
      end 
      else 
      FDockRect.TopLeft := Control.ClientToScreen(Point(0, 0)); 
      FDockRect.BottomRight := Point(FDockRect.Left + Control.Width, 
      FDockRect.Top + Control.Height); 
     end; 
     FEraseDockRect := FDockRect; 
     end; 
    end; 
    DragInit(DragObject, Immediate, Threshold); 
    except 
    DragControl := nil; 
    raise; 
    end; 
end; 

Có thể là lý do ... Vì vậy, câu hỏi của tôi.

  1. Có ai gặp sự cố tương tự khi kéo và thả không?
  2. Nếu tôi phát hiện DragControl = nil làm cách nào tôi có thể hủy kéo và thả hiện tại?

Edit: Hiện nay tôi không có giải pháp cho điều này, nhưng tôi có thể thêm một số thông tin thêm về nó. Các lưới được gọi là supergrid. Đây là một thành phần nội bộ mà chúng tôi đã phát triển cho phù hợp với nhu cầu của mình. Nó kế thừa TcxGrid từ Devexpress. Tôi nghĩ (nhưng không chắc chắn) rằng vấn đề này xảy ra khi người dùng kéo một hàng lưới cùng lúc với dữ liệu tải lại lưới. Bằng cách nào đó, tham chiếu đến hàng hiện tại trở thành không. Về lâu dài, chúng tôi có kế hoạch thay thế supergrid này bằng một mạng lưới nhận thức Bold (như chúng ta sử dụng Bold cho Delphi) cũng thừa kế từ TcxGrid. Sau đó, lưới điện được cập nhật ngay sau khi dữ liệu được thay đổi (không có làm mới bởi người dùng hoặc trong mã) và hy vọng điều này khắc phục được sự cố.

+0

Bạn đã cân nhắc tương tác với tiện ích mở rộng Shell chưa? Tôi phải đối mặt với vấn đề tương tự bằng cách sử dụng TOpenDialog. – menjaraz

+2

Câu hỏi hay. Tôi không có kinh nghiệm sử dụng tính năng kéo và thả VCL từ điều khiển để kiểm soát, nhưng nếu tôi cần làm điều này, tôi sẽ thử mã A. Melander thay vì VCL trần cho khu vực chủ đề này và xem có bản demo hay không mã ở đây chắc chắn hơn; http://melander.dk/delphi/dragdrop/ –

+0

Tôi cũng gặp sự cố tương tự với kéo và thả (delphi 2007). nhưng kỳ lạ loại vấn đề này chỉ xuất hiện (và thường xuyên) khi chạy chương trình từ xa với "netviewer". – DamienD

Trả lời

3
  1. Không, tôi chưa bao giờ gặp phải bất kỳ vấn đề nào trong số này với tính năng kéo và thả của VCL và tôi có một số kinh nghiệm với nó.

  2. DragControl là cục bộ cho đơn vị Điều khiển, vậy làm thế nào để bạn phát hiện DragControl = nil trong mã sản xuất của mình? Thông thường, không cần kiểm tra nó, ít nhất tôi không bao giờ phải làm vậy. Hủy hoạt động kéo, sau đó bằng cách thả chuột trên mục tiêu không chấp nhận hoặc bằng cách nhấn ESC, được thực hiện bằng cách gọi CancelDrag. Và khi bạn nhận thấy chính mình, cuộc gọi đó thường gọi DragDone chỉ khi DragObject <> nil. Do đó, DragObject là nil đã nói rằng không có hoạt động kéo nào đang diễn ra (nữa).

Ngoài ra, bạn quan sát rằng nguồn của AV là từ dòng cụ thể đó trong Controls.DragTo có vẻ sai. Trong thao tác kéo và thả thông thường, DragControlnil không dẫn đến kết quả AV. Tuy nhiên, theo sau Controls.DragFindTarget, nó có thể có vấn đề trong hoạt động kéo và neo, nhưng bạn không đề cập đến việc thực hiện bất kỳ sự kết nối nào.

Bạn có thể làm rõ trong trường hợp nào hoặc mã 'lỗi' này xuất hiện ở mã nào?