tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトル塗りつぶし(黒)の円をPC画面中央に配置する
記事No11384
投稿日: 2015/04/11(Sat) 00:01
投稿者ゆきみち
vb2012を使用してまだ1年になります。
PC画面の中央に半径10cmの塗りつぶしの円を書きたいのですが、
どのようなプログラムを書いたら良いかご存知の方はいませんでしょうか?
これが書けないと私の大学の卒業がかなり怪しくなります。ご協力頂ける方はいないでしょうか?

[ツリー表示へ]
タイトルRe: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11385
投稿日: 2015/04/11(Sat) 02:10
投稿者魔界の仮面弁士
> PC画面の中央に半径10cmの塗りつぶしの円を書きたいのですが、

自フォーム上に描くのでしょうか。
それとも他のアプリの上に描くのでしょうか。


前者だとすれば、最大化表示したフォームの上に、OvalShape コントロールを
貼っておけば済みそうです。もちろん描画しても良いですけど。

後者だとすれば、案としては2つ。一つは下記のように、CopyFromScreen で
現在の画面情報を自フォーム上の上に写し取り、その上に描く方法。
http://hanatyan.sakura.ne.jp/vbnetbbs/wforum.cgi?mode=allread&no=9839&page=0
もう一つは少々面倒ですが、自フォーム以外の場所に直接描く方法。具体的には
GetDC API に IntPtr.Zero を渡してプライマリモニタのDCを取得し、
そこに Ellipse API で塗りつぶすという方法です。お奨めはしませんけど。


問題があるとすれば、描画そのものよりも「半径10cm」という指定についですね。
通常であれば、たとえば 300x300 ドットなどのような指定を指定行いたいところですが、
今回は物理cmで指定されていますので、描画サイズを逆算しないといけません。


たとえば、FullHD(1920x1080)の13インチモニタに描画するとすれば、この場合、
10cm というのは、約666ドット相当になる計算ですよね。

ところが、同じ13インチモニタでも、解像度がHD(1366x768)の画面を使っているとすれば、
その半径 666 ドットの画像が、大きめ(14cm)に表示されてしまう事になります。

解像度が同じモニタだったとしても、液晶の物理サイズが異なれば同様で、
11インチの FullHD なら、8.5cm 相当のサイズに映し出されますし、
17インチであれば 13cm になってしまうわけです。これらの点を吸収せねばなりませんね。

画面解像度からの算出方法はこちら。
http://matome.naver.jp/odai/2136077252002168201


画面の解像度(ドット数)については、Screen.PrimaryScreen.Bounds.Width などで
調べられるのですが、モニタのインチ数というか物理サイズまでは調べられません。
ですから、課題にある「10cm」を満たすためには、実行時に、ユーザーにモニタサイズを
入力してもらうなどしないと、算出することができないと思います。


> どのようなプログラムを書いたら良いかご存知の方はいませんでしょうか?
具体的にはどこまで出来ていて、どこが分からないのでしょうか?

ここの掲示板の利用ルールにもありますように、代わりにプログラムを書いてほしい、という
丸投げな話だとしたら流石に論外ですが、分からない点を明確にして理解したいというのなら
可能な範囲で協力しますよ。


> これが書けないと私の大学の卒業がかなり怪しくなります。
ん? 今日は4月11日。まだ新学期が始まったばかりですよね。
たとえ最高学年であったとしても、3月までまだ十分日数があるのでは…。

[ツリー表示へ]
タイトルRe^2: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11386
投稿日: 2015/04/12(Sun) 21:53
投稿者ゆきみち
返信ありがとうございます。
私が今書いているプログラムは以下の通りです。
Public Class Form1

    Private Sub form1_paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
        Dim gr As Graphics = Me.CreateGraphics
        Dim x, y, decPC_Yoko As Integer


        decPC_Yoko = 255  '横方向の画面の大きさ*

        x = (Me.Size.Width / 2)
        y = (Me.Size.Height / 2)



        ' 中心が画面の中心で半径が100oの緑の円を描画します。
        Dim r As Integer = 100
        gr.FillEllipse(Brushes.Black, x - r, y - r, r * 2, r * 2)

        gr.Dispose()

    End Sub
  
End Class

