WindowsエクスプローラーからファイルをドラッグするときのTcxGridでのマウスの動きの検出に関する問題
-
06-07-2019 - |
質問
最近、Delphi(バージョン2009)で書かれた大きなアプリケーションに、ユーザーがWindowsエクスプローラーからファイルをドラッグしてTcxGridコントロールにドロップできる機能を追加しました。私は、独自のウィンドウプロシージャをグリッドに接続し、WM_DROPFILESメッセージをインターセプトする一般的な方法でこれを実現しました。
originalGridWindowProc := cxGrid.WindowProc; // remember the old one
cxGrid.WindowProc := GridWindowProc; // assign the new one
DragAcceptFiles(cxGrid.Handle, LongBool(True)); // setup to accept dropped files
この機能を拡張して、ユーザーがグリッド内の既存の行にファイルをドロップしたことを検出し、既存のファイルを新しいバージョンで上書きするプロセスを開始しようとしています。
最初に考えたのは、グリッドコントロールのmouseoverイベントが機能するかどうかを確認することでした。ただし、ドラッグ操作中はそうではありません。
その後、Winspectorというプログラムを使用して、マウスがグリッド上を移動するときにグリッドコントロールに送信されたメッセージを確認し、マウスがどの行にあるかを検出して強調表示できるようになりました。上記と同じ手法を使用していますが、この場合、グリッド自体ではなく、GridSiteのウィンドウプロシージャをオーバーライドしています。これは、メッセージがWinspectorに従っているように見えるためです。
originalGridSiteWindowProc := cxGrid.ActiveView.Site.WindowProc;
cxGrid.ActiveView.Site.WindowProc := GridSiteWindowProc;
GridSiteWindowProcの本体は次のとおりです。
procedure Tfrm.GridSiteWindowProc(var message: TMessage);
var
hitTest: TcxCustomGridHitTest;
gridRecord: TcxCustomGridRecord;
begin
//Log(IntToStr(message.Msg));
case message.Msg of
WM_NCHITTEST: begin
hitTest := cxGrid.ActiveView.GetHitTest(cxGrid.ScreenToClient(Mouse.CursorPos));
if hitTest is TcxGridRecordCellHitTest then begin
gridRecord := TcxGridRecordCellHitTest(HitTest).GridRecord;
if Not gridRecord.Focused then
gridRecord.Focused := True;
end;
originalGridSiteWindowProc(message);
end
else
originalGridSiteWindowProc(message);
end;
end;
ご覧のとおり、WM_NCHITTESTメッセージをトラップしてこれを実現しています。 Winspectorによると、このメッセージはドラッグ操作中にグリッドサイトウィンドウにも送信されますが、メッセージ値を文字列リストに出力するLog()ステートメントのコメントを解除すると(後で手動でメモフィールドにダンプします)、何らかの理由で、グリッド上にファイルをドラッグすると、これらのメッセージが1つまたは2つしか表示されないと判断しました。
今-ここで興味深い部分があります。Winspectorを実行してそのウィンドウへのメッセージを監視していると、ファイルのドラッグ操作中に突然すべてのWM_NCHITTESTメッセージの取得を開始します。これは、ウィンドウプロシージャに送られるすべてのメッセージの整数値を、最初に文字列リストバッファではなく別のログウィンドウに直接出力する場合にも当てはまります。私は誰かがこれがなぜ起こっているのか、これを機能させる方法についての手がかりを提供できることを望んでいます。
解決
WM_DROPFILESメッセージを使用するのではなく、OLE Drag'n'Dropを使用する必要があります。 RegisterDropTarget APIを見てください。ドラッグアンドドロップが行われている場所に関する詳細情報を取得できます。より多くの種類のドラッグオブジェクトを受け入れることもできます。