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

在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,一经查实,立即删除!

相关文章

ios7 导航栏 手势 右划 自动返回 相关

http://www.tuicool.com/articles/vMfAVv 纪录一下&#xff0c;转载于:https://www.cnblogs.com/penn-wang/p/4308140.html

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

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

Echarts y轴高度设置(宽度铺满整个父级高度)

Echarts y轴高度设置&#xff08;宽度铺满整个父级高度&#xff09;

利用 Cloudera 实现 Hadoop (二)

安装 规划好了就开始安装Hadoop&#xff0c;如前言中所说使用Cloudera的Hadoop发布版安装Hadoop是十分方便的&#xff0c;首先当然是在每台主机上一个干净的操作系统&#xff08;我用的是Ubuntu 8.04&#xff0c;用户设为Hadoop&#xff0c;其它的版本应该差不多&#xff09;&…

CPaintDC、CClientDC、CWindowDC和CMetaFileDC类的主要特点及区别-Windows绘图基础知识

From: http://blog.csdn.net/zhangxinrun/article/details/5829084 一、设备环境&#xff08;DC&#xff09;的概念&#xff08;1&#xff09;在Windows中&#xff0c;显示工作是基于设备环境的。所谓设备环境&#xff08;DC&#xff09;是一种Windows数据结构&#xff0c;该结…

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

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

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

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

git修改/添加/删除远程仓库

git修改/添加/删除远程仓库

基础——ASP.NET页面的生命周期

页请求&#xff1a;页请求发生在页生命周期开始之前。当用户请求一个页面&#xff0c;ASP.NET将确定是否需要分析或者编译该页面&#xff0c;或者是否可以在不运行页的情况下直接请求缓存响应客户端。 开始&#xff1a;发生请求后&#xff0c;页面就进入了初始化阶段。在该阶段…

主函数 main WinMain _tmain _tWinMain 的区别

From: http://blog.csdn.net/zhangxinrun/article/details/5781451 main是C/C的标准入口函数名 WinMain是windows API窗体程序的入口函数。(int WINAPI WinMain()) 中 WINAPI是__stdcall宏&#xff0c;在windef.h中定义的。 _tmain _tWinMain 是Unicode版本函数别名&#xff0c…

selenium之HTMLTestRunner练习

最近工作不忙&#xff0c;开始学习python&selenium&#xff0c;有很多理解模糊的地方&#xff0c;做下记录&#xff0c;希望大神可以指导。 练习1&#xff1a; 小插曲1&#xff1a;执行代码以后&#xff0c;发现baidu.html空的&#xff0c;执行多次发现原因&#xff0c;必须…

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:还有其他的…

Mac 生成SSH Key并配置到GitLab(单个)

Mac 生成SSH Key并配置到GitLab&#xff08;单个&#xff09;

一封写给自己的信

亲爱的自己&#xff0c;从今天起为了自己骄傲的活着吧&#xff0c;好好爱自己&#xff0c;没有人会心疼你&#xff0c;除了你妈妈。亲爱的自己&#xff0c;不要太在意一些人太在乎一些事&#xff0c;顺其自然以最佳心态面对&#xff0c;因为这世界就是这么不公平&#xff0c;往…

GetClientRect相当于GetWindowRect和ScreenToClient区别

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

汇编中call printf参数压栈时错误理解

EAX, ECX,EDX,EBX均可以32bit,16bit,8bit访问&#xff0c;如下所示: <-------------------EAX------------------------>|<----------------------|-----------|----------->|             |<---------AX--------->|             |&…

ajax传输json数据格式乱码_解决Ajax加载JSon数据中文乱码问题

一、问题描述使用zTree的异步刷新父级菜单时&#xff0c;服务器返回中文乱码&#xff0c;但项目中使用了SpringMvc&#xff0c;已经对中文乱码处理&#xff0c;为什么还会出现呢&#xff1f;此处为的异步请求的配置&#xff1a;Java代码async: {enable: true,url: basePath /s…