+ -
当前位置:首页 → 问答吧 → 请教,如何实现通过拖动鼠标,在图象中任意位置选择一个合适大小的区域画一个矩形框,谢谢!

请教,如何实现通过拖动鼠标,在图象中任意位置选择一个合适大小的区域画一个矩形框,谢谢!

时间:2009-08-20

来源:互联网

我在窗体的static text控件上绘制图像,现在想在图像上通过拖动鼠标画定一个透明的矩形区域,要求每次画矩形都能清除前一次画的矩形,而且不能画到控件外面去,如何实现,请高手们帮忙,谢谢!

作者: happy_jxj   发布时间: 2009-08-20

有几个关健点:

1.透明的矩形:
需要调用SetBkMode,传TRANSPARENT参数。

2.清除前一次画的矩形:
使用双缓冲,每次重新画整个控件区域,步骤:在后台内存中将背景画成纯的背景色,在上面画矩形,将画的图帖出来。

3.不能画到控件外面去:
画图时使用控件的HDC去画,就不会画到外面了。

作者: fengrx   发布时间: 2009-08-20

static text控件...究竟是static还是edit?

作者: Tr0j4n   发布时间: 2009-08-20

1.透明的矩形: 
为dc选择NULL_BRUSH

2.清除前一次画的矩形:
关联一个矩形成员变量,每次刷新绘制该成员变量。
拖动完成后,修改该矩形。

3.不能画到控件外面去: 
画图时使用控件的HDC去画,就不会画到外面了

4.有预览效果
为dc设置下面属性,绘制一遍显示,绘制两遍擦除
dc.SetROP2(R2_XORPEN);

作者: gao_zilai   发布时间: 2009-08-20

使用CStatic,须重载

作者: gao_zilai   发布时间: 2009-08-20

1、创建兼容内存DC
2、选择位图到内存DC
3、在内存DC上画矩形
4、将内存DC拷贝到控件DC中,完成一次绘画

作者: skybblue   发布时间: 2009-08-20

你可以重载CStatic, 自己编辑鼠标和绘制消息.
或者你从主窗口判断坐标点是否落在CStatic内,然后拿到Cstatic的HDC绘制.

作者: I_NBFA   发布时间: 2009-08-20

引用 1 楼 fengrx 的回复:
有几个关健点:

1.透明的矩形:
需要调用SetBkMode,传TRANSPARENT参数。

2.清除前一次画的矩形:
使用双缓冲,每次重新画整个控件区域,步骤:在后台内存中将背景画成纯的背景色,在上面画矩形,将画的图帖出来。

3.不能画到控件外面去:
画图时使用控件的HDC去画,就不会画到外面了。

up
在类中设置一个CRect成员变量,用于记录上一次绘制的矩形。
在绘制新的矩形前,将上一次绘制的矩形擦除

作者: tttyd   发布时间: 2009-08-20

1.OnLButtonDown(UINT nFlags, CPoint point) 类变量保存一点CPoint m_ptOrigin;
2.OnLButtonUp(UINT nFlags, CPoint point)中用PtInRect判断下m_ptOrigin和point是否在static text中,用背景色把上一次话的矩形在画一次(在类中另设个变量保存),画完再用NULL_BRUSH画这一次的矩形。

作者: zyq5945   发布时间: 2009-08-20

如何擦除前一次的矩形框,能给我段代码吗?谢谢!

作者: happy_jxj   发布时间: 2009-08-21

矩形框就是线组成的,用背景色画线在原来用别的画笔画线的地方话一次,就会覆盖原来话的线,效果就像是清除画线。
C/C++ code
void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    CClientDC dc(this);

    HBRUSH pOldBrush;
    pOldBrush =(HBRUSH)dc.SelectObject(HBRUSH(GetStockObject(NULL_BRUSH)));
    CPen pen,*pOldPen;
    //pen.CreatePen(PS_SOLID,1,dc.GetBkColor()); //用背景色画线,也就是覆盖原来的画线
    pen.CreatePen(PS_SOLID,1,RGB(255,0,0)); //用红色画笔画线
    pOldPen = dc.SelectObject(&pen);
    dc.MoveTo(m_ptOrigin);
    dc.LineTo(point);
    dc.SelectObject(pOldBrush);
    dc.SelectObject(pOldPen);

    CView::OnLButtonUp(nFlags, point);
}

作者: zyq5945   发布时间: 2009-08-21

您给的例子也没有清除上一次的画线啊?

