作ったプログラムがうまくいきません、アドバイスお願いします。

タグの編集
投稿者 VBビギナー  (社会人) 投稿日時 2011/4/1 09:42:40
三角形を塗りつぶししたいのですが、どうにもうまくいきません。

プログラムの説明としては、RGBを用いた塗りつぶしです。VScrollの値を用いてRGBを使い、
コマンドボタンを押すと、RGBで出た色で三角形が塗りつぶされるというものなのです。


Private Declare Function ExtFloodFill Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long, ByVal wFillType As Long) As Long
Private Function Paint(X As Long, Y As Long)

     Dim T
    T = Screen.TwipsPerPixelX

    ExtFloodFill Me.hdc, X / T, Y / T, vbBlack, 0
    Me.Refresh

End Function

Private Sub Form_Load()
 
       Form1.AutoRedraw = True
    
    Form1.FillStyle = 0
    
    Line (4000, 1000)-(5000, 3000)
    Line -(3000, 3000)
    Line -(4000, 1000)

End Sub

Private Sub Command1_Click()

   Dim X As Integer
   Dim Y As Integer
   Dim Z As Integer
   
    X = VScroll1.Value
    Y = VScroll2.Value
    Z = VScroll3.Value

     Me.FillColor = RGB(X, Y, Z)
    
    
    
End Sub

回答よろしくお願いいたします。
投稿者 ヴァン  (社会人) 投稿日時 2011/4/1 09:46:51
こんにちは。

>三角形を塗りつぶししたいのですが、どうにもうまくいきません。

何がうまくいかないのでしょうか?
投稿者 VBビギナー  (社会人) 投稿日時 2011/4/1 09:55:50
お返事ありがとうございます。

VBを勉強し始めて間が無いため、具体的な例は挙げれないのですが・・・

強いて言えば、三角形内の塗りつぶしがうまくいかないとしか。。。

最初のAPI関数はこのサイトに乗っていた別例のものをそのまま流用してるので、APIが違うのでしょうか?それとも全く別の問題?

ちなみに別例というのは、オプションボタンを用いて塗りつぶすやつです。

投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/4/1 09:56:59
> Declare Function ExtFloodFill 
塗りつぶしにこの API を使うという点は正しいですが、現状のコードでは
ボタンを押しても、この API を呼び出すには至っていませんよね。

たとえば、Command1_Click の最後に「Paint 0, 0」と記述すれば、三角形の外側が塗りつぶされますし、
三角形の内部点を指定すれば、三角形の内側が塗りつぶされることでしょう。

> Private Function Paint(X As Long, Y As Long)
戻り値を使わないのであれば、Function ではなく Sub を使いましょう。

> Dim T
> T = Screen.TwipsPerPixelX
T の型を明示しましょう。

> ExtFloodFill Me.hdc, X / T, Y / T, vbBlack, 0
本来は、縦座標には TwipsPerPixelX ではなく TwipsPerPixelY を使うべきです。
確かに TwipsPerPixelXとY は同値である事が多いですが、たとえば一部のプリンターでは
縦横の解像度が異なるケースもあります。(もっとも、今回は画面への出力なのですけれども)
投稿者 VBビギナー  (社会人) 投稿日時 2011/4/1 10:27:41
ご指摘いただいた点は変更しました。

Private Declare Function ExtFloodFill Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long, ByVal wFillType As Long) As Long
Private Sub Paint(X As Long, Y As Long)

     Dim T
    T = Screen.TwipsPerPixelY

    ExtFloodFill Me.hdc, X / T, Y / T, vbBlack, 0
    Me.Refresh

End Sub

ただ、型云々というのがいまいち分からないです。

このサイトを読み返してもわかりませんでした、他のサイトで調べたかったのですが、的確なキーワードがわからず断念しました。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/4/1 11:47:21

>> Command1_Click の最後に「Paint 0, 0」と記述すれば、三角形の外側が塗りつぶされますし、
>> 三角形の内部点を指定すれば、三角形の内側が塗りつぶされることでしょう。
> ご指摘いただいた点は変更しました。
変更してみて、結果はどうなりましたか?


