Win32绘制可拖动矩形

3

我正在尝试通过左键单击一个点并拖动来绘制矩形,在您拖动时,矩形会形成预览,以显示矩形的外观。这个功能很好用,但是当我拖回到一个较小的矩形时,旧矩形仍然存在。

    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;

当您仍按住鼠标按钮时? - Aesthete
当我仍然按住鼠标时,我知道为什么会发生这种情况,但是有没有办法去掉那些旧的矩形呢?谢谢。 - user1788175
使用InvalidateRect函数,将最后一个参数设置为TRUE。 - cha
这是真正的代码吗?如果是,那么GDI对象存在问题。如果不销毁greenPen,很快就会用完GDI对象。此外,在SelectObject之后存储前一个对象并在完成后将其返回到DC是个好主意。 - cha
这不是真正的代码,但还是谢谢。我已经将其设置为true,但这意味着一旦我绘制另一个矩形,旧矩形就会被删除。我该如何存储先前的对象?(矩形) - user1788175
1个回答

2

@user1788175 - just use a RECT struct. When the drawing starts, you set the left & top members to the x,y pos of the mouse. When the mouse is released, set the right,bottom members. Swap left,right if necessary, to ensure that left

Here's some code ripped from a class I wrote to deal with with selection rectangles. You can ignore the normalize code - it just converts the pixel coordinates to ones in the range [0..1], so I can draw the selection on a scaled-down version of the image, yet still select the same region if the image is shown at a different scale. My images were 4944x6992, so I had to display a scaled-down version of them.

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);
}


1
我刚偶然发现了这篇文章,因为我正在寻找用鼠标拖动图像的示例。我假设上面的代码是生产代码,所以我想通过指出一些关键性错误来帮助你:你必须处理WM_CAPTURECHANGED并将你的“清理”代码移动到那里。这篇文章总结得很好。此外,你需要在鼠标按钮处理程序中适应多个监视器的代码。使用GET_X_LPARAMGET_Y_LPARAM代替LOWORDHIWORD,只需重新阅读文档即可。+1 - AlwaysLearningNewStuff
嗨。 :) - 当时我写这篇文章的时候是希望能够实现的,但最终我们只是购买了一些软件。这是来自一个OMR软件 - 它被用于创建大学考勤表的“模板”,以便每天可以扫描100多张A4纸,去除歪斜并识别学生ID条形码和表示出席时间的复选框。最终我们选择了Remark Office OMR。感谢你的链接,我的朋友,它将在未来为我服务,我希望如此。不确定是否在一个月或两个月前收到了你的消息,如果是的话很抱歉 - 这几个月过得很艰难。 :-( - enhzflep
我正在努力实现ListView拖放时的自动滚动功能,但遇到了一些问题。我正在尝试表达这个问题,但有些困难。也许我们可以在聊天室里见面讨论一下。我还在尝试实现类似地图查看器的东西,但卡住了。不确定一个月或两个月前是否收到你的消息 我很忙,但已经在这里发布了一些问题...希望我们能在聊天中交流...最好的问候 :) - AlwaysLearningNewStuff
啊,我记起来了。我会查看您个人资料页面上的未解决问题,并看看是否有什么可以做的。我所知道的唯一启动聊天的方法是写太多来回评论。我不熟悉地图查看器 - 它是地理地图还是数据结构地图? - enhzflep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接