The Delphi Bug List

Entry No.
411
VCL - 一般 - ドラッグアンドドロップ
OnStartDrag 内で生成された TDragObject が開放されない
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 4.03 5.0 5.01 6.0 6.01 6.02 Kylix 1.0
Unknown Unknown Unknown Unknown Exists Exists Exists Exists Exists Exists Unknown Unknown Unknown Unknown Unknown
解説
Reported by Thorsten Engler
Delphi のオンラインヘルプにはこう書かれています:

OnStartDrag イベントハンドラは,ユーザーがコントロールまたはコントロール内のオブジェクトのドラッグを開始したときに特別の処理が実行されるようにすることができます。OnStartDrag イベントは,DragKind が dkDrag の場合にのみ発生します。
Sender は,ドラッグされるコントロール,またはドラッグされるコントロールのコンテナになっているコントロールです。
OnStartDrag イベントハンドラは,TDragControlObject のインスタンスを作成して,DragObject パラメータにドラッグカーソル,または必要な場合はドラッグイメージリストを指定することができます。ドラッグ終了時に DragObject の Free メソッドを呼び出す必要はありません
(訳注: 日本語版 Delphi 5 のヘルプから原文に該当する部分を引用)

VCL のソースを見てみましょう:

DragDone の中に以下のコードが見つかります:
    if DragFreeObject then DragSave.Free;
the only other occurrence of DragFreeObject is here: ここ以外に DragFreeObject が現れるのは、以下の場所だけです:
procedure DragInitControl(Control: TControl; Immediate: Boolean);
var
  DragObject: TDragObject;
begin
  DragControl := Control;
  try
    DragObject := nil;
    DragFreeObject := False;
    Control.DoStartDrag(DragObject);
    if DragObject = nil then
    begin
      DragObject := TDragControlObject.Create(Control);
      DragFreeObject := True;
    end;
    DragInit(DragObject, Immediate);
  except
    DragControl := nil;
    raise;
  end;
end;

見て分かるように、Control.DoStartDrag (これが OnStartDrag を呼び出します) が呼ばれる前に DragFreeObject には False がセットされています。DragObject に nil 以外がセットされた場合(ヘルプでは独自のドラッグオブジェクトの実装を提案しています)、DragFreeObject には False がセットされます。したがってそのオブジェクトは開放されません。
解決策 / 回避方法
Matt Lee (10 August 2000):
VCL はそのオブジェクトを開放しませんが、Finished メソッドは呼び出します。Finished メソッドをオーバーライドし、Free を呼び出してください。これにより正しくデストラクタが呼び出され、メモリが開放されます。
ユーザーからのコメント
Hallvard Vassbotn
30 Aug 2001  09:38 AM GMT
バグ #411 は Delphi 6.0 で修正されていますが、後方互換性はあります。
ヘルプの TdragObject から:
"注意: TDragObject は、ドラッグ操作の終了時に自動的に開放されることはありません。ドラッグ操作の終了時に開放されるドラッグオブジェクトを扱う場合には、代わりに TDragObjectEx を使用してください。"
そして TDragObjectEx は:
"直接の上位クラス TDragObject とは異なり、TDragObjectEx とその派生クラスは、ドラッグ操作の終了時に自動的に開放されます。"
Latest update of this entry: 2000-08-10
本家 The Delphi Bug List のエントリーはこちら
The Delphi Bug List 日本語訳 へ