2013-06-25 51 views
4

我正在C#中使用WinForms在具有多種表單的大型應用程序中工作。檢測我的表單是否有焦點

在幾點我有另一種形式來作爲進展屏幕。因爲我無法凍結我的UI線程,所以我必須在新線程中啓動新窗體。我使用progressform.ShowDialog()來啓動表單,但由於它在新線程中,因此可以點擊或返回主表單。我想禁用這個。

我的想法是,我可以在mainForm.GotFocus事件上放置一個EventHandler,並將焦點重定向到progressForm(如果顯示)。但是,當您切換應用程序或在progressFormmainForm之間移動時,GotFocus事件未被觸發。我猜測這是因爲mainForm中的某個元素具有焦點,而不是表單本身。

如果有人知道更好的方法來做到這一點(我沒有致力於EventHandler方法)或EventHandler方法的工作代碼,它會解決我的問題。

編輯

按評論,我嘗試使用Activated事件。

// in InitializeForm() 
this.Activated += FocusHandler; 

// outside of InitializeForm() 
void FocusHandler(object sender, EventArgs e) 
{ 
    if (ProgressForm != null) 
    { 
     ProgressForm.Focus(); 
    } 
} 

但它仍然允許我回到主窗體並單擊按鈕。

+3

使用兩個UI線程是各種各樣問題的祕訣。不要這樣做。 – SLaks

+0

不幸的是,我在項目結束時進來幫助完成它。雙UI線程現在已經在系統中紮根。把它拿出來會比它的價值更麻煩。 – Chris

+2

您是否嘗試過[Form.Activate](http://msdn.microsoft.com/zh-cn/library/system.windows.forms.form.activate.aspx)方法和[Form.Activated](http:///msdn.microsoft.com/en-us/library/system.windows.forms.form.activated.aspx)事件? – Steve

回答

0

我已經嘗試了一些方法,發現這是你想要的不工作,整個構思是從你的主UI過濾某些信息時,會顯示你的進步形式:

public partial class Form1 : Form 
{ 
    [DllImport("user32")] 
    private static extern int SetForegroundWindow(IntPtr hwnd);   
    public Form1() 
    { 
     InitializeComponent();    
    } 
    ChildUI child = new ChildUI(); 
    bool progressShown; 
    IntPtr childHandle; 
    //I suppose clicking on the button1 on the main ui form will show a progress form. 
    private void button1_Click(object sender, EventArgs e) 
    { 
     if(!progressShown) 
      new Thread(() => { progressShown = true; childHandle = child.Handle; child.ShowDialog(); progressShown = false; }).Start(); 
    } 
    protected override void WndProc(ref Message m) 
    { 
     if (progressShown&&(m.Msg == 0x84||m.Msg == 0xA1||m.Msg == 0xA4||m.Msg == 0xA3||m.Msg == 0x6)) 
     //0x84: WM_NCHITTEST 
     //0xA1: WM_NCLBUTTONDOWN 
     //0xA4: WM_NCRBUTTONDOWN 
     //0xA3 WM_NCLBUTTONDBLCLK //suppress maximizing ... 
     //0x6: WM_ACTIVATE   //suppress focusing by tab... 
     { 
      SetForegroundWindow(childHandle);//Bring your progress form to the front 
      return;//filter out the messages 
     } 
     base.WndProc(ref m); 
    } 
} 

,如果你想顯示正常進度表(而不是對話框),使用Application.Run(),出外形正常(使用Show())不處理一些while循環顯示它經過將近權將終止形式:

private void button1_Click(object sender, EventArgs e) 
    { 
     //progressShown = true; 
     //child.Show(); 
     if (!progressShown) 
     {     
      new Thread(() => { 
       progressShown = true; 
       if (child == null) child = new ChildUI(); 
       childHandle = child.Handle; 
       Application.Run(child); 
       child = null; 
       progressShown = false; 
      }).Start(); 
     } 
    } 

我測試過,它的工作原理像一個魅力。