以下是一个涉及的问题,我做了大量的研究,但到目前为止还无法解决。我很高兴找到解决方案或解决方法。虽然框架是旧的(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发送到它后面?
如果有人可以帮助我,或指出正确的方向,我当然会很感激。
由于
答案 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
如果是你正在看到的那个,那么修补程序将解决问题。