このプログラムですると円は中央に来ているとは思いますが、半径の指定がうまく出来ません。
mm表示で出来るようにと
gr.PageUnit = GraphicsUnit.Millimeter
decHaba = (Me.Size.Width * 2.54 * 10) / (gr.DpiX * decPC_Yoko)
を上記プログラムの*の下に入れると今度は画面に円が表示されなくなります。
(恐らく画面がはみ出ているのかと思います。)

どの部分を改善したら良くなりますでしょうか?
お忙しいところ申し訳ありませんが、ご指導のほど何卒宜しくお願い申し上げます。

[ツリー表示へ]
タイトルRe^3: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11387
投稿日: 2015/04/13(Mon) 11:21
投稿者魔界の仮面弁士
> decPC_Yoko = 255  '横方向の画面の大きさ*
> decHaba = (Me.Size.Width * 2.54 * 10) / (gr.DpiX * decPC_Yoko)

DpiX を使っていることから、「1.0 インチ= 25.4ミリメートル」を想定して
計算されているのでしょうか。decPC_Yoko の単位系は何を想定していますか?


>  y = (Me.Size.Height / 2)

Me.Size だと、タイトルバーなども含んだ領域になってしまいますよ。
下記の冒頭の図であれば、(2) のウィンドウ領域を示していることになります。

今回指定したいのは、(1)のクライアント領域ですよね。
http://www.atmarkit.co.jp/fdotnet/dotnettips/379getclientrect/getclientrect.html


> gr.PageUnit = GraphicsUnit.Millimeter
PageUnit で変換されるのは、あくまでも「描画座標」の指定です。

Me.Size や Me.ClientSize は Grapchis.PageUnit の影響を受けませんので、
>   Dim r As Integer = 100
>   gr.FillEllipse(Brushes.Black, x - r, y - r, r * 2, r * 2)
というコードだと、
 「xピクセル−rミリ, yピクセル−rミリ, rミリ×2, rミリ×2」
な値を、ミリメートル単位系のキャンバスに描いていることになってしまいます。
最初からミリメートル単位のキャンバスサイズを得たいのであれば、
Form の ClientSize ではなく、Graphics の ClipBounds を使うのが手っ取り早いでしょう。

もちろん、Form 側から得たピクセル単位を mm単位あるいは cm単位に
計算しなおす手法でも、計算さえ間違えなければ同じ結果が得られますけれどね。


> どの部分を改善したら良くなりますでしょうか?
上記を改修すれば、期待する結果になると思いますよ。



==== 以下蛇足 ===
元のコードに気になる点があるので、少し指摘させてください。(本題からは外れますが)


> Private Sub form1_paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
>   Dim gr As Graphics = Me.CreateGraphics

まず、ここの取り扱いを見直しましょう。

(a)CreateGraphics の利用は避けましょう。簡単に記述できることから、サンプルコード等では
 よく利用されていますが、実際には CreateGraphics が必要になるのは、やや特殊なケースです。

(b)通常は、Paint イベントの e.Grapchis が使われます。Paint イベントは、ウィンドウの再描画が
 必要になったタイミングで発生し、再描画に必要なキャンバスを e.Grapchis として提供してくれます。

(c)また、描画内容があまり変化しない場合(背景画像など)には、再描画の手間を減らすため、
 Bitmap オブジェクトを用意し、そこに Graphics.FromImage でキャンパスを生成して、
 その描画された Bitmap を、Form や PictureBox の BackgroundImage に指定する手法がよく利用されます。

(d) (b) の e.Graphics は、自分で作成したオブジェクトでは無いため、Dispose してはいけません。
 一方、CreateGraphics あるいは (c) の Graphics.FromImage の場合、その Grapchis リソースは
 自分で生成したオブジェクトですので、使用後即座に、Dispose メソッド ないしは Using を用いて
 破棄する必要があります。(この点について、提示頂いたコードでは既に守られているようですね)


>  Dim x, y, decPC_Yoko As Integer
>  x = (Me.Size.Width / 2)
>  y = (Me.Size.Height / 2)

変数 x や y を Integer にするなら、上記は / 2 ではなく \ 2 の方が良いですね。

Integer / Integer の演算結果は Double 型です。(例えば 234.5 などといった値になりえます)
代入している x や y は Integer なので、ここで暗黙の型変換が生じてしまいます。

