Структура WinAPI программы

Создал два дочерних окна, в одном рисуем, в другом появляется урезанная версия этого рисунка.

Так же есть кнопка, и должен располагаться текст. (В моем случае я хотел сделать несколько строк текста, но \n не работает почему-то, но вопрос не в этом.)

И у меня происходит наложение текста на дочернее окно. И они перерисовываются друг за другом и получается мерцание теста. Да я могу текст просто правее расположить, но мне кажется, что это костыльно!

Посмотрите на мой код и пожалуйста скажите все ошибки, недочеты и тд. Как правильно должна быть структурирована программа.

Сам код:

#include <Windows.h>

#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 800
#define WINDOW_XPOS (GetSystemMetrics(SM_CXSCREEN) >> 1) - (WINDOW_WIDTH >> 1)
#define WINDOW_YPOS (GetSystemMetrics(SM_CYSCREEN) >> 1) - (WINDOW_HEIGHT >> 1)
#define CHILD_WIDTH 300
#define CHILD_HEIGHT 300
#define PADDING_L 50
#define PADDING_B 50
#define SMALL_CHILD_W 64
#define SMALL_CHILD_H 64

HINSTANCE hInst;
RECT clientRect;

HBRUSH WINDOW_BACKGROUND = CreateSolidBrush(RGB(41, 49, 51));
HBRUSH CHILD_BACKGROUND = CreateSolidBrush(RGB(76, 81, 74));
HBRUSH BRUSH_COLOR = CreateSolidBrush(RGB(213, 213, 213));
HPEN hPen = CreatePen(PS_NULL, 0, NULL);

HDC child_hdc;
HDC second_hdc;

HWND hBtnStart;

