【问题标题】:Drag and draw border in WM_MOUSEMOVE?在 WM_MOUSEMOVE 中拖动和绘制边框?
【发布时间】:2017-05-06 01:39:22
【问题描述】:

我正在尝试实现一个功能,用户按下鼠标左键,将鼠标拖动到某处,然后绘制一个“带边框的矩形”(没有任何填充的矩形,显示下面的内容,所以基本上只是一个边框) .

我有一些东西正在使用此代码:

         case WM_MOUSEMOVE:
              if (draw) {
                  endX = GET_X_LPARAM(lParam);
                  endY = GET_Y_LPARAM(lParam);
                  hdc = GetDC(hwnd);
                  SelectObject(hdc, GetStockObject(NULL_BRUSH));
                  Rectangle(hdc, startX, startY, endX, endY);
                  ReleaseDC(hwnd, hdc);
              }
            break;

(当 WM_LBUTTONDOWN 被触发时 draw 设置为 true,当 WM_LBUTTONUP 被触发时设置为 false)。

这就是它的样子。我基本上想要这个,里面没有黑线,可能还有更厚的边框。

我遇到的问题是我无法弄清楚如何重绘矩形区域内“丢失”的内容。我想我应该使用 InvalidateRect 而不是 Rectangle 但同样,不确定如何在 WM_PAINT 中重绘。也许我应该以一种完全不同的方式来解决这个问题?这是我第一次使用 Winapi。

【问题讨论】:

  • 通常在使用橡皮筋(以这种方式绘制一个框)时,不会在背景上加上纯色,而是将线条与背景进行异或。要删除该行,只需再次对同一行进行异或运算,即可返回原始背景。
  • 我已经尝试在绘制矩形之前将 ROP2 设置为 XORPEN,如我上面的代码所示,这听起来与您所说的相似,但该功能没有成功:SetROP2(hdc , R2_XORPEN);
  • 谁拥有那个窗口?如果它是您的,那么您执行以下操作: 1. 当鼠标向下时,记住坐标。 2.当鼠标移动时,在前一个矩形上绘制图像,然后在顶部绘制新的矩形。

标签: c++ winapi


【解决方案1】:

感谢 David Heffernan,我有一个解决方案:

case WM_MOUSEMOVE:
      if (draw) {
          // Get current mouse position
          endX = GET_X_LPARAM(lParam);
          endY = GET_Y_LPARAM(lParam);

          // Paint over previous rectangle
          hdc = GetDC(hwnd);
          hdcMem = CreateCompatibleDC(hdc);
          hbmOld = (HBITMAP) SelectObject(hdcMem, screenshot);
          BitBlt(hdc, 0, 0, fullW, fullH, hdcMem, 0, 0, SRCCOPY);
          SelectObject(hdcMem, hbmOld);

          // Change to NULL_BRUSH (no fill)
          hBrush = (HBRUSH) GetStockObject(NULL_BRUSH);
          hOldBrush = (HBRUSH) SelectObject(hdc, hBrush);

          // Change to red pen
          hPen = GetStockObject(DC_PEN);
          hOldPen = SelectObject(hdc, hPen);
          SetDCPenColor(hdc, RGB(255,0,0));

          // Draw new rectangle
          Rectangle(hdc, startX, startY, endX, endY);

          // Restore original brush and brush
          SelectObject(hdc, hOldBrush);
          SelectObject(hdc, hOldPen);

          ReleaseDC(hwnd, hdc);
          DeleteDC(hdcMem);
      }
    break;

基本上,我会在开始绘制之前保存窗口的屏幕截图(在称为屏幕截图的位图中),并在每次鼠标移动时在整个屏幕上绘制。 startX 和 startY 在 WM_LBUTTONDOWN 被触发时设置一次。我认为重绘整个屏幕效率极低,但如果我只是在需要重绘的区域上部分绘制,我就无法让它工作。如果我觉得性能是一个问题,我可能会回到这一点,但从我的测试来看,它似乎非常顺利。

【讨论】:

    猜你喜欢
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    相关资源
    最近更新 更多