MFC第4课

4课绘图之一API画线【参考资料:孙鑫VC++教学视频】

 

我们仍旧开始直接实践:

★相关的知识是绘图方面的知识

现在用VC6直接实践一下MFC编程:

1、程序类型MFC AppWizard(exe)类型;

2、选择Single Document单文档应用程序

3、完成

 

第一项功能:绘制直线;

可以在框架类和视类里面捕获消息:

首先在框架类CMainFrame捕获消息按下左键:

第一步:增加鼠标左键消息响应;

对类名右键:New Window Message and Event handlers for class CMainFrame.

void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

 MessageBox("main frame"); 

         CFrameWnd::OnLButtonDown(nFlags, point);

}

但是,在这个函数中写了 MessageBox("main frame"); 运行后却没有反应,为什么?

view类里面同样增加一个鼠标左键按下响应函数:

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)

{

      // TODO: Add your message handler code here and/or call default

      MessageBox("view frame");

      CView::OnLButtonDown(nFlags, point);

}

当我们运行后,对鼠标左键就有响应了一个警告框;

★注意:用class wizard也能增加消息响应函数;

在框架类和视类里面的响应函数都存在,不妨碍;

原因:view类在框架类之上,覆盖在框架类之上

 

第一趟:

消息循环,就是把消息放在消息队列当中。

 

 

消息映射,对消息的处理。

一,              在基类,对每一种消息,做一个虚函数,当响应的时候,只要重写虚函数就可以了。调用子类的,子类没有的,就调用父类的。子类都背负一个虚表。

二,              消息机制,MFC在后台维护了一个句柄,和C++类对象的对照的一个表。

虚函数 WindowProc函数对消息来处理。

 

OnWndMsg

 

双击一下CDrawView 就直接到了头文件里。

 

在用Ctrl+F 搜索的时候,按F3继续搜索。

 

 

第二步:用菜单命令增加私有成员变量CPoint  m_ptOrigin=0; 初始化为0

响应鼠标左键按下函数为:

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)

{

      // TODO: Add your message handler code here and/or call default

      // 按下去的时候是起点

      m_ptOrigin = point;

      CView::OnLButtonDown(nFlags, point);

}

第三步:用菜单命令增加鼠标左键up响应函数   Add Handler 处理器 + Edit Existing 编辑现成的。

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

      

       CView::OnLButtonUp(nFlags, point);

}

这里面的点就是画线的终点;改变代码如下:

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       //弹起来的时候是终点

       HDC hdc;

       hdc=::GetDC(m_hWnd);

       //将设备移动到起点

       MoveToEx(hdc, m_ptOrigin.x, m_ptOrigin.y, NULL);

       LineTo(hdc, point.x, point.y);

       //释放设备

       ::ReleaseDC(m_hWnd, hdc);

 

       CView::OnLButtonUp(nFlags, point);

}

 

以上我们采用了API函数,也就是全局函数来完成的;

API函数和类的成员函数都有ReleaseDC函数,所以调用API函数就要特别用作用域符号注明是API函数,如果不同名,则可以直接用;

实例: ::ReleaseDC(m_hWnd, hdc);

 

 

 4课绘图之二用CDC类画线【参考资料:孙鑫VC++教学视频】

 

MFC中所有画图的功能都集成到了CDC这个类中:

 

CDC类绘制直线;

仍旧在视类里面捕获消息:

 

注意:画线的代码发生变化,其余步骤不变;

 

直接修改鼠标左键up响应函数

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       //弹起来的时候是终点

       CDC *pDC=GetDC();

 

       //将设备移动到起点

       pDC->MoveTo(m_ptOrigin);

       pDC->LineTo(point);

       //释放设备

       ReleaseDC(pDC);

      

       CView::OnLButtonUp(nFlags, point);

}

以上我们采用了CDC类画线,看起来很简洁;

 

4课绘图之三CClientDC画线【参考资料:孙鑫VC++教学视频】

 

CClientDC类是从CDC这个类派生出来的;

优点:构造函数中调用GetDC;析构函数调用ReleaseDC

也就是说用CClientDC类,就不用显示调用DetDCReleaseDC函数;

 

CClientDC绘制直线;

仍旧在视类里面捕获消息:

 

注意:画线的代码发生变化,其余步骤不变;

 

直接修改鼠标左键up响应函数

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       //弹起来的时候是终点

       CClientDC dc(this);

 

       //将设备移动到起点

       dc.MoveTo(m_ptOrigin);

       dc.LineTo(point);

 

       CView::OnLButtonUp(nFlags, point);

}

以上我们采用了CClientDC类画线,看起来更简洁;

this指针传递,表示在CDrawView上做图;

 

下面 我想和CMainFrame类相关,如何获取父窗口的指针?

 

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

      // TODO: Add your message handler code here and/or call default

      //弹起来的时候是终点

      CClientDC dc(GetParent());//父类的,会在框架窗口,会画在工具栏上。

 

      //将设备移动到起点

      dc.MoveTo(m_ptOrigin);

      dc.LineTo(point);

 

      CView::OnLButtonUp(nFlags, point);

}

 

4课绘图之四CWindowDC画线【参考资料:孙鑫VC++教学视频】

 

CWindowDC类是从CDC这个类派生出来的;

优点:构造函数中调用GetDC;析构函数调用ReleaseDC

也就是说用CClientDC类,就不用显示调用DetDCReleaseDC函数;

可以访问整个屏幕区域,包括客户区和非客户区;

CWindowDC绘制直线;

仍旧在视类里面捕获消息:

 

注意:画线的代码发生变化,其余步骤不变;

 

