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

Posted

技术标签:

【中文标题】如何在打开对话框时禁用拖放【英文标题】:How to disable drag/drop when a dialog box is open 【发布时间】:2011-09-15 19:00:45 【问题描述】:

我正在开发一个大型应用程序,并正在向它添加一些拖放功能。具体来说,我允许用户将文件拖放到主窗口中以打开文件。

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

主应用程序是用 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());
    

【问题讨论】:

您能否在MyDragDropMyDragEnter 方法开始时根据条件检查return 并简单地检查是否显示对话框? 如果我有一个函数可以确定对话框是否正在显示,那么如果有对话框,我可以在 DragEnter 事件中返回 DragDropEffects.None。但我不知道有任何这样的功能 - 如果存在用于此的 API,我很想知道它! 这个网站:hashfactor.wordpress.com/2009/01/28/… 是我能挖掘的全部。祝你好运! 这对第 3 方对话有何作用?例如,Windows 中的常见对话框(打开/保存文件、打印窗口等)。不知何故,这似乎比暂时将 AllowDrop 设置为 false 更复杂...... 【参考方案1】:

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

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;
 

【讨论】:

将“IsEnabled”替换为“CanFocus”,此代码示例完美运行!对于那些不使用 .NET 的人,CanFocus 只是 IsWindowEnabled(HWND) API 调用的简单包装器。如答案所示,在确定拖放是否有效时,请务必检查这一点。见msdn.microsoft.com/en-us/library/ms646303%28VS.85%29.aspx 和msdn.microsoft.com/en-us/library/…

以上是关于如何在打开对话框时禁用拖放的主要内容,如果未能解决你的问题,请参考以下文章

双击ActiveX控件时如何禁用Visual Basic对话框

为啥当我打开对话框时它会禁用所有 qml 项目

如果打开一个对话框,则始终启用WPF拖放

css 打开模式对话框窗口时禁用Body上的滚动

在 MFC 对话框中拖放

在MFC对话框中拖放