Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. C# Win API ExtFloodFill Issue

C# Win API ExtFloodFill Issue

Scheduled Pinned Locked Moved Clever Code
graphicscsharpalgorithmsregexjson
5 Posts 4 Posters 12 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Skippums
    wrote on last edited by
    #1

    I was having trouble using the ExtFloodFill operation to fill an area on a bitmap. Either, the code was setting my entire image to a specific color (using type == 0 for borderfill), or the call to ExtFloodFill returned false because the color I sent it didn't match the color of the background (for type == 1). After searching for about two hours, I finally found some obscure site that had an answer for me. I have copied the working c# code below. I still feel like I need to call DeleteObject for one of the brushes, but I'm not sure. If anyone can add insight to this code (as far a memory management or why I cannot use ExtFloodFill on the DC retrieved from the graphics object), please do so. [DllImport("gdi32.dll")] private static bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop); [DllImport("gdi32.dll")] private static IntPtr CreateCompatibleDC(IntPtr hdc); [DllImport("gdi32.dll")] private static IntPtr CreateSolidBrush(int color); [DllImport("gdi32.dll")] private static bool DeleteDC(IntPtr hdc); [DllImport("gdi32.dll")] private static bool ExtFloodFill(IntPtr hdc, int x, int y, int color, uint type); [DllImport("gdi32.dll")] private static IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj); private static int ToRGB(Color c) { return (c.B << 16) | (c.G << 8) | c.R; } public enum TRO : uint { BLACKNESS = 0x00000042, NOTSRCERASE = 0x001100A6, NOTSRCCOPY = 0x00330008, SRCERASE = 0x00440328, DSTINVERT = 0x00550009, PATINVERT = 0x005A0049, SRCINVERT = 0x00660046, SRCAND = 0x008800C6, MERGEPAINT = 0x00BB0226, MERGECOPY = 0x00C000CA, SRCCOPY = 0x00CC0020, SRCPAINT = 0x00EE0086, PATCOPY = 0x00F00021, PATPAINT = 0x00FB0A09, WHITENESS = 0x00FF0062, CAPTUREBLT = 0x40000000, NOMIRRORBITMAP = 0x80000000, } public static bool FloodFill(Bitmap bitmap, Location location, Color backColor, color fillColor) { Graphics g = null; IntPtr hdc1 = IntPtr.Zero, hdc2 = IntPtr.Zero, oldBrush = IntPtr.Zero; try { g = Graphics.FromImage(bitmap); hdc1 = g.GetHDC(); hdc2 = CreateCompatibleDC(hdc1); SelectObject(hdc2, bitmap.GetHbitmap()); IntPtr newBrush = CreateSolidBrush(ToRGB(fillColor)); oldBrush = SelectObject(hdc2, newBrush); if (ExtFloodFill(hdc2, location.X, location.Y, ToRGB(backCo

    D G 2 Replies Last reply
    0
    • S Skippums

      I was having trouble using the ExtFloodFill operation to fill an area on a bitmap. Either, the code was setting my entire image to a specific color (using type == 0 for borderfill), or the call to ExtFloodFill returned false because the color I sent it didn't match the color of the background (for type == 1). After searching for about two hours, I finally found some obscure site that had an answer for me. I have copied the working c# code below. I still feel like I need to call DeleteObject for one of the brushes, but I'm not sure. If anyone can add insight to this code (as far a memory management or why I cannot use ExtFloodFill on the DC retrieved from the graphics object), please do so. [DllImport("gdi32.dll")] private static bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop); [DllImport("gdi32.dll")] private static IntPtr CreateCompatibleDC(IntPtr hdc); [DllImport("gdi32.dll")] private static IntPtr CreateSolidBrush(int color); [DllImport("gdi32.dll")] private static bool DeleteDC(IntPtr hdc); [DllImport("gdi32.dll")] private static bool ExtFloodFill(IntPtr hdc, int x, int y, int color, uint type); [DllImport("gdi32.dll")] private static IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj); private static int ToRGB(Color c) { return (c.B << 16) | (c.G << 8) | c.R; } public enum TRO : uint { BLACKNESS = 0x00000042, NOTSRCERASE = 0x001100A6, NOTSRCCOPY = 0x00330008, SRCERASE = 0x00440328, DSTINVERT = 0x00550009, PATINVERT = 0x005A0049, SRCINVERT = 0x00660046, SRCAND = 0x008800C6, MERGEPAINT = 0x00BB0226, MERGECOPY = 0x00C000CA, SRCCOPY = 0x00CC0020, SRCPAINT = 0x00EE0086, PATCOPY = 0x00F00021, PATPAINT = 0x00FB0A09, WHITENESS = 0x00FF0062, CAPTUREBLT = 0x40000000, NOMIRRORBITMAP = 0x80000000, } public static bool FloodFill(Bitmap bitmap, Location location, Color backColor, color fillColor) { Graphics g = null; IntPtr hdc1 = IntPtr.Zero, hdc2 = IntPtr.Zero, oldBrush = IntPtr.Zero; try { g = Graphics.FromImage(bitmap); hdc1 = g.GetHDC(); hdc2 = CreateCompatibleDC(hdc1); SelectObject(hdc2, bitmap.GetHbitmap()); IntPtr newBrush = CreateSolidBrush(ToRGB(fillColor)); oldBrush = SelectObject(hdc2, newBrush); if (ExtFloodFill(hdc2, location.X, location.Y, ToRGB(backCo

      D Offline
      D Offline
      darkelv
      wrote on last edited by
      #2

      I believe the forum is Subtle Bugs not Submit Bugs. :-D

      S 1 Reply Last reply
      0
      • D darkelv

        I believe the forum is Subtle Bugs not Submit Bugs. :-D

        S Offline
        S Offline
        Skippums
        wrote on last edited by
        #3

        I didn't post this necessarily looking for an answer as to whether I need to delete the brush. The purpose of posting this is so when people search for ExtFloodFill, they can easily find out what needs to be done to get around the fact that the DC created from the graphics object cannot be used by this method. I only asked about the brush so that future users of the code can ensure on their own that there are no memory leaks, instead of copying the code verbatim. Jeff

        1 Reply Last reply
        0
        • S Skippums

          I was having trouble using the ExtFloodFill operation to fill an area on a bitmap. Either, the code was setting my entire image to a specific color (using type == 0 for borderfill), or the call to ExtFloodFill returned false because the color I sent it didn't match the color of the background (for type == 1). After searching for about two hours, I finally found some obscure site that had an answer for me. I have copied the working c# code below. I still feel like I need to call DeleteObject for one of the brushes, but I'm not sure. If anyone can add insight to this code (as far a memory management or why I cannot use ExtFloodFill on the DC retrieved from the graphics object), please do so. [DllImport("gdi32.dll")] private static bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop); [DllImport("gdi32.dll")] private static IntPtr CreateCompatibleDC(IntPtr hdc); [DllImport("gdi32.dll")] private static IntPtr CreateSolidBrush(int color); [DllImport("gdi32.dll")] private static bool DeleteDC(IntPtr hdc); [DllImport("gdi32.dll")] private static bool ExtFloodFill(IntPtr hdc, int x, int y, int color, uint type); [DllImport("gdi32.dll")] private static IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj); private static int ToRGB(Color c) { return (c.B << 16) | (c.G << 8) | c.R; } public enum TRO : uint { BLACKNESS = 0x00000042, NOTSRCERASE = 0x001100A6, NOTSRCCOPY = 0x00330008, SRCERASE = 0x00440328, DSTINVERT = 0x00550009, PATINVERT = 0x005A0049, SRCINVERT = 0x00660046, SRCAND = 0x008800C6, MERGEPAINT = 0x00BB0226, MERGECOPY = 0x00C000CA, SRCCOPY = 0x00CC0020, SRCPAINT = 0x00EE0086, PATCOPY = 0x00F00021, PATPAINT = 0x00FB0A09, WHITENESS = 0x00FF0062, CAPTUREBLT = 0x40000000, NOMIRRORBITMAP = 0x80000000, } public static bool FloodFill(Bitmap bitmap, Location location, Color backColor, color fillColor) { Graphics g = null; IntPtr hdc1 = IntPtr.Zero, hdc2 = IntPtr.Zero, oldBrush = IntPtr.Zero; try { g = Graphics.FromImage(bitmap); hdc1 = g.GetHDC(); hdc2 = CreateCompatibleDC(hdc1); SelectObject(hdc2, bitmap.GetHbitmap()); IntPtr newBrush = CreateSolidBrush(ToRGB(fillColor)); oldBrush = SelectObject(hdc2, newBrush); if (ExtFloodFill(hdc2, location.X, location.Y, ToRGB(backCo

          G Offline
          G Offline
          Guillaume Leparmentier
          wrote on last edited by
          #4

          Try this [DllImport("gdi32.dll", SetLastError = true)] public static extern bool DeleteObject(IntPtr hObject); public static uint FLOODFILLBORDER = 0; public static uint FLOODFILLSURFACE = 1; public static bool FloodFill(Bitmap bitmap, Location location, Color backColor, color fillColor) { bool succeed = false; using (Graphics ig = Graphics.FromImage(bitmap)) // ig point to your bitmap { IntPtr hdc1 = IntPtr.Zero, hdc2 = IntPtr.Zero; IntPtr hBitmap, hBrush, prevBrush; try { // the DC is your bitmap, so you don't need to select it hdc1 = ig.GetHdc(); // create your brush with "fillColor" hBrush = CreateSolidBrush( ColorTranslator.ToWin32(fillColor) ); // set your brush into the DC prevBrush = SelectObject(hdc1, hBrush); // fill the bitmap area with "backColor" succeed = ExtFloodFill(hdc1, location.X, location.Y, ColorTranslator.ToWin32(backColor), FLOODFILLSURFACE); // restore the previous brush SelectObject(hdc1, prevBrush); // delete your brush (memory usage) DeleteObject(hBrush); if (succeed) { hdc2 = CreateCompatibleDC(hdc1); succeed = BitBlt(hdc1, 0, 0, bitmap.Width, bitmap.Height, hdc2, 0, 0, (int)TRO.SRCCOPY); DeleteDC(hdc2); } } finally { if (IntPtr.Zero != hdc1) ig.ReleaseHdc(hdc1); } } return succeed; } You should use SetLastError = true in your p-invoke function sig, and then call int errorCode = Marshal.GetLastError() to know if the function succeed (and if not, you have the win32 error). Hope this helps, G.

          R 1 Reply Last reply
          0
          • G Guillaume Leparmentier

            Try this [DllImport("gdi32.dll", SetLastError = true)] public static extern bool DeleteObject(IntPtr hObject); public static uint FLOODFILLBORDER = 0; public static uint FLOODFILLSURFACE = 1; public static bool FloodFill(Bitmap bitmap, Location location, Color backColor, color fillColor) { bool succeed = false; using (Graphics ig = Graphics.FromImage(bitmap)) // ig point to your bitmap { IntPtr hdc1 = IntPtr.Zero, hdc2 = IntPtr.Zero; IntPtr hBitmap, hBrush, prevBrush; try { // the DC is your bitmap, so you don't need to select it hdc1 = ig.GetHdc(); // create your brush with "fillColor" hBrush = CreateSolidBrush( ColorTranslator.ToWin32(fillColor) ); // set your brush into the DC prevBrush = SelectObject(hdc1, hBrush); // fill the bitmap area with "backColor" succeed = ExtFloodFill(hdc1, location.X, location.Y, ColorTranslator.ToWin32(backColor), FLOODFILLSURFACE); // restore the previous brush SelectObject(hdc1, prevBrush); // delete your brush (memory usage) DeleteObject(hBrush); if (succeed) { hdc2 = CreateCompatibleDC(hdc1); succeed = BitBlt(hdc1, 0, 0, bitmap.Width, bitmap.Height, hdc2, 0, 0, (int)TRO.SRCCOPY); DeleteDC(hdc2); } } finally { if (IntPtr.Zero != hdc1) ig.ReleaseHdc(hdc1); } } return succeed; } You should use SetLastError = true in your p-invoke function sig, and then call int errorCode = Marshal.GetLastError() to know if the function succeed (and if not, you have the win32 error). Hope this helps, G.

            R Offline
            R Offline
            rnbguy
            wrote on last edited by
            #5

            hi, i am curious how you went with this, i keep getting false from ExtFloodFill

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups