ExtFloodFill with custom scaling

William Kandler 1 Reputation point
2021-07-10T19:17:38.12+00:00

I'm filling irregular shapes with solid colors and my desired coord system is centered origin. I can make this work by setting scaleheight/width to max dimension of picturebox and computing offset=maxdimension/2. But this means every point must be specified as x+offest/y+offset; rather messy.

I can set up for 0/0 centered in pic via

dest.ScaleMode = vbInches 'here's the key; picture's scale mode is inches

dest.ScaleWidth = MaxDimension
dest.ScaleLeft = -dest.ScaleWidth / 2

dest.ScaleHeight = MaxDimension
dest.ScaleTop = -dest.ScaleHeight / 2

But extfloodfill cannot locate the proper fill point(fills from wrong point).

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,585 questions
{count} votes

8 answers

Sort by: Most helpful
  1. William Kandler 6 Reputation points
    2021-07-23T19:49:11.947+00:00

    I have located and fixed my problem. The scalex and scaley functions do not function properly when changing coordinate systems. They only handle simple scaling., Thus, when floodfill and scale(-2.5,-2.5)-(2.5,2.5) come together and you use

    Sub ScaleToPixels(Pic As PictureBox, inp As ObjPt, outv As ObjPt)
    With inp
    outv.x = Pic.ScaleX(.x, Pic.ScaleMode, vbPixels)
    outv.y = Pic.ScaleY(-.y, Pic.ScaleMode, vbPixels)
    End With
    End Sub

    to give floodfill its starting point in pixels, it gives you the scale(-2.5,-2.5)-(2.5,2.5) coordinate system you specified instead of scale(0,0)-(maxx,maxy) that floodfill requires. So you have to something like this.

    Sub ScaleToPixels(Pic As PictureBox, inp As ObjPt, outv As ObjPt)
    With inp
    outv.x = 238 + Pic.ScaleX(.x, Pic.ScaleMode, vbPixels)
    outv.y = 238 - Pic.ScaleY(-.y, Pic.ScaleMode, vbPixels)
    End With
    End Sub

    238 is the mid-point pixel for my case.

    1 person found this answer helpful.
    0 comments No comments

  2. Xiaopo Yang - MSFT 12,721 Reputation points Microsoft Vendor
    2021-07-13T01:40:00.57+00:00

    It's prefer to use WinAPI to set the origin at the center.
    Such As:

    void SetIsotropic(HDC hdc, int cxClient,int xyClient)
    {
     SetMapMode(hdc,MM_ISOTROPIC);
     SetWindowExtEx(hdc,1000,1000,NULL);
     SetViewportExtEx(hdc, cxClient / 2,-xyClient / 2,NULL);
     SetViewportOrgEx(hdc, cxClient / 2, xyClient / 2, NULL);
    }
    

    The previous code Need more care to use.
    And Then perhaps ExtFloodFill will have normal behavior.

    0 comments No comments

  3. William Kandler 1 Reputation point
    2021-07-13T23:42:40.12+00:00

    my test is a 3000x3000 twips picturebox. Here is what I've tried for a working space of +-2.5 with the origin at 0,0 in the center of the box:

    SetMapMode Pic2.hdc, MM_ISOTROPIC
    SetWindowExtEx Pic2.hdc, 3000, 3000, 3000
    SetViewportExtEx Pic2.hdc, 2.5, -2.5, 2.5
    SetViewportOrgEx Pic2.hdc, -2.5, -2.5, PointOf(0, 0)

    Pic.ScaleX(X/Y, Pic.ScaleMode, vbPixels) is then used to get the starting point for floodfill.

    For -2.5/-2.5 it ought to give 0/0 and for 2.5/2.5 it ought to give 200/200, but actually results in -97/-97 and 97/97.

    0 comments No comments

  4. Xiaopo Yang - MSFT 12,721 Reputation points Microsoft Vendor
    2021-07-14T07:02:16.173+00:00

    After Testing, I found There is no problem on ExtFloodFill. As far as the following code concerned, The ExtFloodFill interpreted coordinate correctly.

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
    {  
        switch (message)  
        {  
        case WM_PAINT:  
            {  
                PAINTSTRUCT ps;  
                HDC hdc = BeginPaint(hWnd, &ps);  
                // TODO: Add any drawing code that uses hdc here...  
     RECT rc{};  
      
     GetClientRect(hWnd, &rc);  
     SetMapMode(hdc, MM_ANISOTROPIC);  
     SetWindowExtEx(hdc, 100, 100, NULL);  
     SetViewportExtEx(hdc, rc.right / 2, -rc.bottom / 2, NULL);  
     SetViewportOrgEx(hdc, rc.right / 2, rc.bottom / 2, NULL);  
      
     POINT aptTriangle[] = { 0,50, 100,0,  0,-99, -25,0, 0,50 };  
     Polyline(hdc, aptTriangle, ARRAYSIZE(aptTriangle));  
      
     HBRUSH hBrush = CreateHatchBrush(HS_DIAGCROSS, RGB(0, 0, 255));  
     // ' Select it for use in Form1, noting the previous brush.  
     HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);  
     BOOL retval = FALSE;  
     // ' Flood fill the area outside the ellipse (use a green boundary)  
     retval = ExtFloodFill(hdc, 10, 10, Color::Black, FLOODFILLBORDER);//Picture 1  
     //retval = ExtFloodFill(hdc, 0, 51, Color::Black, FLOODFILLBORDER);//Picture 2  
      
     // ' Select the previously selected pen and brush.  
     SelectObject(hdc, hOldBrush);  
     // ' Delete the pen and brush to free up resources.  
     retval = DeleteObject(hBrush);  
                EndPaint(hWnd, &ps);  
            }  
            break;  
        case WM_DESTROY:  
            PostQuitMessage(0);  
            break;  
        default:  
            return DefWindowProc(hWnd, message, wParam, lParam);  
        }  
        return 0;  
    }  
    

    114474-image.png
    114475-image.png

    0 comments No comments

  5. William Kandler 1 Reputation point
    2021-07-14T18:47:29.167+00:00

    I write my question in vb; you answer in incomplete C.

    You specify:
    SetWindowExtEx(hdc, 100, 100, NULL);
    SetViewportExtEx(hdc, rc.right / 2, -rc.bottom / 2, NULL);
    SetViewportOrgEx(hdc, rc.right / 2, rc.bottom / 2, NULL);

    my obj is a 3000x3000 twits picturebox and my user coord. system is -2.5/-2.5 -> 2.5/2.5; so I should say?:

    SetWindowExtEx hdc, 3000, 3000, NULL
    SetViewportExtEx hdc, 2.5, -2.5, NULL
    SetViewportOrgEx hdc, 2.5, 2.5, NULL

    You then dispay using:
    POINT aptTriangle[] = { 0,50, 100,0, 0,-99, -25,0, 0,50 };
    Polyline(hdc, aptTriangle, ARRAYSIZE(aptTriangle));

    I can't draw my circle using inches at 0/0 with a radius of 2.5 with this code. that (as I originally stated) requires:

    dest.ScaleMode = vbInches

    dest.ScaleWidth = MaxDimension
    dest.ScaleLeft = -dest.ScaleWidth / 2

    dest.ScaleHeight = MaxDimension
    dest.ScaleTop = -dest.ScaleHeight / 2

    Then you fill via:

    retval = ExtFloodFill(hdc, 10, 10, Color::Black, FLOODFILLBORDER)

    My equivalent for center fill is:

    rtn = ExtFloodFill(dest.hDC, 0,0, 0, FLOODFILLBORDER)

    This fills, but not from the CENTER


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.