none
ExtFloodFillを有効にするには? RRS feed

  • 質問

  • vb 2010についてはド素人の私です。

    上図のように閉領域をExtFloodFillを使って緑で塗りつぶしたいのですが、どうもうまくいきません

    組んでみたコードは次の通りです。

    Public Class Form1
        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 Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

        End Sub

        Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            Dim g As Graphics
            g = e.Graphics
            g.Clear(Color.White)

            '##############    3個の円を描く  ##############
            Dim x1 As Integer
            Dim x2 As Integer
            Dim x3 As Integer
            Dim y1 As Integer
            Dim y2 As Integer
            Dim y3 As Integer
            Dim cx1 As Integer
            Dim cx2 As Integer
            Dim cx3 As Integer
            Dim cy1 As Integer
            Dim cy2 As Integer
            Dim cy3 As Integer

            Dim r As Integer
            r = 70
            cx1 = 150
            cx2 = 100
            cx3 = 200
            cy1 = 100
            cy2 = 180
            cy3 = 180

            Dim mypen As New Pen(Color.Black, 1)
            x1 = cx1 - r
            y1 = cy1 - r
            x2 = cx2 - r
            y2 = cy2 - r
            x3 = cx3 - r
            y3 = cy3 - r
            g.DrawEllipse(mypen, x1, y1, r * 2, r * 2)
            g.DrawEllipse(mypen, x2, y2, r * 2, r * 2)
            g.DrawEllipse(mypen, x3, y3, r * 2, r * 2)
            '###############################################

            '###########    閉領域の一つをみどりで塗りつぶす  '#####
            Dim hdc As Long
            Dim x As Integer
            Dim y As Integer
            Dim crColor As Long
            Dim wFillType As Long
            Dim FillColor As New Color
            Dim FillStyle As GraphicsUnit

            x = cx1
            y = cy1

            crColor = &HFFFFFF
            wFillType = 1
            FillStyle = 0
            FillColor = Color.FromArgb(0, 255, 0)
            ExtFloodFill(hdc, x, y, crColor, wFillType)      ←ここがエラーになる。
            '#########################################################

    いったいどうすれば、ExtFloodFillを有効にできるのでしょうか?

    ド素人の私にどうかご教授ください。

    2012年4月20日 11:45

