19

ドラッグアンドドロップが完了しなかった後、MouseUpイベントが食い尽くされてフレームワークによって無視されないようにする簡単な方法はありますか?

1つのメカニズムを説明するブログ投稿を見つけましたが、ステータスフラグ、MouseMoveイベント、手動の「マウス脱退」チェックなど、手動での簿記が大量に含まれています。避けた。

4

1 に答える 1

24

私は最近、自分のプロジェクトにドラッグ アンド ドロップ機能を追加したいと考えていましたが、この問題に遭遇していませんでしたが、興味をそそられ、リンク先のページで説明されている方法よりも優れた方法を思いつくことができるかどうかを本当に知りたかったのです。に。あなたがやりたいことはすべて明確に理解できたと思います。全体として、はるかにエレガントでシンプルな方法で問題を解決できたと思います.

簡単に言うと、このような問題については、何をしようとしているのかを正確に確認できるように、コードを提供していただければ幸いです。私がこれを言うのは、私のソリューションであなたのコードについていくつかのことを想定したからです...うまくいけば、それはかなり近いです。

これがコードです。以下で説明します。

this.LabelDrag.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.LabelDrag_QueryContinueDrag);
this.LabelDrag.MouseDown += new System.Windows.Forms.MouseEventHandler(this.LabelDrag_MouseDown);
this.LabelDrag.MouseUp += new System.Windows.Forms.MouseEventHandler(this.LabelDrag_MouseUp);

this.LabelDrop.DragDrop += new System.Windows.Forms.DragEventHandler(this.LabelDrop_DragDrop);
this.LabelDrop.DragEnter += new System.Windows.Forms.DragEventHandler(this.LabelMain_DragEnter);

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void LabelDrop_DragDrop(object sender, DragEventArgs e)
    {
        LabelDrop.Text = e.Data.GetData(DataFormats.Text).ToString();
    }


    private void LabelMain_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(DataFormats.Text))
            e.Effect = DragDropEffects.Copy;
        else
            e.Effect = DragDropEffects.None;

    }

    private void LabelDrag_MouseDown(object sender, MouseEventArgs e)
    {
        //EXTREMELY IMPORTANT - MUST CALL LabelDrag's DoDragDrop method!!
        //Calling the Form's DoDragDrop WILL NOT allow QueryContinueDrag to fire!
        ((Label)sender).DoDragDrop(TextMain.Text, DragDropEffects.Copy); 
    }

    private void LabelDrag_MouseUp(object sender, MouseEventArgs e)
    {
        LabelDrop.Text = "LabelDrag_MouseUp";
    }

    private void LabelDrag_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
    {
        //Get rect of LabelDrop
        Rectangle rect = new Rectangle(LabelDrop.Location, new Size(LabelDrop.Width, LabelDrop.Height));

        //If the left mouse button is up and the mouse is not currently over LabelDrop
        if (Control.MouseButtons != MouseButtons.Left && !rect.Contains(PointToClient(Control.MousePosition)))
        {
            //Cancel the DragDrop Action
            e.Action = DragAction.Cancel;
            //Manually fire the MouseUp event
            LabelDrag_MouseUp(sender, new MouseEventArgs(Control.MouseButtons, 0, Control.MousePosition.X, Control.MousePosition.Y, 0));
        }
    }

}

ほとんどのデザイナ コードは省きましたが、何が何にリンクされているかを確認できるように、イベント ハンドラのリンク アップ コードを含めました。私の例では、ラベル LabelDrag と LabelDrop の間でドラッグ/ドロップが行われています。

私のソリューションの主な部分は、QueryContinueDrag イベントを使用することです。このイベントは、コントロールで DoDragDrop が呼び出された後にキーボードまたはマウスの状態が変化したときに発生します。既にこれを行っているかもしれませんが、フォームに関連付けられたメソッドではなく、ソースであるコントロールの DoDragDrop メソッドを呼び出すことが非常に重要です。そうしないと、QueryContinueDrag は起動しません!

注意すべきことの 1 つは、ドロップ コントロール上でマウスを離すと QueryContinueDrag が実際に起動するため、それを許可する必要があることです。これは、マウスの位置 (グローバルな Control.MousePosition プロパティで取得) が LabelDrop コントロールの四角形の内側にあることを確認することによって処理されます。また、Control.MousePosition は画面の相対位置を返すため、PointToClient を使用して、MousePosition を Client Window に相対的なポイントに変換する必要があります。

マウスがドロップ コントロール上になく、マウス ボタンがにあることを確認することで、LabelDrag コントロールの MouseUp イベントを効果的にキャプチャできます。:) ここで、実行したい処理を実行できますが、MouseUp イベント ハンドラで使用しているコードが既にある場合、これは効率的ではありません。したがって、ここから MouseUp イベントを呼び出し、必要なパラメーターを渡すだけで、MouseUp ハンドラーは違いを認識しません。

ただし、この例では、MouseDown イベント ハンドラから DoDragDrop を呼び出しているため、このコードで実際に直接 MouseUp イベントが発生することはありません。それが可能であることを示すために、そのコードをそこに入れただけです。

それが役立つことを願っています!

于 2008-08-27T14:00:12.353 に答える