作者: happy_jxj   发布时间: 2009-08-21

m_pParentWnd->InvalidateRect(&oInfoRect);
m_pParentWnd->UpdateWindow();
这样进行清出

作者: churenxh   发布时间: 2009-08-21

我现在用背景色重新画前一次的矩形,怎么画出来的是白色的呢,背景不是白色的啊,新矩形是用黑色笔画的

作者: happy_jxj   发布时间: 2009-08-21

还有一个问题,我发现我画出的矩形位置和我鼠标拖动的位置不一致,矩形有点偏右下方

作者: happy_jxj   发布时间: 2009-08-21

谁知道,请指教

作者: happy_jxj   发布时间: 2009-08-21

引用 14 楼 happy_jxj 的回复:
还有一个问题,我发现我画出的矩形位置和我鼠标拖动的位置不一致,矩形有点偏右下方

应该是没有正确获取鼠标的位置参数。
或者说你获取的鼠标位置是关于别的窗口的,你没有转化成对应你的窗口的坐标位置

作者: tttyd   发布时间: 2009-08-21

窗口之间的左边转换
使用MapWindowPoints函数

作者: tttyd   发布时间: 2009-08-21

窗口之间的坐标转换
使用MapWindowPoints函数

作者: tttyd   发布时间: 2009-08-21

ScreenToClient
ClientToScreen
这两个都是转换坐标的API

作者: zyq5945   发布时间: 2009-08-21

我是新手,对vc还不很熟悉,请高手们帮我看看我的代码,帮我完善一下功能吧,还有代码最好也能优化一下,感觉我的太笨了,谢谢!
CWnd* pWnd = GetDlgItem(IDC_GRAPHSTATIC);
CClientDC dc(pWnd);
CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
CBrush *poldBrush=dc.SelectObject(pBrush);
  CPen pen,*pOldPen;
Tcolor dd;
dd=dc.GetBkColor();
pen.CreatePen(PS_SOLID,1,dc.GetBkColor()); //用背景色画线,也就是覆盖原来的画线
pOldPen = dc.SelectObject(&pen);
dc.Rectangle(CRect(m_oldptOrigin,oldpoint));
dc.SelectObject(poldBrush);
dc.SelectObject(pOldPen);

CBrush *pBrush1=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
CBrush *poldBrush1=dc.SelectObject(pBrush1);
  CPen pen1,*pOldPen1;

pen1.CreatePen(PS_SOLID,1,RGB(0,0,0)); //用黑色画笔画线
   
pOldPen1 = dc.SelectObject(&pen1);

dc.Rectangle(CRect(m_ptOrigin,point));
dc.SelectObject(poldBrush1);
dc.SelectObject(pOldPen1);
m_oldptOrigin=m_ptOrigin;
oldpoint=point;

作者: happy_jxj   发布时间: 2009-08-21

m_ptOrigin是在什么地方赋值的?如何获取的?
还有point

作者: tttyd   发布时间: 2009-08-21

相应OnLButtonDown 和OnLButtonUp消息,记下down和up时的坐标,创建memdc,然后花到memdc上,最后在memdc.BitBlt上来

作者: baodongpo   发布时间: 2009-08-21

m_ptOrigin 是在OnLButtonDown中得到的,上面这段代码是在OnLButtonUp中实现的

作者: happy_jxj   发布时间: 2009-08-21

引用 22 楼 baodongpo 的回复:
相应OnLButtonDown 和OnLButtonUp消息,记下down和up时的坐标,创建memdc,然后花到memdc上,最后在memdc.BitBlt上来



要这么麻烦吗?只是想在控件上画个矩形框选定一块区域

作者: happy_jxj   发布时间: 2009-08-21

引用 24 楼 happy_jxj 的回复:
引用 22 楼 baodongpo 的回复:
相应OnLButtonDown 和OnLButtonUp消息,记下down和up时的坐标,创建memdc,然后花到memdc上,最后在memdc.BitBlt上来



要这么麻烦吗?只是想在控件上画个矩形框选定一块区域

对,一个区域需要两个点来确定,起始点和终点

作者: tttyd   发布时间: 2009-08-21

谁来帮我看看我的代码问题出在哪里?

作者: happy_jxj   发布时间: 2009-08-21

up

作者: happy_jxj   发布时间: 2009-08-22

up上去

作者: happy_jxj   发布时间: 2009-08-24

不懂不懂

作者: fengyingli   发布时间: 2011-11-25