- PR -

C# pictureBoxを使わずにOnPaintで描画した画像にMouseUpなどを使いたい

投稿者投稿内容
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2005-12-04 12:13
引用:

でも、問題があって、OnPaintの中でBeginInvokeしてEndInvokeで乱数発生させたint[] xを使って牌を表示するようにしているのですが、何が問題かわかってないのですが、このウィンドウがほかのウィンドウの後ろになってしまうと、またアクティブにして前にしたとき、int[] xを使って表示した牌が変わってしまうのです。どうしてでしょうか?



OnPaint() で「乱数発生させたint[] xを使って牌を表示するようにしている」からです。

これは、Windows GUI アプリケーションの基本的な仕組みを少し逸脱したスタイルです。

Windows では多数のアプリケーションが共存して動作するため、システムが規定するいくつかの「お約束」に従わなくてはなりません。

OnPaint() は、はじめてウィンドウが表示される時だけではなく、ウィンドウの重なりが変化した時などに「システムから呼び出される」ものです。

なので、OnPaint() では、アプリケーションの「現在の状態に基づいた描画」だけを行うのが基本です。
AKIR
常連さん
会議室デビュー日: 2005/11/08
投稿数: 34
投稿日時: 2005-12-04 13:20
マルチスレッドをやめてランダムシャッフルに変えたら、なおりました。でも、14秒たつと、regionで判定して描画した牌が消えてしまいます。TickCountをやめてform.Created==falseとやったら直りました。
AKIR
常連さん
会議室デビュー日: 2005/11/08
投稿数: 34
投稿日時: 2005-12-04 16:11
formっていうのはForm1 form = new Form1();です。
AKIR
常連さん
会議室デビュー日: 2005/11/08
投稿数: 34
投稿日時: 2005-12-04 19:01
コード:
private void Form1_Load(object sender, System.EventArgs e)
		{
			this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseUp);
		}
	
		Point MouseUpLocation = new Point();
		private void Form1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			MouseUpLocation.X = e.X;
			MouseUpLocation.Y = e.Y;
		}
		protected override void OnPaint(PaintEventArgs pea)
		{
			Form1 form1 = new Form1();
			Image image = Image.FromFile(@"C:\1.jpg");
			Graphics g = pea.Graphics;
			if(image!=null) g.DrawImage(image,0,1);
			Region region1 = new Region(new Rectangle(0,1,20,30));
			while(form1.Created==false)
			{
				if(region1.IsVisible(MouseUpLocation, pea.Graphics))
				{
					if(image!=null) g.DrawImage(image,50,0);
					goto endloop;
				}
				Application.DoEvents();
			}
			endloop:
				if(image!=null) g.DrawImage(image,0,50);
		}


すみませんでした。Form1_LardでMouseEventHandlerのrが抜けてました。
20×30のbmpを用意してくだされば、これでできると思います。
AKIR
常連さん
会議室デビュー日: 2005/11/08
投稿数: 34
投稿日時: 2005-12-04 19:07
あと、Form1_Loadはデザインのフォームをダブルクリックしてコードを自動生成させたほうがいいと思います。
ぶさいくろう
ぬし
会議室デビュー日: 2005/11/22
投稿数: 1232
お住まい・勤務地: 川崎市(は俺も含めてロクな人間が住んでないよw)
投稿日時: 2005-12-04 21:56
引用:

AKIRさんの書き込み (2005-12-04 19:07) より:
あと、Form1_Loadはデザインのフォームをダブルクリックしてコードを自動生成させたほうがいいと思います。


素人さんはそれがいいでしょ。
Kazuki
ぬし
会議室デビュー日: 2004/10/13
投稿数: 298
投稿日時: 2005-12-05 23:28
引用:

AKIRさんの書き込み (2005-12-04 19:07) より:
あと、Form1_Loadはデザインのフォームをダブルクリックしてコードを自動生成させたほうがいいと思います。


これがいいと思うなら,MouseUpとかは何故わざわざコードからしてるんですか?
後は,OnPaintをオーバーライドしなくてもPaintっていう名前のイベントが無かったかな?
(どっちでもいいですが)

後,コードについてですが
コード:
Form1 form1 = new Form1(); // <-こいつの存在理由がわからないです
Image image = Image.FromFile(@"C:\1.jpg"); // OnPaintの度に読み込まなくても
                                            // これならコンストラクタでやったほうが
Graphics g = pea.Graphics;
if(image!=null) g.DrawImage(image,0,1); // FromFileってnull返したっけ?
Region region1 = new Region(new Rectangle(0,1,20,30));
while(form1.Created==false) // 要はwhile(true)と同じこと
{
	if(region1.IsVisible(MouseUpLocation, pea.Graphics))
	{
		if(image!=null) g.DrawImage(image,50,0); // nullチェックいるの?
		goto endloop; // goto使わなくても書けるような処理なのでわざわざgoto使って複雑度上げないほうがいいと思います。
	}
	Application.DoEvents();
}
endloop:
	if(image!=null) g.DrawImage(image,0,50); // nullチェックいるの?


個人的にはOnPaintで描画に関する以外書かないほうがいいと思います。
このロジックなら恐らくOnPaintで無限ループをわざわざ組まなくてもできます。
AKIR
常連さん
会議室デビュー日: 2005/11/08
投稿数: 34
投稿日時: 2005-12-06 08:08
Paintイベントハンドラを使いたいならPictureBoxとかに描画しなくちゃいけないので、pictureBox_Paintとかいうふうになります(ってどっかのサイトからですけど)。
while(true)は知りませんでした。それでできました。何がtrueなんでしょうか?教えて頂けるとうれしいです。これだとForm1 form1 = new Form1はいりませんね。
jpgになってましたね。Sample.bmpだったつもりんですが。image!=nullはチェックしたほうがいいですよ。やらないほうがいいですが、nullのチェック無しでそのC:\1.jpgをほかへ移してデバッグしてみてください。僕はbmpでやりましたが、画像が2倍くらい大きくなって描画されます。OSリインストールしたら直りましたけど。
goto書かないでやる方法を教えてほしいです。
Focus();というのがあるみたいですが、これもPictureBoxとかのコントロールを使わなきゃいけないようで、PictureBox使ったほうがいいのかなぁ?

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