ドロップ禁止場所へドラッグした際にドロップ禁止のイメージを表示するには?

解決


saru  2004-08-18 19:21:31  No: 54238

ダイアログベースで開発しているのですが、
ツリービューでドラッグアンドドロップしたアイテムを
ウィンドウ外に移動させたときにドロップ禁止イメージ
(エクスプローラで表示される円の中に斜線)をドラッグ
イメージに重ねて表示させたいと思っています。

質問1. ドロップ禁止イメージの描画方法

       通常のドラッグイメージは表示出来ているのですが、
       このドロップ禁止イメージ(マーク)を(重ねて)表示させる
       ことが出来ません。

質問2. ウィンドウ外でマウスカーソルとドラッグイメージを
       同じ位置に描画する方法

       ウィンドウ内でドラッグイメージの描画は出来たのですが
       ウィンドウ外に出たときにうまく描画が行えません。
       SetCapture()でウィンドウ外の情報を取得し、マウスカーソルの
       座標は取得出来ているのですが、その座標を使って、
       "DragEnter(NULL, 座標)"でドラッグイメージ(まだ通常の
       ドラッグイメージ)を表示させるとマウスカーソルの位置と
       表示されるドラッグイメージの位置がずれて表示されてしまいます。
       マウスカーソルは座標をウィンドウの左上が"0,0"とした位置からの
       相対する位置に描画しているが、ドラッグイメージはデスクトップの
       左上を"0,0"とした位置から相対した位置に描画しているようです。
       マウスカーソルとドラッグイメージが重なるように表示させる方法
       を教えてください。

以上、ご指導宜しくお願い致します。
開発環境は Windows Xp, VC++6.0, MFC使用です。


saru  2004-08-19 02:28:52  No: 54239

"質問1"が解決しました。
リソースにデフォルトで用意されているドロップ禁止カーソル
(IDC_NODROP)を保存し、ソースコードからLoadCursor()で
取得します。それをカーソルにセットすれば表示出来ました。
以下、ソースコード

HCURSOR hcursor = AfxGetApp()->LoadCursor(IDC_NODROP);
SetCursor(hcursor);

"質問1"は解決です。ありがとうございました。


とおり  2004-08-19 20:51:56  No: 54240

試していないですが
ScreenToClient、ClientToScreen
どちらかでどうでしょう。

#未確認です。駄目だったらゴメンナサイ


saru  2004-08-20 05:28:15  No: 54241

とおりさんこんばんわ、いつも貴重なアドバイス
ありがとうございます。

ClientToScreenとScreenToClientを試してみました。
どちらも座標(らしき)を取得出来ています。

ScreenToClientの場合、その座標をドラッグイメージを
描画するDragEnterに渡すと、ドラッグイメージが
マウスカーソルに対しデスクトップのかなり左上の方から
現われます。

ClientToScreenで同様に試すとドラッグイメージは最初出て
いないのですが、マウスカーソルをデスクトップの左上に
移動させると、ドラッグイメージがいきなり現われます。
現われる位置もマウスカーソルと一致しています。
しかしこの状態では使えないので、使える方法を検討中です。
座標は取れているのでドラッグイメージの描写を工夫しないと
いけないのかも知れません。
もう少し色々やってみます。


あいる  2004-08-20 23:57:26  No: 54242

ここでははじめましてのあいるです。

たぶん・・・ですが、単純にDragMove してないだけとか??
----- TreeView の OnMouseMove 内 -----
  CTreeCtrl  *pCtrl = &GetTreeCtrl();
  UINT       flags;
  HTREEITEM  hTargetItem = pCtrl->HitTest( point,&flags );

  // メンバで CImageList *m_pDragImageList; と定義されていて初期化済
  m_pDragImageList->DragLeave( this );
  pCtrl->SelectDropTarget( hTargetItem );

  // ここで条件に合わせてカーソル変更
  ::SetCursor( AfxGetApp()->LoadStandardCursor( IDC_NO ) );

  m_pDragImageList->DragEnter( this,point );
  m_pDragImageList->DragMove( point );
----
こんな感じの手順でいいかと
SetCaputure してるなら、DragEnter(NULL,point) ではなくthisでいいかと。


saru  2004-08-22 13:08:00  No: 54243

あいるさんご指導ありがとうございます。
返信が遅くなりまして大変申し訳ありません。

最初にちょっと気になったのですが・・・
>ここでははじめましてのあいるです。
これは別の所で知り合っているという意味でしょうか?
それともあいるさんがこの掲示板では初めて発言する
という意味の挨拶なのでしょうか?

すみません、本題に入ります。
原因がわかりました。単純なコーディングミスでした。
あいるさんに書いて頂いたソースコードと
自分のソースコードを見比べていて気づいたのですが、
私はドラッグイメージの描画とドロップ禁止イメージの描画を
if文で分岐して記述しているのですが、ドラッグイメージの
描画の方ではDragEnterとDragMoveを行っていたが、
ドロップ禁止イメージの描画の方では行っていなかった
というの原因でした。
以下間違っていたソースコード。

if ((hitem = HitTest(point, &flags)) != NULL)
{
    m_pimagelist->DragLeave(this);
    SelectDropTarget(hitem);
    m_pimagelist->DragEnter(NULL, m_ScreenPoint);
    m_pimagelist->DragMove(m_ScreenPoint);
} else {
    SetCursor(AfxGetApp()->LoadCursor(IDC_NODROP));
}

↑これではドロップ禁止場所でドラッグイメージの描画が
行われないのは当たり前でした。失礼致しました。
ただ、DragEnterの第一引数が"this"ではやはりウィンドウ内
での描画指定になっているようでしたので"NULL"にしました。
以下修正後のソースコード。

----OnMouseMove内----

HTREEITEM           hitem;
UINT                flags;

//ドラッグ状態にある。
if (m_bDragging)
{
    SetCapture();
    m_ScreenPoint.x = point.x;
    m_ScreenPoint.y = point.y;
    ClientToScreen( &m_ScreenPoint );

    static HCURSOR oldCursol;
    static bool flag = false;
    //ドロップ禁止場所からドロップ許可場所へ戻ってきた場合、
    //通常のカーソルに戻す。
    if (flag == true) {
        SetCursor(oldCursol);
    }
    //ドロップ許可場所では通常のカーソルを設定。
    if ((hitem = HitTest(point, &flags)) != NULL)
    {
        m_pimagelist->DragLeave(this);
        SelectDropTarget(hitem);
        m_hitemDrop = hitem;
        flag = false;
    } else {
        //ドロップ禁止場所ではドロップ禁止イメージのカーソルを設定。
        oldCursol = SetCursor(AfxGetApp()->LoadCursor(IDC_NODROP));
        flag = true;
    }
        //ドラッグイメージの描画。
        m_pimagelist->DragEnter(NULL, m_ScreenPoint);
        m_pimagelist->DragMove(m_ScreenPoint);
}
---------------------

と言った具合に致しました。
一応やりたい動きは出来ましたので、[解決]チェックは
入れておきますが、おかしな点がありましたらご指摘を
宜しくお願い致します。
とおりさん、あいるさんありがとうございました。


saru  2004-08-22 13:12:51  No: 54244

↑と言っておきながら[解決]を押し忘れました。
失礼致しました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加