一般都用GDI实现:

void CXiangpijinView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default CView::OnMouseMove(nFlags, point);
if (Lbrndown)
{ CClientDC dc(this);
int oldmode=dc.SetROP2(R2_NOTXORPEN);
CPen pen(PS_SOLID, 2.0, RGB(,,)), *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); } } void CXiangpijinView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default CView::OnLButtonDown(nFlags, point);
Lbrndown=true;
m_ptOrigin = m_ptEnd = point;
}

主要得益于GDI支持SetROP2,绘图模式。

nDrawMode Specifies the new drawing mode. It can be any of the following values:

R2_BLACK   Pixel is always black.

R2_WHITE   Pixel is always white.

R2_NOP   Pixel remains unchanged.

R2_NOT   Pixel is the inverse of the screen color.

R2_COPYPEN   Pixel is the pen color.

R2_NOTCOPYPEN   Pixel is the inverse of the pen color.

R2_MERGEPENNOT   Pixel is a combination of the pen color and the inverse of the screen color (final pixel = (NOT screen pixel) OR pen).

R2_MASKPENNOT   Pixel is a combination of the colors common to both the pen and the inverse of the screen (final pixel = (NOT screen pixel) AND pen).

R2_MERGENOTPEN   Pixel is a combination of the screen color and the inverse of the pen color (final pixel = (NOT pen) OR screen pixel).

R2_MASKNOTPEN   Pixel is a combination of the colors common to both the screen and the inverse of the pen (final pixel = (NOT pen) AND screen pixel).

R2_MERGEPEN   Pixel is a combination of the pen color and the screen color (final pixel = pen OR screen pixel).

R2_NOTMERGEPEN   Pixel is the inverse of the R2_MERGEPEN color (final pixel = NOT(pen OR screen pixel)).

R2_MASKPEN   Pixel is a combination of the colors common to both the pen and the screen (final pixel = pen AND screen pixel).

R2_NOTMASKPEN   Pixel is the inverse of the R2_MASKPEN color (final pixel = NOT(pen AND screen pixel)).

R2_XORPEN   Pixel is a combination of the colors that are in the pen or in the screen, but not in both (final pixel = pen XOR screen pixel).

R2_NOTXORPEN   Pixel is the inverse of the R2_XORPEN color (final pixel = NOT(pen XOR screen pixel)).

原理: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上再次画线了。

注意:如果背景色是白色,那么画出来的线就是画笔的颜色,如果不是白色,线的颜色为笔色与屏幕颜色异或再取反的颜色。

同理只需替换绘图函数就可可以实现矩形、椭圆的橡皮筋效果。

而GDI+不支持SetRop2,

好像说是因为SetRop2只针对光栅,而GDI+不只是用于光栅,要支持打印机等原因。不懂。

一般来说,新的库应该有方法来取代SetRopt2原来的功能。

这就使得画橡皮条非常困难,网上提供了一些方法以及问题:

1/ 使用DllImport,导入SetRop2  : 结合GDI绘图,这违背了GDI+删去SetRop2的本意。

2/ 更新从起始点到结束点的整个块状区域 : 我觉得为了一条线而刷新整个区域是很愚蠢的事情,虽然可以使用双缓冲等等技术

3/ 使用一个ErasePen和一个DrawPen,ErasePen和背景同色 : 这个方法很有问题,当和其他线条相交时会擦去原来的线条

不知道为什么要把SetRop2去掉。

我自己实现的使用双缓冲来实现橡皮条

void CXiangpijinView::OnDraw(CDC* pDC)
{
CXiangpijinDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here GetClientRect(&rc);
Graphics Gp(pDC->m_hDC);
SolidBrush mybrush(Color( ,,));
Gp.FillRectangle(&mybrush,,,rc.Width(),rc.Height());
Gp.ReleaseHDC(hMemDC); HBITMAP hBitmap,hOldBitmap;
//建立一个屏幕设备环境句柄
hMemDC=CreateCompatibleDC(pDC->m_hDC);
//建立一个与屏幕设备环境句柄兼容、与鼠标指针所在窗口的区域等大的位图
hBitmap=CreateCompatibleBitmap(pDC->m_hDC,rc.Width(),rc.Height());
//把新位图选到内存设备描述表中
hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap);
//把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC,,,rc.Width(),rc.Height(),pDC->m_hDC,,,SRCCOPY); }
void CXiangpijinView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default CView::OnMouseMove(nFlags, point);
if (Lbrndown)
{ BitBlt(GetDC()->m_hDC,0,0,rc.Width(),rc.Height(),hMemDC,0,0,SRCCOPY);
   Graphics Gp3(GetDC()->m_hDC);
        Pen mypen(Color(0,255,0),2.0);
   Gp3.DrawLine(&mypen,m_ptOrigin.x,m_ptOrigin.y,point.x,point.y);  
     Gp3.ReleaseHDC(GetDC()->m_hDC); } } void CXiangpijinView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default CView::OnLButtonDown(nFlags, point);
Lbrndown=true;
m_ptOrigin = m_ptEnd = point;
} void CXiangpijinView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default CView::OnLButtonUp(nFlags, point);
//把新的DC拷贝到hMemDC
BitBlt(hMemDC,,,rc.Width(),rc.Height(),GetDC()->m_hDC,,,SRCCOPY); }

主要原理是绘图前把屏幕DC内容拷贝到兼容的内存位图中,绘图时把兼容dC 上的内容拷贝到屏幕,然后在在当前DC上绘图,一次绘制结束再把 DC上拷贝到兼容DC上。

常用绘图操作

m_map = new Bitmap(rc.Width(),rc.Height());

