投稿者 るきお  (社会人) 投稿日時 2012/2/12 18:45:21
直接の回答ではありません。

ExtFloodFillは誰にも使いこなせない意地悪な関数です。
VBの数々の高度な描画処理の中に採用されなかった理由もこの意地悪さに由来しているのかもしれません。
誰か、簡単でよいので塗りつぶし機能付きのお絵かきプログラムの作り方がわかる方は是非教えてください。

手段は2つあります。
手段1.ExtFloodFillでなんとかする。
手段2.塗りつぶしのロジックを自作する。

手段1については、下田の住人さんもExtFloodFillで描画するところまではできているのに、うまくほかの機能と調和が採れていませんよね?世間に公開されているサンプルでもExtFloodFill自体はなんとかできているものがありますが、望みどおりになるかは疑問があります。
参考:ExtFloodFill in VB.NET
http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=3977&lngWId=10

手段2の「塗りつぶしのロジックを自作」は試したことはありませんが、他の機能と調和させるという意味では有望だと思います。
参考:Flood Fill Algorithms in C# and GDI+
http://www.codeproject.com/Articles/5133/Flood-Fill-Algorithms-in-C-and-GDI
unsafeを使っているのでVBに翻訳するのは困難ですが、.NET言語同士の呼び出しは簡単なのでそのまま利用してVBから呼び出せばいいかもしれません。(私はダウンロードしていないので実際のところは不明です。)

さて、うまくはいきませんでしたが、私が手段1に挑戦してみた結果も載せておきます。
GDI+をほとんど使わず、GDIだけで処理すればなんとかなるのではないかと考えてみました。
Graphics.GetHdc~Graphics.ReleaseHdcの間で行う描画と塗りつぶしはうまくできました。
ただ、ReleaseHdcしないと画面には表示されないようで、目隠しされた状態でのお絵かきを強いられます。(Button2のクリックでReleaseHdcできるようにしておきました。)
また、GetHdc~ReleaseHdcの間を仮に「セッション」と呼ぶことにすると、別のセッションどうしはうまく連携してくれず、前のセッションで描画した線の中に、次のセッションで黄色く塗ろうとすると全体が黄色になってしまいます。
・ReleaseHdcしないでも表示が更新されるようにできれば、全体が1つのセッションになるので問題は解決できますが、その手段が不明です。
・複数セッションをまたいでお互いが連携できるようにしても問題は解決できますが、その手段が不明です。



Option Strict On

Public Class Form1

    Dim oldX, oldY As Integer
    Dim gdi As GDIWrapper

    Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load

        Dim baseImage As Bitmap = New Bitmap(PictureBox1.Width, PictureBox1.Height)
        PictureBox1.Image = baseImage
        gdi = New GDIWrapper(baseImage)

    End Sub

    Private Sub Form1_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        'gdi.Dispose() 
    End Sub

    Private Sub PictureBox1_MouseMove(ByVal sender As ObjectByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove

        If e.Button = System.Windows.Forms.MouseButtons.Left Then
            gdi.DrawLine(Pens.Green, oldX, oldY, e.X, e.Y)
        End If
        oldX = e.X
        oldY = e.Y
    End Sub

    Private Sub PictureBox1_MouseDown(ByVal sender As ObjectByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown

        If e.Button = System.Windows.Forms.MouseButtons.Right Then
            gdi.FloodFill(Color.Yellow, New Point(e.X, e.Y))
        End If
    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        gdi.Dispose()
        PictureBox1.Invalidate()
        gdi = New GDIWrapper(CType(PictureBox1.Image, Bitmap))

    End Sub

End Class


長いので分割します。