質問

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

について説明したブログ投稿を見つけました 一つの仕組み, ただし、これには、ステータス フラグ、MouseMove イベント、手動の「マウス リーブ」チェックなど、かなりの量の手動の記録が必要です。これらはすべて、回避できるのであれば実装する必要はないでしょう。

役に立ちましたか?

解決

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

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

コードは次のとおりです。以下で説明します。

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 をクライアント ウィンドウを基準としたポイントに変換する必要もあります。 画面相対 位置。

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

ただし、DoDragDrop を呼び出しているので、注意してください。 内で この例の MouseDown イベント ハンドラーでは、このコードは次のようになります。 一度もない 実際には、MouseUp イベントを直接取得して発生させます。それが可能であることを示すために、そのコードをそこに挿入しただけです。

お役に立てば幸いです!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top