Delphi 2007 でコンパイルされた私のアプリケーションには、グリッド間でのドラッグ アンド ドロップがあり、ほとんどの場合正常に動作します。しかし、ランダムにアクセス違反が発生することがあります。VCL の Controls.pas メソッド DragTo にデバッグしました。
次のように始まります。
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);
DragControl が nil であるため、最後の行で例外が発生します。DragControl は、TControl 型のグローバル変数です。このメソッドに assigncheck をパッチして、DragControl = nil の場合は CancelDrag を呼び出そうとしましたが、DragObject も nil であるため、これも失敗します。
procedure CancelDrag;
begin
if DragObject <> nil then DragDone(False);
DragControl := nil;
end;
DragControl が nil である理由を調べるために、DragInitControl を調査しました。DragControl が nil の場合に終了する 2 行があります。
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;
理由かもしれません...それで私の質問です。
- ドラッグアンドドロップで同様の問題が発生した人はいますか?
- DragControl = nil を検出した場合、現在のドラッグ アンド ドロップをキャンセルするにはどうすればよいですか?
編集: 現在、これに対する解決策はありませんが、それについてさらに情報を追加できます。グリッドはスーパーグリッドと呼ばれます。これは、当社のニーズに合わせて開発した内部コンポーネントです。Devexpress から TcxGrid を継承します。グリッドがデータをリロードすると同時に、ユーザーがグリッド行をドラッグすると、この問題が発生すると思います (確かではありません)。どういうわけか、現在の行への参照が nil になります。長期的には、このスーパーグリッドを TcxGrid から継承する Bold 対応グリッド (Delphi では Bold を使用しているため) に置き換える計画があります。次に、データが変更されるとすぐにグリッドが更新され (ユーザーまたはコードで更新されません)、これで問題が解決されることを願っています。