Integer \ Integer であれば、演算結果も Integer になります。


> ご指導のほど何卒宜しくお願い申し上げます。
一応、提示されたコードとは別案のサンプルも貼っておきます。

Option Strict On
Public Class Form1

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
        Me.DoubleBuffered = True
    End Sub

    Private Sub Form1_Resize(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Resize
        'フォームのサイズが変わったときに、再描画を指示する
        Me.Invalidate()
    End Sub

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Me.Paint
        Dim g As Graphics = e.Graphics
        g.ResetTransform()

        '単位系を論理センチに変更する。(モニタによっては追加調整の必要アリ)
        '下記を実行しない場合は、ピクセル単位で描画される。
        'g.ScaleTransform(e.Graphics.DpiX / 2.54!, e.Graphics.DpiY / 2.54!)

        '画面の中央が原点となるよう、座標系を水平移動する
        Dim sz As RectangleF = g.ClipBounds
        g.TranslateTransform(sz.Width / 2, sz.Height / 2)

        '赤:一辺10の正方形を「右下が画面の中心」になるように描画
        g.DrawRectangle(Pens.Red, -10, -10, 10, 10)

        '青:一辺10の正方形を「左下が画面の中心」になるように描画
        g.DrawRectangle(Pens.Blue, 0, -10, 10, 10)

        '緑:一辺10の正方形を「右上が画面の中心」になるように描画
        g.DrawRectangle(Pens.Green, -10, 0, 10, 10)

        '紫:一辺10の正方形を「左上が画面の中心」になるように描画
        g.DrawRectangle(Pens.Purple, 0, 0, 10, 10)

        '黒:一辺10の正方形に内接する円を「画面の中心」に描画
        g.FillEllipse(Brushes.Black, -5, -5, 10, 10)

        g.ResetTransform()
    End Sub
End Class


なお、描画処理が複雑でもたつくような場合は、Resize イベントではなく
ResizeEnd で Invalidate するようにしてみてください。ただしその場合、
リサイズ中は再描画されず、リサイズ完了後に描画されることになります。

[ツリー表示へ]
タイトルRe^4: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11390
投稿日: 2015/04/13(Mon) 21:33
投稿者ゆきみち
> > decPC_Yoko = 255  '横方向の画面の大きさ*
> > decHaba = (Me.Size.Width * 2.54 * 10) / (gr.DpiX * decPC_Yoko)
>
> DpiX を使っていることから、「1.0 インチ= 25.4ミリメートル」を想定して
> 計算されているのでしょうか。decPC_Yoko の単位系は何を想定していますか。

⇒decPC_Yokoは画面の横方向の大きさで単位は「o」です。
> gr.PageUnit = GraphicsUnit.Millimeter
> PageUnit で変換されるのは、あくまでも「描画座標」の指定です。
>
> Me.Size や Me.ClientSize は Grapchis.PageUnit の影響を受けませんので、
> >   Dim r As Integer = 100
> >   gr.FillEllipse(Brushes.Black, x - r, y - r, r * 2, r * 2)
> というコードだと、
>  「xピクセル−rミリ, yピクセル−rミリ, rミリ×2, rミリ×2」
> な値を、ミリメートル単位系のキャンバスに描いていることになってしまいます。
> 最初からミリメートル単位のキャンバスサイズを得たいのであれば、
> Form の ClientSize ではなく、Graphics の ClipBounds を使うのが手っ取り早いでしょう。
⇒Graphics の ClipBoundsの使い方がよく分からないのでもう一度ご教示お願い出来ますでしょうか?

蛇足の部分も含めてプログラムを改変して見ました。
ご確認のほど宜しくお願い申し上げます。(まだ、指定した大きさの円を画面のFormの中央に表示することができていません。。。。。)

Private Sub form1_paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
        Dim x, y, decPC_Yoko As Integer
        Dim decHaba As Decimal

        decPC_Yoko = 255   '横方向の画面の大きさ

        'どのPCでも1mmが表示できるようにする
        decHaba = (Me.ClientSize.Width * decPC_Yoko / 10) / (e.Graphics.DpiX * decPC_Yoko)

        x = (Me.ClientSize.Width \ 2)
        y = (Me.ClientSize.Height \ 2)



        ' 中心が画面の中心で半径が100mmの緑の円を描画します。
        Dim r As Integer = 100
        e.Graphics.FillEllipse(Brushes.Black, x - r, y - r, r * 2, r * 2)

    End Sub

[ツリー表示へ]
タイトルRe^5: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11391
投稿日: 2015/04/14(Tue) 10:57
投稿者魔界の仮面弁士
もし、画面サイズに忠実となるよう長さ補正をしたいのであれば、
たとえば 500 px の直線を描画しておき、その直線がモニタ上で
どのくらいの長さに見えるのかを定規ではかってもらい、それを
基準値して入力してもらう必要があると思います。

これにより、dpi (物理1インチあたりのドット数) や
px/cm (物理1センチあたりのドット数)の正確な値が手に入ります。
たとえば、500px の直線が 13.3cm で表示されれば、
500px÷13.3cm≒ 37.59px/cm (95.49dpi) という感じで。

そこまで厳密な値を求めているわけでは無いのであれば、
DpiX や DpiY プロパティ(論理1インチあたりのドット数)を
基準にするだけでも良いでしょうけれどね。



> > decPC_Yoko = 255  '横方向の画面の大きさ*
> > > decHaba = (Me.Size.Width * 2.54 * 10) / (gr.DpiX * decPC_Yoko)
> ⇒decPC_Yokoは画面の横方向の大きさで単位は「o」です。

今回、Graphics.PageUnit を使って単位系を変更したいのですよね。
ご存知の通り、GraphicsUnit.Millimeter で描画するためには、
描画時にミリメートル単位系の値を指定しなければなりません。

では、今回の計算に使った
 (Me.Size.Width * 2.54 * 10) / (gr.DpiX * decPC_Yoko)
の単位系を考えてみます。
この式の『単位』のみを抜き出していくと、decPC_Yokoが「mm」なので
 (px × cm/inch × mm/cm)÷(px/inch × mm)
になりますね。

求めた decHaba をどのように使っているのか分かりませんが、
割り算部分で単位を打ち消していくと、演算結果が mm ではなく
「単位なし」になってしまうわけですが、本当にそれで良いのでしょうか?




> ⇒Graphics の ClipBoundsの使い方がよく分からないのでもう一度ご教示お願い出来ますでしょうか?

Graphics の ClipBounds プロパティは、描画キャンバスのクリッピング領域(に外接する矩形)を表します。

…という説明では意味が分かりにくいと思いますが、要は、Form の Paint イベントにおける
e.Graphics.ClipBounds は、その Form の ClientSize と同じ情報を返すという事です。

ただし、ClientSize は常にピクセル単位系で結果が返されるのに対し、
ClipBounds の場合は、Graphics で用いている座標系および単位系が使われるため、
単位変換を行いやすいということです。(先の私のサンプルでも使っています)
もちろん、ClientSize から求めても良いですけれどね。

[ツリー表示へ]
タイトルRe^6: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11398
投稿日: 2015/04/15(Wed) 19:29
投稿者ゆきみち
返信ありがとうございました。
以下のプログラムで画面の中央に指定した大きさで丸を描けるのではないかと思いますが、
確認のほど宜しくお願い申し上げます。

Public Class Form1

    Private Sub form1_paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
        Dim x, y As Integer
        Dim a, b, c, d, f, h As Decimal


        a = 1366  'パソコン画面の横の解像度
        b = 768   'パソコン画面の縦の解像度
        c = 11.6  'パソコン画面の型(インチ)

        d = Math.Sqrt(a * a + b * b) 'ピタゴラスの定理よりパソコン画面の対角線上のドット数
        f = c * 2.54                 'パソコン画面の対角線上の長さ 1inch = 2.54cm
        h = 10 * f / d               '1ピクセルが何mmに相当するか(=画素ピッチ)を求める


        'Form1の中央のピクセルの値を調べる。
        x = Me.ClientSize.Width \ 2
        y = Me.ClientSize.Height \ 2


        ' 中心が画面の中心で半径10mm(直径20mm)の緑の円を描画します。
        Dim r As Decimal = 10 / h         '1ピクセル:h o= x : 10mm
        e.Graphics.FillEllipse(Brushes.Black, x - r, y - r, r * 2, r * 2)
      
    End Sub



> もし、画面サイズに忠実となるよう長さ補正をしたいのであれば、
> たとえば 500 px の直線を描画しておき、その直線がモニタ上で
> どのくらいの長さに見えるのかを定規ではかってもらい、それを
> 基準値して入力してもらう必要があると思います。
>
⇒ご指摘頂いた方法でも試してみました。同じように良い結果が得ることが出来ました。
 ありがとうございました。ただ、ご指摘の方法をさらに応用してPCの解像度とモニターの大きさ(○○型)
 からでも算出できるような方法も考え、その方法でプログラムをしてみました。モニターの大きさはそのPC
 モニターの仕様を見れば記載されていますし、モニターの解像度はPCの「画面の設定」(Windows8)で
 確認が可能であると思いますので誰が設定しても同じ画素ピッチになるのではないかと思いますが、
 いかがでしょうか?

 私が作成したプログラムは結局、ピクセルをベースにしたものとなりました。
 更にプログラムを良くするのにあたり、改良点がありましたらご指摘頂けると幸いですがいかがでしょうか?

[ツリー表示へ]
タイトルRe^7: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11400
投稿日: 2015/04/15(Wed) 20:20
投稿者魔界の仮面弁士
プログラムがかなり進みましたね。


> 確認のほど宜しくお願い申し上げます。

今回、Decimal を使っておられるようですが、FillEllipse は
Decimal 型の座標指定をサポートしていません。指定できるのは、
Integer/Rectangle または Single/RectangleF 型だけです。

なのでこの段階で、「暗黙の型変換」が発生してしまいます。

データ型の指定ミスを減らすために、「Option Strict On」を利用してみてください。
卒業制作というのであれば、そういった細かい点も拘った方が良いと思いますよ。
(見た目上正しく動くだけではなく、コードの品質も高めておくということです)



>  a = 1366  'パソコン画面の横の解像度
>  b = 768   'パソコン画面の縦の解像度
変数には意味のある名前をつけましょう。a, b, c, d …ではなく、
たとえば screenWidth などといった分かりやすい名前が望ましいです。

もしも 1 文字変数を付けるにしても、
幅なら w (width) とか x とか
高さなら h (height) とは y など、
後から見たときに意味を推測できるようなものを選びます。


ちなみに、画面の解像度を調べるのであれば、固定値にせずとも
Screen.PrimaryScreen.Bounds を使うことができますよ。
(マルチモニタ環境の場合は、Screen.AllScreens で列挙できます)


> f = c * 2.54
単に 2.54 と書くと、Double 型の値を意味してしまいます。
もしも Decimal 型の 2.54 を明示したいのであれば、
 f = c * 2.54D
とすることで、Decimal 型の 2.54 を指定したことになります。


数値の末尾に R または # を付けた場合は Double 型を意味します。
数値の末尾に F または ! を付けた場合は Single 型を意味します。
数値の末尾に D または @ を付けた場合は Decimal 型を意味します。



> x = Me.ClientSize.Width \ 2
> y = Me.ClientSize.Height \ 2
> Dim r As Decimal = 10 / h         '1ピクセル:h o= x : 10mm
> e.Graphics.FillEllipse(Brushes.Black, x - r, y - r, r * 2, r * 2)

座標指定が Integer なのに、サイズ指定が Decimal 型とバラバラです。
整数で指定したいのか小数で指定したいのかはっきりさせましょう。

整数にしたいなら Integer に統一するべきですし、
小数指定が必要なら、(Decimal ではなく)Single で指定することになります。



> モニターの大きさはそのPCモニターの仕様を見れば記載されていますし、
> モニターの解像度はPCの「画面の設定」(Windows8)で確認が可能であると
> 思いますので誰が設定しても同じ画素ピッチになるのではないかと思いますが、
> いかがでしょうか?

ほぼそれで大丈夫だと思いますよ。あとはどこまでの厳密性を求めるか、ですね。

液晶モニターであったとしても、その液晶の推奨解像度以外で表示することは可能です。
たとえば、幅 1280 なモニターに対して、1024 なデスクトップを表示した場合、
画面の左右端に、何も移らない領域ができるか……もしくは、長さ 40 の直線が
長さ 50 に間延びして、滲んで描画されるといった結果になりえます。
(この場合、縦横でドットピッチが異なるケースも生じえますね)

まぁ、それは極端な例ですが、たとえ推奨解像度通りの設定だったとしても、
若干のズレは生じてくるものです。
お使いのモニターに、電源スイッチや明るさ調整のものとは別に、
「ゆがみ補正」などの調整用スイッチが付いていたりはしませんか?
このスイッチの設定次第では、同じ型番のモニタでも、実際の表示サイズに
差が生じる可能性があるわけです。CRT の場合は特に。
そしてその設定値は、プログラムで検知することはできません。
(調整スイッチを持たず、自動調整してくれるモニターもあります)

[ツリー表示へ]
タイトルRe^8: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11401
投稿日: 2015/04/15(Wed) 22:22
投稿者ゆきみち
プログラムを直して見ました。

Option Strict On
Public Class Form1
    Private Sub form1_paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint


        Dim x, y As Integer
        Dim a, b, c, d, f, h As Decimal

        a = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width 'パソコン画面の横の解像度  自分のPCでは1376
        b = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height 'パソコン画面の縦の解像度 自分のPCでは768
        c = CDec(11.6) 'パソコン画面の型(インチ)

        d = CDec(Math.Sqrt(a * a + b * b)) 'ピタゴラスの定理よりパソコン画面の対角線上のドット数
        f = CDec(c * 2.54)                 'パソコン画面の対角線上の長さ 1inch = 2.54cm
        h = 10 * f / d                     '1ピクセルが何mmに相当するか(=画素ピッチ)を求める


        'Form1の中央のピクセルの値を調べる。
        x = Me.ClientSize.Width \ 2
        y = Me.ClientSize.Height \ 2


        ' 中心が画面の中心で半径10mm(直径20mm)の緑の円を描画します。
        Dim r As Decimal = 10 / h         '1ピクセル:h o= x : 10mm
        e.Graphics.FillEllipse(Brushes.Black, x - r, y - r, r * 2, r * 2)
    End Sub


> 今回、Decimal を使っておられるようですが、FillEllipse は
> Decimal 型の座標指定をサポートしていません。指定できるのは、
> Integer/Rectangle または Single/RectangleF 型だけです。

⇒Integer/Rectangle または Single/RectangleF 型だけしか指定できないというのはどのような物を
 見たら理解出来ますでしょうか?


>
> データ型の指定ミスを減らすために、「Option Strict On」を利用してみてください。

⇒「Option Strict On」を使用して見ました。暗黙の型の変換が生じるところが表示されていたので
  直して見ました。


> 数値の末尾に R または # を付けた場合は Double 型を意味します。
> 数値の末尾に F または ! を付けた場合は Single 型を意味します。
> 数値の末尾に D または @ を付けた場合は Decimal 型を意味します。
⇒CDbl、CSng、CDECと同じ意味という理解で宜しいでしょうか?
>

>
> >  a = 1366  'パソコン画面の横の解像度
> >  b = 768   'パソコン画面の縦の解像度
> 変数には意味のある名前をつけましょう。a, b, c, d …ではなく、
> たとえば screenWidth などといった分かりやすい名前が望ましいです。

⇒ご指摘ありがとうございます。今ここで作成しているプログラムは全体の中の一部で
 予備的に作成しているものです。大元のプログラムに入れるときにはご教示頂いたことを踏まえ
 適切な名前を付けるようにします。
>
> ちなみに、画面の解像度を調べるのであれば、固定値にせずとも
> Screen.PrimaryScreen.Bounds を使うことができますよ。
> (マルチモニタ環境の場合は、Screen.AllScreens で列挙できます)
⇒便利な機能を教えて下さり誠にありがとうございます。また、Screen.AllScreensという機能も知り、
 大変勉強になりました。
 
>>
>
> > x = Me.ClientSize.Width \ 2
> > y = Me.ClientSize.Height \ 2
> > Dim r As Decimal = 10 / h         '1ピクセル:h o= x : 10mm
> > e.Graphics.FillEllipse(Brushes.Black, x - r, y - r, r * 2, r * 2)
>
> 座標指定が Integer なのに、サイズ指定が Decimal 型とバラバラです。
> 整数で指定したいのか小数で指定したいのかはっきりさせましょう。
>
> 整数にしたいなら Integer に統一するべきですし、
> 小数指定が必要なら、(Decimal ではなく)Single で指定することになります。

 ⇒基本データ型で非整数型(Demical,Double,Single)や整数型(SByte,Short,Integer,Long)で、
  例えば同じ非整数型であっても使い分けがよく分からなく適当にしているのが現状です。どういった基準で
  選択したら良いでしょうか?

何卒宜しくお願い申し上げます。

[ツリー表示へ]
タイトルRe^9: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11402
投稿日: 2015/04/16(Thu) 03:29
投稿者魔界の仮面弁士
> ⇒Integer/Rectangle または Single/RectangleF 型だけしか指定できないというのはどのような物を
>  見たら理解出来ますでしょうか?

ヘルプで FillEllipse メソッドについてみてみると、4 種類のオーバーロードが
あることがわかります。そこに、Decimal 型を受け付ける物はありませんよね。
https://msdn.microsoft.com/ja-jp/library/system.drawing.graphics.fillellipse.aspx

また、たとえヘルプを引かずとも、コーディング中の入力ヒントにおいても、
各オーバーロードの定義を確認することができます。



> > 数値の末尾に R または # を付けた場合は Double 型を意味します。
> > 数値の末尾に F または ! を付けた場合は Single 型を意味します。
> > 数値の末尾に D または @ を付けた場合は Decimal 型を意味します。
> ⇒CDbl、CSng、CDECと同じ意味という理解で宜しいでしょうか?
ちょっと違います。
CDbl 等で型を後から変換するのではなく、最初から適切な型のリテラルで記述するということです。

たとえば
 Dim s As String = "123"
と書くべきところで、わざわざ
 Dim s As String = CStr(123)
と書いたりはしませんよね。CStr で文字列化せずとも、最初から文字列リテラルで書けば良いわけで。


それに小数値の場合、データ型によって格納精度が異なりますから、
後付けでデータを変換する方法だと、どの段階で変換するのかによって、
誤差が丸められてしまうなどして、データに微細なズレが生じることがあります。



>  ⇒基本データ型で非整数型(Demical,Double,Single)や整数型(SByte,Short,Integer,Long)で、
>   例えば同じ非整数型であっても使い分けがよく分からなく適当にしているのが現状です。どういった基準で
>   選択したら良いでしょうか?

(大学の卒業という話をしていましたが、そういうところは講義で触れられているのでは…?)

えぇと、Single や Double などは「浮動小数点型」と呼ばれる型です。
算数用語でいうところの『概数』を扱う型だと思って下さい。

非常に大きな値から非常に小さな値まで扱えるのが特徴で、
「負の無限大」「正の無限大」「非数値」という特殊な値も管理します。
科学計算や物理計算などを扱うのに向いています。

CPU 側にも、浮動小数点演算のための専用命令(あるいはユニット)を備えていることから、
処理速度が速いこともメリットです(整数型の処理速度には敵いませんが)。
Graphics クラスが Single 型を使う仕様になっているのも、こうした理由からですね。

その代りあくまで概数なので、取り扱われる値は近似値となります。
内部的には 二進数の小数で値を管理しているため、0.5 や 0.75 といった値なら
誤差なく扱えるのですが、0.1 などの値は近似値となってしまいます。
この点がデメリットとなりますね。


そこで、金額計算などのように誤差が許されない場面では、代わりに
Decimal が使われます。こちらは十進数の小数を誤差なく扱えますが、
その分、メモリ効率や演算速度といった面ではは劣ります。その上、取り扱える値の範囲も、
Single や Double に比べると圧倒的に狭いものとなってしまいます。
とはいえ、金額計算に使う分には、十分な桁数ではあるですけれどね。


今回の場合、最終目標は画面上への描画処理ですから、
Decimal ではなく Single を使う方が適切だと思いますよ。

[ツリー表示へ]
タイトルRe^10: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11403
投稿日: 2015/04/16(Thu) 08:22
投稿者ゆきみち
> >  ⇒基本データ型で非整数型(Demical,Double,Single)や整数型(SByte,Short,Integer,Long)で、
> >   例えば同じ非整数型であっても使い分けがよく分からなく適当にしているのが現状です。どういった基準で
> >   選択したら良いでしょうか?
>
> (大学の卒業という話をしていましたが、そういうところは講義で触れられているのでは…?)

⇒私は情報処理系の学生ではなく(医療系の学生)、VBは実験機器を作成するために使用しています。
 なので、こういったことの講義は全くうけたことがありません。私のような初心者が上記のようなことを理解
  できるようなお勧めの本がありましたら是非、ご教示して頂けないでしょうか?
>
> 今回の場合、最終目標は画面上への描画処理ですから、
> Decimal ではなく Single を使う方が適切だと思いますよ。

⇒了解しました。ご指導ありがとうございます。

[ツリー表示へ]
タイトルRe^11: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11404
投稿日: 2015/04/16(Thu) 10:08
投稿者魔界の仮面弁士
> > 今回の場合、最終目標は画面上への描画処理ですから、
> > Decimal ではなく Single を使う方が適切だと思いますよ。
>
> ⇒了解しました。ご指導ありがとうございます。

話のついでに、小数を扱う場合の注意点について触れておきます。


たとえば、3 で割った値に 3 をかけなおすケースを考えてみましょう。

 Dim dec1 As Decimal = 1D / 3D
 Dim dec2 As Decimal = dec1 * 3D    '0.99999…になる

 Dim sng1 As Single = 1.0F / 3.0F
 Dim sng2 As Single = sng1 * 3.0F   '1.0 に戻る

データ型によって結果が異なってきますね。

これは要するに、0.33333333 + 0.33333333 + 0.33333333 の結果を、
0.99999999 として扱うのが正しいのか、それとも、概数計算として
1/3 + 1/3 + 1/3 ≒ 1.0 とするべきかという考え方の違いであって、
どちらかが間違いというわけではありません。


ただし概数であるがゆえに、浮動小数点型を用いた場合には、
 If (0.1R + 0.2R) = 0.3R Then
 If (1.0F - 0.9F) = 0.1F Then
などが False になるといった、分かりにくい現象も発生します。
(Decimal 型であれば一致するのですけれども)

そのため、浮動小数点数が等しいかどうかを調べるときは、
等号『=』で判定するのではなく、「その差が十分に小さいかどうか」で
判断することが求められるケースもあります。ご注意ください。
http://dobon.net/vb/dotnet/beginner/floatingpointerror.html


> ⇒私は情報処理系の学生ではなく(医療系の学生)、VBは実験機器を作成するために使用しています。
>  なので、こういったことの講義は全くうけたことがありません。私のような初心者が上記のようなことを理解
>   できるようなお勧めの本がありましたら是非、ご教示して頂けないでしょうか?

すみません。自分も独学なのですが、特定の本を読んで…というのは思い当たりません。

ただ小中学生の頃から、プログラミング関連の本はプログラム言語を問わず
図書館で借りまくっていた記憶があります(月に4〜5冊のペース)。
基本的には、BASIC 系の書籍とアルゴリズム関連の書籍を中心に読み漁っていました。
当時はインターネットも無く、書籍が知識の入り口でしたからね…。

大学に入ってから初めて Visual Basic に触れましたが(当時は VB2.0)、
製品に付属していた紙のマニュアルは読破していました。
VB2010の電子マニュアルでいうと、下記のセクションに相当する箇所です。
https://msdn.microsoft.com/ja-jp/library/2x7h1hfk%28vs.100%29.aspx

今にして思えば闇雲な学習法ではありましたが、効率は兎も角として、
当時のそれらが力になっているのだという思いはあります。
読んでみても意味の分からない部分も、一応目を通しておくと、
後々になって、急に理解できるようになることも少なくありませんし。

[ツリー表示へ]
タイトルRe^12: 塗りつぶし(黒)の円をPC画面中央に配置する
記事No11408
投稿日: 2015/04/20(Mon) 22:07
投稿者ゆきみち
魔界の仮面弁士様

ご指導ありがとうございました。
今回のことを通してまた新たな知識を得ることができました。
また、伺うことがあるかもしれませんが、その際は何卒よろしくお願い申し上げます。

[ツリー表示へ]