虚拟商品交易网站建设,做外贸推广,做网站优化给业务员提成,谷雨网页设计作业目录
一.创建单文档项目
二.消息映射机制
三.WM_PAINT消息触发
四.CVIEW类
五.设备上下文
六.资源类和资源的关系
七.画线#xff0c;矩形
八.画布
九.画笔
十.画刷
十一.利用TRACE打印日志
十二.文本编程
十三.ID号
十四.菜单栏
十五.菜单命令路由
十六.工具…目录
一.创建单文档项目
二.消息映射机制
三.WM_PAINT消息触发
四.CVIEW类
五.设备上下文
六.资源类和资源的关系
七.画线矩形
八.画布
九.画笔
十.画刷
十一.利用TRACE打印日志
十二.文本编程
十三.ID号
十四.菜单栏
十五.菜单命令路由
十六.工具栏 一.创建单文档项目
应用程序选择 文档模板属性 用户界面功能 高级功能 生成的类会生成 APPVIEWDOCMainFrame 因为这两个项目在同一个解决方案下面所以把MFCPaint设置为启动项目
编译MFCPaint项目 二.消息映射机制
在 MFCPaintView.h 文件中记录了 MFCPaintView 类的原型在 MFCPaintView.cpp 中记录 MFCPaintView 类的实现虚函数的实现消息映射机制。源码如下
BEGIN_MESSAGE_MAP(CMFCPaintView, CView)ON_WM_CONTEXTMENU()ON_WM_RBUTTONUP()ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_MOUSEMOVE()ON_WM_CREATE()ON_WM_CHAR()
END_MESSAGE_MAP()
一些消息比如 WM_PAINT这样的消息又框架封装自动处理这个消息映射到OnDraw函数处理这个函数在CView中是虚函数MFCPaintView中仍然是虚函数但在MFCPaintView实例化时进行了实现。还有一些消息的处理需要依赖消息映射表来处理
在 BEGIN_MESSAGE_MAP 宏中CMFCPaintView 是接收消息的类而 CView 则是基类。 CMFCPaintView表示接收消息的类也称为派生类。在这个例子中CMFCPaintView 是自定义的视图类是从 MFC 框架提供的 CView 类派生而来的。CMFCPaintView 类扩展了 CView 类的功能并可以添加自定义的成员函数、变量和逻辑。 CView表示基类也称为父类或者超类。在这个例子中CView 是 MFC 框架中的一个类用于实现视图。它提供了一些基本的功能和接口包括绘图、响应用户输入、窗口管理等。CMFCPaintView 类通过派生自 CView 类继承了 CView 类的功能并可以在派生类中进行扩展和自定义。
通过将 CMFCPaintView 作为接收消息的类我们可以在 CMFCPaintView 类中定义消息处理函数并将它们与相应的消息进行关联。当窗口接收到对应的消息时框架会自动调用相应的处理函数来处理该消息。
而 CView 则是作为基类在宏的第二个参数中提供给 BEGIN_MESSAGE_MAP它是处理消息的起点当消息映射表中的消息没有匹配到具体的处理函数时框架会继续向基类查找直到找到匹配的处理函数或者到达消息映射表的末尾。这样的设计使得消息处理可以在派生类和基类中灵活地进行组织和划分。
给消息映射表添加映射MFCPaintView右键选择属性选择消息选择想要添加的消息即可 比如添加 WM_CHAR消息处理就会在MFCPaintView中添加一个函数
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg 是 MFC 框架中的一个宏用于声明一个消息处理函数。在 MFC 中消息处理函数需要使用 afx_msg 宏进行声明以便正确连接到消息映射机制。
在MFCPaintView中就会添加一个方法。 三.WM_PAINT消息触发
WM_PAINT 消息是 Windows 操作系统发送给窗口的一个重要消息它用于通知窗口需要进行绘图操作。当窗口的客户区域即窗口内部可以进行绘图操作的区域需要刷新或重绘时Windows 就会发送 WM_PAINT 消息给窗口以便窗口进行相应的绘图操作。
WM_PAINT 消息的触发通常由以下几种情况引起 窗口首次创建当一个窗口首次被创建时Windows 会自动发送 WM_PAINT 消息给窗口以便对窗口进行初始的绘图操作。 窗口被激活当一个窗口从非激活状态转换为激活状态时Windows 会发送 WM_PAINT 消息给窗口以便窗口可以重新绘制自己。 窗口尺寸变化当窗口的大小发生变化时Windows 会发送 WM_PAINT 消息给窗口以便窗口可以根据新的大小来重新绘制自己。 窗口重叠变化当窗口与其他窗口发生重叠变化时或者其他窗口遮盖了部分窗口的客户区域时Windows 会发送 WM_PAINT 消息给被遮盖的窗口以便窗口可以重新绘制被遮盖的区域。 窗口被显式地要求重绘开发人员可以通过调用 InvalidateRect 或 InvalidateRgn 函数来显式地要求窗口进行重绘操作。当这些函数被调用时Windows 会发送 WM_PAINT 消息给窗口。
当窗口接收到 WM_PAINT 消息时通常会执行以下操作 开始绘图操作通过调用 BeginPaint 函数来获取一个设备上下文DC以便进行后续的绘图操作。 绘制内容使用获取到的设备上下文进行绘图操作包括绘制图形、文本、图像等。 结束绘图操作通过调用 EndPaint 函数来释放设备上下文并通知系统绘图操作已完成。
在MFC消息映射表没有WM_PAINT的映射WM_PAINT是如何调用OnDraw()函数处理
在 MFC 中如果消息映射表中没有 WM_PAINT 的映射框架会自动调用 CWnd::DefWindowProc 函数来处理该消息进而调用 OnPaint 函数来进行绘图操作。所以即使没有显式地映射 WM_PAINT 消息我们也可以在 OnDraw 函数中实现窗口绘图。 四.CVIEW类
CView 类是 MFCMicrosoft Foundation Classes框架中的一个基类用于实现视图View的功能。在 MFC 应用程序中视图通常用于显示和处理用户界面的可视化部分。
CView 类是从 CWnd 类派生而来的因此它继承了 CWnd 类的一些基本窗口功能。CView 类主要用于以下几个方面的功能 绘图CView 类提供了 OnDraw 函数用于绘制视图内容。开发人员可以重写该函数在其中使用 GDI图形设备接口绘制图形、文本、位图等。绘图操作可以响应窗口消息如 WM_PAINT也可以通过代码触发。 响应用户输入CView 类可以处理鼠标、键盘等用户输入消息。开发人员可以重写 OnMouse...、OnKey... 等函数来响应相应的用户输入事件并执行相应的操作。 布局管理CView 类可以用于管理视图的布局。开发人员可以通过调整控件的位置、大小、对齐方式等属性来控制视图元素的布局和外观。 与文档类的交互CView 类通常与文档类CDocument紧密相关。视图类负责将文档类中的数据呈现给用户并将用户的修改反馈给文档类。开发人员可以通过重写 OnUpdate 函数实现视图的数据更新和刷新。 与框架交互CView 类还可以与 MFC 框架中的其他类进行交互如与窗口类CFrameWnd进行通信、与菜单类CMenu进行菜单操作、与工具栏类CToolBar进行工具条操作等。
也就是说CVIEW主要控制程序的视图元素。使用VS2019时就会自动的生成一个类继承自这个类我们在编写程序时只需要注意处理消息即可在类中对消息处理的实现最后往往会再调用一个CVIEW中的消息对应处理方法。因为系统往往只会给一次消息对这个消息可以有多个类进行处理而且处理都不一样这就是再调用一次的作用。 五.设备上下文
设备上下文Device Context简称 DC是一个抽象概念用于表示用于绘图和输出的设备环境。设备上下文封装了与设备相关的绘图表面、画笔、字体、剪辑区域等信息提供了一组函数和属性用于在特定设备上进行绘图操作。
设备上下文是由操作系统提供的它可以代表不同类型的设备如显示器、打印机、屏幕缓冲区等。每个设备上下文都有自己的属性和功能可以通过设备上下文进行绘制、填充、剪辑、文本输出等操作。
在 Windows 应用程序开发中设备上下文通常用于使用 GDI图形设备接口进行绘图。GDI 提供了一组函数和数据结构用于在设备上进行绘图操作。设备上下文是 GDI 中的核心概念通过设备上下文可以获取和操作设备相关的绘图资源如画笔、画刷、字体等。
在 MFCMicrosoft Foundation Classes框架中设备上下文由 CDCCDC 类型的指针表示。CDC 类封装了设备上下文操作的功能例如绘图、调色板管理、文本输出等。通过获取设备上下文指针可以使用 CDC 类的成员函数来进行相应的绘图操作。
设备上下文的使用是有一定规则的例如在使用完设备上下文后需要释放相关资源避免资源泄露。通常在获取设备上下文之后需要调用 ReleaseDC() 或者 DeleteDC() 函数来释放设备上下文。
获取设备上下文
void CMyView::OnDraw(CDC* pDC)
{// 获取设备上下文指针CDC* pDC GetDC();// 使用设备上下文进行绘图操作// ...// 释放设备上下文资源ReleaseDC(pDC);
}CDC类中提供了很多系统调用如获取资源设置资源等等。 六.资源类和资源的关系
资源则是具体的实际资源可以是文件、图像、音频、数据库连接等等它是应用程序所需要的资料或者工具。资源可以以不同的形式存在例如在内存中、硬盘上、网络上等。它们可以被资源类所管理和操作。
资源类通过对资源进行封装和抽象提供了一种统一的接口和管理方式使得应用程序能够更方便地访问和利用资源。资源类可以对资源进行创建、加载、释放、更新等操作同时还可以提供一些额外的功能如缓存、安全性控制、多线程支持等。
资源类就像是对资源所用的一些属性等信息进行抽象可以提供对类实例化设置属性来设置资源的属性再通过系统调用来使用资源释放资源。 七.画线矩形
想要实现画线功能需要捕捉到鼠标左键摁下鼠标左键抬起的位置就可以绘制处一条直线。
还可以实现更复杂的功能当鼠标左键摁下后不抬起鼠标移动同时会划出一条线跟随鼠标移动。View相关的类是控制界面的绘制需要在其中写代码
在 MFCPaintView.h 文件中是MFCPaintView这个类给该类加上几个属性 CPoint m_start;// 起始点用于绘制线条的CPoint m_cur; // 当前点用于绘制线条CPoint m_ptStop; // 终止点用于绘制线条BOOL m_bStatus; // 绘制状态用于绘制线条CString m_strText; // 用户输入的字符串
有意思的时CPoint这个类是鼠标的坐标继承自一个结构体
typedef struct tagPOINT
{LONG x;LONG y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
处理鼠标摁下消息记录线的起始点处理鼠标移动的消息记录一下临时值线的临时终点处理鼠标抬起的消息记录线的终点
现在讨论一下实现的思路
OnLButtonDown()处理鼠标左键摁下记录起始点同时设置状态值为TRUE表示鼠标已经摁下FALSE表示鼠标没有抬起OnMouseMove()处理鼠标移动消息判断状态值未抬起。就记录临时重点调用 InvalidateRect(NULL); 进行界面重绘OnLButtonUp()处理鼠标左键抬起记录线的终点调用 InvalidateRect(NULL); 进行界面重绘修改状态值
// CMFCPaintView 消息处理程序void CMFCPaintView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值m_start point;m_bStatus TRUE;CView::OnLButtonDown(nFlags, point);
}void CMFCPaintView::OnLButtonUp(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值m_ptStop point;//CDC* pDC GetDC();// 1. 什么是上下文// 2. 什么是设备上下文//pDC-MoveTo(m_start);//pDC-LineTo(m_stop);//ReleaseDC(pDC);InvalidateRect(NULL);m_bStatus FALSE;CView::OnLButtonUp(nFlags, point);
}void CMFCPaintView::OnMouseMove(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值if (m_bStatus){m_cur point;InvalidateRect(NULL); // 调用OnDraw界面重回
// CDC* pDC GetDC();
// pDC-MoveTo(m_start);
// pDC-LineTo(point);
// ReleaseDC(pDC);}CView::OnMouseMove(nFlags, point);
}
InvalidateRect(NULL)是一种触发重绘的方法它可以使窗口客户区域全部无效并强制触发WM_PAINT消息以便应用程序对客户区进行重绘。
具体而言InvalidateRect(NULL)函数会将整个窗口客户区域标记为无效即需要重新绘制并记录下这个无效区域的位置和大小。然后它会向系统发送WM_PAINT消息以通知应用程序客户区需要重新绘制。
在应用程序收到WM_PAINT消息后它会根据无效区域的位置和大小重新绘制客户区。
需要指出的是InvalidateRect(NULL)函数通常是在需要强制更新整个客户区时使用的因为它会将整个客户区标记为无效即使只有一小部分区域需要更新。如果只需要更新某个特定的区域则可以使用InvalidateRect()函数的其他重载版本它们可以指定需要更新的区域。
在OnDraw来实现画直线 // 当像素超过1时线型会失效CPen pen(PS_DASHDOT, 1, RGB(255, 0, 0));// 返回一个笔CPen* pOldPen pDC-SelectObject(pen);CPoint start m_start, cur m_cur;start.y--;if (m_bStatus){cur.y--;pDC-MoveTo(m_start);pDC-LineTo(m_cur);pDC-MoveTo(start);pDC-LineTo(cur);}else{cur m_cur;cur.y--;pDC-MoveTo(m_start);pDC-LineTo(m_cur);pDC-MoveTo(start);pDC-LineTo(cur);}// 还原原来的笔pDC-SelectObject(pOldPen);
绘制矩形 if (m_bStatus){// 选择NULL就会用上下文的刷子不选空就会用指定的刷子else{pDC-FillRect(CRect(m_start, m_ptStop), NULL);} 八.画布
在MFC中画布Canvas是指一个表示绘图区域的设备上下文Device ContextDC它提供了绘制图形和文本的基本操作。
画布通常与窗口客户区关联它对应于屏幕上的一个矩形区域用于绘制窗口的内容。在MFC中可以通过调用CWnd类的GetDC函数来获取当前窗口客户区的设备上下文句柄从而获得画布的访问权。
一旦获取了画布的设备上下文句柄就可以使用GDI图形设备接口函数来绘制各种图形和文本。例如可以使用LineTo函数在画布上绘制一条直线使用Rectangle函数绘制矩形使用TextOut函数绘制文本等。 九.画笔
实例化画笔类CPen并设置到CDC中会返回以一个旧的画笔 CPen pen(PS_DASHDOT, 1, RGB(255, 0, 0));// 返回一个笔CPen* pOldPen pDC-SelectObject(pen);
绘制完成后需要恢复
pDC-SelectObject(pOldBrush); 十.画刷
实例化画刷类CBrush并设置到CDC中会返回以一个旧的画刷 CBrush brush(RGB(255, 0, 0)), brush2(RGB(0, 255, 0));CBrush* pOldBrush pDC-SelectObject(brush);
绘制完成后需要恢复
pDC-SelectObject(pOldBrush); 十一.利用TRACE打印日志 LOGPEN logpen;pOldPen-GetLogPen(logpen);TRACE(style %d color %08x width %d\r\n,logpen.lopnStyle, logpen.lopnColor, logpen.lopnWidth);
LOGPEN logpen; 是一个定义变量的语句它声明了一个名为logpen的变量并指定了它的数据类型为LOGPEN结构体类型。
在Windows GDI中LOGPEN结构体用于描述一个逻辑画笔的属性包括画笔样式、宽度和颜色等信息。LOGPEN结构体的定义如下
typedef struct tagLOGPEN {UINT lopnStyle; // 画笔样式POINT lopnWidth; // 画笔宽度当样式为PS_GEOMETRIC时表示线段两端的宽度COLORREF lopnColor; // 画笔颜色
} LOGPEN;十二.文本编程
模仿写一个文本编辑器
响应字符消息WM_CHAR
void CMFCPaintView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{// TODO: 在此添加消息处理程序代码和/或调用默认值TRACE(%c\r\n, nChar);CClientDC dc(this);m_strText (TCHAR)nChar;InvalidateRect(NULL);CView::OnChar(nChar, nRepCnt, nFlags);
}每当接受一个新字符就触发重绘在OnDraw进行实现
每次都是要遍历真个字符串未匹配到换行符就放入到sub中匹配到换行符把先前sub中的打印出来同时调用CSIZE的GetTextExtent()方法获取此时 | 应该放置的位置并调用全局的方法SetCaretPos(sz.cx 2, y);重置位置。 CString sub _T();int y 0;for (int i 0; i m_strText.GetLength(); i){if ((m_strText.GetAt(i) \n) || (m_strText.GetAt(i) \r)){pDC-TextOut(0, y, sub);CSize sz pDC-GetTextExtent(sub);sub.Empty();y sz.cy 2;continue;}sub m_strText.GetAt(i);}if (sub.IsEmpty() false)pDC-TextOut(0, y, sub); //Textout()只能显示单行文本CSize sz pDC-GetTextExtent(sub);//方式一//CPoint pt; //CPoint 是Point的子类//pt.y y;//pt.x sz.cx 2;//SetCarePos(pt.x, pt.y);// 方式二//SetCarePos(CPoint(sz.cx 2, y));//方式三::SetCaretPos(sz.cx 2, y);
CSize sz pDC-GetTextExtent(sub); 是一个将字符串绘制到设备上下文pDC的语句并返回绘制的文本区域的大小。 十三.ID号
在MFCMicrosoft Foundation Classes中资源的ID号用于唯一标识和引用资源。MFC中的资源可以是窗口、对话框、菜单、图标、位图、字符串等。
资源的ID号具有以下作用 标识资源每个资源在MFC中都有一个唯一的ID号通过ID号可以标识不同的资源。例如对话框资源有一个ID号可以通过该ID号在代码中引用对话框资源。 引用资源通过资源的ID号可以在代码中引用并使用该资源。通过调用MFC提供的函数或宏可以根据资源的ID号加载、显示、修改或处理相应的资源。 管理资源通过ID号可以方便地管理和组织资源。在代码中可以使用资源的ID号进行资源的加载、卸载、创建等操作并且可以使用ID号将不同类型的资源关联起来。 多语言支持资源的ID号对于实现多语言支持非常重要。通过为不同语言的资源定义不同的ID号可以根据当前的语言环境加载相应的资源并实现多语言界面。 十四.菜单栏
在资源视图-IDR_MAINFRAME中可以编辑菜单栏
主菜单是没有ID的子菜单可以设置 给菜单添加响应函数在类视图中找打MFCPaintView选择类向导选择消息选择添加处理程序 方法被添加 查看消息映射表消息翻译为WM_COMMAND再进行区分。 十五.菜单命令路由
有view和doc触发了view但是没有触发doc
去掉view类的菜单响应函数打开doc类的响应函数。触发view类不触发doc viewdoc
去掉doc类的菜单响应函数打开框架类的响应函数触发doc类不触发app doc框架
去掉app类的菜单响应函数打开app类的响应函数框架》app 响应菜单命令顺序View doc 框架 app 十六.工具栏
工具栏资源就在资源视图 TOOLBAR中 添加一个工具
选中最后一个空的手动绘制 需要注意这个需要绘制两个填入ID处理方式与菜单一样。
删除工具拖着方块移出区域即可。