Структура 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;
}