トップ回答者
c# pictureBoxの質問です。

質問
-
c# の pictureBoxの質問です!
pictureBoxの中にイメージを呼び出して表示まではできています。そして、拡大の機能を追加してイメージの上に線を引けるところまで出来ています。
しかし、線を引いた後、拡大をすると線を引いた所が拡大の倍率に合わせて表示できず最初、線を引いた所にそのまま残っています。要するにイメージに線を引いたのに、pictureBoxの中に線を引いたわけです。
言葉ではよく分からないと思い、コードを載せておきますので見ていただければと思います。 あと、コードも書き直していただければ幸いです。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace WindowsFormsApplication12 { public partial class Form1 : Form { //引いた線の最後のポイント private Point LastPoint; //引いた線をリストに入れる private List<Point> pointList; private List<List<Point>> curveList; //表示する画像 private Bitmap img; //倍率 private double ratio = 1F; //画像を表示させる位置 private Point imgPoint; //画像を表示させる範囲 private Rectangle imgRect; //選択された位置 private Point clickPoint; public Form1() { InitializeComponent(); pointList = new List<Point>(); curveList = new List<List<Point>>(); //ホイールイベントの追加 this.pictureBox1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseWheel); //表示する画像を呼び出す img = new Bitmap(WindowsFormsApplication12.Properties.Resources.hekiga); //初期化 imgPoint = new Point(pictureBox1.Width / 2, pictureBox1.Height / 2); imgRect = new Rectangle(0, 0, img.Width, img.Height); ratio = 1.0; clickPoint = imgPoint; //写真を表示する pictureBox1.Invalidate(); } private void Form1_Load(object sender, EventArgs e) { } private void pictureBox1_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Middle) { Image image = new Bitmap(pictureBox2.Width, pictureBox2.Height); Graphics g = Graphics.FromImage(image); g.Clear(Color.White); foreach (List<Point> curve in curveList) { try { g.DrawLines(Pens.Black, curve.ToArray()); } catch { } } image.Save("画像.png", System.Drawing.Imaging.ImageFormat.Png); } } private void pictureBox1_MouseWheel(object sender, MouseEventArgs e) { int lines = e.Delta * SystemInformation.MouseWheelScrollLines / 120; PictureBox pb = (PictureBox)sender; //倍率を変更する if (lines > 0) { ratio *= 2F; if (ratio > 100.0) ratio = 100.0; } else if (lines < 0) { ratio *= 0.5F; if (ratio < 0.01) ratio = 0.01; } //画像の表示範囲を計算する imgRect.Width = (int)Math.Round(img.Width * ratio); imgRect.Height = (int)Math.Round(img.Height * ratio); imgRect.X = (int)Math.Round(pb.Width / 2 - imgPoint.X * ratio); imgRect.Y = (int)Math.Round(pb.Height / 2 - imgPoint.Y * ratio); //スクロールバ hScrollBar1.Minimum = 0; hScrollBar1.Maximum = imgRect.Width - pb.Width; if (hScrollBar1.Minimum >= hScrollBar1.Maximum) { hScrollBar1.Value = hScrollBar1.Maximum; } else { hScrollBar1.Value = imgRect.X * (-1); } vScrollBar1.Minimum = 0; vScrollBar1.Maximum = imgRect.Height - pb.Height; if (vScrollBar1.Minimum >= vScrollBar1.Maximum) { vScrollBar1.Value = vScrollBar1.Maximum; } else { vScrollBar1.Value = imgRect.Y * (-1); } //写真を変換する pictureBox1.Invalidate(); } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { PictureBox pb = (PictureBox)sender; //マウスが押された位置を写真上の位置に変換 clickPoint = new Point( (int)Math.Round((e.X - imgRect.X) / ratio), (int)Math.Round((e.Y - imgRect.Y) / ratio)); Invalidate(); } private void vScrollBar1_Scroll(object sender, ScrollEventArgs e) { imgRect.Y = vScrollBar1.Value * (-1); //写真を表示する pictureBox1.Invalidate(); } private void hScrollBar1_Scroll(object sender, ScrollEventArgs e) { imgRect.X = hScrollBar1.Value * (-1); //写真を表示する pictureBox1.Invalidate(); } private void pictureBox1_Paint(object sender, PaintEventArgs e) { if (img != null) { //補間方法として高品質双三次補間を指定する e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //画像を指定された範囲に描画する e.Graphics.DrawImage(img, imgRect); pictureBox1.Focus(); // 情報を表示 UpDwon.Text = ratio.ToString(); String Msg = String.Format("{0} , {1}", clickPoint.X, clickPoint.Y); Position.Text = Msg; } foreach (List<Point> curve in curveList) { try { e.Graphics.DrawLines(Pens.Magenta, curve.ToArray()); } catch { } } try { e.Graphics.DrawLines(Pens.Magenta, pointList.ToArray()); } catch { } } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { LastPoint = new Point(e.Location.X , e.Location.Y ); pointList.Add(LastPoint); } else { LastPoint = e.Location; } pictureBox1.Invalidate(); pictureBox2.Invalidate(); } private void pictureBox2_Paint(object sender, PaintEventArgs e) { foreach (List<Point> curve in curveList) { try { e.Graphics.DrawLines(Pens.Black, curve.ToArray()); } catch { } } try { e.Graphics.DrawLines(Pens.Black, pointList.ToArray()); } catch { } } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { List<Point> curve = new List<Point>(); curve.AddRange(pointList); curveList.Add(curve); pointList.Clear(); } } } }
- 編集済み mataeo1877 2012年8月1日 1:01
回答
-
pointList.AddにPictureBox座標じゃなく、画像の座標を入れないといけないよねぇ
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace WindowsFormsApplication1 { public partial class Form1 : Form { //引いた線の最後のポイント private Point LastPoint; //引いた線をリストに入れる private List<Point> pointList; private List<List<Point>> curveList; //表示する画像 private Bitmap img; //倍率 private double ratio = 1F; //画像を表示させる位置 private Point imgPoint; //画像を表示させる範囲 private Rectangle imgRect; //選択された位置 private Point clickPoint; public Form1() { InitializeComponent(); pointList = new List<Point>(); curveList = new List<List<Point>>(); //ホイールイベントの追加 this.pictureBox1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseWheel); //表示する画像を呼び出す //表示する画像を呼び出す img = new Bitmap(WindowsFormsApplication12.Properties.Resources.hekiga); //初期化 imgPoint = new Point(pictureBox1.Width / 2, pictureBox1.Height / 2); imgRect = new Rectangle(0, 0, img.Width, img.Height); ratio = 1.0; clickPoint = imgPoint; pictureBox1.Invalidate(); } private void Form1_Load(object sender, EventArgs e) { } private void pictureBox1_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Middle) { Image image = new Bitmap(pictureBox2.Width, pictureBox2.Height); Graphics g = Graphics.FromImage(image); g.Clear(Color.White); foreach (List<Point> curve in curveList) { try { g.DrawLines(Pens.Black, curve.ToArray()); } catch { } } image.Save("画像.png", System.Drawing.Imaging.ImageFormat.Png); } } private void pictureBox1_MouseWheel(object sender, MouseEventArgs e) { int lines = e.Delta * SystemInformation.MouseWheelScrollLines / 120; PictureBox pb = (PictureBox)sender; //倍率を変更する if (lines > 0) { ratio *= 2F; if (ratio > 100.0) ratio = 100.0; } else if (lines < 0) { ratio *= 0.5F; if (ratio < 0.01) ratio = 0.01; } //画像の表示範囲を計算する imgRect.Width = (int)Math.Round(img.Width * ratio); imgRect.Height = (int)Math.Round(img.Height * ratio); imgRect.X = (int)Math.Round(pb.Width / 2 - imgPoint.X * ratio); imgRect.Y = (int)Math.Round(pb.Height / 2 - imgPoint.Y * ratio); //スクロールバ hScrollBar1.Minimum = 0; hScrollBar1.Maximum = imgRect.Width - pb.Width; if (hScrollBar1.Minimum >= hScrollBar1.Maximum) { hScrollBar1.Value = hScrollBar1.Maximum; } else { // hScrollBar1.Value = imgRect.X * (-1); } vScrollBar1.Minimum = 0; vScrollBar1.Maximum = imgRect.Height - pb.Height; if (vScrollBar1.Minimum >= vScrollBar1.Maximum) { vScrollBar1.Value = vScrollBar1.Maximum; } else { //vScrollBar1.Value = imgRect.Y * (-1); } //写真を変換する pictureBox1.Invalidate(); } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { PictureBox pb = (PictureBox)sender; //マウスが押された位置を写真上の位置に変換 clickPoint = new Point( (int)Math.Round((e.X - imgRect.X) / ratio), (int)Math.Round((e.Y - imgRect.Y) / ratio)); Invalidate(); } private void vScrollBar1_Scroll(object sender, ScrollEventArgs e) { imgRect.Y = vScrollBar1.Value * (-1); //写真を表示する pictureBox1.Invalidate(); } private void hScrollBar1_Scroll(object sender, ScrollEventArgs e) { imgRect.X = hScrollBar1.Value * (-1); //写真を表示する pictureBox1.Invalidate(); } private void pictureBox1_Paint(object sender, PaintEventArgs e) { if (img != null) { //補間方法として高品質双三次補間を指定する e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //画像を指定された範囲に描画する e.Graphics.DrawImage(img, imgRect); pictureBox1.Focus(); // 情報を表示 UpDown1.Text = ratio.ToString(); String Msg = String.Format("{0} , {1}", clickPoint.X, clickPoint.Y); Position.Text = Msg; } foreach (List<Point> curve in curveList) { try { e.Graphics.DrawLines(Pens.Magenta, curve.ToArray()); } catch { } } try { e.Graphics.DrawLines(Pens.Magenta, pointList.ToArray()); } catch { } } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { LastPoint = new Point(e.Location.X, e.Location.Y); LastPoint = new Point( (int)Math.Round((e.X - imgRect.X) / ratio), (int)Math.Round((e.Y - imgRect.Y) / ratio)); pointList.Add(LastPoint); Draw(); } else { LastPoint = e.Location; } pictureBox1.Invalidate(); pictureBox2.Invalidate(); } private void pictureBox2_Paint(object sender, PaintEventArgs e) { foreach (List<Point> curve in curveList) { try { e.Graphics.DrawLines(Pens.Black, curve.ToArray()); } catch { } } try { e.Graphics.DrawLines(Pens.Black, pointList.ToArray()); } catch { } } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { List<Point> curve = new List<Point>(); curve.AddRange(pointList); curveList.Add(curve); pointList.Clear(); Draw(); pictureBox1.Invalidate(); } } private void Draw() { if (pointList.Count >= 2) { using (Graphics g = Graphics.FromImage(img)) { g.DrawLines(Pens.Black, pointList.ToArray()); } } } } }
あと、コードも書き直していただければ幸いです。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク 山本春海 2012年8月15日 6:08
-
「private void pictureBox1_MouseMove(object sender, MouseEventArgs e)」この e.Location って、「絵」の座標でしたっけ?絵の大きさが 200×200、PictureBox の大きさが 100×100 として、絵の座標(10, 10)を左上として表示している場合に PictureBox 上の座標(10, 10)をクリックすると、絵としては(20, 20)の座標になると思います。e.Location は(20, 20)になるんでしたっけ?
言葉ではよく分からないと思い、コードを載せておきますので
コードに書いたことと期待する事が違うから、質問をしているのですよね?期待する事を十分に説明せずに、どうして他人があなたの考えを知って、コードに書かれていることとの違いを指摘できると思うのですか?
Jitta@わんくま同盟
- 回答としてマーク 山本春海 2012年8月15日 6:08
-
要するにイメージに線を引いたのに、pictureBoxの中に線を引いたわけです。
ソースコードを読む限り、イメージ(Bitmap img)に線を引かずに、pictureBox(pictureBoxのイベントで渡されるe.Graphics)に線を引いています。
実際、ファイル保存するイメージには線を引けていますよね? 同じことをすればイメージに線を引けます。プログラムはソースコードに書かれた通りに動作します。期待と違う動作をしたのなら、期待と違うコードを書いていないかを確認しましょう。
すべての返信
-
pointList.AddにPictureBox座標じゃなく、画像の座標を入れないといけないよねぇ
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace WindowsFormsApplication1 { public partial class Form1 : Form { //引いた線の最後のポイント private Point LastPoint; //引いた線をリストに入れる private List<Point> pointList; private List<List<Point>> curveList; //表示する画像 private Bitmap img; //倍率 private double ratio = 1F; //画像を表示させる位置 private Point imgPoint; //画像を表示させる範囲 private Rectangle imgRect; //選択された位置 private Point clickPoint; public Form1() { InitializeComponent(); pointList = new List<Point>(); curveList = new List<List<Point>>(); //ホイールイベントの追加 this.pictureBox1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseWheel); //表示する画像を呼び出す //表示する画像を呼び出す img = new Bitmap(WindowsFormsApplication12.Properties.Resources.hekiga); //初期化 imgPoint = new Point(pictureBox1.Width / 2, pictureBox1.Height / 2); imgRect = new Rectangle(0, 0, img.Width, img.Height); ratio = 1.0; clickPoint = imgPoint; pictureBox1.Invalidate(); } private void Form1_Load(object sender, EventArgs e) { } private void pictureBox1_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Middle) { Image image = new Bitmap(pictureBox2.Width, pictureBox2.Height); Graphics g = Graphics.FromImage(image); g.Clear(Color.White); foreach (List<Point> curve in curveList) { try { g.DrawLines(Pens.Black, curve.ToArray()); } catch { } } image.Save("画像.png", System.Drawing.Imaging.ImageFormat.Png); } } private void pictureBox1_MouseWheel(object sender, MouseEventArgs e) { int lines = e.Delta * SystemInformation.MouseWheelScrollLines / 120; PictureBox pb = (PictureBox)sender; //倍率を変更する if (lines > 0) { ratio *= 2F; if (ratio > 100.0) ratio = 100.0; } else if (lines < 0) { ratio *= 0.5F; if (ratio < 0.01) ratio = 0.01; } //画像の表示範囲を計算する imgRect.Width = (int)Math.Round(img.Width * ratio); imgRect.Height = (int)Math.Round(img.Height * ratio); imgRect.X = (int)Math.Round(pb.Width / 2 - imgPoint.X * ratio); imgRect.Y = (int)Math.Round(pb.Height / 2 - imgPoint.Y * ratio); //スクロールバ hScrollBar1.Minimum = 0; hScrollBar1.Maximum = imgRect.Width - pb.Width; if (hScrollBar1.Minimum >= hScrollBar1.Maximum) { hScrollBar1.Value = hScrollBar1.Maximum; } else { // hScrollBar1.Value = imgRect.X * (-1); } vScrollBar1.Minimum = 0; vScrollBar1.Maximum = imgRect.Height - pb.Height; if (vScrollBar1.Minimum >= vScrollBar1.Maximum) { vScrollBar1.Value = vScrollBar1.Maximum; } else { //vScrollBar1.Value = imgRect.Y * (-1); } //写真を変換する pictureBox1.Invalidate(); } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { PictureBox pb = (PictureBox)sender; //マウスが押された位置を写真上の位置に変換 clickPoint = new Point( (int)Math.Round((e.X - imgRect.X) / ratio), (int)Math.Round((e.Y - imgRect.Y) / ratio)); Invalidate(); } private void vScrollBar1_Scroll(object sender, ScrollEventArgs e) { imgRect.Y = vScrollBar1.Value * (-1); //写真を表示する pictureBox1.Invalidate(); } private void hScrollBar1_Scroll(object sender, ScrollEventArgs e) { imgRect.X = hScrollBar1.Value * (-1); //写真を表示する pictureBox1.Invalidate(); } private void pictureBox1_Paint(object sender, PaintEventArgs e) { if (img != null) { //補間方法として高品質双三次補間を指定する e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //画像を指定された範囲に描画する e.Graphics.DrawImage(img, imgRect); pictureBox1.Focus(); // 情報を表示 UpDown1.Text = ratio.ToString(); String Msg = String.Format("{0} , {1}", clickPoint.X, clickPoint.Y); Position.Text = Msg; } foreach (List<Point> curve in curveList) { try { e.Graphics.DrawLines(Pens.Magenta, curve.ToArray()); } catch { } } try { e.Graphics.DrawLines(Pens.Magenta, pointList.ToArray()); } catch { } } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { LastPoint = new Point(e.Location.X, e.Location.Y); LastPoint = new Point( (int)Math.Round((e.X - imgRect.X) / ratio), (int)Math.Round((e.Y - imgRect.Y) / ratio)); pointList.Add(LastPoint); Draw(); } else { LastPoint = e.Location; } pictureBox1.Invalidate(); pictureBox2.Invalidate(); } private void pictureBox2_Paint(object sender, PaintEventArgs e) { foreach (List<Point> curve in curveList) { try { e.Graphics.DrawLines(Pens.Black, curve.ToArray()); } catch { } } try { e.Graphics.DrawLines(Pens.Black, pointList.ToArray()); } catch { } } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { List<Point> curve = new List<Point>(); curve.AddRange(pointList); curveList.Add(curve); pointList.Clear(); Draw(); pictureBox1.Invalidate(); } } private void Draw() { if (pointList.Count >= 2) { using (Graphics g = Graphics.FromImage(img)) { g.DrawLines(Pens.Black, pointList.ToArray()); } } } } }
あと、コードも書き直していただければ幸いです。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク 山本春海 2012年8月15日 6:08
-
「private void pictureBox1_MouseMove(object sender, MouseEventArgs e)」この e.Location って、「絵」の座標でしたっけ?絵の大きさが 200×200、PictureBox の大きさが 100×100 として、絵の座標(10, 10)を左上として表示している場合に PictureBox 上の座標(10, 10)をクリックすると、絵としては(20, 20)の座標になると思います。e.Location は(20, 20)になるんでしたっけ?
言葉ではよく分からないと思い、コードを載せておきますので
コードに書いたことと期待する事が違うから、質問をしているのですよね?期待する事を十分に説明せずに、どうして他人があなたの考えを知って、コードに書かれていることとの違いを指摘できると思うのですか?
Jitta@わんくま同盟
- 回答としてマーク 山本春海 2012年8月15日 6:08
-
要するにイメージに線を引いたのに、pictureBoxの中に線を引いたわけです。
ソースコードを読む限り、イメージ(Bitmap img)に線を引かずに、pictureBox(pictureBoxのイベントで渡されるe.Graphics)に線を引いています。
実際、ファイル保存するイメージには線を引けていますよね? 同じことをすればイメージに線を引けます。プログラムはソースコードに書かれた通りに動作します。期待と違う動作をしたのなら、期待と違うコードを書いていないかを確認しましょう。
-
こんにちは、mataeo1877 さん。
MSDN フォーラムのご利用ありがとうございます。オペレーターの山本です。
ご質問の件、動作しましたとのこと。よかったですね。
問題が解決している場合には、参考になった投稿の "回答としてマーク" ボタンをクリックしてこのスレッドを閉じてくださいね。
問題が解決しているようなので、参考になったと思われる投稿に勝手ながら私のほうで回答としてマークさせていただきました。
また、他国の MSDN フォーラムでも同じ内容の投稿をされていらっしゃいますよね。
そちらのスレッドを参照されている方のためにも、解決策を投稿してスレッドも閉じておいてくださいね。
お手数ですが、よろしくお願いいたします。
______________________
日本マイクロソフト株式会社 フォーラム オペレーター 山本 春海- 編集済み 山本春海 2012年8月15日 6:10