2009-06-12 36 views
19

鄉親前形式,如何顯示在C#

請沒有人知道如何從一個不可見的應用程序,有它獲得焦點(即出現在其他窗口的頂部)顯示的形式?我正在使用C#.NET 3.5。

我懷疑我已經採取了 「完全錯誤的做法」 ......我不Application.Run(新TheForm())代替我(新TheForm())。的ShowModal()。 ..表單基本上是一種模態對話,帶有幾個複選框;一個文本框,以及確定和取消按鈕。用戶勾選複選框並在描述中鍵入(或其他),然後按下OK,表單消失,並且該過程從窗體讀取用戶輸入,處理它並繼續處理。

這是有效的,除非表單顯示它沒有得到焦點,而是出現在「主機」應用程序後面,直到您在任務欄(或其他任何地方)單擊它。這是一個令人討厭的行爲,我預測這會導致很多「支持呼叫」,而現有的VB6版本沒有這個問題,所以我在可用性方面倒退......並且用戶不會接受(和也不應該)。

因此......我開始認爲我需要重新考慮整個社會......我應該先把表單作爲一個「正常應用」來展示,然後將處理的剩餘人員附加到OK按鈕上點擊事件。它應該有效,但這需要時間,我沒有(我已經超過時間/預算)...所以首先,我真的需要嘗試使目前的方法工作...即使是快速和 - 髒方法。

那麼請有人知道如何「強制」一個.NET 3.5窗體(通過公平的手段或家禽)來獲得焦點?我在想「神奇」的Windows API調用(我知道

暮光區:這似乎只是工作中的一個問題,我們正在使用Windows XP SP3上的Visual Studio 2008 ... I我只是未能在Vista Ulrich的Visual C#2008上在家中使用SSCCE(見下文)重現此問題...此工作正常。當我運行EXE的時候,但是沒有直接從IDE(我剛剛忍受的時候)(或者Ctrl-F5'ed)......在家裏,這個表單顯示的很好,不管怎樣,總是令人尷尬的!

它可能也可能不相關,但Visual Studi當項目在調試模式下運行並且在「即時」編輯代碼時,它在今天早上崩潰並燒燬了......它被卡住了,我認爲這是無盡的錯誤信息循環。錯誤消息是關於「無法調試這個項目,因爲它不是當前的項目,或者什麼......所以我只是用進程管理器把它關閉了,它再次啓動,甚至提出恢復」失去「文件,我接受了報價

using System; 
using System.Windows.Forms; 

namespace ShowFormOnTop { 
    static class Program { 
     [STAThread] 
     static void Main() { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      //Application.Run(new Form1()); 
      Form1 frm = new Form1(); 
      frm.ShowDialog(); 
     } 
    } 
} 

背景:我移植現有的VB6實現到.NET ......這是一個‘插件’的‘叫MapInfo客戶端’GIS應用的。現有的客戶端「無形地工作」,我的指令是「使新版本儘可能接近舊版本」,它運行良好(經過多年修補);它只是用不支持的語言編寫的,所以我們需要端口它

關於我:雖然我有一個底部擦拭證書,但我一直都是C#和.NET的noob,我已經是一個專業程序員10年了;所以我有點「知道一些東西」。

任何見解都會受到歡迎...並感謝大家花時間閱讀這些內容。 Consiseness不是(顯然)我的特長。

乾杯。基思。

回答

44

只需

yourForm.TopMost = true; 
+0

我會去給它一個節。謝謝你的建議。我很欣賞它。 – corlettk 2009-06-12 23:26:09

+0

只需在Form_Load中設置this.TopMost = true就像魅力一樣。謝謝你,謝謝你,謝謝! – corlettk 2009-06-13 01:27:37

+0

我有一個類似的問題,並嘗試在Load事件中使用this.Focus()和this.Activate(),但沒有成功,但在Load事件中設置this.TopMost = true完全適合我!偉大的職位,並感謝一百萬的答案。 +1 – Jim 2012-05-15 16:05:39

4

有)Form.ShowDialog(的過載它接受一個I​​Win32Window對象。該IWin32Window被視爲該窗體的父窗口。

如果您有父窗口作爲System.Windows.Forms.Form,請繼續並傳遞它。如果沒有,得到HWND(也許通過P /調用FindWindow()),並創建一個虛擬的IWin32Window實現,它只是返回HWND(More details)。

+0

應用程序中沒有其他窗口...只是這個「小對話」(允許用戶輸入一些元數據以進行更新)。 – corlettk 2009-06-12 15:49:56

3
  1. 你說當你使用Application.Run時它工作正常。你爲什麼不想用Application.Run呢?
  2. 您是否試過從OnLoadOnShown撥打BringToFront()
0

這似乎是行爲是特定於XP ...因此我無法在Vista上重現它。

http://www.gamedev.net/community/forums/topic.asp?topic_id=218484

編輯: PS:這是過去我的就寢時間(凌晨2點;-)。

感謝您的迴應......我可以嘗試......「有幾件事情......我甚至可能會在明天去辦公室試試他們...是的,是的......我曾經有過一次生活,但我把它換成理髮和工作;-)

