3

多くのMDI子ウィンドウを備えたアプリケーションがあります。通常、ユーザーはウィンドウのクライアント領域と非クライアント領域の両方をクリックすることで、1つのMDI子ウィンドウを前面に表示できます。これは通常、マウスボタンを押すとすぐに発生するようです。

ここで、ユーザーがクライアント領域でMDI子フォームをクリックすると、ウィンドウが期待どおりに前面に表示されないことがあります。ただし、フォームのタイトルバーをクリックすると、ウィンドウが前面に表示されますが、マウスボタンを離した場合に限ります。これには、ユーザーが1つのMDI子ウィンドウを別のウィンドウの後ろにドラッグできるという効果があり、マウスボタンを離すと、ドラッグされたウィンドウが前面に表示されます。

その結果、複数のMDI子ウィンドウが部分的に重なり合っている場合、通常のようにウィンドウを前面に表示することはできません。これはフォーカスとは無関係のようです。MDI子ウィンドウはフォーカスを持つことができますが、それでも別のMDI子ウィンドウの背後にあります。

さらに、これは、アプリケーションをしばらく使用した後、ランダムに発生するようです。ユーザーから送信されたシリアル化されたプログラム状態(「保存」ファイル)を使用してバグを再現できます。

私の質問には2つの部分があります。これが発生する理由と、プログラムをデバッグしてこれが発生する理由を見つけるにはどうすればよいですか。

ウィンドウメッセージWM_ACTIVATE(または同様のもの)が適切に処理されていないようですが、これはC#アプリケーションであり、メッセージキューで異常なことは何もしていません。

編集:ここにspy++からのいくつかの追加情報があります。

以下は、すべてが正常に発生した場合のspy++からの出力です。

<00013> 00D209AA S WM_PARENTNOTIFY fwEvent:WM_LBUTTONDOWN xPos:146 yPos:147
<00014> 00D209AA R WM_PARENTNOTIFY
<00015> 00D209AA S WM_WINDOWPOSCHANGING lpwp:0012EE90
<00016> 00D209AA R WM_WINDOWPOSCHANGING
<00017> 00D209AA S WM_CHILDACTIVATE
<00018> 00D209AA S WM_NCPAINT hrgn:D3043A75
<00019> 00D209AA R WM_NCPAINT
<00020> 00D209AA S WM_ERASEBKGND hdc:C20124F7
<00021> 00D209AA S WM_GETTEXTLENGTH
<00022> 00D209AA R WM_GETTEXTLENGTH cch:1
<00023> 00D209AA S WM_GETTEXT cchTextMax:4 lpszText:0012DC48
<00024> 00D209AA R WM_GETTEXT cchCopied:1 lpszText:0012DC48 (" ")
<00025> 00D209AA R WM_ERASEBKGND fErased:True
<00026> 00D209AA S WM_WINDOWPOSCHANGING lpwp:0012EB80
<00027> 00D209AA R WM_WINDOWPOSCHANGING
<00028> 00D209AA S WM_MDIACTIVATE hwndDeactivate:014809AE hwndActivate:00D209AA (activating)
<00029> 00D209AA S WM_NCACTIVATE fActive:True
<00030> 00D209AA R WM_NCACTIVATE
<00031> 00D209AA S WM_IME_SETCONTEXT fSet:1 iShow:C000000F
<00032> 00D209AA R WM_IME_SETCONTEXT
<00033> 00D209AA S WM_SETFOCUS hwndLoseFocus:00B20A2A
<00034> 00D209AA R WM_SETFOCUS
<00035> 00D209AA R WM_MDIACTIVATE
<00036> 00D209AA R WM_CHILDACTIVATE
<00037> 00D209AA S WM_WINDOWPOSCHANGED lpwp:0012EE90
<00038> 00D209AA R WM_WINDOWPOSCHANGED
<00039> 00D209AA S WM_MOUSEACTIVATE hwndTopLevel:012C093A nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN
<00040> 00D209AA R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE

バグが再現された状態でアプリケーションを実行して出力を取得すると、クライアント領域をクリックすると次のようになります。

<01315> 023E0AA0 S WM_PARENTNOTIFY fwEvent:WM_LBUTTONDOWN xPos:139 yPos:142
<01316> 023E0AA0 R WM_PARENTNOTIFY
<01317> 023E0AA0 S WM_MOUSEACTIVATE hwndTopLevel:012C093A nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN
<01318> 023E0AA0 R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE

メッセージ番号を見ると、発生していないメッセージがたくさんあることがすぐにわかります。具体的には、WM_CHILDACTIVATEです。

解決

MdiParentウィンドウが表示される前に、フォームの1つが設定されていませんでした。

4

2 に答える 2

3

試すべきいくつかの提案があります:

  • 子フォームにクリックイベントを追加し、クリック呼び出しShow()でフォームを前面に表示します
  • MdiParentプロパティがすべての子フォームに設定されていることを確認してください
  • IsMdiContainerプロパティが親フォームに設定されていることを確認してください
  • WindowState子フォームのセットNormal
  • Activate()フォームをアクティブにしてフォーカスを与えるために使用します

親からのzオーダーを利用して、子に焦点を当てることもできます。

this.ActiveMdiChild.SendToBack();
Control.ControlCollection ct = ((MdiClient)this.ActiveMdiChild.Parent).Controls;
((Form)ct[0]).Activate();

うまくいけば、これらの提案の1つ以上が問題を解決するでしょう。

于 2011-10-19T20:15:28.463 に答える
1

この質問への答えは、あなたが共有したよりもあなたのアプリケーションの実装に深くあるかもしれません。

サードパーティのUIライブラリを使用していますか?(例:DevExpressまたはTelerikまたは...)これらのライブラリは、多くの場合、pinvoke win32 apiを使用して、スキンが適切なウィンドウやきちんとした機能を実現します。昔ながらのWinFormを使用している場合は、知っておくとよいでしょう。

保存したアプリケーションの状態で問題を再現できるという事実は、子ウィンドウの作成方法にバグがあることを示しています。この保存された状態ファイルのロードをステップ実行して、すべての子ウィンドウが同じ方法でロードされるかどうかを確認します。これは、どこかの1行のコードに帰着する可能性のある種類の問題です。

また、問題を再現する複数の保存された状態ファイルを収集できれば、傾向を特定できる可能性があります。おそらく、上記の動作を一貫して表示するのは、アプリケーション内の1つの特定のウィンドウですか?

現在このスレッドにある他の提案とは異なり、Mdiの子にはShowDialog()を使用しないでください。(フォームにMdiParentを割り当ててShowDialogを実行しようとすると、Microsoftが例外をスローすることを願っています)。MdiChildrenはモーダルウィンドウであることが許可されておらず、これはあなたが見ているような悪い振る舞いを引き起こす可能性が非常に高いです。例:通常の子フォームがフォーカスを取得しようとしているときに、1つのフォームがモーダル/オントップになりたい。

于 2011-10-20T03:30:34.883 に答える