>> 縦座標には TwipsPerPixelX ではなく TwipsPerPixelY を使うべきです。
> T = Screen.TwipsPerPixelY
> ExtFloodFill Me.hdc, X / T, Y / T, vbBlack, 0
今度は、横座標に TwipsPerPixelY が使われてしまっていますよ。



> ただ、型云々というのがいまいち分からないです。
100 なら「整数型(Integer)」、100.0 なら「倍精度浮動小数点型(Double)」、
"100" なら「文字列型(String)」といった違いです。
VB では、変数宣言時の As 句などを通じて、それぞれのデータ型を明示できます。

で。

型の違いが処理結果に影響を与えてしまうケースもありますので、最終的には
型を意識したコードを記述できるようになっていた方が望ましいのですが、
今回程度の程度の違いであれば、VB 側が暗黙の型変換をおこなって対処してくれますので、
VB 自体に不慣れで、そこまで理解が追いつかないようであれば、型の理解は
ある程度後回しにしてしまってもよいと思います。
投稿者 VBビギナー  (社会人) 投稿日時 2011/4/1 13:25:37
いろいろと試してたら、できました・・・

Private Declare Function ExtFloodFill Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long, ByVal wFillType As Long) As Long
Private Function Paint(X As Long, Y As Long)

     Dim T
    T = Screen.TwipsPerPixelX

    ExtFloodFill Me.hdc, X / T, Y / T, vbBlack, 0
    Me.Refresh

End Function

Private Sub Form_Load()
 
       Form1.AutoRedraw = True
    
    Form1.FillStyle = 0
    
    Line (4000, 1000)-(5000, 3000)
    Line -(3000, 3000)
    Line -(4000, 1000)

End Sub

Private Sub Command1_Click()
 
  
     Me.FillColor = RGB(VScroll1.Value, VScroll2.Value, VScroll3.Value)
    Paint 4000, 1500
    
    
End Sub


上みたいな感じです。Xやらを使わずに、RGBの中に直接VScrooll.Valueを入れたらできました。
投稿者 cupid  (社会人) 投稿日時 2011/4/8 21:05:07
ポリゴン塗りつぶしごときに、APIを使うなんて方向性を間違えている。
桑原桑原。

VB.Netでは次の様にやるのが常道。
   Dim g As Graphics = Me.CreateGraphics
   nhokan = 0
   Dim arc(nhokan) As Point
   For lp = 0 To nhokan - 1
     arc(lp).X = .....
     arc(lp).Y = .....
   Next
   arc(nhokan).X = arc(0).X
   arc(nhokan).Y = arc(0).Y
' - 中塗り - 
   Dim myBrush As SolidBrush = New SolidBrush(Color.FromArgb(96, 224, 192, 240))
   g.FillPolygon(myBrush, arc)
   myBrush.Dispose()
' - 外周 - 
   Dim pen1 As New Pen(Color.FromArgb(190, 140, 210), 2)
   g.DrawPolygon(pen1, arc)
   pen1.Dispose()
   g.Dispose()

g を定義しないでやる場合は、Paintイベントを使うが、書き方はほぼ同じ。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/4/9 02:58:10
> ポリゴン塗りつぶしごときに、APIを使うなんて方向性を間違えている。
いえ、今回の質問はどうみても VB.NET での質問ではありませんので、失礼ながら
Graphics クラスを使おうとする方が、回答の方向性がズレているかと思いますよ。

# というか…提示されたコードは某所のサンプルにそっくりですが、nhokan が 0 なので、
# たとえ VB.NET であったとしても、これでは目的を達成できないと思います。(汗

もし仮に、API 無しで塗りつぶしを実装させるべきだという意味であれば、
ソリッドスキャンコンバージョン法なり、スキャンラインシードフィル法なりの
アルゴリズムを組み込んで実装することができるでしょう。
(その回答を元質問者が望むかどうかは別として)