【问题标题】:Win32 Draw a Dragging RectangleWin32 绘制拖动矩形
【发布时间】:2012-10-31 10:25:55
【问题描述】:

我正在尝试在您左键单击一个点然后拖过时绘制一个矩形,而您在矩形上的拖动会获得表单以向您显示矩形外观的预览。这很好用,除非当我拖回一个较小的矩形时,旧的矩形仍然存在。

    case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);
    // TODO: Add any drawing code here...

    if(painting)
    {



            HPEN greenPen=CreatePen(PS_SOLID, 1, RGB(0,255,0));
            SelectObject(hdc,greenPen);
            Rectangle(hdc, x1, y1, x2, y2);

    }


    EndPaint(hWnd, &ps);
    break;
case WM_LBUTTONDOWN:
    painting=true;
    x1=LOWORD(lParam);
    y1=HIWORD(lParam);
    InvalidateRect(hWnd, NULL ,false);
    break;
case WM_MOUSEMOVE:



        x2=LOWORD(lParam);
        y2=HIWORD(lParam);

        InvalidateRect(hWnd, NULL ,false);


    break;
case WM_LBUTTONUP:

    painting=false;
    break;

【问题讨论】:

  • 当您还按下鼠标按钮时?
  • 是的,虽然我仍然按下鼠标,但我知道为什么会发生这种情况,但有什么办法可以摆脱那些旧的矩形?谢谢
  • 使用 InvalidateRect 和 TRUE 作为最后一个参数
  • 是真码吗?如果是,则 GDI 对象存在问题。如果不销毁 greenPen,您很快就会用完 GDI 对象。此外,最好在 SelectObject 之后存储前一个对象,并在完成后将其返回 DC。
  • 这不是真正的代码,但谢谢。我已将其设置为 true 但这意味着只要我绘制另一个矩形,旧矩形就会被删除。如何存储上一个对象? (矩形)

标签: c++ visual-c++ gdi


【解决方案1】:

@user1788175 - 只需使用 RECT 结构。绘图开始时,您将左侧和顶部成员设置为鼠标的 x,y 位置。释放鼠标后,设置右、下成员。必要时左右交换,以确保左

这是从我编写的用于处理选择矩形的类中提取的一些代码。您可以忽略规范化代码 - 它只是将像素坐标转换为 [0..1] 范围内的坐标,因此我可以在图像的缩小版本上绘制选择,但如果图像仍然选择相同的区域以不同的比例显示。我的图像是 4944x6992,所以我必须显示它们的缩小版本。

