void CHomeResDlg::OnSelchangedTreeBudget(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
HTREEITEM hCurItem = pNMTreeView->itemNew.hItem;
CString node_name=m_Tree.GetItemText(pNMTreeView->itemNew.hItem);
//在标题栏显示节点信息
SetWindowText(node_name);
if(m_Tree.GetParentItem(hCurItem) != NULL)
{
CString strDate = m_Tree.GetItemText(m_Tree.GetParentItem(hCurItem));
int nPos = strDate.Find('/');
strDate = strDate.Left(nPos);
m_CurTime.wYear = atoi(strtok(strDate.GetBuffer(strDate.GetLength()),"-"));
m_CurTime.wMonth = atoi(strtok(NULL,"-"));
m_CurTime.wDay = atoi(strtok(NULL,"-"));
m_Date.SetTime(m_CurTime);
strDate.ReleaseBuffer();
CString strText = m_Tree.GetItemText(hCurItem);
m_lCurID = m_Tree.GetItemData(hCurItem);
m_strContent = strtok(strText.(strText.GetLength GetBuffer ()),"/");
m_nType = m_cobType.SelectString(-1,strtok(NULL,"/"));
CString strMoney = strtok(NULL,"/");
strMoney = strMoney.Right(strMoney.GetLength() - 2);
m_fMoney = (float)atof(strMoney);
m_nHandler = m_cobHandle.SelectString(-1,strtok(NULL,"/"));
strText.ReleaseBuffer();
UpdateData(FALSE);
}
else
{
m_lCurID = 0;
}
*pResult = 0;
}
编程中大量用到
NMHDR
结构,并在后续处理中将该结构转换成其他结构,如在
listview中转换成LV_DISPINFO,NM_LISTVIEW
等,他们究竟是什么关系呢?
1.他们都属于Win32控件的通知消息
从Windows 95和Windows NT 3.51版开始,Windows提供了一些先进的Win32控件.这些新
控件弥补了传统控件的某些不足之处,并使Windows的界面丰富多彩且更加友好.MFC的
新控件类封装了这些控件
如CSliderCtrl
CTreeCtrl等,较之传统的Windows 3.x控件,新的Win32控件更加复杂和先进.在新控件
发送通知消息的同时,往往还需要附加一些数据来描述控件的状态
.传统的WM_COMMAND
消息通知机制显然不能完成这一任务,因为WM_COMMAND消息的wParam和lParam已经被占
满了(见6.1.1),无法容纳新的数据.
在Win32中,采用新的WM_NOTIFY消息来实现新控件的消息通知机制.在该消息的wParam
中含有控件的ID,lParam中则有一个指针,这个指针指向一个结构.这个结构要么是NM
HDR结构,要么是一个以NMHDR
结构作为第一个成员的扩充结构.通过NMHDR
结构及其扩充
结构可以传递附加数据.从理论上讲,可以通过扩充结构传送任意多的数据.需要指出
的是,由于NMHDR
结构是扩充结构的第一个成员,因此lParam中的指针即可以认为是指向
NMHDR
结构的,也可以认为指向包含NMHDR
结构的扩充结构的.
NMHDR
结构如下所示:
typedef struct tagNMHDR {
HWND hwndFrom; //控件窗口的句柄
UINT idFrom; //控件的ID
UINT code; //控件的通知消息码
} NMHDR
;
一个典型的扩充结构如下所示,该结构用于列表视图控件的LVN_KEYDOWN通知消息.
typedef struct tagLV_KEYDOWN {
NMHDR
hdr; //NMHDR
结构作为第一个成员
WORD wVKey;
UINT flags;
} LV_KEYDOWN;
WM_NOTIFY的消息映射由宏ON_NOTIFY负责,该消息映射宏具有如下形式:
ON_NOTIFY( wNotifyCode, id, memberFxn )
参数wNotifyCode说明了通知消息码,参数id是控件的ID,第三个参数则是消息处理函数
名.消息处理函数应该按下面的形式声明,其中参数pNotifyStruct指向NMHDR
及其扩充
结构,参数result指向一个处理结果.
afx_msg void memberFxn( NMHDR
* pNotifyStruct, LRESULT * result );
利用ClassWizard可以很方便地加入WM_NOTIFY消息映射及其处理函数,一个典型的WM_N
OTIFY消息映射如下所示,其中LVN_KEYDOWN是IDC_LIST1列表视图控件发出的通知消息.
ON_NOTIFY( LVN_KEYDOWN, IDC_LIST1, OnKeydownList1 )
消息处理函数OnKeydownList1的定义如下面所示.在函数中ClassWizard自动把pNHHDR指
针强制转换成LV_KEYDOWN型并赋给pLVKeyDow指针,这样,在函数中可通过这两个指针访
问LV_KEYDOWN扩充结构及其所含的NMHDR
结构.另外,在函数返回时,ClassWizard自动
将处理结果赋0值.
void CMyDlg::OnKeydownList1(NMHDR
* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
// TODO: Add your control notification handler
// code here
*pResult = 0;
}
可以利用ON_NOTIFY_RANGE宏把多个ID连续的控件发出的相同消息映射到同一个处理函数
上,具体形式如下,其中参数id和idLast分别说明明了一组连续的控件ID中的头一个和
最后一个ID.
ON_NOTIFY_RANGE( wNotifyCode, id, idLast, memberFxn )
相应的消息处理函数应按下面的形式声明,与普通的WM_NOTIFY消息处理函数相比,该函
数多了一个参数id用来说明发送通知消息的控件ID.
afx_msg void memberFxn( UINT id, NMHDR
* pNotifyStruct, LRESULT * result );
ClassWizard不支持ON_NOTIFY_RANGE宏,所以需要手工建立消息映射和消息处理函数