Очистка нарисованного прямоугольника

#c #api #winapi #gdi

#c #API #winapi #gdi

Вопрос:

Как я могу очистить определенный прямоугольник? Я отображаю круги и текст внутри каждого круга (вывод текста) в окне. Я пытаюсь реализовать это так, чтобы при нажатии левой кнопки мыши на определенный круг круг и текст исчезали, то есть очищать прямоугольник, в котором расположены круг и текст.

скриншот программы

 #include <windows.h>; 
#include <ctime>
#include <cmath>

struct Cell {
    int x, y;
    struct rgb {
        int r, g, b,z;
    }
    mainColor,
    borderColor,
    circleColor,
    textColor,
    circleSize, 
    circleBorderColor;  
};

HWND hWnd;
HDC hdc;
HPALETTE hPal;
BOOL bForceBkgd;
COLORREF color;
HBRUSH brush;

const int rectSize = 90;
const int circleSize = 40;

int y = 0, x = 0, yCoord, xCoord;
char buf[50];

bool flag = 0;
Cell cells[7][7];
HINSTANCE hInst; //Дескриптор програми
LPCTSTR szWindowClass = "QWERTY";
LPCTSTR szTitle = "  ";
// Попередній опис функцій
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

bool isInCircle(int x, int y, int x0, int y0, int R) {
    if (pow((x - x0), 2)   pow((y - y0), 2) <= pow(R, 2)) {
        return true;
    }
    return false;
}

// main program
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    srand(time(NULL));

    MSG msg;
    // window class register
    MyRegisterClass(hInstance);
    // creating a program window
    if (!InitInstance(hInstance, nCmdShow))
    {
        return FALSE;
    }
    // messages processing cycle
    while (GetMessage(amp;msg, NULL, 0, 0))
    {
        TranslateMessage(amp;msg);
        DispatchMessage(amp;msg);
    }
    return msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW; 
    wcex.lpfnWndProc = (WNDPROC)WndProc; 
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance; 
    wcex.hIcon = LoadIcon(NULL, IDI_SHIELD); 
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wcex.hbrBackground = GetSysColorBrush(COLOR_WINDOW   3); 
    wcex.lpszMenuName = NULL; 
    wcex.lpszClassName = szWindowClass; 
    wcex.hIconSm = NULL;
    return RegisterClassEx(amp;wcex); 
}

// FUNCTION: InitInstance (HANDLE, int)

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    HWND hWnd;
    hInst = hInstance; 
    hWnd = CreateWindow(szWindowClass, // window class name
        szTitle, // program name
        WS_OVERLAPPED | WS_SYSMENU, 
        400, // position on x
        0, // position on y
        718, 
        790, 
        NULL, 
        NULL,
        hInstance, 
        NULL); 
    if (!hWnd) 
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow); 
    UpdateWindow(hWnd); 
    return TRUE;
}

