簡體   English   中英

Show和ShowDialog無效

[英]Show and ShowDialog won't work

它與我以前見過的任何東西都不一樣。
當我調用(new System.Windows.Forms.Form())。ShowDialog()時,表單會顯示一毫秒或者其他東西然后消失。
我跟蹤了電話並得到了:

System.Windows.Forms.Form.Dispose
System.ComponentModel.Component.Dispose
System.Windows.Forms.Application.ThreadWindows.Dispose
System.Windows.Forms.Application.ThreadContext.DisposeThreadWindows
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner
System.Windows.Forms.Application.ThreadContext.RunMessageLoop
System.Windows.Forms.Form.ShowDialog Esfand.Program.Main C#

我已經嘗試過任何解決此問題的方法。

雖然我在嘗試顯示此表單之前已經顯示了登錄表單。
我不認為登錄表單上有任何特殊內容(通常無聊的東西,連接到服務器,發送憑據,接收數據)。
我正在使用表單的主線程。 我具有消息傳遞和消息循環的經驗。 我已經在登錄表單中使用了線程。

編輯:澄清Cody Gray的建議:

這就是我在void Main(string[])

LoginForm login = new LoginForm ();
login.ShowDialog ();//works
if (login.DialogResult == DialogResult.OK)
{
    MainForm f = new MainForm ();
    f.ShowDialog ();//won't work
}

在新線程中創建和顯示MainForm使得所有內容都重新開始工作。但是每個表單上都會出現隨機錯誤,導致此解決方案不夠好。

編輯2:
FormClosing事件甚至不會觸發。

System.Windows.Forms.Form A;
A = new Form();
A.FormClosing += new FormClosingEventHandler((sender, e) => { System.Diagnostics.Debugger.Break();/*won't work. tried Breakpoints and other stuff too*/ });
A.ShowDialog();

編輯3:HandleDestroyed事件堆棧跟蹤:

>   Esfand.exe!Esfand.Program.Main.AnonymousMethod__1(object sender = {System.Windows.Forms.Form}, System.EventArgs e = {System.EventArgs}) Line 50 + 0x6 bytes C#
    System.Windows.Forms.dll!System.Windows.Forms.Control.OnHandleDestroyed(System.EventArgs e) + 0x9e bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Form.OnHandleDestroyed(System.EventArgs e) + 0x13 bytes   
    System.Windows.Forms.dll!System.Windows.Forms.Control.WmDestroy(ref System.Windows.Forms.Message m) + 0x54 bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x547 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Form.WndProc(ref System.Windows.Forms.Message m) + 0x6d bytes 
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg = 2, System.IntPtr wparam, System.IntPtr lparam) + 0x15e bytes    
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DestroyHandle() + 0xf7 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Control.DestroyHandle() + 0x3e3 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Control.Dispose(bool disposing) + 0x347 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.Dispose(bool disposing) + 0x19 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Form.Dispose(bool disposing) + 0x26a bytes    
    System.dll!System.ComponentModel.Component.Dispose() + 0x1b bytes   
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadWindows.Dispose() + 0xb3 bytes  
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.DisposeThreadWindows() + 0x12d bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID, int reason, int pvLoopData) + 0x58e bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = 4, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.Application.ModalApplicationContext}) + 0x593 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x81 bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window owner) + 0x765 bytes    
    Esfand.exe!Esfand.Program.Main(string[] a = {string[0]}) Line 51 + 0x10 bytes   C#

這件事正在使程序中的每個表單都引發唯一錯誤(例如,“無法注冊拖放事件處理程序”)

這是代碼中核心問題的有力暗示。 當您具有AllowDrop屬性設置為true的任何控件時,將調用RegisterDragDrop()本機函數。 在創建表單的本機窗口時調用它。 不幸的是,如果您擁有64位版本的Windows並且強制程序以32位模式運行,那么引發任何異常都是非常糟糕的時間。 這個答案的主題。

RegisterDragDrop()失敗的理由很少。 但是一個。 我們已經可以從你的代碼片斷中告訴你,你一直在修改Program.cs。 樣板版本如下所示:

static class Program {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]                // <=== Here!!!
    static void Main() {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

我把Big Arrow放在重要的代碼行上。 [STAThread]屬性在任何GUI程序中都是必不可少的。 它告訴CLR應該初始化COM並將程序的主線程配置為單線程單元。 公寓是一個非常重要的COM實現細節,其范圍超出了這個答案。 如果缺少該屬性,則程序的主線程將加入多線程單元MTA。 惡意代碼不安全的地方,例如拖放,剪貼板和外殼對話框。

忘記使用該屬性可能會導致令人困惑的異常。 當您的開發機器啟動64位版本的Vista或Win7時,尤其糟糕的是,Windows版本的出現在關鍵時刻出現異常的麻煩,如鏈接的答案所述。

Program.Main()方法的正確版本沒有此問題,否則使用建議的做法:

    [STAThread]                // <=== Don't forget this
    static void Main() {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        using (var login = new LoginForm()) {
            if (login.ShowDialog() != DialogResult.OK) return;
        }
        Application.Run(new MainForm());
    }

嘗試檢查是否拋出線程異常錯誤。 檢查您是否在Application_ThreadException事件中看到任何內容。

static void Main()
{
    Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
    try
    {
        //Your existing code
    }
    catch (Exception ex)
    {
    }
}

private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
}

編輯:另一種選擇是明確將MainForm設置為正在創建的newForm的所有者。

newForm.ShowDialog(MainForm);

我有一種感覺,默認情況下,所有者被設置為您的登錄表單已關閉,這是自動關閉您的新表單

當事件隊列上有WM_QUIT消息時,看起來IMsoComponentManager.FPushMessageLoopP()將調用Application.ThreadContext.DisposeThreadWindows()

您是否在LoginForm的按鈕事件處理程序中發布了退出消息?

嘗試將表單定義為類成員。 不在函數內部。

你的Main方法看起來很奇怪。 我想你錯過了對Application.Run()的調用。 由於您不希望應用程序在登錄表單關閉后立即退出,因此您可能需要一個ApplicationContext MSDN有一個示例: http : //msdn.microsoft.com/en-us/library/ms157901.aspx

另一種可能性是使用不可見的形式調用Application.Run()作為參數,然后顯示其他形式(並且在應用程序退出之前永遠不會關閉),但在我看來這是一個相當丑陋的黑客。

我的理解是表單需要在應用程序上下文中運行。

我以下列方式繼承了一些代碼,這些代碼從Main上下文啟動了幾種形式:

var form1 = Form1();
Application.Run(form1);

// form returns, check public method form.ButtonPushed etc
if (form.Button1Pushed)
{
    var form2 = Form2();
    Application.Run(form2);
}

這將成功啟動幾種形式。

感覺不像是一種非常優雅的做事方式,但它可以工作...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM