ウ”~、分かりません。苦”るじい~。前回触れましたが、テストしてみるとEaselのPaintメソッドの動作が異常です。仕様はCANVASと同じく、指定位置の色が連続して続く領域を指定色で塗りつぶすはずなのですが、

(EZImage.exe)

テストしてみるとEasel.Canvas全体が塗りつぶされてしまいます。

なんで???どして???

 

The story is that ... 最初、webで色々と調べ、どうもC#にはBasicの"Paint"命令のような、「任意の色で、任意の位置から塗りつぶす」メソッドがないことが分かりました。(注)

注:Win32 APIにはExFloodFill(HDC, int, int, COLORREF, uint)という関数があり、私のEZImageではこれを使っています。(21年前のTBEditorではこのExFloodFillはおろか、FloodFill関数も知らず、Fuzzy氏のアルゴリズムをもとに独自コーディングしています。)

 

従って道は二つ、独自にCでデコーディングするか、Win32を使うか、です。前者はトライされた方も多いのですが、コードが結構長いので安きに流されて後者を選択し、C#でExFloodFillを使う例を調べました。以下が当初のEaselのコードの関連部分です。

 

using System.Runtime.InteropServices;    //ExtFloodFill関数を使用する為

        [DllImport("gdi32.dll")]
        static extern bool ExtFloodFill(IntPtr hdc, int nXStart, int nYStart, uint crColor, uint fuFillType);

        //指定色で塗潰す
        public bool Paint(int x, int y, Color col)
        {
            bool result = false;    //戻り値変数
            IntPtr hDC = gHandle.GetHdc();    //gHandleはEasel.Canvas(Imageクラスオブジェクト)のGraphicsです。
            IntPtr hBrush = CreateSolidBrush((uint)ColorTranslator.ToWin32(col));    //colで塗りつぶすブラシを作成
            IntPtr hOldBrush = SelectObject(hDC, hBrush);    //塗りつぶしブラシを選択し、既存ブラシをhOldBrushに保存
            //hDC内の(x, y)位置のピクセル色をGetPixelで取得し、その色が連続する領域を塗りつぶす

            result = ExtFloodFill(hDC, x, y, GetPixel(hDC, x, y), 1);    //"#define  FLOODFILLSURFACE  1" in wingdi.h
            SelectObject(hDC, hOldBrush);    //ブラシを既存のものに戻す
            DeleteObject(hBrush);    //作成した塗りつぶしブラシを開放する
            gHandle.ReleaseHdc(hDC);    //取得したDCハンドルを開放する
            return result;
        }

 

一見よさげなコードなんですが、結果は↑の通り。(青で矩形を描き、その中を赤で塗りつぶそうとしたので、本来であれば少なくとも青の矩形は残るはずなのだが、完全に塗りつぶされている=与えられたデバイスコンテキストが無地になっている?)

 

チェックは以下の要領で行いました。

 

(1)指定位置のピクセル色取得値はが正しいか?

これは背景色を黒(ARGB = 0)にして、gdiplus.dllのGetPixel(Win32 API)とC#の(uint)ColorTranslator.ToWin32(Canvas.GetPixel())でチェックしてみました。すると、

Win32では789261(0x0C0B0D)、C#(0x000000)となり、C#の方が正しいように思えます。(描画色はColor.Blueなので0x0000FF)

 

(2)デバイスコンテキストは正しいか?

EaselクラスインスタンスのImageクラスインスタンスであるCanvasから取得したグラフィックス(gHandle)と、ピクチャーボックス(picBox)のImageプロパティから取得したグラフィックスを取得し、それぞれのDC値をとって対比すると、

これは全く同じですね。

 

しかし、いくらいじっても結果は総て塗りつぶされる(GetPixel(Win32 API))か、全く描画しない((uint)ColorTranslator.ToWin32(Canvas.GetPixel()))か、のいずれかで、もういじるところがなくなってしまいました。

 

矢張りExFloodFillを諦めて、独自コードで塗りつぶしを行うべきなのでしょうかね?(面倒だけど。)