2012-05-08 120 views
1

まず、私の母国語ではないので、私の英語のために申し訳ありません。Win32Exception:ウィンドウハンドルを作成中にエラーが発生しました。(ネストされたコントロールが多数あります)

.NET Windowsフォームアプリケーションで問題が発生し、何らかの理由でVirtaul PC Windows 7(x64)でのみ問題が発生しました。

多くのカスタムコントロールを含むメインアプリケーションフォームのサイズを変更すると、アプリケーションの1か所でWin32Exceptionが発生しました.2つのタブコントロールなどが積み重ねられています。例外メッセージは「ウィンドウハンドルの作成中にエラーが発生しました。マイクロソフトのサポートサイトでその問題の解決策を見つけたのを少し時間を費やしていました。それは私の場合と非常に似ていました。サイトからのQoute:

.NETアプリケーションでは、深くネストされている場合に親のサイズを変更すると、ドッキングコントロールがサイズ変更されないことがあります。この問題は、64ビットおよび32ビットプラットフォームで発生しますが、32ビットシステムではより深いネストレベルが必要です。

トップレベルコントロールがレイアウトされると、SetBoundsCoreはSetWindowPosを呼び出して子コントロールのサイズを変更します。各子コントロールは、SetWindowPosを呼び出すSetBoundsCoreを呼び出すレイアウトイベントをトリガするWM_WINDOWPOSCHANGED通知を受け取ります。 SetWindowPosへの各呼び出しは、カーネルモードに入り、WM_WINDOWPOSCHANGED通知を配信するために戻ってきます。最終的にスレッドはカーネルスタック空間を使い果たし、SetWindowPosは自動的に失敗します。

私は成功した私の場合には、この解決策を適用
protected override void OnSizeChanged(EventArgs e) 
    { 
     if (this.Handle != null) 
     { 
      BeginInvoke((MethodInvoker)(() => base.OnSizeChanged(e);)); 
     } 
    } 

:作成したカスタムTabControlのを(から継承され

提案された解決策は、(私の場合はパネルやTabControlの(ような))のコンテナコントロールのOnSizeChangedメソッドをオーバーライドすることですプレーンwinforms TabControlクラス)と私のカスタムコントロールインスタンスでTabControlインスタンスを変更しました。そして問題はなくなった!しかし...

... CCnetビルドマシンでビルドを開始したとき、私はさまざまなユニットテストでWin32Exception-s "ウィンドウハンドルを作成中にエラーが発生しましたが、最も面白いのは問題のない場所ですコントロール(カスタムTabControlオブジェクトを含む)単体テスト!エラーケースは違っていましたが、私のカスタムコントロールとは関係ありませんでした。私が変更を元に戻したとき、すべてが正常だったので、ビルドが作成されました(ユニットテストは正常に実行されました)。

適用された変更がユーザーアプリケーションの作業性を修正したが、ビルドを作成するときに単体テストに失敗するということは私を完全に混乱させました。

ところで、ローカルマシンでは、すべてのユニットテストはどの場合でも問題なく実行されます(修正の有無にかかわらず)。

私はこの問題の調査に多くの時間を費やしましたが、現在は1つの前提しかありません:ccnetビルドマシンは1つのプロセスですべての単体テストを実行し、テストはテストデータ(gdiオブジェクト)を正しく(ティアダウン時)エラー "ウィンドウハンドルを作成中にエラーが発生しました"は、通常、許可されたgdiオブジェクトハンドル(10000)に達したときに発生します。

専門家の意見をお聞かせください。ありがとうございます。

答えて

0

エラーには直接関係しませんが、ハンドルプロパティにアクセスするとウィンドウハンドルが強制的に作成されることがあります。これは時には不可能です。ハンドルのチェックは次のように実行されるべきではありません。

if (this.Handle != null) 

代わりに、IsHandleCreatedプロパティをチェック:

if (this.IsHandleCreated) 

を私はしばらく前にこの問題についてthe blog postでこれを言及していたが、持っていないようです注目されている。

+0

ありがとう!私は適切な変更を行います。私もresharperがインストールされていると、それは常に私に "if(this.Handle!= null)"という重複した種類の "条件が常に真である"という行をマークしています。正直なところ、作成されたハンドルを持たないコントロールでサイズ変更が行われる可能性があるのか​​どうか分かりません。処分されたコントロールだけに可能ですか? –

+0

はい、sizeプロパティは、ハンドルが作成される前に変更できます(通常、コントロールが表示されているとき)。デザイナを介してSizeが設定されている場合など、コントロールのコンストラクタで設定されます。 – roken

0

CCNETマシンで単体テストとして実行している場合、非対話型サービスコンテキストで実行されている可能性があります。そのため、ウィンドウが表示されないためにウィンドウが作成されない可能性があります。

+0

単体テストの実装の詳細については触れていませんでしたが、フォームインスタンスを作成してもレンダリングしないと思います。私が間違いなく知っているのは、アクセサオブジェクトはプライベートフィールドにアクセスするために使用されるということです。ただし、表示(レンダリング)されているかどうかに関係なく、作成中に各gdiオブジェクトインスタンスに対してハンドルが作成されます。 –

0

深く入れ子になったコントロールで同じ問題が発生しました。しかし、適切な解決策のために、私はSetBoundsCoreを上書きして遅延させなければならなかった。

protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) 
    { 
     if (this.IsHandleCreated) 
     { 
      this.BeginInvoke(
          (MethodInvoker)delegate 
          { 
           base.SetBoundsCore(x, y, width, height, specified); 
          }); 
     } 
    } 
関連する問題