// FUNCTION: WndProc (HWND, unsigned, WORD, LONG)

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    
    RECT rt;
    HPEN pen;
    
    static unsigned short index = 0, index1 = 0, strSize = 257;
    static char* str = new char[strSize];
    static unsigned short const strSize1 = 500;

    switch (message)
    {
    case WM_CREATE: //the message will appear when creating a window
        for (int i = 0; i < 7; i  )
        {
            for (int j = 0; j < 7; j  )
            {
                //serial numberoftheelement
                cells[i][j].x = j;
                cells[i][j].y = i;
                
                //setting the grid color
                cells[i][j].borderColor.r = 0   12 * (i   j);
                cells[i][j].borderColor.g = 0;
                cells[i][j].borderColor.b = 255 - 12 * (i   j);
                //setting the colorofthe circle
                cells[i][j].circleColor.r = rand() % 256;
                cells[i][j].circleColor.g = rand() % 256;
                cells[i][j].circleColor.b = rand() % 256;
                //setting textcolor
                cells[i][j].textColor.r = rand() % 256;
                cells[i][j].textColor.g = rand() % 256;
                cells[i][j].textColor.b = rand() % 256;
                //setting circleSize                
            }
        }
        break;

    case WM_PAINT: //redraw the widow
        hdc = BeginPaint(hWnd, amp;ps); //start graphical output
        GetClientRect(hWnd, amp;rt);
        SetBkMode(hdc, TRANSPARENT);
        
        //cycle of creating a grid with circles
        for (int i = 0; i < 7; i  )
        {
            for (int j = 0; j < 7; j  )
            {
                //Setting a custom pen and fill for the grid
                pen = CreatePen(PS_SOLID, 5, RGB(cells[i][j].borderColor.r, cells[i][j].borderColor.g, cells[i][j].borderColor.b));
                brush = CreateSolidBrush(RGB(cells[i][j].mainColor.r, cells[i][j].mainColor.g, cells[i][j].mainColor.b));
                SelectObject(hdc, brush);
                SelectObject(hdc, pen);

                //Meshing
                Rectangle(hdc, cells[i][j].x * rectSize, cells[i][j].y * rectSize   circleSize, (cells[i][j].x   1) * rectSize, (cells[i][j].y   1) * rectSize   circleSize);

                //Remove Penand Mesh Fill
                DeleteObject(pen);
                DeleteObject(brush);

                //Setting a custom pen and fill for circles
                
                if (i < 1 amp;amp; j < 6) {
                    int z = 1   rand() % (30 - 1);
                    //int z = 10;
                    pen = CreatePen(PS_SOLID, 5, RGB(cells[i][j].circleBorderColor.r, cells[i][j].circleBorderColor.g, cells[i][j].circleBorderColor.b));
                    brush = CreateSolidBrush(RGB(cells[i][j].circleColor.r, cells[i][j].circleColor.g, cells[i][j].circleColor.b));
                    SelectObject(hdc, brush);
                    SelectObject(hdc, pen);

                    //Making circles
                    Ellipse(hdc, cells[i][j].x * rectSize   z, cells[i][j].y * rectSize   z   circleSize, (cells[i][j].x   1) * rectSize - z, (cells[i][j].y   1) * rectSize - z   circleSize);

                    //Remove pen and circle fill
                    DeleteObject(pen);
                    DeleteObject(brush);
                    char arr[strSize1];
                    for (int i = 0; i < strSize1;)
                    {
                        char ch = rand() % 127;
                        if (isalnum(ch))
                        {
                            arr[i] = ch;
                              i;
                        }
                    }

                    // text output
                    SetTextColor(hdc, RGB(cells[i][j].textColor.r, cells[i][j].textColor.g, cells[i][j].textColor.b));
                    TextOut(hdc, cells[i][j].x * rectSize   40, cells[i][j].y * rectSize   circleSize   39, amp;arr[index  ], 1);
                }
            }
        }
        //Displaying text on the screen
        
        EndPaint(hWnd, amp;ps);
        break;

    case WM_MOUSEMOVE:

        y = HIWORD(lParam);
        x = LOWORD(lParam);
        rt.top = 7;
        rt.left = 0;
        rt.right = 7 * rectSize;
        rt.bottom = circleSize;
    
        break;

    case WM_LBUTTONDOWN:

        yCoord = y;
        xCoord = x;

        yCoord -= circleSize;
        yCoord /= rectSize;
        xCoord /= rectSize;

        //Checking if coordinates are included in circle coordinates
        if (xCoord < 7 amp;amp; yCoord < 7 amp;amp; isInCircle(x, y - circleSize, xCoord * rectSize   rectSize / 2, yCoord * rectSize   rectSize / 2, (rectSize - 20) / 2)) {
            //InvalidateRect(hWnd, NULL, TRUE);
            
            GetPixel(hdc, x, y);
            flag = 1;
            flag = 1;
        }
        break;

    case WM_DESTROY:                //completion of work
        PostQuitMessage(0);
        break;

    default:
        //Processing messages that are not processed by the user
        return DefWindowProc(hWnd, message, wParam, lParam);
    }

    return 0;
}
 

Комментарии:

1. Вам нужно использовать чистую кисть

2. Обычно вам нужно помнить каждый объект, который вы рисуете. Затем при удалении одного вы должны стереть фон и при необходимости снова нарисовать другой объект в этой области.

3. Поместите информацию о каждом круге в список и WM_PAINT нарисуйте то, что есть в списке. Когда пользователь нажимает на круг, удалите запись для этого круга из списка и сделайте окно недействительным, чтобы вызвать перерисовку.

4. Вы использовали случайные числа в WM_PAINT , что приведет к тому, что эллипс и текст будут отличаться при каждом перерисовывании. Подумайте о том, чтобы переместить их в WM_CREATE . Вы можете использовать InvalidateRect WM_LBUTTONDOWN и указать клиентские координаты прямоугольника области обновления, что устранит мерцание и увеличит скорость перерисовки.