建立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结构体的更多相关文章

  1. ABAP中不修改内表参照的结构,给内表/结构体增加字段

    Situation: DATA:       itab  TYPE STANDARD TABLE OF zsrsodtla_stru1,      wa_itab TYPE zsrsodtla_str ...

  2. matlab学习笔记12_2创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段

    一起来学matlab-matlab学习笔记12 12_2 结构体 创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段 觉得有用的话 ...

  3. MFC中显示 .bmp格式的位图

    最近在看VisualC++ 图像处理的书籍,表示一直在从基础做起,今天就记录一个简单功能的实现,显示.bmp格式的位图. 首先需要理解的是窗口创建的过程包括两个步骤:首先擦除窗口的背景,然后在对窗口进 ...

  4. MFC中树控件CTreeCtrl的用法

    树形控件可以用于树形的结构,其中有一个根接点(Root)然后下面有许多子结点,而每个子结点上有允许有一个或多个或没有子结点.MFC中使用CTreeCtrl类来封装树形控件的各种操作.通过调用 BOOL ...

  5. MFC中的CString类使用方法指南

    MFC中的CString类使用方法指南 原文出处:codeproject:CString Management [禾路:这是一篇比较老的资料了,但是对于MFC的程序设计很有帮助.我们在MFC中使用字符 ...

  6. MFC 中的设计模式分析

    MFC 中的设计模式分析 最近在学习设计模式,突然想到MFC里面其实也包含有设计模式的原理,于是分析了一下,做一个笔记,网上也找了一些资料,在此一并感谢. 创建型模式 单例模式(Singleton P ...

  7. GDI+学习笔记(九)带插件的排序算法演示器(MFC中的GDI+实例)

    带插件的排序算法演示器 请尊重本人的工作成果,转载请留言.并说明转载地址,谢谢. 地址例如以下: http://blog.csdn.net/fukainankai/article/details/27 ...

  8. MFC中CString转换成char数组的问题

    由于结构体中用到联合体(联合体需要确定分配内存分配大小)或其它因素,需要用char数组来保存字符串,但是在MFC中一般都是用CString来存放字条串.关于它们之间的转换,在VS2008中有时会出现异 ...

  9. 在MFC中使用Cstring

    此文介绍了关于MFC使用CString的资料,可一参考一下. 转自于VC知识库:http://www.vckbase.com/index.php/wv/829 通过阅读本文你可以学习如何有效地使用 C ...

随机推荐

  1. hdu_5748_Bellovin(LIS)

    题目链接:hdu_5748_Bellovin 题意: 给你一个数列ai,设f(a1,a2,a3,..an)=(f1,f2,f3,...,fn),其中fi表示以ai结尾的最长递增子序列长度,注意:必须要 ...

  2. LeetCode OJ 99. Recover Binary Search Tree

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

  3. Git 开发新的功能分支

    软件开发中,总有无穷无尽的新的功能要不断的添加进来.添加一个新功能时,你肯定不希望因为一些实验性质的代码把主分支搞乱了, 所以每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并 ...

  4. 【Machine Learning in Action --1】机器学习入门指南

    摘自:http://www.jianshu.com/p/c3634a7f2320 机器学习算法 Coursera 上面 Stanford 的 机器学习 课程是优质的算法相关入门课程.Andrew Ng ...

  5. Ajax交互,浏览器接收不到服务器的Json数据(跨域问题)

    该问题的情景如下: 问题描述 Ajax的请求代码放在一台机器上,而服务器的java 路由程序放在另一个机子上,所以Ajax的url填写的是带"http://"  的地址,而不是相对 ...

  6. linux sort 用法

    sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式: sort [-bcfMnrtk][源文件][-o 输出文件]补充说明:sort可针对文本文件的内容,以行为单位来排序. 参 数: ...

  7. UVA 10308 Roads in the North

    input u1 v1 w1 u2 v2 w2 ... un vn wn 1<=vi,ui<=n+1 /n output 距离最远的两个点的距离 做法:一颗全连通且只有一条路从一个顶点到达 ...

  8. Java BigDecimal Class

    Using BigDecimal to perform precise calculations with floats. BigDecimal is a class type. So declare ...

  9. Core Data & MagicalRecord

    iOS 本地数据持久化存储: 1.plist 2.归档 3.NSUserDefaults 4.NSFileManager 5.数据库 一.CoreData概述 CoreData是苹果自带的管理数据库的 ...

  10. hdu1285 确定比赛名次(拓扑排序)

    确定比赛名次 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submis ...