none
ドラッグ中のアイテムを半透明で表示する方法 RRS feed

  • 質問

  • Window内のリストボックスからリストボックスへドラッグドロップする際、
    Window内で常にドラッグ中のアイテムを半透明で表示するにはどうすればよいでしょうか?

    要は下記URIのようなものを作りたいだけです。

    http://ant0x.udap.jp/tips/tips_DragGhostImage.htm

    上のサンプルはWin32APIを使用していますが、
    Win32APIを使用しないでスマートに実現できる方法がありましたら教えてください。
    2007年3月29日 6:26

すべての返信

  • FC-Shiro 様
    ありがとうございます。

    ソースを拝見させていただきましたが、
    やはりWin32APIを使用しているようです。

    最終的な目的は表題の通りですが、
    問題を明確にするため、追記させていただきます。

    現在、下記のように作成中です。
    1)ドラッグ中の半透明アイテムのビジュアルを決定するのは、ドラッグ元のListBox。
    2)ドラッグ中の半透明アイテムのビジュアルはAdornerを使用する。
    3)ドラッグドロップ操作はSystem.Windows.DragDrop.DoDragDrop()メソッドを使う。
    4)ドラッグドロップを管理するマネージャクラスを作成して、
      Attached Propertyを使用して ListBoxにドラッグ元、ドロップ先の機能を個別に追加できるようにする。
      (マネージャが使用するIドラッグ元、Iドロップ先インターフェースをListBox用に実装したクラスを作成して適用)
      下記のサンプルをベースに作成しています。
      http://blogs.msdn.com/llobo/archive/2006/12/08/drag-drop-library.aspx

    問題となっているのは、DoDragDrop中にマウス座標を上手く取得することができないため、
    ドラッグ中の半透明アイテムのビジュアルをマウスに追随させることができない点です。
    (ドラッグドロップ中は処理が確定するまでMouse.GetPosition()からもマウス座標を取得できない?)

    DoDragDrop中にマウス座標を取得する方法として現在分かっているのは、下記の方法です。

    1)Win32APIからマウス座標を取得する。
     →ドラッグ元のQueryContinueイベントハンドラ内でWin32APIから取得したマウス座標を適用する。

    2)DragEventArgsからマウス座標を取得する。
     →ウィンドウ全体のAllowDropを"True"にして、PreviewDragOverイベントハンドラ内でマウス座標を適用する。
     
    できればどちらも避けたいです。
    そこで、ドラッグドロップ中に上記方法以外でマウス座標を取得できる方法
    がありましたら教えていただけないでしょうか。

    もちろん、表題を(できるだけスマートに)実現できれば、上記と全く異なる方法でも構いません。
    よろしくお願いします。
    2007年3月30日 2:49
  • ドラッグするときの半透明のイメージのマウスポインタの位置を穴あきにすることで、その下のコントロールの

    MouseMoveや、MouseDownのイベントが動作します。座標はそのときのをMouseEventArgsから取得できると思います。

     

    わざとマウスポインタ位置を穴あきにするテクニックを利用しないと半透明イメージマウスイベントを取得してしまうためか

    いろいろ試行錯誤してしまうはめになります。この方法が適用できるケースか分かりませんが、ご参考程度に。

    2007年4月3日 6:53
  • ターゲットとなるUIElementで

    Mouseのイベントを拾ってしまっているので,

    ターゲットではないところの上では表示されないですね。

     

    Mouseのイベントは,

    いくつかの Add系のメソッドがあるので,

    Mouse.AddPreviewMouseMoveHandler(ウィンドウインスタンス,ソース側のハンドラ);

    にしてやるカラクリに変えればいいような気がするんですけどね。

     

    以下のように受け取れると思うので試してみて,

     

    Code Snippet

     

    class Class1

    {

        public void Initialize()

        {

            UIElement wnd = Application.Current.MainWindow;

            Mouse.AddMouseMoveHandler(wnd, OnMouse_Move);

        }

        public void OnMouse_Move(Object sender, MouseEventArgs e)

        {

            UIElement container = Application.Current.MainWindow.Content as UIElement;

            if(container != null)

            {

                Console.WriteLine("Mouse_Move: {0}", e.GetPosition(container));

            }

        }

    }

     

    public partial class Window1 : System.Windows.Window

    {

        Class1 cls;

        public Window1()

        {

            InitializeComponent();

            cls = new Class1();

            cls.Initialize();

        }

    }

     

    で,Initializeになっているけど,

    場所は,実際は,Manager内のOnDragSourceAdvisorChanged などです。

    Application.Current.MainWindowでなく,

    引数で実際に渡した方がいいような気もするんですけどね。

    一応,元のコードに近い形にしてあります。

    2007年4月3日 12:05
  •  tngar さんからの引用

    3)ドラッグドロップ操作はSystem.Windows.DragDrop.DoDragDrop()メソッドを使う。


    と言う事で、DoDragDrop()中は、MouseMoveイベントは発生しませんね。(泣)

    DoDragDrop()は、ole32.dllのDoDragDropを呼んでいるようです。
    ですので、受ける時も、IOleDropSourceやIOleDropTargetインターフェイスを通じて受けているようですね。
    (内部で受けて、WPFのイベントに置き換えて発行。と言うような形で実装しているようです。)

    今回の場合、アプリケーションを超えてのDrag&Dropが必要無いのであれば、
    System.Windows.DragDrop.DoDragDrop()メソッド
    を使用しない独自実装を考えていったほうがよさそうです。

    アプリケーションを超えてのDragを実装するときには、DoDragDrop()メソッドを使っていくのでしょう。

    2007年4月4日 0:41
  • ご返答いただきありがとうございます。

    >ふる様
    申し訳ありません。「穴あき」の概念が理解できませんでした。
    現在、半透明ビジュアルは「IsHitTestVisible = false」としているため、マウスイベントが取れない状態となっています。
    たとえば、半透明ビジュアルの"PreviewDragOver"イベント等からマウス座標を取得して適用しつつ、
    その下のコントロール(リストボックス等)のイベントも取得する方法がある、ということでしょうか?
    具体的な方法をご教示いただけるとありがたいです。

    >稍丼様
    残念ながら、FC-Shiro様のおっしゃる通り、DoDragDrop()中は、MouseMoveイベントは発生しないようです。
    Add系のメソッドについては大変勉強になりました。

    >FC-Shiro
    やはりそのようですね。
    今回はアプリケーションを超えてのドラッグドロップがありそうなので、
    「1)Win32APIからマウス座標を取得する。」でいきたいと考えています。
    2007年4月4日 5:37
  • そういえば別スレの話で,

    DoDragDrop()以降ドロップまでは

    MouseMoveイベントは発生しないから困ってる話があったですね。

    もう忘れてました。(汗)

    2007年4月4日 7:07