回答

  • 0これが使えないならもうお手上げです。ほかに良い記述方法が思いつきません。

    Win32API を使うのであれば、使うためのお作法があります。

    正攻法としては MSDN のページ でシグネチャを確認し、正しく型を対応させることです。
    HDC などのハンドルは IntPtr 型、int 型は Integer 型などです。
    正しい書き換えがわからないのであれば、関数名と「P/Invoke」と「Declare」あたりをキーワードをつければ見つけられるかもしれませんね。ただ、VB6 のコードは使えないので気をつけてください。

    あとhdcなんですが、どんな値を設定すればよいかさえも思いつきません。

    なら、あきらめますか?
    「思いつきません」と書くのは結構ですが、「そうですか」で返されたら終わりますよ。
    「素人」や「初心者」は免罪符にすらなりませんし、自分で調べられるようになることは今後開発を続けていく上で必要なスキルです。

    とりあえず、検索すると言うことを覚えていただく意味でも、「VB.NET HDC」あたりでも検索してみませんかね。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。

    2012年4月21日 15:36
    モデレータ
  • web内を探っているうちに、「vb中学校」なるものを見つけることが出来まして、そこでひろったものを参考にしてコードを思い切って書き改めました。

    今度はうまくいきました。 Azuleanさんの叱咤激励、感謝します。

    Imports System.Runtime.InteropServices
    Public Class Form1

       
        Private Declare Function ExtFloodFill Lib "gdi32" ( _
       ByVal hdc As IntPtr, _
       ByVal x As Integer, _
       ByVal y As Integer, _
       ByVal crColor As Integer, _
       ByVal wFillType As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean

        Private Const FLOODFILLBORDER As UInteger = 0   ' 境界色を目印にして塗りつぶすとき
        Private Const FLOODFILLSURFACE As UInteger = 1  ' 領域色を目印にして塗りつぶすとき(複数色の境界色で囲まれているときなど)

        '色を指定するためのブラシ作成関数
        Private Declare Function CreateBrushIndirect Lib "gdi32" (ByRef lpLogBrush As LOGBRUSH) As IntPtr
        '不要になったブラシの解放
        Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        'デバイスコンテキストの取得
        Private Declare Function GetWindowDC Lib "user32" (ByVal hwnd As IntPtr) As IntPtr
        'デバイスコンテキストの開放
        Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        '色を指定するために使う関数(ブラシのもちかえ)
        Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As IntPtr, _
            ByVal hObject As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean

        'CreateBrushIndirectに渡す引数の構造体
        Private Structure LOGBRUSH
            Public lbStyle As Integer
            Public lbColor As Integer
            Public lbHatch As Integer
        End Structure
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

        End Sub

        Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            Dim g As Graphics
            g = e.Graphics
            g.Clear(Color.White) '画面を真っ白に。

            '##############    3個の円を描く  ##############
            Dim x1 As Integer
            Dim x2 As Integer
            Dim x3 As Integer
            Dim y1 As Integer
            Dim y2 As Integer
            Dim y3 As Integer
            Dim cx1 As Integer
            Dim cx2 As Integer
            Dim cx3 As Integer
            Dim cy1 As Integer
            Dim cy2 As Integer
            Dim cy3 As Integer

            Dim r As Integer
            r = 70
            cx1 = 150
            cx2 = 100
            cx3 = 200
            cy1 = 100
            cy2 = 180
            cy3 = 180

            Dim mypen As New Pen(Color.Black, 4)
            x1 = cx1 - r
            y1 = cy1 - r
            x2 = cx2 - r
            y2 = cy2 - r
            x3 = cx3 - r
            y3 = cy3 - r
            g.DrawEllipse(mypen, x1, y1, r * 2, r * 2)
            g.DrawEllipse(mypen, x2, y2, r * 2, r * 2)
            g.DrawEllipse(mypen, x3, y3, r * 2, r * 2)
            '###############################################

            '###########    閉領域の一つをみどりで塗りつぶす  '#####

            Dim hwnd As IntPtr = Me.Handle              'フォームのハンドル
            Dim hdc As IntPtr = GetWindowDC(hwnd)       'デバイスコンテキスト
            Dim x As Integer
            Dim y As Integer
            Dim crColor As Integer = ColorTranslator.ToWin32(Color.FromArgb(255, 255, 255, 255)) 'System.Drawing.Colorをint型に変換する関数
            Dim wFillType As UInteger

            Dim hNewBrush As Integer
            Dim hOldBrush As Integer

            Dim NewBrush As LOGBRUSH

            x = cx1
            y = cy1


            wFillType = FLOODFILLSURFACE
            'ブラシの作成
            NewBrush.lbColor = ColorTranslator.ToWin32(Color.FromArgb(255, 0, 155, 0))
            NewBrush.lbStyle = 0
            NewBrush.lbHatch = 0
            hNewBrush = CreateBrushIndirect(NewBrush)
            'ブラシを持ち替える
            hOldBrush = SelectObject(hdc, hNewBrush)

            'ブラシの色で塗りつぶし
            ExtFloodFill(hdc, x, y, crColor, wFillType)
            '#########################################################
            '解放 これは必要なのかわからないけど念のため
            ReleaseDC(hwnd, hdc)                       'デバイスコンテキストを開放する
            hNewBrush = SelectObject(hdc, hOldBrush)   '元のブラシに戻す
            DeleteObject(hNewBrush)                     '不要になったブラシを開放する


        End Sub

    End Class

    2012年4月21日 17:12

すべての返信

  • >ExtFloodFill(hdc, x, y, crColor, wFillType)      ←ここがエラーになる。

    どんな?

    コンパイル時のエラーですか? それとも実行時?

    2012年4月20日 13:41
  • さっそくのレスありがとうございます。

    実行時にでてくるエラーです。

    箱のようなものの中にこう記載されてるんです

    PInvokeStackImbalanceが検出されました。

    PInvoke関数'閉領域塗りつぶし!閉領域塗りつぶし.Form1::ExtFloodFill'

    がスタックを不安定にしています。PInvokeシグネチャがアンマネージターゲット

    シグネチャに一致していないことが原因として考えられます。呼び出し規約、お

    よびPInvokeシグネチャのパラメーターがターゲットのアンマネージシグネチャ

    に一致していることを確認してください。

    2012年4月20日 14:48
  • >PInvokeStackImbalanceが検出されました。

    ということだと

    >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

    の宣言が間違っているか、使い方が間違っているか、あるいはその両方です。

    >ExtFloodFill(hdc, x, y, crColor, wFillType)      ←ここがエラーになる。

    で、hdc に値を設定しているコードが見当たりませんが、転記ミスですか?

    hdc に適切な値を設定しなければ、期待する動作は得られません。

    2012年4月21日 1:26
  • >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

    >の宣言が間違っているか、使い方が間違っているか、あるいはその両方です。

    これが使えないならもうお手上げです。ほかに良い記述方法が思いつきません。

    あとhdcなんですが、どんな値を設定すればよいかさえも思いつきません。

    2012年4月21日 8:55
  • 0これが使えないならもうお手上げです。ほかに良い記述方法が思いつきません。

    Win32API を使うのであれば、使うためのお作法があります。

    正攻法としては MSDN のページ でシグネチャを確認し、正しく型を対応させることです。
    HDC などのハンドルは IntPtr 型、int 型は Integer 型などです。
    正しい書き換えがわからないのであれば、関数名と「P/Invoke」と「Declare」あたりをキーワードをつければ見つけられるかもしれませんね。ただ、VB6 のコードは使えないので気をつけてください。

    あとhdcなんですが、どんな値を設定すればよいかさえも思いつきません。

    なら、あきらめますか?
    「思いつきません」と書くのは結構ですが、「そうですか」で返されたら終わりますよ。
    「素人」や「初心者」は免罪符にすらなりませんし、自分で調べられるようになることは今後開発を続けていく上で必要なスキルです。

    とりあえず、検索すると言うことを覚えていただく意味でも、「VB.NET HDC」あたりでも検索してみませんかね。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。

    2012年4月21日 15:36
    モデレータ
  • web内を探っているうちに、「vb中学校」なるものを見つけることが出来まして、そこでひろったものを参考にしてコードを思い切って書き改めました。

    今度はうまくいきました。 Azuleanさんの叱咤激励、感謝します。

    Imports System.Runtime.InteropServices
    Public Class Form1

       
        Private Declare Function ExtFloodFill Lib "gdi32" ( _
       ByVal hdc As IntPtr, _
       ByVal x As Integer, _
       ByVal y As Integer, _
       ByVal crColor As Integer, _
       ByVal wFillType As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean

        Private Const FLOODFILLBORDER As UInteger = 0   ' 境界色を目印にして塗りつぶすとき
        Private Const FLOODFILLSURFACE As UInteger = 1  ' 領域色を目印にして塗りつぶすとき(複数色の境界色で囲まれているときなど)

        '色を指定するためのブラシ作成関数
        Private Declare Function CreateBrushIndirect Lib "gdi32" (ByRef lpLogBrush As LOGBRUSH) As IntPtr
        '不要になったブラシの解放
        Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        'デバイスコンテキストの取得
        Private Declare Function GetWindowDC Lib "user32" (ByVal hwnd As IntPtr) As IntPtr
        'デバイスコンテキストの開放
        Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        '色を指定するために使う関数(ブラシのもちかえ)
        Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As IntPtr, _
            ByVal hObject As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean

        'CreateBrushIndirectに渡す引数の構造体
        Private Structure LOGBRUSH
            Public lbStyle As Integer
            Public lbColor As Integer
            Public lbHatch As Integer
        End Structure
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

        End Sub

        Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            Dim g As Graphics
            g = e.Graphics
            g.Clear(Color.White) '画面を真っ白に。

            '##############    3個の円を描く  ##############
            Dim x1 As Integer
            Dim x2 As Integer
            Dim x3 As Integer
            Dim y1 As Integer
            Dim y2 As Integer
            Dim y3 As Integer
            Dim cx1 As Integer
            Dim cx2 As Integer
            Dim cx3 As Integer
            Dim cy1 As Integer
            Dim cy2 As Integer
            Dim cy3 As Integer

            Dim r As Integer
            r = 70
            cx1 = 150
            cx2 = 100
            cx3 = 200
            cy1 = 100
            cy2 = 180
            cy3 = 180

            Dim mypen As New Pen(Color.Black, 4)
            x1 = cx1 - r
            y1 = cy1 - r
            x2 = cx2 - r
            y2 = cy2 - r
            x3 = cx3 - r
            y3 = cy3 - r
            g.DrawEllipse(mypen, x1, y1, r * 2, r * 2)
            g.DrawEllipse(mypen, x2, y2, r * 2, r * 2)
            g.DrawEllipse(mypen, x3, y3, r * 2, r * 2)
            '###############################################

            '###########    閉領域の一つをみどりで塗りつぶす  '#####

            Dim hwnd As IntPtr = Me.Handle              'フォームのハンドル
            Dim hdc As IntPtr = GetWindowDC(hwnd)       'デバイスコンテキスト
            Dim x As Integer
            Dim y As Integer
            Dim crColor As Integer = ColorTranslator.ToWin32(Color.FromArgb(255, 255, 255, 255)) 'System.Drawing.Colorをint型に変換する関数
            Dim wFillType As UInteger

            Dim hNewBrush As Integer
            Dim hOldBrush As Integer

            Dim NewBrush As LOGBRUSH

            x = cx1
            y = cy1


            wFillType = FLOODFILLSURFACE
            'ブラシの作成
            NewBrush.lbColor = ColorTranslator.ToWin32(Color.FromArgb(255, 0, 155, 0))
            NewBrush.lbStyle = 0
            NewBrush.lbHatch = 0
            hNewBrush = CreateBrushIndirect(NewBrush)
            'ブラシを持ち替える
            hOldBrush = SelectObject(hdc, hNewBrush)

            'ブラシの色で塗りつぶし
            ExtFloodFill(hdc, x, y, crColor, wFillType)
            '#########################################################
            '解放 これは必要なのかわからないけど念のため
            ReleaseDC(hwnd, hdc)                       'デバイスコンテキストを開放する
            hNewBrush = SelectObject(hdc, hOldBrush)   '元のブラシに戻す
            DeleteObject(hNewBrush)                     '不要になったブラシを開放する


        End Sub

    End Class

    2012年4月21日 17:12