0

プリズムフレームワーク[.net4.0]を使用してwpfアプリケーションを開発しています。StockTraderRIのRegionPopupBehaviorを使用してポップアップウィンドウを実装しました。これで、メインウィンドウを閉じるときに、ウィンドウタイトルバー[メインウィンドウ]の右上にある閉じるボタンを使用するか、

Application.Current.Shutdown() 

ボタンクリックで呼び出すと、「Invalid Window Handle」というメッセージが表示されたwin32例外が発生し、スタックトレースはアプリのRun()呼び出しへのすべての相互運用呼び出しです。

私は無駄への答えをグーグルとSOで検索しています。閉じるときにブレークを設定して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

4

1 に答える 1

1

私のチームのテクニカルリードが問題を発見し、このエラーを削除しました。ポップアップ領域は、独自のウィンドウで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での動作と複合コマンドの使用について多くのことを学びました...

于 2013-02-18T02:10:32.780 に答える