@Vlad_beg

Как правильно нарисовать линию в WINAPI?

При клике должна рисоваться линия от точки где была нажата мышка и заканчиваться в точке, где мышка была отпущена. В моем случаи ничего не происходит, никак не могу понять чего не хватает.

LONG WINAPI WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{

    HDC hdc;
    BOOL fDraw = FALSE;
    POINT ptPrevious = { 0 };
    HPEN Pen = CreatePen(PS_SOLID, 3, RGB(0, 0, 255));


    switch (Message) {
        case WM_LBUTTONDOWN: {
            fDraw = TRUE;
            ptPrevious.x = LOWORD(lParam);
            ptPrevious.y = HIWORD(lParam);
            break;
        }

        case WM_LBUTTONUP: {
            if (fDraw)
            {
                hdc = GetDC(hWnd);
                MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL);
                LineTo(hdc, LOWORD(lParam), HIWORD(lParam));
                ReleaseDC(hWnd, hdc);
            }
            fDraw = FALSE;
            break;
        }


        case WM_PAINT: {
            if (fDraw)
            {
                hdc = GetDC(hWnd);
                MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL);
                LineTo(hdc, ptPrevious.x = LOWORD(lParam),
                    ptPrevious.y = HIWORD(lParam));
                ReleaseDC(hWnd, hdc);
            }
            break;
        }


        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hWnd, Message, wParam, lParam);
    }
    return 0;
}
  • Вопрос задан
  • 1847 просмотров
Решения вопроса 1
SerJook
@SerJook
кодер
Несколько комментариев по вашему коду:

Переменные Pen, ptPrevious, fDraw не сохраняются между вызовами функции, сделайте их статическими или глобальными. В текущем варианте ваш код создает ОГРОМНОЕ количество GDI-объектов.

static HPEN Pen =  CreatePen(PS_SOLID, 3, RGB(0, 0, 255));
static BOOL fDraw = FALSE;
static POINT ptPrevious = { 0, 0 };


При обработке WM_PAINT нельзя использовать GetDC(). Если вы не заметили, это нагружает процессор.
Правильно будет использовать BeginPaint() и EndPaint();

case WM_PAINT: {
        PAINTSTRUCT ps;
        hdc = BeginPaint(hWnd, &ps);
        // TODO: рисовать здесь
        EndPaint(hWnd, &ps);
        break;
    }


Чтобы нарисованное не стиралось при обновлении окна, вам надо рисовать в Back Buffer (не знаю, как это по-русски). Для этого вам надо создать BITMAP c помощью CreateCompatibleBitmap, HDC с помощью CreateCompatibleDC, загрузить в созданный HDC BITMAP с помощью SelectObject, и рисовать на HDC. Потом вызывать BitBlt и копировать бэкбуфер в реальный HDC окна (внутри обработчика WM_PAINT).
Другой вариант (без back buffer): сохраняйте координаты ваших линий в некий массив, и выводите их все в обработчике WM_PAINT.

Если же вам не нужно, чтоб нарисованное не стиралось, просто уберите обработчик WM_PAINT.

Еще небольшая придирка: вместо LOWORD(lParam) при получении координат надо использовать GET_X_LPARAM и GET_Y_LPARAM.

ptPrevious.x = GET_X_LPARAM(lParam);
ptPrevious.y = GET_Y_LPARAM(lParam);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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