乾杯。基思。

1

我從我一直在研究的應用程序中入侵了這個。我們有一個大型應用程序,用於加載由不同團隊編寫的一系列模塊。我們已經編寫了其中一個模塊,並且需要在此初始化期間打開登錄對話框。它被設置爲'.TopMost = true',但那不起作用。

它使用WindowsFormsSynchronizationContext打開一個對話框,然後獲取對話框的結果。

我很少做GUI編碼,並懷疑這可能是矯枉過正,但它可能會幫助某人,如果他們卡住了。我在理解狀態如何傳遞給SendOrPostCallback時遇到了問題,因爲我可以找到的所有示例都沒有使用它。

此外,這是取自一個工作的應用程序,但我刪除了幾位代碼,並更改了一些細節。道歉,如果它不編譯。

public bool Dummy() 
{ 

// create the login dialog 
DummyDialogForm myDialog = new DummyDialogForm(); 

// How we show it depends on where we are. We might be in the main thread, or in a background thread 
// (There may be better ways of doing this??) 
if (SynchronizationContext.Current == null) 
{ 
    // We are in the main thread. Just display the dialog 
    DialogResult result = myDialog.ShowDialog(); 
    return result == DialogResult.OK; 
} 
else 
{ 
    // Get the window handle of the main window of the calling process 
    IntPtr windowHandle = Process.GetCurrentProcess().MainWindowHandle; 

    if (windowHandle == IntPtr.Zero) 
    { 
     // No window displayed yet 
     DialogResult result = myDialog.ShowDialog(); 
     return result == DialogResult.OK; 
    } 
    else 
    { 
     // Parent window exists on separate thread 
     // We want the dialog box to appear in front of the main window in the calling program 
     // We would like to be able to do 'myDialog.ShowDialog(windowHandleWrapper)', but that means doing something on the UI thread 
     object resultState = null; 
     WindowsFormsSynchronizationContext.Current.Send(
      new SendOrPostCallback(delegate(object state) { resultState = myDialog.ShowDialog(); }), resultState); 

     if (resultState is DialogResult) 
     { 
      DialogResult result = (DialogResult) resultState; 
      return result == DialogResult.OK; 
     } 
     else 
      return false; 

    } 
} 

}

3

Form.Activate()曾在我的情況。

1

Activate()也適用於我。

BringToFront()在這種情況下什麼也沒做,我不知道爲什麼。

-1

這是我用來將一個開放表單作爲我的應用程序的一部分帶到前面。 你甚至可以使用它與一個按鈕。但表單需要打開或應用程序會中斷。

「YourOpenForm」必須是屬性窗口中表單的名稱。

private void button1_Click(object sender, EventArgs e) 
    { 
     Application.OpenForms["YourOpenForm"].BringToFront(); 
    } 

祝你好運!

2

這是最後的解決方案,我經過20次不同的嘗試中寫道:

/* A workaround for showing a form on the foreground and with focus, 
* even if it is run by a process other than the main one 
*/ 
public static void ShowInForeground(this Form form, bool showDialog = false) 
{ 
    if (showDialog) 
    { 
     //it's an hack, thanks to http://stackoverflow.com/a/1463479/505893 
     form.WindowState = FormWindowState.Minimized; 
     form.Shown += delegate(Object sender, EventArgs e) { 
      ((Form)sender).WindowState = FormWindowState.Normal; 
     }; 
     form.ShowDialog(); 
    } 
    else 
    { 
     //it's an hack, thanks to http://stackoverflow.com/a/11941579/505893 
     form.WindowState = FormWindowState.Minimized; 
     form.Show(); 
     form.WindowState = FormWindowState.Normal; 

     //set focus on the first control 
     form.SelectNextControl(form.ActiveControl, true, true, true, true); 
    } 
}