Pen mypen(Color(0,255,0),2.0);

m_Gpp = new Graphics(m_map);

m_Gpp->DrawEllipse(&mypen,po.X,po.Y,8.0,8.0);

Graphics Gp3(GetDC()->m_hDC);

Gp3.DrawImage(m_map,0,0);

Gp3.ReleaseHDC(GetDC()->m_hDC);

mFC 橡皮线的更多相关文章

  1. VC++ MFC橡皮筋技术

    在MFC下绘制直线,使用橡皮筋技术,可以使直线效果跟随鼠标移动 //OnLButtionDown        m_ptOrigin = m_ptEnd = point;  //OnMouseMove ...

  2. vs2010静态链接MFC库报链接错误

    由于需要将MFC程序在其它电脑上运行,所以需要将动态链接的MFC改成静态链接,本以为很简单,没想到链接的时候出现下面的链接错误: uafxcw.lib(afxmem.obj) : error LNK2 ...

  3. MFC中成员变量的声明顺序与析构顺序

    第一次用博客,第一篇随笔,就写今天遇到的一个问题吧. 在VS2008的MFC对话框程序,窗口成员变量的声明顺序与其析构顺序相反,即,先声明的变量后析构,后声明的变量先析构.未在其他模式下测试. cla ...

  4. VC中的MFC到底是什么?

    1. 微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class libraries),以C++类的形式封装了Windows API ...

  5. MFC&Halcon之实时视频监控

    上一篇实现了在MFC的窗体内显示图片,本篇介绍如何在MFC窗体内实时显示摄像头的影像. 要实现的功能是点击一个“开始”按钮,可以显示影像,再点击“停止”按钮,可以停止显示. 因为实时显示影像需要在一个 ...

  6. MFC快速入门 - 菜单

    本文仅用于学习交流,商业用途请支持正版!转载请注明:http://www.cnblogs.com/mxbs/p/6231104.html 打开VS2010,依次打开File – New – Proje ...

  7. MFC画线功能总结

    本文仅用于学习交流,商业用途请支持正版!转载请注明:http://www.cnblogs.com/mxbs/p/6216464.html MFC画线功能要点有二:其一,鼠标按下时记录初始位置为线的起始 ...

  8. MFC消息映射机制以及画线功能实现

    ---此仅供用于学习交流,切勿用于商业用途,转载请注明http://www.cnblogs.com/mxbs/p/6213404.html. 利用VS2010创建一个单文档标准MFC工程,工程名为Dr ...

  9. mfc+vtk

    MFC中view类主要处理显示视图,doc类处理文档,mainframe主要为整个窗口的和工程的设置管理.由此,VTK与MFC联合编程时,需要主要的是数据操作,以及显示要很好的与MFC中的结构结合,做 ...

随机推荐

  1. EXP 导出出错解决方案

    前言: 今天想要把 当前用户下的数据库 导出来,使用命令 导出数据库可用语句: exp bpmp/bkc123@127.0.0.1:5050/bkcyunty file=D:\bak\db_61.dm ...

  2. Spring Cloud 微服务的那点事

    什么是微服务 微服务的概念源于2014年3月Martin Fowler所写的一篇文章“Microservices”. 微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调 ...

  3. 关于ARM NEON学习的一些资料

    在对基于ARM-v7处理器及以上的程序进行优化时,可以使用neon优化技术来加速程序.不过搞这个的人比较少,所以网上有用的资料很稀少.我翻了半天国内国外的博客,发现还是ARM公司的帮助网站最有用: h ...

  4. 【WP8】自定义EventAggregator

    MVVM模式实现了ViewModel和View的分离,但是有很多时候我们需要进行页面间通信 比如,我们在设置界面修改了某个项的值,需要同步到主页面,让主页面做相关的逻辑,由于每个页面对应一个ViewM ...

  5. json字符串使用注意问题

    json本身是字符串,即 json字符串 js使用 要把 json字符串 转为  javascript对象 json字符串转为js对象的方法:jquery的parseJSON var str='[{& ...

  6. Oracle-10.2.0.1,打补丁10.2.0.5:在 debian 版本4【不含4】以上,及 ubuntu 7.04【不含7.04】以上都可以安装!

    如题. todo 特殊的:ubuntu 16.04 LTS 版本 无法安装成功,原因待查找!!! 最近测试练习安装linux x64上的 oracle10.2.0.5, 都要吐了.

  7. Python 程序员都会喜欢的 6 个库

    在编程时,小挫折可能与大难题一样令人痛苦.没人希望在费劲心思之后,只是做到弹出消息窗口或是快速写入数据库.因此,程序员都会喜欢那些能够快速处理这些问题,同时长远来看也很健壮的解决方案. 下面这6个Py ...

  8. oop思维意识,类 模块命名空间,类扩展之继承 、组合、mixin三种模式

    python的书都是讲怎么创建类怎么实例化对象,一般会用使用了,但还不具备这种编程意识.这是从python学习手册第四版节选出来的,书中说oop不仅是一种技术,更是一种经验.学习大神的看法,为什么需要 ...

  9. UML类图关系(转,添加了实例)

    UML类图关系(泛化 .继承.实现.依赖.关联.聚合.组合) 在UML类图中,常见的有以下几种关系: 泛化(Generalization),  实现(Realization),关联(Associati ...

  10. 探究Visual Studio生成的.vs文件夹内部结构和作用

    https://shiyousan.com/post/636441130259624698 在某个契机的引发下,对VS解决方案中自动生成的.vs文件夹产生了兴趣,以前总对这个文件夹不怎么上心,最近正好 ...