MFC中的NMHDR结构体和NMUPDOWN结构体
建立spin控件,创建UDN_DELTAPOS一个消息函数后:
void CSpinDlg::OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
// TODO: Add your control notification handler code here
*pResult = ;
}
问题1:参数NMHDR* pNMHDR, LRESULT* pResult干嘛用?
NMHDR结构体,查看MSDN,经过应用,其意义如下
typedef struct tagNMHDR {
HWND hwndFrom; //控件的句柄
UINT idFrom; //控件的ID号
UINT code; //通知代码,即消息类型
} NMHDR;
ID号很好知道,创建的时候就有分配了一个ID,如IDC_SPIN1
通知代码,既消息类型,也可以知道该消息是UDN_DELTAPOS 控件句柄呢,马上开始想到经常用的CWnd* GetDlgItem( int nID ),然而该函数返回的是一个指针对象,并不是句柄。
可以用SDK 平台函数:返回是指定控件的句柄
HWND GetDlgItem(
HWND hDlg, // handle of dialog box 对话框窗口句柄
int nIDDlgItem // identifier of control 控件标示符,即ID
);
可以执行下代码,验证是否正确
void CSpinDlg::OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
HWND hwnd; hwnd = ::GetDlgItem(m_hWnd,IDC_SPIN1); //注意写法 m_hWnd是对话框窗口句柄,父窗口
if ((pNMHDR->idFrom == IDC_SPIN1) && (pNMHDR->code == UDN_DELTAPOS) && (pNMHDR->hwndFrom == hwnd))
{
MessageBox("Spin down","Spin",MB_OK);
} *pResult = ;
}
当你点击Spin按钮时,弹出对话框,提示Spin down,说明是对的。
另一种方式也可以获取控件句柄
if ((pNMHDR->idFrom == IDC_SPIN1) && (pNMHDR->code == UDN_DELTAPOS) && (pNMHDR->hwndFrom == GetDlgItem(IDC_SPIN1)->m_hWnd/*hwnd*/))
{
MessageBox("Spin down","Spin",MB_OK);
}
m_hWnd是属于CWin的一个成员,而CWnd* GetDlgItem( int nID ) const 返回一个指向CWnd的一个指针,所以就可以利用改指针来引用m_hWnd成员,
从而获得该控件的句柄。
问题2:NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; 为什么这样写,目的是干嘛呢?
首先知道NM_UPDOWN是NMUPDOWN结构体名的宏,把pNMHDR强制转化为该类型,该结构体如下
typedef struct _NM_UPDOWN {
NMHDR hdr; //NMHDR structure that contains additional information about the notification message.
int iPos; //该控件当前值
int iDelta; //用该值确认是往上加,还是往下减
} NMUPDOWN, FAR *LPNMUPDOWN;
在BOOL CSpinDlg::OnInitDialog()函数中加入下面几行代码,进行初始化
CSpinButtonCtrl *pSpin = (CSpinButtonCtrl *)GetDlgItem(IDC_SPIN1);
// pSpin->SetRange(100, 0); //按上面的箭头是减,按下面的箭头是加
pSpin->SetRange(, ); //按上面的箭头是加,按下面的箭头是减
pSpin->SetBase(); //按十进制方式
pSpin->SetPos(); //把当前值设置为8
然后在void CSpinDlg::OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult) 加上验证代码
void CSpinDlg::OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
HWND hwnd; hwnd = ::GetDlgItem(m_hWnd,IDC_SPIN1); if ((pNMHDR->idFrom == IDC_SPIN1) && (pNMHDR->code == UDN_DELTAPOS) && (pNMHDR->hwndFrom == hwnd))
{
MessageBox("Spin down","Spin",MB_OK); //写法1
} if ((pNMUpDown->hdr.idFrom == IDC_SPIN1)&& (pNMUpDown->hdr.code == UDN_DELTAPOS) && (pNMUpDown->hdr.hwndFrom == hwnd))
{
MessageBox("Spin down too","Spin",MB_OK); //写法2
} if (pNMUpDown->iPos == )
{
MessageBox("当前值是8","Spin",MB_OK);
} if(pNMUpDown->iDelta == )
{
MessageBox("加1","Spin",MB_OK);
} if(pNMUpDown->iDelta == -)
{
MessageBox("减-1","Spin",MB_OK);
} *pResult = ;
}
可以逐步验证每个成员的意义是否正确,其中写法1和写法2是结果是相同的。
问题3:NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR
该函数中的两个不同类型结构体,经强制转换赋给另外一个结构体,最终两结构体都占用同快内存吗?还有pNMHDR里的成员会怎么传递呢?
首先看个例1
#include <iostream>
using namespace std; typedef struct _A
{
int hwnd;
int idFrom;
int code;
}A; typedef struct _B
{
A hdr;
int iPos;
int iDelta;
}B; int main(void)
{
A a;
A *pa; //定义结构体指针变量
pa = &a;
pa->hwnd = ;
pa->idFrom = ;
pa->code = ; B *b = (B *)pa; //强制转换赋b,指针b和pa就指向同一块内存 cout<<b->hdr.hwnd<<endl;
cout<<b->hdr.idFrom<<endl;
cout<<b->hdr.code<<endl; cout<<b->iPos<<endl;
cout<<b->iDelta<<endl; return ;
}
输出结果:
1
10
100
1245120
4332217
例1中经强制转换并赋给b后,b和pa指向同块内存,貌似成员值也赋过来了。最后两行的值由于没初始化,根据不同系统输出不确定的值。
在看个例2
#include <iostream>
using namespace std; typedef struct _A
{
int hwnd;
int idFrom;
int code;
}A; typedef struct _B
{
int iPos;
int iDelta;
A hdr; //位置放在最后
}B; int main(void)
{
A a;
A *pa; //定义结构体指针变量
pa = &a;
pa->hwnd = ;
pa->idFrom = ;
pa->code = ; B *b = (B *)pa; //强制转换赋b,指针b和pa就指向同一块内存 cout<<b->hdr.hwnd<<endl;
cout<<b->hdr.idFrom<<endl;
cout<<b->hdr.code<<endl; cout<<b->iPos<<endl;
cout<<b->iDelta<<endl; return ;
}
输出结果:
100
1245120
4332217
1
10
例2中,在结构体B中的A hdr;成员放置到最后,其输出结果就有大所不同。
如下简单示意图,假设A结构体定义变量后,内存分配情况:
内存地址 内存中的值
0x00002 -> 1
0x00006 -> 10
0x0000c -> 100
经过强制转换,赋给b后,使b、pa和a三个变量都同时指向同块内存的首地址。结构体变量b分配的内存空间在结构
体变量pa的内存基础上继续分配了0x00010、0x00014两个地址,故结构体变量b的前三个成员变量值就是1、10、100。
所以不能理解成员变量值传递,而是要从内存上去理解。成员变量只是一个代号而已。

