VC++ MFC橡皮筋技术

在MFC下绘制直线,使用橡皮筋技术,可以使直线效果跟随鼠标移动

//OnLButtionDown
       m_ptOrigin = m_ptEnd = point; 
//OnMouseMove
    CClientDC dc(this);
    if (nFlags == MK_LBUTTON )
    {
        dc.SetROP2(R2_NOT);
        dc.MoveTo(m_ptOrigin);
        dc.LineTo(m_ptEnd);
        m_ptEnd = point;
        dc.MoveTo(m_ptOrigin);
        dc.LineTo(m_ptEnd);
    } 
但是这个只能实现黑色直线的绘制,我们想要画其他颜色的线,并且希望使用不同类型的线和线宽,因此要建一个画笔,指定想要的画笔的类型,如实线、虚线、点线,指定线宽和画笔颜色。
void CGraphic1View::OnMouseMove(UINT nFlags, CPoint point) 
{    
    if(MK_LBUTTON == nFlags)
    {
        CClientDC dc(this);
        int oldmode=dc.SetROP2(R2_NOTXORPEN);
        CPen pen(m_nLineStyle, m_nLineWidth, m_clr), *oldpen;
        oldpen = dc.SelectObject(&pen);

        dc.MoveTo(m_ptOrigin);
        dc.LineTo(m_ptEnd);

        m_ptEnd=point;

        dc.MoveTo(m_ptOrigin);
        dc.LineTo(m_ptEnd);

        dc.SelectObject(oldpen);
        dc.SetROP2(oldmode);
        ReleaseDC(&dc);
    }
    CScrollView::OnMouseMove(nFlags, point);
}
其中
CPen pen(m_nLineStyle, m_nLineWidth, m_clr), *oldpen;
m_nLineStyle是线型,m_nLineWidth是线宽,m_clr是画笔颜色,也可以指定如下:
CPen pen(0, 0, RGB(255, 0, 0)), *oldpen;

 

下面说一下,橡皮筋效果是如何实现的。当我们按下鼠标左键后,有m_ptOrigin = m_ptEnd = point; 
这时鼠标移动就会发送WM_MOUSEMOVE消息,调用OnMouseMove进行处理,我们就在这个响应函数中实现橡皮筋的效果。if(MK_LBUTTON == nFlags)判断是否左键按下的鼠标移动。SetROP2函数主要用于设定当前前景色的混合模式。参数取值R2_NOT就是取反的意思,即前景色为背景色的反色,经常用R2_NOT来画橡皮线,因为两次取反可以还原背景色,但是只能话黑色的线。

而R2_NOTXORPEN画出来的颜色与R2_XORPEN相反,R2_XORPEN是屏幕颜色和画笔颜色的异或。OnMouseMove第一次被调用时,还没画线,所以屏幕的颜色是白色的,R2_XORPEN是当前画笔的颜色取反,那么R2_NOTXORPEN就是当前画笔颜色了。就是说第一次画的线是画笔的颜色。

第二次调用OnMouseMove时,m_ptOrigin和m_ptEnd两个点还没变,所以可以用这两个点再画线,将第一次画的线覆盖掉,变成画布的颜色,然后在新的point点和m_ptOrigin之间重新画线,颜色为画笔颜色。在旧的直线上面画线,因为线本来有颜色,所以R2_XORPEN(屏幕的颜色==画笔颜色)就会变成黑色(1 xor 1=0,0 xor 0=0),取反,即R2_NOTXORPEN为白色,就是画布的颜色,看起来就像消失了一样,其实只不过是线变成白色了(如果画笔不是白色,比如使用你系统设置了护眼配色,客户区变成不伤眼的浅绿色,这样显示出来的颜色还是白色,而不是客户区的颜色)。旧的直线删除了,就可以在新的点point上再次画线了。

 

扩展:如果想实现矩形、椭圆的橡皮筋效果将语句

dc.MoveTo(m_ptOrigin);    
dc.LineTo(m_ptEnd);
换成:
dc.Rectangle(CRect(this->m_ptOrigin, m_ptEnd));
或者
dc.Ellipse(CRect(this->m_ptOrigin, m_ptEnd));
就可以了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值