投稿者 yamada  (社会人) 投稿日時 2010/7/30 13:52:34
ありがとうございます。
まず、ByValをByRef指定に変えたところエラーが出なくなりました。QuickBASICをやったことがあるのでこれはわかりました。
ところが実行しても何も起こらないので、もう一度よくサンプルを見てみるとExtFloodFillやSelectObjectは、ハンドルを渡すのではなくデバイスコンテキストなるものを渡すのだとわかりました。
VB2008でAPIを使うのは初めてでVB6も未経験なので、デバイスコンテキストとか何のことかよくわかりませんがとりあえずこうすればできるというのはわかったのでやってみました。
すると塗りつぶしはされるようになりましたが、色が必ず白で塗られるので、この時点で魔界の弁護士さんのご指摘に気付きました。(CreatePenIndirectがブラシへのハンドルを返す)

一応目的とすることはできたので解決とします。ピクチャーボックスに描いたクロスステッチやコッホ島内部の塗りつぶしもできました。
シード・フィル アルゴリズムについては宿題ということで。
なんというか、もっと単純な問題だと思っていたのに意外と大変だったので助かりました。
調べてみてわかったのは、この塗りつぶしというのは結構いろいろなところで質問されていてよくある質問なのかもしれません。VB2008で解決する方法はみつからなかったので、同じような疑問を持った方の解決の助けになるかと思い、長く重複していますが、一応できたのを再掲しておきます。
'フォームに図形を描いて、Windowsのペイントのように塗りつぶすサンプル 
Imports System.Runtime.InteropServices
'↑MarshalAs属性を使用するには必要みたいです 

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 UIntegerAs <MarshalAs(UnmanagedType.Bool)> Boolean


    'hdc            塗りつぶしを行うデバイスハンドル / 正しくはデバイスコンテキスト 
    'x              塗りつぶしを行う開始座標(x) 
    'y              塗りつぶしを行う開始座標(y) 
    'crColor        塗りつぶしを行う対象色 or 境界線色 
    'wFillType      塗りつぶしモードフラグ 

    ' 塗りつぶしモードフラグ 
    Public Const FLOODFILLBORDER As UInteger = 0UI
    ' crColorの色の境界線色まで塗りつぶしなさいモード  
    Public Const FLOODFILLSURFACE As UInteger = 1UI
    ' crColorの色の部分を塗りつぶしなさいモード  

    '色を指定するためのブラシ作成関数 
    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 IntegerAs <MarshalAs(UnmanagedType.Bool)> Boolean

    'CreateBrushIndirectに渡す引数の構造体 
    Private Structure LOGBRUSH
        Public lbStyle As Integer
        Public lbColor As Integer
        Public lbHatch As Integer
    End Structure

    Private Sub Button1_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles Button1.Click
        Dim g As Graphics = Me.CreateGraphics

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

        Dim wFillType As UInteger = FLOODFILLBORDER '赤まで塗りつぶせモード 

        Dim hNewBrush As Integer
        Dim hOldBrush As Integer
        Dim NewBrush As LOGBRUSH

        g.Clear(Me.BackColor)
        g.DrawRectangle(Pens.Red, 100, 100, 100, 100)   '赤で四角を描く 

        'ブラシの作成  
        NewBrush.lbColor = ColorTranslator.ToWin32(Color.Blue)
        NewBrush.lbStyle = 0
        NewBrush.lbHatch = 0
        hNewBrush = CreateBrushIndirect(NewBrush)

        'ブラシを持ち替える  
        hOldBrush = SelectObject(hwdc, hNewBrush)
        'ブラシの色で塗りつぶし 
        ExtFloodFill(hwdc, x, y, crcolor, wFillType)

        '解放 これは必要なのかわからないけど念のため 
        ReleaseDC(hwnd, hwdc)                       'デバイスコンテキストを開放する 
        hNewBrush = SelectObject(hwdc, hOldBrush)   '元のブラシに戻す 
        DeleteObject(hNewBrush)                     '不要になったブラシを開放する 

    End Sub
End Class