DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Formでの描画

  • 題名: Formでの描画
  • 著者: てんてん
  • 日時: 2004/03/17 19:06:15
  • ID: 3122
  • この記事の返信元:
    • (なし)
  • この記事への返信:
  • ツリーを表示
環境/言語:[環境(XP) 使用言語(C#)]
分類:[.NET]

お世話になります。 てんてんと言います。
みなさんに教えて欲しい事がありますので宜しくお願いします。

Form1とForm2があり、Form1からForm2を呼び出してます。
呼び出し後Form1に配置したbutton1でForm2に四角を描画、
またForm1に配置したbutton2でForm2に丸を描画させるには
どうすればよいのでしょうか?
円の描画は System.Drawing.Graphics.DrawEllipse
四角の描画は System.Drawing.Graphics.DrawRectagnle

Form2にPublicメソッド等を作成し、それをButtonのCLickイベントで
呼び出し、描画すればよいでしょう。

実際には再描画に対応するために、メソッドで渡ってきた情報は
Form2の内部変数として保持し、Paintイベントで描画することになります。
  • 題名: Re[2]: Formでの描画
  • 著者: てんてん
  • 日時: 2004/03/17 19:47:40
  • ID: 3125
  • この記事の返信元:
  • この記事への返信:
  • ツリーを表示
Sugi@ぱぱんぶぃびぃさん ありがとうございます。

> 円の描画は System.Drawing.Graphics.DrawEllipse
> 四角の描画は System.Drawing.Graphics.DrawRectagnle
>
> Form2にPublicメソッド等を作成し、それをButtonのCLickイベントで
> 呼び出し、描画すればよいでしょう。
>
> 実際には再描画に対応するために、メソッドで渡ってきた情報は
> Form2の内部変数として保持し、Paintイベントで描画することになります。

Form2にPublicメソッドを作成し、それをButtonのCLickイベントで呼び出すまでは
わかりますが、その後の描画はどうすればよいのでしょうか?
> わかりますが、その後の描画はどうすればよいのでしょうか?

ですから、
>> 円の描画は System.Drawing.Graphics.DrawEllipse
>> 四角の描画は System.Drawing.Graphics.DrawRectagnle
です。

これらのメソッドの引数を調べてもらえばわかりますが、
描画に必要な引数があると思います。
その引数をForm2内のローカル変数として保存しておきます。
あとはPaintイベントが発生したらその情報を元に描画すれば
良いだけです。
Publicメソッドが実行された初回のみはFormのRefreshメソッドか
Invalidateメソッドを実行することによりPaintイベントを発生
させるか、描画処理を内部で起動するようにするとか?

> これらのメソッドの引数を調べてもらえばわかりますが、
> 描画に必要な引数があると思います。
> その引数をForm2内のローカル変数として保存しておきます。
> あとはPaintイベントが発生したらその情報を元に描画すれば
> 良いだけです。
> Publicメソッドが実行された初回のみはFormのRefreshメソッドか
> Invalidateメソッドを実行することによりPaintイベントを発生
> させるか、描画処理を内部で起動するようにするとか?
なるほど、わかりました。
ありがとうございました。

> >> 円の描画は System.Drawing.Graphics.DrawEllipse
> >> 四角の描画は System.Drawing.Graphics.DrawRectagnle
これをタイプするとSystem.Drawing.GraphicsにDrawRectagnleの定義がありません
と言うエラーがでます。
これは何か足らないのでしょうか?
■No3128に返信(てんてんさんの記事)
>
>>これらのメソッドの引数を調べてもらえばわかりますが、
>>描画に必要な引数があると思います。
>>その引数をForm2内のローカル変数として保存しておきます。
>>あとはPaintイベントが発生したらその情報を元に描画すれば
>>良いだけです。
>>Publicメソッドが実行された初回のみはFormのRefreshメソッドか
>>Invalidateメソッドを実行することによりPaintイベントを発生
>>させるか、描画処理を内部で起動するようにするとか?
> なるほど、わかりました。
> ありがとうございました。
>
>>>> 円の描画は System.Drawing.Graphics.DrawEllipse
>>>> 四角の描画は System.Drawing.Graphics.DrawRectagnle
> これをタイプするとSystem.Drawing.GraphicsにDrawRectagnleの定義がありません
> と言うエラーがでます。
> これは何か足らないのでしょうか?
>
>
>

タイプするとって言う意味がわからない・・・
> タイプするとって言う意味がわからない・・・
Publicメソッドを作成して四角の描画のSystem.Drawing.Graphics.DrawRectagnle
を書くとと言う意味です。
2004/03/17(Wed) 22:11:02 編集(投稿者)

スペルミス?
誤:DrawRectagnle
正:DrawRectangle
■No3133に返信(MoMoMoさんの記事)
> 2004/03/17(Wed) 22:11:02 編集(投稿者)
>
> スペルミス?
> 誤:DrawRectagnle
> 正:DrawRectangle
>
インテリセンスを使えば間違えないです。(普通は・・・)

> インテリセンスを使えば間違えないです。(普通は・・・)

そうですよね。。。

もしかして

System.Drawing.Graphics.DrawRectagnle

をそのままPublicメソッドにコピーして、
関数のように使おうとしている??
■No3135に返信(MoMoMoさんの記事)
>
>>インテリセンスを使えば間違えないです。(普通は・・・)
>
> そうですよね。。。
>
> もしかして
>
> System.Drawing.Graphics.DrawRectagnle
>
> をそのままPublicメソッドにコピーして、
> 関数のように使おうとしている??
>

おぉ、強引ですなぁ。
私の書き方で誤解されているのかもしれませんが、
Formのメソッドは独自のものを作成してくださいね。
そのメソッドの引数として、描画メソッドに必要な情報を渡すという意味です。
こんにちは みなこです。
Sugi@ぱぱんぶぃびぃさん、私もこれから同じような事をしようとやってますが
上手くいきません。
何かサンプルみたいな物がありませんか?

りょうさん、先日はお世話になりました。
またわかりやすく教えて下さい。
■No3152に返信(みなこさんの記事)
> こんにちは みなこです。
> Sugi@ぱぱんぶぃびぃさん、私もこれから同じような事をしようとやってますが
> 上手くいきません。
> 何かサンプルみたいな物がありませんか?
>
> りょうさん、先日はお世話になりました。
> またわかりやすく教えて下さい。

Form1からForm2を呼び出しているのですか?それとも逆ですか?
それを教えてください。
りょうさん、またお世話になります

> Form1からForm2を呼び出しているのですか?それとも逆ですか?
> それを教えてください。
Form1からForm2を呼び出しています。
また私の場合、Formは多数あります。
上手くいかないとか、漠然と言っておられるようですが、
どのあたりがどう上手くいかないかと説明していただかないことには
答えようがないと思うのですが...。

なんか白熱してきたんで、簡単なサンプル(1部抜粋ですが)出しときます。(^_^;
プロジェクトにForm1とForm2を追加し、
Form1にbuttonを2つ貼り付けて、button1とbutton2としてください。

(C#は守備範囲外なのでソースが汚くてわかりにくいかもしれません。)

また、エラー処理などは一切行っていません。

//============= Form1のコードの抜粋 ===================

private Form2 SubForm = new Form2();

private void button1_Click(object sender, System.EventArgs e)
{
  // Form2を表示します

  SubForm.Show();

}

private void button2_Click(object sender, System.EventArgs e)
{
  // Form2で定義されている、SetRectangleメソッドを呼び出します
  // 引数は四角形の色と四角形のサイズと位置を表すRectangle

  SubForm.SetRectangle(Color.Red, new Rectangle(10,10,50,50));
}


//============= Form2のコードの抜粋 ===================

private Rectangle rct;
private Color clr;

public void SetRectangle(Color newColor, Rectangle newRectangle)
{
  rct = newRectangle;
  clr = newColor;
  this.Invalidate();
}

private void Form2_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
  // rctとclrに値がセットされている場合は描画します
  if(!rct.Equals(Rectangle.Empty) && !clr.Equals(Color.Empty))
  {
    Pen pen = new Pen(clr);
    e.Graphics.DrawRectangle(pen, rct);
    pen.Dispose();
  }
}

アプリケーションの仕様やアプローチの仕方はいろいろとあると思いますが、
簡単なものならこんなとこでしょうか?
サンプルありがとうございました。
正常に動作しました。

追加で質問なのですが、Form1側のbutton2_ClickでRectangleを2回書くと
1回しか描画しません
Form2側でメソッドを2個作成すれば可能ですが、多数あった場合はどうすればいいのでしょうか?

例)
private void button2_Click(object sender, System.EventArgs e)
{
  // Form2で定義されている、SetRectangleメソッドを呼び出します
  // 引数は四角形の色と四角形のサイズと位置を表すRectangle

  SubForm.SetRectangle(Color.Red, new Rectangle(10,10,50,50));
  SubForm.SetRectangle(Color.Blue, new Rectangle(30,30,50,50));
}
■No3170に返信(みなこさんの記事)
> サンプルありがとうございました。
> 正常に動作しました。
>
> 追加で質問なのですが、Form1側のbutton2_ClickでRectangleを2回書くと
> 1回しか描画しません
> Form2側でメソッドを2個作成すれば可能ですが、多数あった場合はどうすればいいのでしょうか?
>
> 例)
> private void button2_Click(object sender, System.EventArgs e)
> {
>   // Form2で定義されている、SetRectangleメソッドを呼び出します
>   // 引数は四角形の色と四角形のサイズと位置を表すRectangle
>
>   SubForm.SetRectangle(Color.Red, new Rectangle(10,10,50,50));
>   SubForm.SetRectangle(Color.Blue, new Rectangle(30,30,50,50));
> }
>
二度目に呼び出されたSetRectangleで上書きされてしまっているのではないですか?

> 二度目に呼び出されたSetRectangleで上書きされてしまっているのではないですか?

Rectangleで指定してる座標が違うのに上書きされるんですか?
これってForm2_Paintが再描画してるってことですか?
■No3173に返信(みなこさんの記事)
>
>>二度目に呼び出されたSetRectangleで上書きされてしまっているのではないですか?
>
> Rectangleで指定してる座標が違うのに上書きされるんですか?
> これってForm2_Paintが再描画してるってことですか?
>
>

この分野あんまり詳しくないもんで・・・

だれか、くわしいひといませんか〜〜〜?
>Rectangleで指定してる座標が違うのに上書きされるんですか?
>これってForm2_Paintが再描画してるってことですか?

サンプルはイメージをつかんでいただくために簡略化してあります。

コードをみていただければわかると思うのですが、
SetRectangleメソッドでは内部の変数に対し値を常に上書きしています。
この値を参照して、Paintイベントで四角形を1つ描いているだけですから、
座標が違うとかいうのは全く関係ありません。

複数の図形を描く場合はデータを配列なりコレクションにするとか
あるいは描画自体を内部でImageオブジェクトに対し行って、
そのImageを描画する等いろいろなアプローチがあります。

それら場合のデータの渡し方(メソッドやプロパティ)については
これからご自分でいろいろと試行錯誤しながら考えていってください。
おはようございます。
ちょっと教えて下さい。

this.Invalidate();の後にthis.UpDate();を付けると解決したのですが
this.Invalidate();とthis.UpDate();でブレイクかけても
Form_Paintに入ってきません。

どこで描画をしてるんでしょうか?
■No3186に返信(みなこさんの記事)
> this.Invalidate();の後にthis.UpDate();を付けると解決したのですが

何を解決されたのでしょうか??
No3170でみなこさんが投稿されたソースコードの例の問題点は、
No3175でSugi@ぱぱんぶぃびぃさんが指摘されている通り、
No3159のSugiさんのサンプルでSetRectangleメソッドで複数の描画情報を
保存できるようにはなっていないためで、サンプルソースの仕様によるものです。
No3170でおっしゃっている問題はUpdateメソッドを呼んでも解決しないはずです。

> this.Invalidate();とthis.UpDate();でブレイクかけても
> Form_Paintに入ってきません。

Paintイベントのチェックをしたいなら、ブレークポイントは使ってはいけません。
ブレークポイントを使ってブレークするとVS.NETが前面に出てきてしまうので、
このためにまたPaintイベントが発生してしまうので、チェックにならないからです。

> どこで描画をしてるんでしょうか?

Paintイベントですね。
Updateメソッドの呼び出しによりPaintイベントが発生しています。

Updateメソッドの呼び出し箇所にデバッグ文を入れます。

Debug.WriteLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " PAINT BEFORE");
// Updateメソッドの呼び出しはここに記述

Debug.WriteLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " PAINT AFTER");

で、Paintイベントには下記の記述を追加します。

Debug.WriteLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " PAINT");

これでPaintイベントが発生しているタイミングを確認できます。

ちなみにUpdateメソッドを呼ばないと再描画されないというのは、
コーディング方法によるもので、Sugiさんのサンプルのようなコーディングであれば、
Invalidateメソッドを呼ぶだけでOKです。

・Invalidateメソッドはコントロール(Formも含む)の無効になった領域を設定します。
実際の再描画はアプリがアイドル状態になったときに行われます。
・Updateメソッドは強制的に即時に再描画します。

SetRectangleメソッドでthis.Invalidate(); より後に
いろいろコードを追加していませんか?
  • 題名: Re[22]: Formでの描画
  • 著者: みなこ
  • 日時: 2004/03/20 23:30:27
  • ID: 3200
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
よねKENさん、ありがとうございます。

> 何を解決されたのでしょうか??
私の書き方がおかしかったようです。すいません。
色々ネットで調べていたらInvalidateの後ろにUpDateで解決すると言うサイトがあって、実際にやってみたら正常に再描画してたので解決したものだと思ってました。

>>どこで描画をしてるんでしょうか?
> Paintイベントですね。
> Updateメソッドの呼び出しによりPaintイベントが発生しています。
やっぱりPaintイベントでしたか!
それがUpdateメソッドを書いたら毎回Paintイベントに入って来てたんですがInvalidateのみの時はPaintイベントには入って来てなかったので、どこで描画してたのかわからなくなってました。

> SetRectangleメソッドでthis.Invalidate(); より後に
> いろいろコードを追加していませんか?
this.Invalidate();の後にはUpdateしかありませんよ。

DOBON.NET | プログラミング道 | プログラミング掲示板