还是不理解的话,可以把A中的三个成员变量地址打出来,然后把B中的成员变量地址也打出来对比就知道了。
cout<<"hwnd地址"<<&a.hwnd<<" "<<a.hwnd<<endl;
cout<<"idFrom地址"<<&a.idFrom<<" "<<a.idFrom<<endl;
cout<<"code地址"<<&a.code<<" "<<a.code<<endl;
...
...
备注:
设置增量步长可以使用SetAccel(int nAccel,UDACCEL* pAccel )函数:
1、参数nAccel表示由pAccel指定的UDACCEL结构的数目.
2、pAccel指向一个UDACCEL结构数组的指针
如下,步长为2
UDACCEL udaccel;
udaccel.nInc = ; //步长为2的增或减
udaccel.nSec = ; //在改变前所等待的秒数 Spin1->SetAccel(,&udaccel);
MFC中的NMHDR结构体和NMUPDOWN结构体的更多相关文章
- ABAP中不修改内表参照的结构,给内表/结构体增加字段
Situation: DATA: itab TYPE STANDARD TABLE OF zsrsodtla_stru1, wa_itab TYPE zsrsodtla_str ...
- matlab学习笔记12_2创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段
一起来学matlab-matlab学习笔记12 12_2 结构体 创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段 觉得有用的话 ...
- MFC中显示 .bmp格式的位图
最近在看VisualC++ 图像处理的书籍,表示一直在从基础做起,今天就记录一个简单功能的实现,显示.bmp格式的位图. 首先需要理解的是窗口创建的过程包括两个步骤:首先擦除窗口的背景,然后在对窗口进 ...
- MFC中树控件CTreeCtrl的用法
树形控件可以用于树形的结构,其中有一个根接点(Root)然后下面有许多子结点,而每个子结点上有允许有一个或多个或没有子结点.MFC中使用CTreeCtrl类来封装树形控件的各种操作.通过调用 BOOL ...
- MFC中的CString类使用方法指南
MFC中的CString类使用方法指南 原文出处:codeproject:CString Management [禾路:这是一篇比较老的资料了,但是对于MFC的程序设计很有帮助.我们在MFC中使用字符 ...
- MFC 中的设计模式分析
MFC 中的设计模式分析 最近在学习设计模式,突然想到MFC里面其实也包含有设计模式的原理,于是分析了一下,做一个笔记,网上也找了一些资料,在此一并感谢. 创建型模式 单例模式(Singleton P ...
- GDI+学习笔记(九)带插件的排序算法演示器(MFC中的GDI+实例)
带插件的排序算法演示器 请尊重本人的工作成果,转载请留言.并说明转载地址,谢谢. 地址例如以下: http://blog.csdn.net/fukainankai/article/details/27 ...
- MFC中CString转换成char数组的问题
由于结构体中用到联合体(联合体需要确定分配内存分配大小)或其它因素,需要用char数组来保存字符串,但是在MFC中一般都是用CString来存放字条串.关于它们之间的转换,在VS2008中有时会出现异 ...
- 在MFC中使用Cstring
此文介绍了关于MFC使用CString的资料,可一参考一下. 转自于VC知识库:http://www.vckbase.com/index.php/wv/829 通过阅读本文你可以学习如何有效地使用 C ...
随机推荐
- 解析好的静态页面.shtml浏览器无法解析.需要apache解析后再返回给浏览器
解析好的静态页面.shtml浏览器无法解析.需要apache解析后再返回给浏览器 让Apache支持SHTML(SSI)的配置方法 http.conf放开addtype text/html .shtm ...
- hdu 1212 Big Number(大数取模)
Problem Description As we know, Big Number is always troublesome. But it's really important in our A ...
- ECOS-认证地址
ECOS系统授权认证,需要和Shopex认证中心互联.当服务器DNS无效时.需要绑定host强行解析服务器强行解析以下vim /etc/hosts 122.144.135.142 service.sh ...
- CTRL key
ctrl key其实是用于扩展键盘,单独一个ctrl键没有什么作用,也没有ascii码,当与其他键相结合时,相当于创造出一个新键.例如:用getchar()侦测输入的字符,当按下ctrl+a时,只输出 ...
- 使用 Flex 库项目---打包swc
来源:http://help.adobe.com/zh_CN/flashbuilder/using/WSe4e4b720da9dedb5-1a92eab212e75b9d8b2-7ffe.html ...
- 剑指offer 旋转数组
class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { //常规的遍历方法时间是O(N ...
- Zabbix3.0 客户端搭建
zabbix客户端安装 我们这边使用编译安装 软件包版本 zabbix-3.0.3.tar.gz 添加用户组 #groupadd zabbix #useradd -s /sbin/nologin -g ...
- TextureView+SurfaceTexture+OpenGL ES来播放视频(一)
引自:http://www.ithao123.cn/content-8733143.html 最近发现视频直播类应用层出不穷,比如233手游直播,蓝鲸直播,微录客等等什么的,连android界大神老罗 ...
- 第一个前台页面----xflow的页面
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><%@ tagl ...
- 2015年4月27日---C语言:输出特殊图案,请在c环境中运行,看一看,Very Beautiful!
---恢复内容开始--- 题目:输出特殊图案,请在c环境中运行,看一看,Very Beautiful! 1.程序分析:字符共有256个.不同字符,图形不一样. 2.程序源代码: [code=c] #i ...