Задать вопрос
@legacy_js

Как правильно изменять размер левого края окна с winapi?

Проблема с изменением размера левой стороны окна. После изменения размера левого края, окно начинает дергаться и мигать, как будто находится в двух разных позициях( на видео мигание не видно) почти одновременно.
Но самое что я не могу понять это, почему курсор мыши отдаляется от края окна, чем дольше тяну, тем больше отдаляется. С правым краем такого нет(понятно что у правого края не надо изменять новое значение), край двигается сразу же за курсором. Думаю проблема в WM_MOUSEMOVE, не правильно делаю расчеты, но пробовал по разному, результат тот же.
Видео

Использую стиль WS_POPUP, в WS_PAINT и WS_NCPAINT двойная буферизация
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    static bool dragging = false;
    static POINT startPoint;
    static RECT startRect;

    switch (message)
    {
        case WM_MOUSEMOVE:
        {
            if (dragging)
            {
                POINT currentPoint = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                GetCursorPos(&currentPoint);
                ScreenToClient(hwnd, &currentPoint);

                // Смещение для ПРАВОЙ СТОРОНЫ ОКНА
                int deltaXRight = currentPoint.x - startPoint.x;
                // Новая ширина ПРАВОЙ СТОРОНЫ ОКНА
                int newWidth = startRect.right - startRect.left + deltaXRight;

                // Смещение для Левой СТОРОНЫ ОКНА
                int deltaXLeft = currentPoint.x - startPoint.x;
                //int deltaXLeft = startPoint.x + currentPoint.x;
                // Новая ширина ЛЕВОЙ СТОРОНЫ ОКНА
                int newWidthLeft = startRect.right - startRect.left - deltaXLeft;
                // Новая позиция левой стороны
                int newCurrentWidthLeft = startRect.left + deltaXLeft;

                if (startPoint.x > startRect.right - startRect.left - BORDERWIDTH)
                {
                    SetWindowPos(hwnd, NULL, 0, 0, newWidth, startRect.bottom - startRect.top, SWP_NOZORDER | SWP_NOMOVE);
                }
                else if (startPoint.x < BORDERWIDTH && newWidthLeft > MIN_WIDTH)
                {
                    SetWindowPos(hwnd, NULL, newCurrentWidthLeft, startRect.top, newWidthLeft, startRect.bottom - startRect.top,
                        SWP_NOZORDER);
                }
            }
            break;
        }
        case WM_NCHITTEST:
        {
            POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
            ScreenToClient(hwnd, &pt);

            RECT closeButton = GetCloseButtonRect(hwnd);
            RECT maximizeButton = GetMaximizeButtonRect(hwnd);
            RECT minimizeButton = GetMinimizeButtonRect(hwnd);

            if (PtInRect(&closeButton, pt)) {
                return HTCLOSE;
            }
            else if (PtInRect(&maximizeButton, pt)) {
                return HTMAXBUTTON;
            }
            else if (PtInRect(&minimizeButton, pt)) {
                return HTMINBUTTON;
            }
            // Если курсор в заголовке, возвращаем HTCAPTION
            if (pt.y < GetTitleBarHeight()) {
                return HTCAPTION; // Указываем, что курсор в заголовке
            }

            LRESULT hit = DefWindowProc(hwnd, message, wParam, lParam);
            if (hit == HTCLIENT)
            {
                RECT rc;
                GetClientRect(hwnd, &rc);
                if (pt.x > rc.right - 10) {
                    return HTRIGHT; // Правый край
                }
                else if (pt.x <= 10) {
                    return HTLEFT; // Левый край
                }
            }
            return hit;
        }

        case WM_NCLBUTTONDOWN:
        {
            POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
            ScreenToClient(hwnd, &pt);

            RECT closeButton = GetCloseButtonRect(hwnd);
            RECT maximizeButton = GetMaximizeButtonRect(hwnd);
            RECT minimizeButton = GetMinimizeButtonRect(hwnd);

            if (PtInRect(&closeButton, pt)) {
                PostMessage(hwnd, WM_CLOSE, 0, 0);
            }
            if (PtInRect(&maximizeButton, pt)) {
                ShowWindow(hwnd, IsZoomed(hwnd) ? SW_RESTORE : SW_MAXIMIZE);
            }
            if (PtInRect(&minimizeButton, pt)) {
                SendMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
            }
            if (pt.y < GetTitleBarHeight()) {
                // Начинаем перетаскивание окна
                PostMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, lParam);
                return HTCAPTION;
            }

            dragging = true;

            startPoint.x = GET_X_LPARAM(lParam);
            startPoint.y = GET_Y_LPARAM(lParam);

            GetWindowRect(hwnd, &startRect);
            ScreenToClient(hwnd, &startPoint);

            SetCapture(hwnd); // Захватываем мышь
            break;
        }

        case WM_LBUTTONUP: {
            // Остановка изменения размера окна при отпускании левой кнопки мыши
            if (dragging) {
                dragging = false;
                ReleaseCapture(); // Освобождаем мышь
            }
            break;
        }

        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}
  • Вопрос задан
  • 86 просмотров
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 1
@adg2004
Что бы такую ошибку найти я бы для начала писал бы в файл все изменения размеров окна и строки из которых эти изменения происходят, после анализа полученного лога все встанет на свои места.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы