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

ピクチャーボックス

分類:[.NET]

現在VB.NETにてピクチャーボックス(画像関係)の勉強をしていますが
解らないところが多々あるので皆様のお力を少し貸してください。
具体的には
1、ピクチャーボックスに表示した画像をクリップボードに送ること
2、ピクチャーボックスに表示されている画像の拡大&縮小
3、上記2の拡大縮小の時の範囲を画像上で行う
以上3つが今わからなくて困っている主な所です。
どうか良いアドバイスお願いいたします。
■No1683に返信(水野さんの記事)
> 現在VB.NETにてピクチャーボックス(画像関係)の勉強をしていますが
> 解らないところが多々あるので皆様のお力を少し貸してください。
> 具体的には
> 1、ピクチャーボックスに表示した画像をクリップボードに送ること
> 2、ピクチャーボックスに表示されている画像の拡大&縮小
> 3、上記2の拡大縮小の時の範囲を画像上で行う
> 以上3つが今わからなくて困っている主な所です。
> どうか良いアドバイスお願いいたします。
>

3については判りませんが、1および2は

 クリップボードに画像をコピーする
 http://dobon.net/vb/dotnet/graphics/copytoclipboard.html

 画像を拡大、縮小して表示する
 http://dobon.net/vb/dotnet/graphics/scaling.html

ではダメなのでしょうか?

 画像の一部を切り取って表示する
 http://dobon.net/vb/dotnet/graphics/triming.html

を組み合わせれば3もできるかもしれません。
貴重なご意見ありがとうございますm(__)m
一様参照させていただきました。1・2は大体解決しましたが
3は私の説明不足のところもありましたが、やりたいこととい
うのは、基本的に”クリックしたとことを中心”にかくだいされて
いくという感じにしたいので画像上からクリックした場所を取り
それを元にクリックした回数で拡大させていこうかと考えております。
良い意見ありましたらおねがいいたします。
■No1685に返信(水野さんの記事)
> 貴重なご意見ありがとうございますm(__)m
> 一様参照させていただきました。1・2は大体解決しましたが
> 3は私の説明不足のところもありましたが、やりたいこととい
> うのは、基本的に”クリックしたとことを中心”にかくだいされて
> いくという感じにしたいので画像上からクリックした場所を取り
> それを元にクリックした回数で拡大させていこうかと考えております。
> 良い意見ありましたらおねがいいたします。

PictureBox上のクリック地点は、マウス関連イベント(MouseDown等)の"e.X"と"e.Y"で取得できます。
あとはクリック地点から拡大時の左上座標と範囲を計算して、拡大して表示すればできると思いますが、一筋縄ではいかなそうですね。

PictureBoxに表示されているイメージをそのまま利用すれば楽でしょうが、
できないとなると大元の画像から拡大することになりそうなので、
クリック毎の座標等を記憶しておいて、クリック回数(倍率)に応じて左上座標と
範囲を調整してイメージを取得する事になると思います。

実際に作らずに思いついたまま書いたので見当違いでしたらごめんなさい。
重ね重ねありがとうございますm(__)m
大まかな流れは創造つきましたが実際どのようなプログラムで
進めていけば良いのでしょう?VB.NETを始めてまだ数日ですので
イベント&MouseDownというのがどういうものなのか良くわかり
ませんできればお時間空いたときでも良いので詳しくご指導して
いただけませんか?お願いいたしますm(__)m
2003/12/08(Mon) 13:32:47 編集(投稿者)

■No1688に返信(水野さんの記事)
> 重ね重ねありがとうございますm(__)m
> 大まかな流れは創造つきましたが実際どのようなプログラムで
> 進めていけば良いのでしょう?VB.NETを始めてまだ数日ですので
> イベント&MouseDownというのがどういうものなのか良くわかり
> ませんできればお時間空いたときでも良いので詳しくご指導して
> いただけませんか?お願いいたしますm(__)m

返信が遅れてすみません。
一応サンプルができましたので公開します。
(見やすいように全角スペースを入れているので、コピー&ペーストする場合はスペースに置き換えてください)

