为子控件添加自定义绘图方式

在MFC应用程序中,有时会遇到需要让指定的控件实现自绘。但是看该控件的事件,没有一个像是能承担这种责任的。

我们都知道控件也是窗口,也都有消息循环。所以:

方案一:写个新类,继承自某个窗口类,在它的WM_PAINT消息中实现自绘。这种方法需要定义一个新类,不是太方便。


方法二:利用SetWindowLong修改该控件的消息处理函数,在WM_PAINT消息中实现自绘。本文就采用此方案。


------------------------------------------------------------

方案二实现过程,环境:Win XP + VC2010(MFC)

完整源码


1. 界面:


2. 为Button1添加点击事件

void CdelDlg::OnBnClickedButton1()
{m_bgIndex = (m_bgIndex + 1) % 7;Invalidate();					// 刷新背景
}

3. 添加2个全局变量和2个全局函数(绘图函数和子控件新的消息处理函数)

// 定义全局变量和全局函数
WNDPROC oldProc_PIC1 = 0;					// 保存IDC_PIC1控件默认的消息处理函数地址
CString imgPath;							// 保存背景图片地址BOOL DrawPic(HWND hWnd)						// 在指定的控件上画图
{CImage img;if(SUCCEEDED(img.Load(imgPath))){CWnd *pWnd = CWnd::FromHandle(hWnd);CPaintDC dc(pWnd);					// dc必须用指定的控件窗口来初始化,否则将看不到绘图结果CRect rect;pWnd->GetClientRect(rect);			// 获取控件的大小img.Draw(dc.m_hDC, rect);return TRUE;}return FALSE;							// 绘图失败
}LRESULT NewProc_PIC1(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)		// IDC_PIC1控件对应的新的消息函数
{switch (message){case WM_PAINT:if(DrawPic(hWnd))return S_OK;elsebreak;default:break;}return CallWindowProc(oldProc_PIC1, hWnd, message, wParam, lParam);		// 调用默认的消息函数
}

4. 在对话框的OnInitDialog()中为子控件IDC_PIC1 指定新的消息循环函数

BOOL CdelDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);			// 设置大图标SetIcon(m_hIcon, FALSE);		// 设置小图标oldProc_PIC1 = (WNDPROC)SetWindowLong(GetDlgItem(IDC_PIC1)->m_hWnd, GWL_WNDPROC, (LONG)NewProc_PIC1);	// 为控件设置新的消息处理函数return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

5. 处理对话框的WM_PAINT和子控件(IDC_PIC1)的WM_PAINT消息

5.1 主对话框的WM_PAINT消息处理

void CdelDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CString file[] = {"1.jpg", "2.jpg", "3.jpg", "11.jpg", "12.bmp", "Smiley.png", "11.gif"};m_imgPath.Format("res\\%s", file[m_bgIndex]);imgPath = m_imgPath;DrawPic(this->m_hWnd);		// 在控件上绘图//CDialogEx::OnPaint();}
}

5.2 子控件(IDC_PIC1)的WM_PAINT消息处理,即步骤3中的NewProc_PIC1()


点滴经验

1. 本来我想在对话框的PreTranslateMessage()中拦截子控件的WM_PAINT消息的,但是经过试验才知道,窗口在第一次启动时不会触发WM_PAINT消息的,只有失去焦点或重新获得焦点时才会触发WM_PAINT消息。所以放弃使用该方法。

2. CPaintDC的构造函数有个参数的,一般看到的代码中都是用dc(this)来初始化的,因为这个代码是在类的成员函数中,所以没问题。另外在进行绘图时,所指定的rect要与初始化dc的这个参数(如pWnd)对应的坐标(pWnd->GetClientRect(rect))相对应,否则可能看不到绘图结果或绘图的位置不对。

3. 在对话框的自绘处理中,要屏蔽掉其基类的OnPaint(),否则自绘上去的图形将被覆盖。但是,将基类的OnPaint()语句放在自绘语句的最后,是可以的,即我文中的代码可以取消对CDialogEx::OnPaint()的注释。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/406312.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

根据父类id查询所有的父级_父类子类抽象类,super final 重写方法,搞懂继承中复杂的知识点...

继承继承(Inheritance)可以实现类之间共享属性和方法&#xff0c;是面向对象编程的另一个特性使用继承可以最大限度地实现代码复用。定义&#xff1a;继承就是在已有类的基础上构建新的类&#xff0c;一个类继承已有类后&#xff0c;可以对被继承类中的属性和方法进行重用。继承…

【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十八:SDRAM模块① — 单字读写...

