如何在对话框打开时禁用拖放

How to disable drag/drop when a dialog box is open

本文关键字:拖放 对话框      更新时间:2023-10-16

我正在开发一个大型应用程序,并为其添加了一些拖放功能。特别是,我允许用户将文件拖放到主窗口中以打开文件。

问题是,当主窗口显示对话框(例如,当前打开的文件中项目的属性窗口)时,仍然允许进行拖放操作。如果主窗口显示模式对话框,我宁愿不允许这种情况发生。这是因为当对话框打开时在应用程序中加载新文件可能会使程序崩溃:调用对话框的代码不希望在对话框打开时更改打开的文件(这就是为什么对话框是模态的…)

主要应用程序是用C++编写的,但我发布了一个C#示例。症状/行为在两个平台上都是相同的,但我可以用C#用更少的代码来演示它。我非常熟悉这两种语言/平台,因此我可以根据需要将任何答案翻译成合适的语言。

为了演示我的示例代码的问题,编译并运行以下C#代码。它将创建一个"主窗口",这是一个有效的投放目标。将文件从Windows资源管理器拖放到主窗口:您应该会看到一个"已删除"的消息框。现在,单击表单上的按钮弹出一个对话框。再次尝试在对话框打开时将文件拖放到主窗口上。请注意,即使打开了模式对话框,也允许放置。当对话框打开时,如何防止这种情况发生?

显而易见的答案是在打开对话框时将AllowDrop临时设置为false。问题是主应用程序非常大,因此有很多地方可以打开对话框。很难找到每一个打开对话框并添加此代码的地方。此外,这里的每个开发人员都需要知道,每次打开模式窗口时都要执行此操作;不太可能每个人都记得。我担心这不是一个很好的解决方案。

当然,有一种更易于维护的方法可以做到这一点,不需要在打开对话框的每个地方都添加代码吗?

using System;
using System.Windows.Forms;
using System.Drawing;
public class MyDialog : Form {
    public MyDialog() {
        Text = "MyDialog";
    }
}
public class MainForm : Form {
    public MainForm() {
        Button btn = new Button();
        btn.Location = new Point(0, 0);
        btn.Text = "ShowDialog";
        btn.Size = new Size(75, 23);
        btn.Click += new EventHandler(GoToDialog);
        this.AllowDrop = true;
        this.Controls.Add(btn);
        this.Text = "Drop Target";
        this.DragDrop += new DragEventHandler(this.MyDragDrop);
        this.DragEnter += new DragEventHandler(this.MyDragEnter);
    }
    private void MyDragDrop(object sender, DragEventArgs e) {
        MessageBox.Show("dropped");
    }
    private void MyDragEnter(object sender, DragEventArgs e) {
        e.Effect = DragDropEffects.Copy;
    }
    private void GoToDialog(object sender, EventArgs e) {
        using (MyDialog ab = new MyDialog()) {
            ab.ShowDialog(this);
        }
    }
}
static class Program {
    [STAThread]
    static void Main() {
        Application.Run(new MainForm());
    }
}

我不确定C#中的工作原理,所以如果这个答案不正确,请告诉我。在C++MFC中,显示对话框时会禁用主窗口。你可以测试主窗口是否被禁用,如果是的话可以忽略掉

private void MyDragDrop(object sender, DragEventArgs e) {
    if (CanFocus)
        MessageBox.Show("dropped");
}
private void MyDragEnter(object sender, DragEventArgs e) {
    if (CanFocus)
        e.Effect = DragDropEffects.Copy;
    else
        e.Effect = DragDropEffects.None;
}