LRESULT CALLBACK ChildProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    static int x = 0, y = 0, x_prev = 0, y_prev = 0, N = 20;
    static BOOL fDrawEllipse;
    static HBITMAP hBMP;
    static HDC hMemDC;

    switch (msg) {
    case WM_CREATE: {
        child_hdc = GetDC(hwnd);

        hMemDC = CreateCompatibleDC(child_hdc);
        hBMP = CreateCompatibleBitmap(child_hdc, CHILD_WIDTH, CHILD_HEIGHT);
        SelectObject(hMemDC, hBMP);

        SelectObject(hMemDC, hPen);
        SelectObject(hMemDC, BRUSH_COLOR);
        FillRect(hMemDC, &clientRect, CHILD_BACKGROUND);
        return 0;
    }
    case WM_LBUTTONDOWN: {
        x = LOWORD(lParam);
        y = HIWORD(lParam);
        fDrawEllipse = true;
        Ellipse(hMemDC, x - 5, y - 5, x + 5, y + 5);
        BitBlt(child_hdc, 0, 0, CHILD_WIDTH, CHILD_HEIGHT, hMemDC, 0, 0, SRCCOPY);
        return 0;
    }
    case WM_PAINT: {
        BitBlt(child_hdc, 0, 0, CHILD_WIDTH, CHILD_HEIGHT, hMemDC, 0, 0, SRCCOPY);
        return 0;
    }
    case WM_MOUSEMOVE: {
        if (fDrawEllipse) {
            x_prev = x;
            y_prev = y;
            x = LOWORD(lParam); 
            y = HIWORD(lParam);
            for (int i = 0; i < N; ++i) {
                int px = x_prev + (x - x_prev) * i / N;
                int py = y_prev + (y - y_prev) * i / N;
                Ellipse(hMemDC, px - 5, py - 5, px + 5, py + 5);
                BitBlt(child_hdc, 0, 0, CHILD_WIDTH, CHILD_HEIGHT, hMemDC, 0, 0, SRCCOPY);
            }
        }
        return 0;
    }
    case WM_LBUTTONUP: {
        fDrawEllipse = false;
        x_prev = 0; y_prev = 0; x = 0; y = 0;
        return 0;
    }
    case WM_DESTROY: {
        ReleaseDC(hwnd, child_hdc);
        DeleteObject(WINDOW_BACKGROUND);
        DeleteObject(CHILD_BACKGROUND);
        DeleteObject(BRUSH_COLOR);
        DeleteObject(hPen);
        DeleteDC(hMemDC);
        DeleteDC(child_hdc);
        PostQuitMessage(0);
        return 0;
    }
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

LRESULT CALLBACK SecondProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

    switch (msg) {
    case WM_CREATE: {
        second_hdc = GetDC(hwnd);
        return 0;
    }
    case WM_PAINT: {
        StretchBlt(second_hdc, 0, 0, SMALL_CHILD_W, SMALL_CHILD_H, child_hdc, 0, 0, CHILD_WIDTH, CHILD_HEIGHT, SRCCOPY);
        return 0;
    }
    case WM_DESTROY: {
        ReleaseDC(hwnd, second_hdc);
        PostQuitMessage(0);
        return 0;
    }
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    static HBITMAP hBMP;
    static HWND child;
    static HWND sChild;
    static HDC hdc;
    static PAINTSTRUCT ps;
    switch (msg) {
    case WM_CREATE: {

        hdc = GetDC(hwnd);

        GetClientRect(hwnd, &clientRect);

        WNDCLASSEX wc{};
        wc.cbSize = sizeof(WNDCLASSEX);
        wc.lpfnWndProc = ChildProc;
        wc.hInstance = hInst;
        wc.hbrBackground = CHILD_BACKGROUND;
        wc.lpszClassName = "ChildClass";
        wc.hCursor = LoadCursor(nullptr, IDC_CROSS);

        RegisterClassEx(&wc);

        child = CreateWindowEx(0, wc.lpszClassName, (LPCTSTR)nullptr, WS_CHILD | WS_BORDER | WS_VISIBLE,
                                    clientRect.left + PADDING_L, clientRect.bottom - CHILD_HEIGHT - PADDING_B, CHILD_WIDTH, CHILD_HEIGHT, 
                                    hwnd, nullptr, hInst, nullptr);

        ShowWindow(child, SW_NORMAL);
        UpdateWindow(child);

        wc = {};
        wc.cbSize = sizeof(WNDCLASSEX);
        wc.lpfnWndProc = SecondProc;
        wc.hInstance = hInst;
        wc.hbrBackground = CHILD_BACKGROUND;
        wc.lpszClassName = "SecondClass";
        wc.hCursor = LoadCursor(nullptr, IDC_ARROW);

        RegisterClassEx(&wc);

        sChild = CreateWindowEx(0, wc.lpszClassName, (LPCTSTR)nullptr, WS_CHILD | WS_BORDER | WS_VISIBLE,
                                PADDING_L, PADDING_B, SMALL_CHILD_W, SMALL_CHILD_H,
                                hwnd, nullptr, hInst, nullptr);

        ShowWindow(sChild, SW_NORMAL);
        UpdateWindow(sChild);

        hBtnStart = CreateWindow("BUTTON", "Click!", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                 clientRect.right - 120, clientRect.top + 20, 100, 30, hwnd, (HMENU)1001, 
                                 ((LPCREATESTRUCT)lParam)->hInstance, nullptr);

        return 0;
    }
    case WM_PAINT: {
        UpdateWindow(hBtnStart);
        UpdateWindow(sChild);
        UpdateWindow(child);
        LPCSTR text = "TEST\nTEST";
        TextOut(hdc, 100, 100, text, strlen(text));
        return 0;
    }
    case WM_DESTROY: {
        ReleaseDC(hwnd, hdc);
        PostQuitMessage(0);
        return 0;
    }
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE,
                   _In_ LPSTR lpCmdLine, _In_ int nShowCmd) {
    HWND hwnd{};
    MSG msg{};
    WNDCLASSEX wc;

    hInst = hInstance;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = WINDOW_BACKGROUND;
    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
    wc.hIconSm = nullptr;
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = "WindowClass";
    wc.lpszMenuName = nullptr;
    wc.style = CS_VREDRAW | CS_HREDRAW;

    if (!RegisterClassEx(&wc))
        return EXIT_FAILURE;

    hwnd = CreateWindowEx(WS_EX_WINDOWEDGE, wc.lpszClassName, "Окно windows",
                          WS_OVERLAPPEDWINDOW, WINDOW_XPOS, WINDOW_YPOS, WINDOW_WIDTH, WINDOW_HEIGHT,
                          nullptr, nullptr, hInstance, nullptr);

    if (hwnd == INVALID_HANDLE_VALUE)
        return EXIT_FAILURE;

    ShowWindow(hwnd, nShowCmd);
    UpdateWindow(hwnd);

    BOOL bRet;
    while (bRet = GetMessage(&msg, nullptr, 0, 0)) {
        if (bRet == -1)
            return EXIT_FAILURE;
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

Ответы (0 шт):