トップ回答者
Form1.Invalidate()を実行させたい。

質問
-
Form2内のコードから、Form1のInvalidateを直接呼び出したいと思っているのですが、
できません。
どうすればできますか?よろしくお願いいたします(_ _)
Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;namespace testFm1InvalidateAppli
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public int counter = 0;
Form2 form2;
private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
Image theImage = new Bitmap(myAssembly.GetManifestResourceStream("testFm1InvalidateAppli.image1.png"));
e.Graphics.DrawImage(theImage, counter, counter);
counter++;
}private void Form1_Load(object sender, EventArgs e)
{
form2= new Form2();
form2.Show();
}
}
}Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;namespace testFm1InvalidateAppli
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}private void Form2_Load(object sender, EventArgs e)
{}
private void button1_Click(object sender, EventArgs e)
{
//ここにForm1.Invalidate()を記述したいのですが・・・
}
}
}
回答
-
おはようございます!(^^)!ふ~です。
Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;namespace testFm1InvalidateAppli
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Paint+=new PaintEventHandler(Form1_Paint);
}public int counter = 0;
Form2 form2;private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();//このアセンブリの全てのリソース名を取得する
//string[] resources = myAssembly.GetManifestResourceNames();//リソース名を一つずつ表示する
//foreach (string resource in resources)
// Debug.WriteLine(resource);Image theImage = new Bitmap(myAssembly.GetManifestResourceStream
("testFm1InvalidateAppli.Resources.image1.PNG"));
e.Graphics.DrawImage(theImage, counter, counter);
counter++;
}private void Form1_Load(object sender, EventArgs e)
{
form2 = new Form2();
form2.Show();
}
}
}Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;namespace testFm1InvalidateAppli
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}private void Form2_Load(object sender, EventArgs e)
{}
private void button1_Click(object sender, EventArgs e)
{
// Form1を取得する。
Form1 frm = (Form1)Application.OpenForms[0];// Form1の描画領域を無効にする
frm.Invalidate();
}
}
}
すべての返信
-
考えられるパターンは以下です。
1.Form2へForm1のインスタンスを渡してしまう。幸い実行したいのがInvalidateメソッドなので、Form2でそのインスタンスをForm型へキャストしてしまえば良い。従って、Form2はForm1へ依存しない疎結合が保たれる。
2.Form2へForm1のインスタンスを渡す場合、インターフェース経由にして疎結合を保つ。
3.Form1でInvalidateを呼び出すメソッドを定義する。Form2ではイベントを定義し、先に定義したメソッドをイベントハンドラとする。ただ、形的にはこれで動作するが、Form2のイベントとして意味づけができるかどうかという問題もある。つまり、Form2で何かが起こった時に発動するのがイベントであるが、何かが起こった時ではなく、いろいろなケースの場合に発動しなければならない場合、簡単に言えばそのイベントにどういう名前を付けたらよいのかわからなくなることもあるんじゃないかと思います。
簡単にやるなら1ですが、実際には2か3を選択することになるんじゃないかと思います。
#はしょって書いてしまいましたが、わかりにくいところがあれば言ってください。
-
おはようございます!(^^)!ふ~です。
Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;namespace testFm1InvalidateAppli
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Paint+=new PaintEventHandler(Form1_Paint);
}public int counter = 0;
Form2 form2;private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();//このアセンブリの全てのリソース名を取得する
//string[] resources = myAssembly.GetManifestResourceNames();//リソース名を一つずつ表示する
//foreach (string resource in resources)
// Debug.WriteLine(resource);Image theImage = new Bitmap(myAssembly.GetManifestResourceStream
("testFm1InvalidateAppli.Resources.image1.PNG"));
e.Graphics.DrawImage(theImage, counter, counter);
counter++;
}private void Form1_Load(object sender, EventArgs e)
{
form2 = new Form2();
form2.Show();
}
}
}Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;namespace testFm1InvalidateAppli
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}private void Form2_Load(object sender, EventArgs e)
{}
private void button1_Click(object sender, EventArgs e)
{
// Form1を取得する。
Form1 frm = (Form1)Application.OpenForms[0];// Form1の描画領域を無効にする
frm.Invalidate();
}
}
} -
acslearner さんからの引用 「Paint+=new PaintEventHandler(Form1_Paint);」
にはどういう意味があるのでしょうか?
Form1のPaintイベントにForm1_Paintを割り当てる。
デザイナのプロパティウィンドウでPaintイベントをダブルクリックしたときとほぼ同じです。
acslearner さんからの引用 上記なしで
「 Form1 frm = (Form1)Application.OpenForms[0];
// Form1の描画領域を無効にする
frm.Invalidate();」
を加えただけで、一応目的のものができたのですが、注意点などあれば教えてください。
OpenForms[0]がお望みのものであるかは、アプリケーションの構成次第です。
例えば、類似の事例で、2番目のFormに対してInvalidateしたくなった時はどうするかとか考えないといけませんね。
また、Form2をForm1やForm3から利用し、呼び出し元のForm(Form1かForm3)にInvalidateを実行したいときは、このような順番決め打ちや呼び出し元限定のコードは使いにくくなります。
そのため、Form2側では親のフォームが何かを意識しないようにするコーディングが望ましいのかもしれません。
例えば、Form2側でイベントを呼び出すような実装にしておき、呼び出し側のFormからはそのイベントに登録しておくとか。
-
こんにちは!(^^)!ふ~です。
> 「Paint+=new PaintEventHandler(Form1_Paint);」はどういう意味があるのか?
ソースを貼り付けて動作し易いように、プロパティで設定した内容を明らかにする為、コードで表現しております。
VS2005, VS2008では、Form1のプロパティのイベントの表示のPaintで、イベントハンドラがご存じのように簡単
に作成できます。この作成されたソースコードは、Form1.Designer.csの『Windows フォーム デザイナで生成されたコード』
となります。
ここを展開(+をクリック)すると、 this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
のソースコードが有る筈です。
この自動生成作業を手動で、Paint+=new PaintEventHandler(Form1_Paint);と作成しただけです。手作業ですので
省略できる部分は省略しておりますが、全く同じものです。