Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am working on a large application and am adding some drag/drop functionality to it. Specifically, I am allowing the user to drag and drop a file into the main window to open the file.

The problem is that the drag/drop operation is still allowed to happen when the main window is displaying a dialog box (for example, a properties window for an item in the currently-open file). I would rather not allow this to happen if the main window is displaying a modal dialog box. This is because loading the new file in the application while the dialog box is open would probably crash the program: the code calling the dialog box does not expect the open file to be changed while the dialog box is open (that is why the dialog box was modal...).

The main application is written in C++, but I am posting a C# sample. The symptom/behavior is the same on both platforms, but I can demonstrate it in much less code with C#. I am very familiar with both languages/platforms so I can translate any answers to the appropriate language as needed.

To demonstrate the problem with my sample code, compile and run the following C# code. It will create a "main window" that is a valid drop target. Drag and drop a file from Windows Explorer onto the main window: you should see a "dropped" message box. Now, click the button on the form to pop up a dialog box. Again, attempt to drag and drop a file onto the main window while the dialog box is open. Notice that the drop is allowed even though a modal dialog box is open. How can I prevent this from happening when the dialog is open?

The obvious answer is to temporarily set AllowDrop to false while opening the dialog box. The problem is that the main application is very large and so there are numerous places that open dialog boxes. It will be difficult to find every single place that opens a dialog and add this code. Plus, every developer here would need to know to perform this action every time they open a modal window; it is unlikely that everyone will remember. I am worried that this is not a very good solution.

Surely there is a more maintainable method of doing this that doesn't require adding code in every place that a dialog is opened?

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());
    }
}
like image 460
James Johnston Avatar asked Nov 04 '22 20:11

James Johnston


1 Answers

I'm not sure how things work in C#, so let me know if this answer is incorrect. In C++ MFC, the main window is disabled when a dialog is displayed. You can test to see if the main window is disabled and ignore the drop if so.

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;
} 
like image 166
Mark Ransom Avatar answered Nov 09 '22 11:11

Mark Ransom