Click here to Skip to main content
15,867,594 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
How am I supposed to draw the rectangles colored? My task is to draw different color rectangles with the left mouse button and add them to the vector. (and the right button to drag them)

The drawing works fine, but I don't know how to make them random colors.

What I have tried:

POINT LeftButtonDown;
POINT ptCurrent;
POINT ptClicked;
vector<CRect> vRect;
bool isRubberBand = false;
bool IsClicked(CRect r, int x, int y);

void select(HWND hWnd, CRect r);
void deselect(HWND hWnd, CRect r);
void DrawRubberBand(HWND hWnd);
void MoveFromTo(HDC hdc, CRect& rectSelected, POINTS anchor, POINTS now);

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    CRect add;
    static CRect rectSelected;
    TCHAR s[100] = L"";
    HDC             hdc;
    static POINTS   anchor;

    switch (message)
    {
    case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    break;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code that uses hdc here...
        for (auto& rc : vRect)
        {
            Rectangle(hdc,
                rc.left,
                rc.top,
                rc.right,
                rc.bottom
            );
        }
        EndPaint(hWnd, &ps);
    }
    break;

    case WM_LBUTTONDOWN:
    {
        LeftButtonDown.x = LOWORD(lParam); //Start point
        LeftButtonDown.y = HIWORD(lParam);

        isRubberBand = true;

        ptCurrent.x = LOWORD(lParam); //current point
        ptCurrent.y = HIWORD(lParam);

        DrawRubberBand(hWnd); //draw the rect
    }
    break;

    case WM_LBUTTONUP: // adding to a vector
    {
        if (!isRubberBand)
        {
            return 0;
        }
        isRubberBand = false;

        //InvalidateRect(hWnd, NULL, TRUE);
        add.SetRect(LeftButtonDown.x, LeftButtonDown.y, ptCurrent.x, ptCurrent.y); //setting the coords of the rect
        vRect.push_back(add); //add the rect
        UpdateWindow(hWnd);
    }
    break;

    case WM_MOUSEMOVE:

        if (wParam & MK_LBUTTON) //drawing the rectangle
        {
            hdc = GetDC(hWnd);
            if (!isRubberBand)
            {
                break;
            }
            DrawRubberBand(hWnd);

            ptCurrent.x = LOWORD(lParam);
            ptCurrent.y = HIWORD(lParam);

            DrawRubberBand(hWnd);

        }
        if (wParam & MK_RBUTTON) //dragging the rectangle
        {
            hdc = GetDC(hWnd);
            POINTS now = MAKEPOINTS(lParam);
            if (PtInRect(&rectSelected, POINT{ now.x,now.y }))
            {
                SetROP2(hdc, R2_NOTXORPEN);
                MoveFromTo(hdc, rectSelected, anchor, now);
                InvalidateRect(hWnd, NULL, TRUE);
                anchor = MAKEPOINTS(lParam);
            }

            ReleaseDC(hWnd, hdc);
        }
        break;

    case WM_RBUTTONDOWN:
    {
        bool isFind = false;
        int x{ LOWORD(lParam) }, y{ HIWORD(lParam) };
        for (auto& rc : vRect)
        {
            if (!isFind && IsClicked(rc, x, y))
            {
                select(hWnd, rc);
                rectSelected = rc;
                anchor = MAKEPOINTS(lParam);
                isFind = TRUE;
            }
            else {
                deselect(hWnd, rc);
            }
        }
        //select-deselect
    }
    break;
    case WM_RBUTTONUP:
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}


bool IsClicked(CRect r, int x, int y)
{
    POINT pt{ x, y };
    return (bool)PtInRect(&r, pt);
}
void select(HWND hWnd, CRect r) {
    HDC hdc = GetDC(hWnd);
    HPEN selectPen = CreatePen(PS_DOT, 0, RGB(255, 0, 0));
    SelectObject(hdc, selectPen);
    Rectangle(hdc, r.left, r.top, r.right, r.bottom);
    DeleteObject(selectPen);
}
void deselect(HWND hWnd, CRect r) {
    HDC hdc = GetDC(hWnd);
    Rectangle(hdc, r.left, r.top, r.right, r.bottom);
}

void DrawRubberBand(HWND hWnd) {
    HDC hdc = GetDC(hWnd);

    SetROP2(hdc, R2_NOT);
    SelectObject(hdc, GetStockObject(NULL_BRUSH));
    Rectangle(hdc,
        LeftButtonDown.x,
        LeftButtonDown.y,
        ptCurrent.x,
        ptCurrent.y
    );
    ReleaseDC(hWnd, hdc);
}
void MoveFromTo(HDC hdc, CRect& rectSelected, POINTS anchor, POINTS now)
{
    Rectangle(hdc, rectSelected.left, rectSelected.top, rectSelected.right, rectSelected.bottom);
    for (auto it = vRect.begin(); it != vRect.end(); it++)
    {
        if (*it == rectSelected)
        {
            vRect.erase(it);
            break;
        }
    }
    rectSelected.left = rectSelected.left + now.x - anchor.x; //x
    rectSelected.top = rectSelected.top + now.y - anchor.y;    //y
    rectSelected.right = rectSelected.right + now.x - anchor.x; //x
    rectSelected.bottom = rectSelected.bottom + now.y - anchor.y; //y
    Rectangle(hdc, rectSelected.left, rectSelected.top, rectSelected.right, rectSelected.bottom);
    vRect.push_back(rectSelected);
}
Posted
Updated 4-Dec-20 5:13am
Comments
CHill60 4-Dec-20 8:08am    
Are you asking how to colour the rectangles or how to select random colours?
Member 14980346 4-Dec-20 11:31am    
I am asking how to color them because in order to draw them I am using RubberBanding
(I don't know if this matters..) I have been told that I need to use a bitmap, but I don't know how to work with it.

1 solution

Create a coloured Pen object and select that into the device context before you draw the rectangle. See Windows GDI - Win32 apps | Microsoft Docs[^].
 
Share this answer
 
Comments
Member 14980346 4-Dec-20 11:33am    
Either I don't know where to create the pen, or it doesn't work.
Richard MacCutchan 4-Dec-20 11:39am    
If you follow the link and select the Pens item in the menu at left, you will most likely find a sample that shows how to do it.
Richard MacCutchan 4-Dec-20 11:44am    
Trying to do all that drawing outside of your WM_PAINT handler will not work. You need to set the various parameters in your keyboard handler and then use InvalidateRect to schedule a repaint. Then in the WM_PAINT handler you should use the various settings to preform your drawings. Take a look at EFNet #Winprog[^] for tutorials on how to write Windows compliant code.
CPallini 4-Dec-20 14:34pm    
5.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900