- PR -

DrawLineの平行移動

投稿者投稿内容
カウンター
大ベテラン
会議室デビュー日: 2004/02/19
投稿数: 123
投稿日時: 2004-11-09 17:12
GraphicsオブジェクトのDrawLineで描画したラインを平行移動したいのですが、上手くいきません。
ライン自体は問題なく描画できるのですが、平行移動させてもラインが移動しないんです。
また、ラインを描画したフォームの上に別のアプリ(ブラウザ等なんでも)を開いてから、
再度フォームを開くとラインが消えています。
平行移動の方法をご存知の方、ご指導お願いします。

コード:

'垂直線の描画
grp = Me.chtMAIN.CreateGraphics
grpState = grp.Save()
grp.DrawLine(Pens.Black, 1439, 0, 1439, 840)

'垂直線の平行移動
    grp.Restore(grpState)
grp.ResetTransform()
grp.TranslateTransform(VerX, 0)



[ メッセージ編集済み 編集者: カウンター 編集日時 2004-11-09 17:30 ]
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2004-11-09 20:47
Graphics.TranslateTransformは変換行列を設定するだけです。平行移動するわけではありません。Graphics.Transformプロパティを変化させるだけです。

コード:

GraphicsState state = g.Save();

//変換行列のセット
g.ResetTransform();
g.TranslateTransform(dx, dy);

//描画
g.DrawLine(Pens.Black, 1439, 0, 1439, 840);

g.Restore(state);



引用:

また、ラインを描画したフォームの上に別のアプリ(ブラウザ等なんでも)を開いてから、
再度フォームを開くとラインが消えています。



「消えた」というよりは、「描いていない」だけです。再度表示するときにはもう一回書く必要がありますよね。それがPaintイベントですので、そこにもう一度描画するコードを書いてください。
カウンター
大ベテラン
会議室デビュー日: 2004/02/19
投稿数: 123
投稿日時: 2004-11-10 09:21
yaさん ありがとうございます。

では、一度書いた垂直線を消して別の位置に再描画することで平行移動したように見せることは出来るのでしょうか?
試しに、描画前にセーブして、描画した後でリストアして再描画してみたのですが、線が増えるだけでした。
コード:
	grpState = grp.Save()

	grp.DrawLine(Pens.Black, X, 0, X, 840)

	grp.Restore(grpState)

	grp.DrawLine(Pens.Black, X+100, 0, X+100, 840)



リストアの仕方が間違っているのでしょうか?
ちなみに、Clearメソッドも試してみたんですが線以外も消えてしまうのでダメでした。
よろしくお願いします。
cats
大ベテラン
会議室デビュー日: 2002/11/29
投稿数: 221
お住まい・勤務地: 東京
投稿日時: 2004-11-10 14:07
SaveやRestoreは、描画オブジェクト(クリッピング状態やペンやブラシ)に対してであって、画面の描画内容は無関係だと思います。
カウンター
大ベテラン
会議室デビュー日: 2004/02/19
投稿数: 123
投稿日時: 2004-11-10 14:23
catsさん、ありがとうございます。

引用:

SaveやRestoreは、描画オブジェクト(クリッピング状態やペンやブラシ)に対してであって、画面の描画内容は無関係だと思います。



描画オブジェクトって言うのは、ここではgrpの事ですよね?
それとも、catsさんの言う「画面」にあたるのがgrp何でしょうか?
よろしくお願いします。

ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2004-11-10 14:35
引用:

では、一度書いた垂直線を消して別の位置に再描画することで平行移動したように見せることは出来るのでしょうか?
試しに、描画前にセーブして、描画した後でリストアして再描画してみたのですが、線が増えるだけでした。



Graphicsオブジェクトについて根本的に理解が間違っている気がしますね。
紙に絵を描く場合で例えてみるとそれぞれ対応するのは
筆(等) Graphicsオブジェクト
紙 画面
のような対応になります。
筆(Graphics)を洗った(Graphics.Restore)からといって、紙(画面)に書いた線が消えますか?

で、一つずつ考えていきましょう。
この場合、戻さなくてはならないのは「画面」です。ですが、「画面」は各々のコントロールが内部状態を元に描画したその結果です。つまり、復元することは無理です。
ですので、そういう発想ではなくて「毎回新規に描画する」という発想をします。

具体的には

コード:

public class TestForm : Form
{
	...
	private int line_dx = 100;
	private void TestForm_Paint(object sender, PaintEventArgs e)
	{
		GraphicsState state = g.Save();

		//変換行列のセット
		....

		//描画
		...

		g.Restore(state);
	}

	private void MoveLineToRight(int x)
	{
		line_dx += x;
		this.Invalidate(); //無効化して
		this.Update(); //再描画させる
	}

	private void button1_Click(object sender, EventArgs e)
	{
		MoveLineToRight(100);
	}
	...
}



こんな感じになります(簡略化のため全体を無効化してますが、無効化領域を指定したほうがよいです)。
cats
大ベテラン
会議室デビュー日: 2002/11/29
投稿数: 221
お住まい・勤務地: 東京
投稿日時: 2004-11-10 14:53
描画オブジェクトは、現在の座標系やクリッピング状態のことだと思います。
(ペンとブラシは、デフォルトがないので違っていたかも)

例えば、画面を4分割して、それぞれに写真をハート型に表示したいとき、こんな感じになります。
コード:
Graphics g = e.Graphics;
float	w = ClientSize.Width/2F, h = ClientSize.Height/2F;
GraphicsPath gp = new GraphicsPath();
gp.AddPie(10,60,100,100,-180,180);
gp.AddPie(110,60,100,100,-180,180);
gp.AddLine(210,110,110,210);
gp.AddLine(110,210,10,110);
for (int i=0;i<2;++i)
{
	for (int j=0;j<2;++j)
	{
		GraphicsState gs = g.Save();
		g.TranslateTransform(i*w,j*h);
		g.Clip = new Region(gp);
		g.DrawImage(bmp,0,0,w,h);
		g.Restore(gs);
	}
}

MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2004-11-10 15:42
カウンターさんの最初にイメージしていた
描画オブジェクトは 「ディスプレイリスト」のように
もう一段上位のCGでの概念です。
SVGでの<svg:line ... のような,
お絵かきソフトの線分のような

[ メッセージ編集済み 編集者: MMX 編集日時 2004-11-10 15:44 ]

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