直接修改鼠标左键up响应函数

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       //弹起来的时候是终点

       CWindowDC dc(GetParent());

 

       //将设备移动到起点

       dc.MoveTo(m_ptOrigin);

       dc.LineTo(point);

 

       CView::OnLButtonUp(nFlags, point);

}

在标题栏+菜单栏上(非客户区)可以访问整个屏幕。 

能否画到vc上,或者桌面上?

桌面本身就是一个窗口。

 

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

      // TODO: Add your message handler code here and/or call default

      //弹起来的时候是终点

      CWindowDC dc(GetDesktopWindow());

 

      //将设备移动到起点

      dc.MoveTo(m_ptOrigin);

      dc.LineTo(point);

 

      CView::OnLButtonUp(nFlags, point);

}

则可以画到vc上,或者桌面上;

 

4课绘图之五CPen修改颜色【参考资料:孙鑫VC++教学视频】

 

★如何画其他颜色的线条?

 

CPen修改颜色

仍旧在视类里面捕获消息:

 

注意:画线的代码发生变化,其余步骤不变;

 

 

RGB这个宏 参数三个  红绿蓝 三个值的改变来调整颜色。

 

直接修改鼠标左键up响应函数

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       //弹起来的时候是终点

       CPen pen(PS_SOLID, 1, RGB(255, 0, 0));  // 创建一个画笔

       CClientDC dc(this); 

       CPen *pOldPen=dc.SelectObject(&pen);   //这个笔选在设备表

 

       //将设备移动到起点

    dc.MoveTo(m_ptOrigin); 移动到原点。

    dc.LineTo(point);    终点

 

       dc.SelectObject(pOldPen); 先前的画笔选择

 

       CView::OnLButtonUp(nFlags, point);

}

这是画出红色的直线;

 

阴影线 粗细只能1或者更小

 

以下代码是设置新笔,保存旧的笔;

CPen *pOldPen=dc.SelectObject(&pen);

 

4课绘图之六CBrush填充区域【参考资料:孙鑫VC++教学视频】

 

★如何矩形区域区域颜色?

 

CBrush填充区域

仍旧在视类里面捕获消息:

 

注意:画线的代码发生变化,其余步骤不变;

 

直接修改鼠标左键up响应函数

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

      

       CBrush brush(RGB(255,0,0));

       CClientDC dc(this);

       dc.FillRect(CRect(m_ptOrigin, point), &brush);

//用指定的画刷来填充指定的矩形 ,当然也有自己缺省的画刷。

    不用将brush选中在设备描述表中。都是指定的!! 指定的画刷,指定的矩形区域。

       CView::OnLButtonUp(nFlags, point);

}

这是画出红色的矩形;

 

下面讨论位图画刷:

首先要添加一个位图资源,insert菜单里面resource,添加new了一个Bitmap,它的资源IDIDB_BITMAP1,程序如下:

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

      

       CBitmap bitmap;

       bitmap.LoadBitmap(IDB_BITMAP1);        加载这幅位图。

       CBrush brush(&bitmap);       创建位图的画刷,位图对象的指针。

 

       CClientDC dc(this);

       dc.FillRect(CRect(m_ptOrigin, point), &brush);

 

       CView::OnLButtonUp(nFlags, point);

}

 

 

4课绘图之七透明画刷【参考资料:孙鑫VC++教学视频】

 

★如何矩形区域不相互遮挡?

 

CBrush透明画刷

仍旧在视类里面捕获消息:

 

注意:画线的代码发生变化,其余步骤不变;

 

直接修改鼠标左键up响应函数

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

      

       CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));//获取透明画刷对象指针   

       CClientDC dc(this);

       CBrush *pOldBrush=dc.SelectObject(pBrush);      //将透明画刷选入DC

 

       dc.Rectangle(CRect(m_ptOrigin,point));           //画矩形

       dc.SelectObject(pOldBrush);                    //释放透明画刷

 

       CView::OnLButtonUp(nFlags, point);

}

 

画出的矩形相互不遮挡,也就是透明的;

 

★★★★★注意点:

1)静态方法不属于某一个具体对象,而属于类本身,在类加载的时候就已经为类静态方法分配了代码去,故可用CBrush::FromHandle()形式调用。非静态的方法,是属于某个对象的。

2)静态方法中,不能引用非静态的数据成员和方法。

3)静态数据成员需要在类外单独做初始化,形式如: 变量类型 类名::变量名=初始值;

 

4课绘图之八曲线【参考资料:孙鑫VC++教学视频】

 

★如何绘制拖动的曲线?

 

绘制拖动的曲线

第一步:增加一个BOOL m_bDraw;

在构造函数中m_bDraw=FALSE;

鼠标左键按下down响应函数中设置m_bDraw=TRUE;

用这个变量表示鼠标按下;

CDrawView::CDrawView()

{

      // TODO: add construction code here

      m_ptOrigin=0;

      m_bDraw=FALSE;   鼠标起来的时候

}

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)

{

      // TODO: Add your message handler code here and/or call default

      // 按下去的时候是起点

      m_ptOrigin = point;

      m_bDraw=TRUE;  鼠标按下去的时候

      CView::OnLButtonDown(nFlags, point);

}

增加鼠标左键move响应函数,用右击菜单栏添加

void CDrawView::OnMouseMove(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

      

       CClientDC dc(this);

       if(m_bDraw==TRUE)

       {

              dc.MoveTo(m_ptOrigin);  移动到原点,就是第一次按下去的时候

              dc.LineTo(point);

              m_ptOrigin=point;   下一个起点就是上一个终点

       }

       CView::OnMouseMove(nFlags, point);

}

 

 

SetROp2 是在CDC来的。绘画的模式的设置。

你可能感兴趣的:(MFC,MFC第4课)