实验十八&#xff1a;SDRAM模块① — 单字读写 笔者与SDRAM有段不短的孽缘&#xff0c;它作为冤魂日夜不断纠缠笔者。笔者尝试过许多方法将其退散&#xff0c;不过屡试屡败的笔者&#xff0c;最终心情像橘子一样橙。《整合篇》之际&#xff0c;笔者曾经大战几回儿&#xff0c;不…

gateway请求拦截_一种网关对用户请求进行统一拦截判断是否放行的方法与流程...

本发明涉及互联网技术领域&#xff0c;特别涉及一种网关对用户请求进行统一拦截判断是否放行的方法。背景技术&#xff1a;随着互联网发展的越来越快&#xff0c;技术也更新的非常频繁&#xff0c;比如开发一个系统的架构由最初始的单个服务器就能处理演变到现在的利用springcl…

spark sql 上个月_Spark学习之路 (十八)SparkSQL简单使用

一、SparkSQL的进化之路1.0以前&#xff1a;Shark1.1.x开始&#xff1a;SparkSQL(只是测试性的) SQL1.3.x:SparkSQL(正式版本)Dataframe1.5.x:SparkSQL 钨丝计划1.6.x&#xff1a;SparkSQLDataFrameDataSet(测试版本)x:SparkSQLDataFrameDataSet(正式版本)SparkSQL:还有其他的…

GetClientRect相当于GetWindowRect和ScreenToClient区别

From: http://www.cnblogs.com/yongtaiyu/archive/2011/05/18/2049554.html GetWindowRect是取得窗口在屏幕坐标系下的RECT坐标&#xff08;包括客户区和非客户区&#xff09;&#xff0c;这样可以得到窗口的大小和相对屏幕左上角(0,0)的位置。 GetClientRect取得窗口客户区(…

xxljob 配置具体定时任务_记一次xxl-job定时任务没有触发的问题

当初选了xxl-job就是因为它的触发机制比较靠谱,到点准时发,而且有日志可以看。 昨天突然发现部署在一台本地机器上的xxl-job到点并没有触发,且没有任何日志。通过管理页面查询触发日志,发现日志还是有的,只是和筛选条件不甚匹配。比如选取了昨天的日志,结果集中包含了今天…

TOMCAT启动完成但是ECLIPSE仍然显示starting....

最近重新部署了一个TOMCAT服务&#xff0c;但是启动碰到个问题&#xff0c;虽然TOMCAT控制台已显示启动成功&#xff0c;但是ECLIPSE右下角仍然一直显示STARTING&#xff0c;最后TOMCAT超时&#xff0c;启动失败。之前以为是拷贝工程的问题&#xff0c;但其实是SERVER配置的问题…

例解 autoconf 和 automake 生成 Makefile 文件

From: http://www.ibm.com/developerworks/cn/linux/l-makefile/ 简介&#xff1a; 本文介绍了在 linux 系统中&#xff0c;通过 Gnu autoconf 和 automake 生成 Makefile 的方法。主要探讨了生成 Makefile 的来龙去脉及其机理&#xff0c;接着详细介绍了配置 Configure.in 的方…

爱慕内衣信息化颠覆流程重构供应链

通过IT&#xff0c;爱慕内衣进行了供应链流程的颠覆和重构。在北京慕集团首席信息官赵先生脑海中&#xff0c;一直有着这样一幅“大图景”&#xff1a;只要需要&#xff0c;老总在自己的办公室里能看到每一寸原料的采购情况&#xff0c;每一件成衣的生产和销售情况&#xff0c;…

mysql中 课程1比课程2成绩高_小菜菜mysql练习解读分析1——查询 01 课程比 02 课程成绩高的学生的信息及课程分数...

查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数好的&#xff0c;第一道题&#xff0c;刚开始做&#xff0c;就栽了个跟头&#xff0c;爽歪歪&#xff0c;至于怎么栽跟头的——需要分析题目&#xff0c;查询的是&#xff0c;查询的是(1)学生的信息…

window mysql集群视频_windows7实现mysql集群cluster-mysql簇

http://bitar.cn下载&#xff1a;mysql-cluster-gpl-7.4.7-winx64内置了&#xff1a;mysql-5.6.25&#xff0c;ndb-7.4.7文档可参考 mysql参考手册【mysql簇】管理(MGM)节点新建文件夹&#xff0c;存放ndb_mgm.exe 和ndb_mgmd.exe,就是管理(MGM)节点不需要mysql客户端端口监督程…

Human_height

Country/RegionAverage male heightAverage female heightSample population / age rangeMethodologyYearSourceArgentina1.745 m (5 ft 81⁄2 in)1.610 m (5 ft 31⁄2 in)19Measured1998–2001[1]Australia1.748 m (5 ft 9 in)1.634 m (5 ft 41⁄2 in)18Measured1995[2]Austra…