- PR -

フォームの再描画処理で発生するオブジェクト参照のエラーについて

1
投稿者投稿内容
笊頭刹那
ベテラン
会議室デビュー日: 2005/10/17
投稿数: 55
お住まい・勤務地: オーストラリア
投稿日時: 2005-10-25 17:37
お世話になっています刹那です。

フォームのOnPaint(またはForm1_Paint)で描画処理を行うフォームを作っているのですが、そのフォームが起動中に他のゲーム(Age of Empire2)を起動→終了すると「オブジェクト参照がオブジェクトインスタンスに含まれていません」とエラーが出て終了してしまいます。
動作的にウィンドウを最大化して画面のサイズを変えて…とするものでもなりそうな予感です、他にゲーム持ってないので試せませんが…ちなみに、自分で画面サイズや色設定変えてみましたが問題なく動作しました、このことからDirectX関連が関係するのかとも思ったのですが、ウィンドウズを再開したときにも同様の現象に見舞われましたOrz。ランチャーなので常備起動させておかなければならないので致命的なんですよね(汗。ちなみに、自分で対策として

コード:
// 簡略化したコードです、実験してもこれでエラー発生しました。
override void OnPaint(PaintEventArgs e)
{
    if(e!=null)
         e.Graphics.DrawRectangle(--略--);
}



コード:
override void OnPaint(PaintEventArgs e)
{
    try
    {
        e.Graphics.DrawRectangle(--略--);
    }
}


など試してみたのですが、問題は改善せず、例外を拾ってくれず、コードの実行はApplication.Run(---)の部分で停止しますorz

加え、ハンドルされていない例外処理時に独自メッセージを表示するようにしているのですが、そのメッセージも(たぶん重過ぎて?動作の雰囲気的にはそのような感じです、MessageBox.Showなんですけどね…)表示されません(表示部分のコードで止まって先に進まない、しばらくすると強制終了してしまう。)

一応スタックトーレースです。
--------------------------------------------------------------------------------
System.Windows.Forms.UnsafeNativeMethods.DispatchMessageA(MSG& msg) at System.Windows.Forms.ComponentManager.System.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) at System.Windows.Forms.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) at System.Windows.Forms.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.Run(Form mainForm)\\r\\n at setuna.seedofweed.soft.Nihilunch.Program.Main() in d:\\\\my documents\\\\visual studio projects\\\\nihilunch\\\\program.cs:line 32"
---------------------------------------------------------------------------------

スタックトレースなどを見ると内部的ななにかで…という感じがするのですが、まず、調べ方が良く分からず(それでもいろいろと調べてみたんですが…)困っています。これに対する情報を持っている方がいらっしゃいましたらご提供お願いいたします。

(コメントアウトしてもエラーが発生したので関係ないとは思いますが、フォームはリージョンを使用して形を変更しOpacity?で半透明化処理を行っています)

環境 Windows XP
スタイル:Style XPを使用・使用を停止(アンインストールじゃないです)の両方で試してみた、が駄目でしたorz。
Microsoft Visual Studio.net 2003 -> Visual C#.net
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-10-25 17:54
引用:

刹那さんの書き込み (2005-10-25 17:37) より:

そのフォームが起動中に他のゲーム(Age of Empire2)を起動→終了すると
「オブジェクト参照がオブジェクトインスタンスに含まれていません」とエラーが出て終了してしまいます。


ゲームのせいというよりは、スクリーンの解像度などが自動で切り替わるからでしょうね。
画面のプロパティから変更した場合は起きませんか?

引用:

自分で対策として

コード:

    if(e!=null)
         e.Graphics.DrawRectangle(--略--);




これは、

コード:

    if (e.Graphic != null) {
        e.Graphics.DrawRectangle(--略--);
    }


と、しないと意味がないのではないでしょうか?

# それでも、例外が発生しそうですが...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
笊頭刹那
ベテラン
会議室デビュー日: 2005/10/17
投稿数: 55
お住まい・勤務地: オーストラリア
投稿日時: 2005-10-25 17:54
言葉足らずでしたすいません。

>自分で画面サイズや色設定変えてみましたが問題なく動作しました
の意味が、まさに自分で画面のプロパティを変更した場合という意味です。

>e!=null
はじめに、e.Graphics!=nullでチェックしていたのですが、オブジェクト(略とでたので、「eが存在していないのか…?」と思いe!=nullに変更したんです、言葉足らずでした。
ちなみに、動作を見るかぎりeもe.Graphicsも存在しているようです。

まったくのクリーンなフォームでOnPaintの部分で描画を行うものを作成し、起動中にAge Of E...を起動してもこういう現象が起こるので関係する部分がOnPaintの部分だと思います。

いろいろと試してみたのですが、これでも駄目でした
コード:
OnPaint
{
    try
    {
        if(e==null)
            return;
        if(e.Graphics==null)
            return;
        Graphics g = e.Graphics;
        g.DrawRectangle(--ry--)
//        base.OnPaint(e);
     }
     catch
     {}
}


コメントアウトしなくてももちろん駄目でしたorz
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2005-10-26 10:24
引用:

など試してみたのですが、問題は改善せず、例外を拾ってくれず、コードの実行はApplication.Run(---)の部分で停止しますorz



Application.ThreadException イベントとして捕捉出来ませんか?>例外
笊頭刹那
ベテラン
会議室デビュー日: 2005/10/17
投稿数: 55
お住まい・勤務地: オーストラリア
投稿日時: 2005-10-26 14:54
>例外処理時に独自メッセージを表示するようにしている
でそれを利用しています、イベントとして補足し、スタックトレースなどのエラー情報を変数に入れ、クリップボードに貼り付け、MessageBox.Showを表示しているんですが、止まります。

このエラー内容からしてよく起こりそうなのですが、探しても原因が分かりませんね…
笊頭刹那
ベテラン
会議室デビュー日: 2005/10/17
投稿数: 55
お住まい・勤務地: オーストラリア
投稿日時: 2005-10-26 23:34
かなり遠回りしましたが一応解決しました。

同じ問題を持っている方のために方法を記述しておきます。

・OnPaintやPaintイベントを使わずにWndProcでWM_PAINTを拾いthis.CreateGraphics()でGraphicsオブジェクトを作成する
・SystemEvents.DisplaySettingChangedイベントを追加してそこでthis.Invalidate();を呼び出す(呼び出さないとうまく描画されない)

コード:
//------------------------------------------------------------------------
//	WndProc
//
//------------------------------------------------------------------------
protected override void WndProc(ref Message m)
{
	base.WndProc (ref m);
	switch(m.Msg)
	{
		case Win32Api.WM_PAINT:
			this.CreateGraphics().DrawImage(shadow,0,0);
			break;
	}
}

private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
	this.Invalidate();
}



まだ問題多いですが、強制終了しなくなっただけマシになりましたorz

お騒がせいたしました。
1

スキルアップ/キャリアアップ(JOB@IT)