LRESULT CALLBACK cSelBoxImg::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    RECT mappedRect, tmpRect, myRect;
    HBRUSH myBrush;
    BITMAP bm;
    PAINTSTRUCT ps;
    HDC mDC;
    HBITMAP tmpBmp;

    switch (uMsg)
    {
    case WM_LBUTTONDOWN:
        if (bMouseSelectionEnabled)
        {
            bRubberBanding = true;
            mouseClickDownPos.x = LOWORD(lParam);
            mouseClickDownPos.y = HIWORD(lParam);

            curMousePos = mouseClickDownPos;
            selectionRect.left = min(curMousePos.x, mouseClickDownPos.x);
            selectionRect.right = max(curMousePos.x, mouseClickDownPos.x);
            selectionRect.top = min(curMousePos.y, mouseClickDownPos.y);
            selectionRect.bottom = max(curMousePos.y, mouseClickDownPos.y);
            normalizeSelRect();
            InvalidateRect(mHwnd, NULL, isBkgTransparent);
            PostMessage(GetParent(hWnd),  WM_COMMAND, GetDlgCtrlID(hWnd), (LPARAM)hWnd);
        }
        return 1;

    case WM_LBUTTONUP:
        if (bMouseSelectionEnabled)
            if (bRubberBanding)
            {
                bRubberBanding = false;
                mouseClickUpPos.x = LOWORD(lParam);
                mouseClickUpPos.y = HIWORD(lParam);

                selectionRect.left = min(mouseClickUpPos.x, mouseClickDownPos.x);
                selectionRect.right = max(mouseClickUpPos.x, mouseClickDownPos.x);
                selectionRect.top = min(mouseClickUpPos.y, mouseClickDownPos.y);
                selectionRect.bottom = max(mouseClickUpPos.y, mouseClickDownPos.y);

                normalizeSelRect();
                InvalidateRect(mHwnd, NULL, isBkgTransparent);
                PostMessage(GetParent(hWnd),  WM_COMMAND, GetDlgCtrlID(hWnd), (LPARAM)hWnd);
            }
        return 1;

    case WM_MOUSEMOVE:
        if (bMouseSelectionEnabled)
            if (bRubberBanding)
            {
                curMousePos.x = LOWORD(lParam);
                curMousePos.y = HIWORD(lParam);

                selectionRect.left = min(curMousePos.x, mouseClickDownPos.x);
                selectionRect.right = max(curMousePos.x, mouseClickDownPos.x);
                selectionRect.top = min(curMousePos.y, mouseClickDownPos.y);
                selectionRect.bottom = max(curMousePos.y, mouseClickDownPos.y);
                //                UpdateWindow(hWnd);
                //RedrawWindow(hWnd, NULL, NULL, RDW_UPDATENOW);
                normalizeSelRect();
                InvalidateRect(hWnd, NULL, false);
                PostMessage(GetParent(hWnd),  WM_COMMAND, GetDlgCtrlID(hWnd), (LPARAM)hWnd);
                //       printf("Message posted\n");
            }
        return 0;

    case WM_PAINT:

        mDC = BeginPaint(hWnd, &ps);

        GetClientRect(hWnd, &tmpRect);
    //        GetObject(mBmp, sizeof(bm), &bm);
        mappedRect.left = mLeft * tmpRect.right;
        mappedRect.right = mRight * tmpRect.right;
        mappedRect.top = mTop * tmpRect.bottom;
        mappedRect.bottom = mBottom * tmpRect.bottom;

        displayImage();
        if  (mBmp) drawRect(mDC, mappedRect, RGB(0,0,255));
        DeleteObject(tmpBmp);
        EndPaint(hWnd, &ps);

        return 0;

    case WM_ERASEBKGND:
        if (isBkgTransparent)
        {
            GetClientRect(hWnd, &myRect);
            myBrush = (HBRUSH) GetWindowLong(hWnd, GCL_HBRBACKGROUND);
            FillRect((HDC)wParam, &myRect, myBrush);
            printf("background cleared\n");
        }
        return true;

    case WM_SETCURSOR:
        SetCursor(mCursor);
        return true;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

【讨论】:

  • 我只是偶然发现了这篇文章,因为我正在搜索使用鼠标拖动图像的示例。我假设以上内容来自生产代码,因此我想通过指出一些关键错误来帮助您:您必须处理 WM_CAPTURECHANGED 并将您的“清理”代码移到那里。 This article 总结得很好。此外,您需要在鼠标按钮处理程序中为多个监视器调整代码。使用GET_X_LPARAMGET_Y_LPARAM 而不是LOWORDHIWORD,只需重新阅读文档即可。 +1
  • 嗨。 :) - 这是我写它时的希望,但我们最终只是购买了一些软件。它来自一个 OMR 软件——它被用来创建一个大学考勤表的“模板”,这样每天可以扫描 100 左右的 A4 页,去歪斜,然后识别学生 ID 条形码和指示的复选框在课堂上的时间。我们最终选择了 Remark Office OMR。感谢朋友的链接,希望以后能对我有好处。不确定我是否在一两个月前收到了你的消息,如果是这样,对不起 - 这几个月很艰难。 :-(
  • 我在拖放时努力实现列表视图自动滚动功能。我试图表达这个问题,但有一些问题。也许我们可以在这里见面聊天讨论。我也在尝试实现类似地图查看器的功能,但被卡住了。 不确定我是否在一两个月前收到了你的消息我很忙,但在这里发布了一些问题......希望我们可以在聊天中交谈以赶上......最好的问候: )
  • 啊,是的,现在我想起来了。我会查看您个人资料页面中的未解决问题,看看我能做什么(如果有的话)。我知道在这里发起聊天的唯一方法是写太多来回的 cmets。我不熟悉地图查看器 - 是地理地图还是数据结构地图?
猜你喜欢
  • 2014-01-25
  • 2021-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-30
  • 1970-01-01
  • 1970-01-01
  • 2015-04-28
相关资源
最近更新 更多