画线不起作用,可能是什么问题?

问题描述 投票:1回答:3

我想通过在线应该开始的第一个坐标上单击鼠标来绘制线,以及线应该结束的第二个坐标。当我运行我的项目时没有任何反应。我无法找出我的代码丢失的内容。

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;
}
c++ winapi
3个回答
1
投票

因为声明的变量是局部变量,所以可以使用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);
   }

2
投票

从根本上说,问题是因为没有一个数据是持久的。因为它们都是局部变量,所以当WndProc返回时它们的内容会消失。 fDraw在每条消息上都设置为FALSE,对于WM_LBUTTONDOWN或WM_MOUSEMOVE消息永远不会成立。因此没有任何反应

你需要创建一些类来保存fDrawptPrevious和一个结构来保存要绘制的线的坐标。在WM_MOUSEMOVE和WM_LBUTTONUP消息中使用InvalidateRect。然后只绘制它们以响应WM_PAINT消息(使用绘制消息中提供的DC)。

使用CWnd MFC类可以大大简化这些任务。


1
投票

不要让DC三次,得到它一次并在鼠标上释放它。此外,您的绘图最终将被验证,因此您需要记录鼠标移动并在WM_PAINT处理程序中重复此内容。

© www.soinside.com 2019 - 2024. All rights reserved.