建立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. LeetCode OJ 257. Binary Tree Paths

    Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 ...

  2. LeetCode OJ 220.Contains Duplicate 3

    Given an array of integers, find out whether there are two distinct indices i and j in the array suc ...

  3. differences between null pointer and void pointer.

    These are two different concepts, you cannot compare them. What the difference between the skunk and ...

  4. IOS设备上网页中的页面滚动效果模拟

    可能咋一看不知道我说的是个啥,因为iOS本来就用这功能的啊,还模拟它干啥?先听我说下项目背景哈 我现在开发的是一个webapp,主要是用在ipad上,这个app的大小是固定大小的,为了防止触摸它出现弹 ...

  5. 手机版WEB开发经验分享,手机版网站开发注意事项,网站自适应,手机版网站自适应,移动安卓APP自适应

    转自 http://my.oschina.net/cart/blog/282477 做前端开发不短了,用过jQuery Mobile jqMobi 也纯手工写过.. 最后总结如下: jQuery Mo ...

  6. js css优化-- 合并和压缩

    在项目框架中,首先要引用很多css和js文件,80%的用户响应时间都是浪费在前端.而这些时间主要又是因为下载图片.样式表.JavaScript脚本.flash等文件造成的.减少这些资源文件的Reque ...

  7. android平台编译IW

    不知道怎么编译IW,所以就搜索网络上的博客http://blog.csdn.net/jksl007/article/details/16862435 首先,iw依赖于libnl库,而目前android ...

  8. git 提交到github时不用每次都输入用户名,密码

    Permanently authenticating with Git repositories, Run following command to enable credential caching ...

  9. CSS样式 初学

    CSS样式 参考网站: CSS用法:3种 一:直接样式表 如<p style="color:red;">这是一个段落</p> 二:内部样式表 如:<s ...

  10. hiho#1128 : 二分·二分查找

    input 1<=n<=1e6 1<=k<=2*1e9 a1 a2 ... an 1<=an<=2*1e9 output k存在则输出k是第几大的数,否则输出-1 ...