MiniDraw的一些小总结

之前接触过MFC,但是,那是很久之前的事了,起码有一年多,而且之前的也是非常皮毛的...

这次是狠下心来要好好学学MFC,因为以后要用到....

第一次实现的是一个MiniDraw小程序,实现画直线、椭圆、矩形、根据鼠标移动画线、多边形还有撤销上一操作


问题一:拖动画直线------绘图模式!

其实拖动画直线的原理在于,每次拖动都是画线两次,一次是使用和背景颜色一样的画笔画,即达到擦除的效果,另外一次则是画出当前鼠标停留处与起点之间的直线。我在里面使用的是R2_XORPEN这种模式,其实也可以用R2_NOT,但是在鼠标移动的时候,当图元相交时,会出现空白这种情况...因为是采用与背景颜色相反嘛...


这里碰到的问题是设置绘图模式。CDC::SetROP2 这个函数是用来设置绘图模式的,就是这个设置不同,所以会得出不懂得效果,这里记下各种模式:

绘图模式nDrawMode的取值
符号常量
作用
运算结果
R2_BLACK
黑色
pixel = black
R2_WHITE
白色
pixel = white
R2_NOP
不变
pixel = scCol
R2_NOT
反色
pixel = ~scCol
R2_COPYPEN
覆盖
pixel = pbCol
R2_NOTCOPYPEN
反色覆盖
pixel = ~pbCol
R2_MERGEPENNOT
反色或
pixel = ~scCol | pbCol
R2_MERGENOTPEN
或反色
pixel = scCol | ~pbCol
R2_MASKNOTPEN
与反色
pixel = scCol & ~pbCol
R2_MERGEPEN
pixel = scCol | pbCol
R2_NOTMERGEPEN
或非
pixel = ~(scCol | pbCol)
R2_MASKPEN
pixel = scCol & pbCol
R2_NOTMASKPEN
与非
pixel = ~(scCol & pbCol)
R2_XORPEN
异或
pixel = scCol ^ pbCol
R2_NOTXORPEN
异或非
pixel = ~(scCol ^ pbCol)
其中,R2_COPYPEN(覆盖)为缺省绘图模式,R2_XORPEN(异或)较常用。

问题二:实现画出鼠标移动路径(即自由画线)-----封装!
一开始,对于这个,我想到的是使用vector来存储鼠标的点,然后,如果有多条线的话,那么就设置一个标志点分开比如(-1,-1)这种坐标点。这种想法我实现了,但是,别人给的建议是把这个也封装,这样子才和OOD的思想吻合。最后,我也把这种图元封装。其实,从空间上来说,两者开销差不多,可以说是相等,因为前者使用特殊坐标存储结束标志,后者使用了指针指向这个对象。但是,确实是后者简便一些,因为这样可以使得所有的图元都是继承于一个基类,然后使用这个基类指针指向各个图元对象,从而调用画图命令。后者更有条理 (当然,这是相对于编程语言来说的),而且,后者的代码量要少一些,可读性也强一些

问题三:内存泄漏----虚析构函数!
使用基类指针指向派生类时,delete的时候小心内存泄漏。基类的析构函数最好是设成虚析构函数。这里涉及到两个概念:
动态绑定:动态绑定是指在执行期间(非编译期)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法
静态绑定:所谓静态绑定是指在程序编译过程中,把函数(方法或者过程)调用与响应调用所需的代码结合的过程称之为静态绑定。
这是摘自百科的定义,其实,针对我自己的程序,说得白话一点就是:
不用虚,则静态绑定,根据指针类型决定调用函数
用虚,则动态绑定,根据指向的类型调用函数
一下面用一个别人的例子说明:
#include <iostream>
using namespace std;

class Base
{
public:
       Base( void )
       {
             cout << "Base::Base( )" << endl;
       }
       
       virtual ~Base( void ) //基类有虚析构函数时

       {
              cout << "Base::~Base( )" << endl;
       }
};

class Derived : public Base
{
public:
       Derived( void )
       {
                m_pData = new int;
                cout << "Derived::Derived( )" << endl;
       }
       
       ~Derived( void )
       {
                delete m_pData;
                m_pData = NULL;
                cout << "Derived::~Derived( )" << endl;
       }
private:
        int* m_pData;
};

int main( void )
{
    Derived* pD = new Derived;
    
 	Base* pB = pD;
 	
 	//通过基类的指针去删除派生类的对象,而基类有虚析构函数时

 	delete pB;
 	pB = NULL;
    
 	system( "PAUSE" );
 	return EXIT_SUCCESS;
}

/*-------派生类的析构函数被调用,派生类的对象被回收
Base::Base( )
Derived::Derived( )
Derived::~Derived( )
Base::~Base( )
请按任意键继续. . .
---------------------------------*/
所以,基类一定要注意使用虚析构函数!!!

问题四:结束的标志---画多边形
做之前,运行过两个别人的demo,我发现,存在的问题都是,画多边形的时候,停不下来,只是多个点的一直在连线,第一个只能选取画其他图元的时候能结束画一个多边形,而第二个也是这样能退出,但是,如果点击撤销,就会崩掉....
所以,算是前车之鉴,我设置了鼠标右键作为一个多边形结束的标志

问题五:自身的一些问题!
对于写代码的效率,我还需要提高啊....以前就是一直存在这个问题,今后要改一改,就像赖床和一觉睡到大中午的坏习惯一样,必须改!再者,我需要看一些C++的书,毕竟很久没有写C++了,所以需要一点点捡回来...写博客也是为了做一个记录


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值