2011-06-15 51 views
5

我正在處理大型應用程序,並且正在爲其添加一些拖放功能。具體來說,我允許用戶將文件拖放到主窗口中以打開文件。如何禁用對話框打開時的拖放功能

問題是,當主窗口顯示一個對話框(例如,當前打開的文件中的項目的屬性窗口)時,拖放操作仍然允許發生。如果主窗口顯示一個模式對話框,我寧願不允許發生這種情況。這是因爲在打開對話框的同時在應用程序中加載新文件可能會使程序崩潰:調用對話框的代碼不希望打開的文件在對話框打開時被更改(這就是爲什麼對話框是模態...)。

主要應用程序是用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()); 
    } 
} 
+0

你可以在MyDragDrop或MyDragEnter方法的開始處根據條件檢查返回嗎?只需檢查一個對話框是否顯示? – Robb 2011-06-15 18:32:32

+0

如果我有一個函數可以確定是否顯示一個對話框,那麼如果有對話框,我可以在DragEnter事件中返回DragDropEffects.None。但我不知道任何這樣的功能 - 如果API存在這個我想知道它! – 2011-06-15 18:37:08

+0

這個網站:http://hashfactor.wordpress.com/2009/01/28/c-check-if-a-form-is-already-opened/是我能挖掘出來的。祝你好運! – Robb 2011-06-15 18:43:26

回答

2

我不確定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; 
} 
+0

將「IsEnabled」替換爲「CanFocus」,此代碼示例完美無缺!對於那些不使用.NET的人來說,CanFocus只是一個圍繞IsWindowEnabled(HWND)API調用的簡單包裝。如答案所示,請務必在確定拖放是否有效時進行檢查。請參閱http://msdn.microsoft.com/en-us/library/ms646303%28VS.85%29.aspx和http://msdn.microsoft.com/en-us/library/system.windows.forms.control .canfocus.aspx – 2011-06-15 20:44:27