Delphi 2007でコンパイルした私のアプリケーションには、グリッド間にドラッグアンドドロップがあり、ほとんどの場合うまく機能します。しかし、時々ランダムに私はアクセス違反を持っています。私はVCLでControls.pasメソッドDragToにデバッグしました。Delphi VCLドラッグアンドドロップのバグ?
それはこのように始まる:
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型のグローバル変数です。 DragControl = nilの場合、assigncheckでこのメソッドにパッチを当てて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を継承します。私は、グリッドをデータを再読み込みすると同時にグリッドの行をドラッグすると、この問題が発生すると考えています(しかしわかりません)。どういうわけか、現在の行への参照はゼロになります。長期的には、このスーパーグリッドを、TcxGridから継承するBold対応のグリッド(DelphiのBoldを使用している)と置き換える予定です。次に、データが変更されると(ユーザーまたはコードによってリフレッシュされない場合)、グリッドが更新され、うまくいけば問題が解決されます。
シェル拡張機能との対話を考えましたか? TOpenDialogを使用して同様の問題に直面しました。 – menjaraz
優秀な質問です。私はVCL組み込みのドラッグ&ドロップを使ってコントロールからコントロールに移動する経験はありませんが、もしこれを行う必要があれば、この分野のVCLの代わりにA. Melanderのコードを試してみてください。ここのコードはより強固です。 http://melander.dk/delphi/dragdrop/ –
私はドラッグアンドドロップ(デルファイ2007も同様)に関する同様の問題を抱えていました。しかし、間違いなく、この種の問題は "netviewer"を使ってリモートでプログラムを実行している場合にのみ(そして頻繁に)現れます。 – DamienD