繁体   English   中英

使用PopupRegion的WPF Prism应用程序在关闭时抛出无效的窗口句柄

[英]WPF Prism application using PopupRegion throws Invalid Window Handle on close

我正在使用棱镜框架[.net 4.0]开发一个wpf应用程序。 我已经使用来自StockTrader RI的RegionPopupBehavior实现了一个弹出窗口。 现在,当我使用窗口标题栏[主窗口]右上方的关闭按钮或使用

Application.Current.Shutdown() 

调用按钮单击后,出现Win32异常,并显示消息“ Invalid Window Handle”,并且堆栈跟踪是所有回传给应用程序Run()调用的interop调用。

我已经搜索了谷歌,所以无济于事。 我在关闭期间设置了中断,并检查了Windows集合,但它仅将主窗口显示为活动状态(如果弹出窗口被隐藏)。 请注意,当我单击关闭时,无论弹出窗口是否打开,我都会收到错误消息。

这是堆栈跟踪:

at MS.Win32.HwndWrapper.DestroyWindow(Object args)
   at MS.Win32.HwndWrapper.Dispose(Boolean disposing, Boolean isHwndBeingDestroyed)
   at MS.Win32.HwndWrapper.Dispose()
   at System.Windows.Interop.HwndSource.Dispose(Boolean disposing)
   at System.Windows.Interop.HwndSource.WeakEventDispatcherShutdown.OnShutdownFinished(Object sender, EventArgs e)
   at System.EventHandler.Invoke(Object sender, EventArgs e)
   at System.Windows.Threading.Dispatcher.ShutdownImplInSecurityContext(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.Dispatcher.ShutdownImpl()
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at RNDGroup.App.App.Main() in c:\Users\jgilliland\Projects\Common\Source\Prism GUI\RNDGroup.App\obj\x86\Release\App.g.cs:line 0
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

我的问题是,如果有人在类似情况下以前看过它,如何解决此问题;或者我该如何进一步调试该Win32异常? 谢谢,j

我团队的技术负责人发现了问题,并消除了此错误。 弹出区域用于在其自己的窗口中显示/隐藏或激活/停用VirtualKeyboardView。 当我从用户单击按钮时显示键盘切换到每当文本框获得焦点时显示键盘时,就开始出现“无效的窗口句柄” win32异常。

焦点事件有点有趣,我看到了用户进行相同的单击/聚焦会导致多个焦点事件。 无论如何,故事的结尾是我意识到问题是重复的焦点事件,但我找不到问题的根源。 我的队友能够找到由文本框这些看似重复的焦点事件引起的递归问题。 解决方案是跟踪导致键盘显示的最后一个文本框元素,并实质上忽略重复的焦点事件。 这样就删除了无效的窗口句柄的win32异常。

我知道这是一个奇怪的问题,甚至是一个更奇怪的答案,但这是我第一次在这样的论坛上发布问题,显然我首先需要学习如何更好地提出问题。 但是,由于我的团队工作非常有帮助,我得以摆脱了错误,继续在辅助弹出区域中的wpf中实现了此虚拟键盘。 一直以来都是学习经历。

这是一些代码,可能有助于阐明答案。 这来自VirtualKeyboardService,该服务管理显示和隐藏键盘视图。

/// <summary>
/// Opens the keyboard.
/// </summary>
public void OpenKeyboard()
{
    lock (_lock)
    {
        // allow for ignoring a refocus one time
        if (_ignoreOnce)
        {
            _ignoreOnce = false;
            return;
        }
        // open keyboard if not already open
        if (!_isKeyboardOpen)
        {
            var viewName = typeof(VirtualKeyboardView).FullName;
            _regionManager.RequestNavigate(RegionNames.PopupRegion, new Uri(viewName, UriKind.Relative));
            _isKeyboardOpen = true;
            _lastImpression = null;
        }
    }
}

这就是关闭虚拟键盘的方法,当用户单击关闭按钮或按下Enter键,Tab键或esc键时,从键盘的视图模型中调用该方法。 也可以从MainWindow的Activated事件的事件处理程序中调用它。
/// ///关闭键盘。 /// ///如果设置为true [还原文本]。 public void CloseKeyboard(bool revertText = false){lock(_lock){//关闭键盘视图var view = _regionManager.Regions [RegionNames.PopupRegion] .ActiveViews.FirstOrDefault();

        if (view != null)
        {
            _regionManager.Regions[RegionNames.PopupRegion].Deactivate(view);
            _isKeyboardOpen = false;
            _lastImpression = CurrentTarget;
        }

        // revert text if needed
        if (revertText && CurrentTarget != null)
        {
            CurrentTarget.Text = CurrentText;
        }
    }
}

这也很棘手,那就是忽略功能开始发挥作用的地方。 当用户单击“离开”以激活主窗口时,我必须能够关闭键盘视图,该窗口可能集中在文本框上,从而导致键盘视图重新出现。 忽略一次选项允许中断该循环。 自动显示虚拟键盘涉及很多不同的用例。 我学到了很多有关在wpf中使用行为和复合命令的知识...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM