MDI Child .Show()方法在Framework中引发NullReferenceException

时间:2009-01-24 02:28:11

标签: .net winforms exception

以下是一个涉及的问题,我做了大量的研究,但到目前为止还无法解决。我很高兴找到解决方案或解决方法。虽然框架是旧的(1.0)我现在不能升级到1.1或更高版本(客户端目前不愿意支付转换费用),我甚至不确定这会解决问题...非常感谢任何帮助:

平台:在Windows XP上运行的.NET 1.0 VB.NET Windows窗体MDI应用程序

问题:MDI子窗口(child1)调用不同MDI子窗口(child2)的.Show()方法,并抛出NullReferenceException

这只发生在一个特定的表单(child1)中,并且仅当该子表单处于最大化状态时,并且MDI父窗口也处于最大化状态。

从child1中的代码打开的任何其他子表单抛出异常(即错误不会被隔离以打开一种类型的表单)。

当从调试器运行时,只有在抛出异常时“打入调试器”时才会抛出异常(尽管此错误稍后会显示,这是真正的问题)。这种行为似乎可以在框架中解释,只要捕获到异常但没有完成任务(参见下面反映的代码)。

异常似乎是从框架(1.0)本身抛出的。请参阅下面的堆栈跟踪:

system.windows.forms.dll!System.Windows.Forms.NativeWindow::WindowClassCallback(__int32 hWnd = 461572, __int32 msg = 36, __int32 wparam = 0, __int32 lparam = 1239164) + 0x48 bytes 
    system.windows.forms.dll!System.Windows.Forms.UnsafeNativeMethods::CreateWindowEx(__int32 dwExStyle = 327744, String* lpszClassName = "WindowsForms10.Window.8.app13", String* lpszWindowName = "Diary Entry: ROSIE MILES", __int32 style = 1204748288, __int32 x = -2147483648, __int32 y = -2147483648, __int32 width = 480, __int32 height = 380, __int32 hWndParent = 920114, __int32 hMenu = 0, __int32 hInst = 285212672, System.Object pvParam = null) + 0x3c bytes  
    system.windows.forms.dll!System.Windows.Forms.NativeWindow::CreateHandle(System.Windows.Forms.CreateParams cp = {System.Windows.Forms.CreateParams}) + 0x1d6 bytes  
    system.windows.forms.dll!System.Windows.Forms.Control::CreateHandle() + 0x19a bytes 
    system.windows.forms.dll!System.Windows.Forms.Form::CreateHandle() + 0x12f bytes    
    system.windows.forms.dll!System.Windows.Forms.Control::get_Handle() + 0x2f bytes    
    system.windows.forms.dll!System.Windows.Forms.Form::SetVisibleCore(bool value = true) + 0x1e9 bytes 
    system.windows.forms.dll!System.Windows.Forms.Control::set_Visible(bool value = true) + 0x1e bytes  
    system.windows.forms.dll!System.Windows.Forms.Control::Show() + 0x14 bytes  
>   SpecMed.exe!SpecMed.ScheduleForm.viewScheduleMenuItem_Click(Object sender = {System.Windows.Forms.MenuItem}, System.EventArgs e = {System.EventArgs}) Line 1508 + 0xb bytes Basic
    system.windows.forms.dll!System.Windows.Forms.MenuItem::OnClick(System.EventArgs e = {System.EventArgs}) + 0x8d bytes   
    system.windows.forms.dll!MenuItemData::Execute() + 0x1e bytes   
    system.windows.forms.dll!System.Windows.Forms.Command::Invoke() + 0x4c bytes    
    system.windows.forms.dll!System.Windows.Forms.Command::DispatchID(__int32 id = 299) + 0x2c bytes    
    system.windows.forms.dll!System.Windows.Forms.Control::WmCommand(System.Windows.Forms.Message m = {System.Windows.Forms.Message}) + 0x4a bytes  
    system.windows.forms.dll!System.Windows.Forms.Control::WndProc(System.Windows.Forms.Message m = {System.Windows.Forms.Message}) + 0x1f3 bytes   
    system.windows.forms.dll!ControlNativeWindow::OnMessage(System.Windows.Forms.Message m = {System.Windows.Forms.Message}) + 0x19 bytes   
    system.windows.forms.dll!ControlNativeWindow::WndProc(System.Windows.Forms.Message m = {System.Windows.Forms.Message}) + 0xda bytes 
    system.windows.forms.dll!System.Windows.Forms.NativeWindow::Callback(__int32 hWnd = 6621754, __int32 msg = 273, __int32 wparam = 299, __int32 lparam = 0) + 0x4a bytes  
    system.windows.forms.dll!System.Windows.Forms.Application::ComponentManagerSystem.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FPushMessageLoop(__int32 dwComponentID = 1, __int32 reason = -1, __int32 pvLoopData = 0) + 0x2c1 bytes 
    system.windows.forms.dll!ThreadContext::RunMessageLoop(__int32 reason = -1, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.ApplicationContext}) + 0x1c5 bytes  
    system.windows.forms.dll!System.Windows.Forms.Application::Run(System.Windows.Forms.Form mainForm = {SpecMed.MainForm}) + 0x34 bytes    
    SpecMed.exe!SpecMed.Program.Main() Line 15 + 0x1d bytes Basic

