рисовать линии не работает, в чем может быть проблема? - PullRequest
1 голос
/ 24 марта 2019

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

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_MOUSEMOVE: {
            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;
}

Ответы [ 3 ]

2 голосов
/ 24 марта 2019

По сути, проблема в том, что ни одна из ваших данных не является постоянной. Поскольку все они являются локальными переменными, их содержимое исчезает, когда возвращается WndProc. fDraw имеет значение FALSE для каждого сообщения и никогда не будет истинным для сообщений WM_LBUTTONDOWN или WM_MOUSEMOVE. Поэтому ничего не происходит.

Вы захотите создать некоторый класс для хранения fDraw, ptPrevious и структуру для хранения координат линии (ий) для рисования. Используйте InvalidateRect в сообщениях WM_MOUSEMOVE и WM_LBUTTONUP. Затем рисуйте их только в ответ на сообщение WM_PAINT (используя DC, указанный в сообщении рисования).

Использование класса MFC CWnd может значительно упростить эти задачи.

1 голос
/ 25 марта 2019

Поскольку объявленные переменные являются локальными переменными, переменные могут быть объявлены с помощью Static.

   static BOOL fDraw = FALSE;
   static POINT ptPrevious = { 0 };

Кроме того, вы забыли использовать функцию SelectObject для выбора пера в DC.

Вы также можете использовать перерисовку WM_PAINT для улучшения вашего кода:

Пример:

   LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   {
   HDC hdc;
   PAINTSTRUCT ps;
   static BOOL fDraw = FALSE;
   static BOOL fDraw_begin = FALSE;
   static POINT ptPrevious;
   static RECT rcClient; 
   static POINT pt;
   static HPEN Pen;

   switch (message)
   {
   case WM_CREATE:
   {
          Pen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
          break;
   }

   case WM_LBUTTONDOWN:
   {
          ptPrevious.x = (LONG)LOWORD(lParam);
          ptPrevious.y = (LONG)HIWORD(lParam);
          return 0;
   }

   case WM_LBUTTONUP:
   {
          if (fDraw = TRUE)
          {
                 fDraw = FALSE;
                 fDraw_begin = TRUE;
                 InvalidateRect(hwnd, &rcClient, TRUE);
                 UpdateWindow(hwnd);

          }
          return 0;
   }

   case WM_MOUSEMOVE: 
   {
          if (wParam && MK_LBUTTON)
          {
                 GetClientRect(hwnd, &rcClient);
                 hdc = GetDC(hwnd);
                 SetROP2(hdc, R2_NOTXORPEN);
                 if (!IsRectEmpty(&rcClient))      // Detecting whether the rectangular area is empty
                 {
                       MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL);
                       LineTo(hdc, (LONG)LOWORD(lParam),
                              (LONG)HIWORD(lParam));
                 }
                 MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL);
                 LineTo(hdc, (LONG)LOWORD(lParam),
                       (LONG)HIWORD(lParam));
                 pt.x = (LONG)LOWORD(lParam);
                 pt.y = (LONG)HIWORD(lParam);
                 fDraw = TRUE;

                 ReleaseDC(hwnd, hdc);
          }      
          return 0;
   }

   case WM_PAINT:
   {
          hdc = BeginPaint(hwnd, &ps);
          SelectObject(hdc, Pen);
          if (fDraw_begin)
          {
                 fDraw_begin = FALSE;
                 MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL);
                 LineTo(hdc, pt.x,
                       pt.y);
          }
          EndPaint(hwnd, &ps);
          ReleaseDC(hwnd, hdc);
          return 0;
   }

   case WM_DESTROY:
   {
          DeleteObject(Pen);
          PostQuitMessage(0);
          return 0;
   }

   }
   return DefWindowProc(hwnd, message, wParam, lParam);
   }
1 голос
/ 24 марта 2019

Не получайте DC три раза, получите его один раз и отпустите при наведении мыши.Кроме того, ваш чертеж будет в конечном итоге проверен, поэтому вам нужно зарегистрировать движение мыши и повторить этот процесс в обработчике WM_PAINT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...