'----------------------------------------------------------------------
' これは200x200サイズのPictureBoxで作成しています。
' PictureBox内をクリックすると、その座標を中心に2倍、3倍、・・・としていきます。
' PictureBoxの再描画は行っていないので、他のウィンドウに隠れたりすると表示のみ等倍に戻ってしまいます。
' 拡大のみです。縮小はしません。
'----------------------------------------------------------------------
Public Class Form1
 Inherits System.Windows.Forms.Form

 Dim bmap As Image = Image.FromFile("C:\サンプル.jpg")
 Dim sMagnification As Single '拡大率
 Dim sMinX As Single '拡大時の左上点X座標
 Dim sMinY As Single '拡大時の左上点Y座標
 Dim sMinX2 As Single '前回拡大時の左上点X座標
 Dim sMinY2 As Single '前回拡大時の左上点X座標

 Const csIncreases As Single = 1.0F '拡大率増加量
 Const ciDspWidth As Integer = 200 '表示領域横幅
 Const ciDspHeight As Integer = 200 '表示領域縦幅

#Region " Windows フォーム デザイナで生成されたコード "
 '省略します
#End Region

 Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
  Dim g As Graphics = PictureBox1.CreateGraphics()

  'PictureBoxの表示クリア
  g.Clear(PictureBox1.BackColor)

  '拡大時の左上点座標の算出
  sMagnification = sMagnification + csIncreases
  sMinX = ((e.X + sMinX2) * (sMagnification / (sMagnification - csIncreases))) - (ciDspWidth / 2)
  sMinY = ((e.Y + sMinY2) * (sMagnification / (sMagnification - csIncreases))) - (ciDspHeight / 2)

  '元の画像の大きさをsMagnification倍にして表示する
  g.DrawImage(bmap, -(sMinX), -(sMinY), sMagnification * bmap.Width, sMagnification * bmap.Height)

  '左上点座標を記録
  sMinX2 = sMinX
  sMinY2 = sMinY

  'Graphicsオブジェクトを破棄
  g.Dispose()

 End Sub

 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
  PictureBox1.Image = bmap
  sMagnification = 1
  sMinX = 0
  sMinY = 0
  sMinX2 = 0
  sMinY2 = 0
 End Sub
End Class
■No1715に返信(琴さんの記事)
横から口を挟んで申し訳ありません。

琴さんのコードでは、はじめPictureBox1.Imageに画像を設定して、その後、Graphicsを取得して表示していますが、どちらかの方法に統一した方が良いのではないでしょうか?琴さんのコードだと、やはりPictureBox1のPaintイベントハンドラで画像を描画し、PictureBox1.Imageは使わないとするのがシンプルだと思うのですが。

もし、琴さんが意図した書き方であったならば、申し訳ありません。どちらにせよ、これだけのコードを書くのは大変なことであり、感謝です。
■No1730に返信(管理人さんの記事)
> 横から口を挟んで申し訳ありません。
>
> 琴さんのコードでは、はじめPictureBox1.Imageに画像を設定して、その後、Graphicsを取得して表示していますが、どちらかの方法に統一した方が良いのではないでしょうか?琴さんのコードだと、やはりPictureBox1のPaintイベントハンドラで画像を描画し、PictureBox1.Imageは使わないとするのがシンプルだと思うのですが。
>
> もし、琴さんが意図した書き方であったならば、申し訳ありません。どちらにせよ、これだけのコードを書くのは大変なことであり、感謝です。

いろいろ試しながら作ったのであちこちに粗があってすみません。
PictureBox1.Imageの使用に意図はまったくありません。
管理人様のおっしゃる通り、描画方法を統一した方がメンテナンスや改修等もやりやすいと思います。
(他にもPictureBox1.Width・Heightで取得できる値を定数化していたりとボロボロです)
今後も見やすい・判りやすいソースを目指して精進させていただきます。
ありがとうございました。
長く丁寧にコードを書いてくれてありがとうございましたm(__)m
自分ではまだ完全に理解できてないぐらい高度なプログラムだと
思いました。拡大は上記の文のおかげで解決しました。
本当にありがとうございました☆
解決済み!
2003/12/09(Tue) 17:26:34 編集(投稿者)
2003/12/09(Tue) 16:20:54 編集(投稿者)

■No1736に返信(水野さんの記事)
> 長く丁寧にコードを書いてくれてありがとうございましたm(__)m
> 自分ではまだ完全に理解できてないぐらい高度なプログラムだと
> 思いました。拡大は上記の文のおかげで解決しました。
> 本当にありがとうございました☆

画像処理を作るのは数年ぶりだったのでこちらもいい勉強になりました。
ありがとうございました。

ちょっと時間ができたので縮小と再描画処理も作ってみました。
ご参考までにどうぞ。

'----------------------------------------------------------------------
' サイズ指定の定数を排除したのでどんなサイズのPictureBoxでもOKです。
' (BorderStyleプロパティがFixedSingleの時は2を、Fixed3Dの時は4をそれぞれWidthとHeightから引いてください)
' PictureBox内を左クリックすると、その座標を中心に2倍、3倍、・・・としていきます。
' 同様に右クリックで縮小されます。等倍(1/1)以降は1/2倍、1/3倍、・・・としていきます。
' 拡大率の制限はありません。オーバーフローするまで際限なく拡大・縮小ができます。
' いくつかの変数名および型に変更が入っています。ご注意ください。
' 細かい間違いがいくつかありましたので修正しました。
'----------------------------------------------------------------------
Public Class Form1
 Inherits System.Windows.Forms.Form

 Dim bmap As Image = Image.FromFile("C:\サンプル.jpg")
 Dim sMagnification As Single '拡大率
 Dim sMagnification2 As Single '前回の拡大率
 Dim sMinX As Single '拡大・縮小時の左上点X座標
 Dim sMinY As Single '拡大・縮小時の左上点Y座標
 Dim sMinX2 As Single '前回の左上点X座標
 Dim sMinY2 As Single '前回の左上点Y座標
 Dim iRCount As Integer '左クリック回数(拡大率分母)
 Dim iLCount As Integer '右クリック回数(拡大率分子)

 Const ciIncreases As Integer = 1 '拡大率増減量

#Region " Windows フォーム デザイナで生成されたコード "
 '省略します。
#End Region

 Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
  Dim g As Graphics = PictureBox1.CreateGraphics()

  If e.Button = MouseButtons.Left Then '左クリック時(拡大)
   'クリックカウントの増減
   If iRCount = ciIncreases Then
    iLCount = iLCount + ciIncreases
   Else
    iRCount = iRCount - ciIncreases
   End If

  ElseIf e.Button = MouseButtons.Right Then '右クリック時(縮小)
   'クリックカウントの増減
   If iLCount = ciIncreases Then
    iRCount = iRCount + ciIncreases
   Else
    iLCount = iLCount - ciIncreases
   End If

  Else
   'Graphicsオブジェクトを破棄
   g.Dispose()
   Exit Sub

  End If

  '拡大(縮小)率の算出(分母・分子のどちらかは必ず1になります)
  sMagnification = iLCount / iRCount

  '拡大(縮小)時の左上点の算出
  sMinX = ((e.X + sMinX2) * (sMagnification / sMagnification2)) - (PictureBox1.Width / 2)
  sMinY = ((e.Y + sMinY2) * (sMagnification / sMagnification2)) - (PictureBox1.Height / 2)

  'PictureBox1の表示クリア
  g.Clear(PictureBox1.BackColor)

  '元の画像の大きさをiMagnification倍にして表示する
  g.DrawImage(bmap, -(sMinX), -(sMinY), sMagnification * bmap.Width, sMagnification * bmap.Height)

  '拡大率&左上点座標を記録
  sMagnification2 = sMagnification
  sMinX2 = sMinX
  sMinY2 = sMinY

  'Graphicsオブジェクトを破棄
  g.Dispose()
 End Sub

 Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
  '元の画像の大きさをiMagnification倍にして再描画する
  e.Graphics.DrawImage(bmap, -(sMinX), -(sMinY), sMagnification * bmap.Width, sMagnification * bmap.Height)
 End Sub

 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
  '初期設定
  sMagnification = 1.0F
  sMagnification2 = 1.0F
  iRCount = 1
  iLCount = 1
  sMinX = 0
  sMinY = 0
  sMinX2 = 0
  sMinY2 = 0
 End Sub
End Class
解決済み!
■No1741に返信(琴さんの記事)
本当にすみません、またまた一つだけ言わせてください。

PictureBox1_MouseDownで画像を描画する時、PictureBox1のInvalidateメソッドを呼び出すとPaintイベントにより画像が描画されますので、画像を描画するコードの変わりにInvalidateメソッドを使った方が良いでしょう。
  • 題名: Re[10]: おまけです
  • 著者: 琴
  • 日時: 2003/12/10 9:20:29
  • ID: 1764
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No1759に返信(管理人さんの記事)
> 本当にすみません、またまた一つだけ言わせてください。
>
> PictureBox1_MouseDownで画像を描画する時、PictureBox1のInvalidateメソッドを呼び出すとPaintイベントにより画像が描画されますので、画像を描画するコードの変わりにInvalidateメソッドを使った方が良いでしょう。

この方法だと、PictureBox1の表示をクリアする処理もいらなくなってソースもシンプルになりますね。
また一つ勉強になりました。ありがとうございました。
解決済み!

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