我已经反映了这种方法,因为它很难获得对问题的一些了解。 WindowClass.Callback()方法的代码是:

public IntPtr Callback(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
{
    try
    {
        UnsafeNativeMethods.SetWindowLong(hWnd, -4, this.defWindowProc);
        this.targetWindow.AssignHandle(hWnd);
        return this.targetWindow.Callback(hWnd, msg, wparam, lparam);
    }
    catch (Exception)
    {
    }
    return IntPtr.Zero;
}

正如您所看到的,异常被捕获但没有做任何事情。

用户界面显示:

此异常的原因似乎随后出现,调用(child1)和被调用(child2)子窗体的行为很糟糕。

在UI中,即使忽略了异常,MDI父级也会显示两个MDI Child控件框(即两组最小化,恢复和关闭框)和两个子图标(参见屏幕截图)。一个控制盒被禁用。

alt text http://www.freeimagehosting.net/uploads/a65a085cd3.jpg alt text http://www.freeimagehosting.net/uploads/fcbee0eccf.jpg

关闭child2表单后,child1变得无响应,无法重新绘制。

研究:

在网上搜索,我发现了以下文章,这些文章似乎描述了类似或几乎相同的问题(但在不同的框架下),但这些解决方案都没有帮助。

http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/66cee5a3-c743-4be6-ae63-7416b81a9688/(听起来完全一样的问题,但似乎没有发布任何解决方案)。

http://support.microsoft.com/kb/871045(类似但不一样的问题,解决方案似乎没有帮助)。

http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic39112.aspx :(听起来像是同一个问题,但对于不同的框架)。

调用子表单(child1)上有一些第三方控件(Janus WinForms Suite),我怀疑它是以某种方式导致问题。这些控件是.NET控件而不是Activex。

尝试解决方案

我尝试在child1上引发一个事件,MDI Parent处理,然后MDI Parent打开child2。仍然是同样的问题。

在child1调用child2.Show()之后,我尝试设置child2的MDI父级。仍然没有改善。

我已经尝试在child2.InitialiseComponents()调用之前设置child2的MDI Parent。没有改善。

输入所有这些后,我开始认为问题不在于调用child2,而是在打开child2时如何处理child1,最大化并因此将child1发送到它后面?

如果有人可以帮助我,或指出正确的方向,我当然会很感激。

由于

2 个答案:

答案 0 :(得分:1)

解决方法:

我找到了一种解决方法,但并不是特别优雅,但目前似乎有效:

通过检查调用表单是否最大化并存储它,然后可以在.Show()调用之前最小化(或恢复)调用表单(防止问题),然后将调用的表单WindowState设置为最大化。将被调用的表单状态设置为最大化可以模拟通常应该发生的行为(除了在调整表单大小时闪烁一点)。

代码:

'-- workaround to prevent UI problem with maximised child form calling another maxmised child form --'
Dim isMaximised As Boolean = (WindowState = FormWindowState.Maximized)

'-- minimise the current form so the problem wont occur when we call the new child Form --'
If isMaximised Then WindowState = FormWindowState.Minimized

Dim form As DiaryEntryForm = DiaryEntryForm.GetForm(scheduleId, Me)
'-- if the calling child was originally maximised, then maximsed the called form to similute what should normally happen --'
If isMaximised Then form.WindowState = FormWindowState.Maximized
form.Show()

但我会继续尝试寻找解决方案。任何帮助赞赏。感谢。

答案 1 :(得分:0)

您是否尝试将菜单合并为MDI子项显示的一部分?如果是这样,你可能会遇到这个问题

http://support.microsoft.com/kb/895579

如果是你正在看到的那个,那么修补程序将解决问题。