NMHDR 与 NM_LISTVIEW,NM_TREEVIEW 的关系

本文详细介绍了Windows消息处理机制中的WM_NOTIFY消息及其核心结构NMHDR。解释了WM_NOTIFY消息如何携带控件通知,并通过实例展示了如何使用NMHDR结构处理ListView控件的通知。

NMHDR   =   Notify   Message   Handler

  1. typedef struct tagNMHDR   
  2. {  
  3.     HWND hwndFrom;  
  4.     UINT_PTR idFrom;  
  5.     UINT code;  
  6. } NMHDR;  

消息通过下面的宏定义之: 
  ON_NOTIFY(   wNotifyCode,   idControl,   memberFxn   ) 
  wNotifyCode   
  通知消息标识符代码,如   TBN_BEGINADJUST。   
  idControl   
  发送通知的控件的标识符。   
  memberFxn   
  接收到通知时调用的成员函数。

WM_NOTIFY中,lParam中放的是一个称为NMHDR结构的指针。在wParam中放的则是控件的ID。  
   
    NMHDR结构是很值得一提的,该结构包括有关制作该通知的控件的任何内容,而不受空间和类型的限制,他的来历也是很有意思的。  
    在最初的windows3.x中,根本就不存在什么WM_NOTIFY,控件通知它们父窗口,如鼠标点击,控件背景绘制事件,通过发送一个消息到父窗口。简单的通知仅发送一个WM_COMMAND消息,包含一个通知码和一个在wParam中的控件ID及一个在lPraram中的控件句柄。这样一来,wParam和lParam就都被填充了,没有额外的空间来传递一些其它的消息,例如鼠标按下的位置和时间。  
     为了克服这个困难,windows3.x就提出了一个比较低级的解决策略,那就是给一些消息添加一些附加消息,最为明显的就是控件自画用到的DRAWITEMSTRUCT。不知道大家对这个结构熟悉不,不过,如果你是老手,你应该非常清楚这个结构,这个结构包含了9个内容,几乎你需要控制的信息都给你提供了。为什么说它比较低级呢?因为不同的消息附加的内容不同,结果就是一盘散沙,非常混乱。  
     在win32中,MS又提出了一个更好的解决方案:引进NMHDR结构。这个结构的引进就是消息统一起来,利用它可以传递复杂的信息。这个结构的布局如下:  
typedef struct tagNMHDR    

{  
    HWnd  hWndFrom;// 相当于原WM_COMMAND传递方式的lParam  
    UINT   idFrom;      // 相当于原WM_COMMAND传递方式的wParam(low-order)  
    UINT   code; // 相当于原WM_COMMAND传递方式的NotifyCode(wParam's high- order)          

}NMHDR;  
         

    对于这个结构的应用于WM_NOTIFY信息结构,结果WM_NOTIFY就变成了: 
          A、无附加信息。结构变得很简单,就是一个NMHDR结构。 
          B、有附加信息。定义一个大的结构,它的第一个元素就是NMHDR结构,它的后面放置附加信息。


举例://得到选中的列
void   CMyView::OnColumnclick(NMHDR*   pNMHDR,   LRESULT*   pResult)    
{       
      NM_LISTVIEW*   pNMListView   =   (NM_LISTVIEW*)pNMHDR;  
      //得到选中的列      
      int nColumn=pNMListView->iSubItem;  

  
  成员函数将用下列原型声明:  
 afx_msg   void   memberFxn(NMHDR *pNotifyStruct,LRESULT   *pResult); 

由此知识就可方便解释NM_LISTVIEW与NM_TREEVIEW了,

其实:

NM_LISTVIEW 为

 #define LPNM_LISTVIEW   LPNMLISTVIEW
 #define NM_LISTVIEW     NMLISTVIEW

而NMLISTVIEW结构为:
 

typedef struct tagNMLISTVIEW {
    NMHDR hdr;
    int iItem;
    int iSubItem;
    UINT uNewState;
    UINT uOldState;
    UINT uChanged;
    POINT ptAction;
    LPARAM lParam;
} NMLISTVIEW, *LPNMLISTVIEW;

// ChangeRequest.cpp : 实现文件 // #include “stdafx.h” #include “DrawingCheck.h” #include “ChangeRequest.h” #include “afxdialogex.h” // ChangeRequest 对话框 IMPLEMENT_DYNAMIC(ChangeRequest, CDialogEx) ChangeRequest::ChangeRequest(CWnd* pParent /=NULL/) CDialogEx(IDD_DIALOG2, pParent) { } ChangeRequest::~ChangeRequest() { } void ChangeRequest::SetListDatas(vector Datas) { listDatas = Datas; } void ChangeRequest::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST1, m_list); } BEGIN_MESSAGE_MAP(ChangeRequest, CDialogEx) ON_NOTIFY(NM_CLICK, IDC_LIST1, &ChangeRequest::OnLvnItemClickList) ON_NOTIFY(NM_CUSTOMDRAW, IDC_LIST1, &ChangeRequest::OnNMCustomdrawList1) END_MESSAGE_MAP() BOOL ChangeRequest::OnInitDialog() { CDialog::OnInitDialog(); DWORD dwStyle = m_list.GetExtendedStyle(); dwStyle |= LVS_EX_ONECLICKACTIVATE; dwStyle |= LVS_EX_FLATSB; //扁平风格的滚动条 dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮 dwStyle |= LVS_EX_GRIDLINES;//网格线 CImageList high; high.Create(1, 30, TRUE | ILC_COLOR32, 1, 1);//行高 m_list.SetImageList(&high, LVSIL_SMALL); m_list.SetExtendedStyle(dwStyle); //设置扩展风格 m_list.InsertColumn(0, _T("序号"), LVCFMT_CENTER, 38); m_list.InsertColumn(1, _T("跳转变更申请"), LVCFMT_CENTER, 100); m_list.InsertColumn(2, _T("链接"), LVCFMT_CENTER, 0); int size = listDatas.size(); for (int i = 0; i < size; i++) { CString aStrNo; aStrNo.Format(L"%d", i + 1); m_list.EnsureVisible(i, TRUE); m_list.InsertItem(i, aStrNo); } map<CString, CString>::iterator it; for (int i=0;i< listDatas.size(); i++) { m_list.SetItemText(i, 1, L"跳转"); m_list.SetItemText(i, 2, listDatas[i]); } return 0; } void ChangeRequest::OnLvnItemClickList(NMHDR *pNMHDR, LRESULT *pResult) { LPNMLISTVIEW pNMItemActivate = reinterpret_cast(pNMHDR); int m_nSel; int iCol; if (pNMItemActivate != NULL) { m_nSel = pNMItemActivate->iItem; iCol = pNMItemActivate->iSubItem; } if (m_nSel != -1 && iCol == 1)//跳转 { CString strPath; strPath = m_list.GetItemText(m_nSel, 2); ShellExecute(NULL, NULL, strPath, NULL, NULL, SW_SHOWNORMAL); } *pResult = 0; } void ChangeRequest::OnNMCustomdrawList1(NMHDR * pNMHDR, LRESULT * pResult) { NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR); NM_LISTVIEW * pNMListView = (NM_LISTVIEW*)pNMHDR; CRect rect; CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc); // 将设备上下文句柄转换为设备上下文类 *pResult = CDRF_DODEFAULT; if (CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage) { *pResult = CDRF_NOTIFYITEMDRAW; } else if (CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage) { *pResult = CDRF_NOTIFYSUBITEMDRAW; } else if ((CDDS_ITEMPREPAINT | CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage) { COLORREF crText, crBkgnd; if (1 == pLVCD->iSubItem) { crText = RGB(24, 144, 255); crBkgnd = RGB(255, 255, 255); } else { crText = RGB(0, 0, 0); crBkgnd = RGB(255, 255, 255); } pLVCD->clrText = crText; pLVCD->clrTextBk = crBkgnd; } },修改该代码,保持原有逻辑转为QT框架,其中控件替代: CListCtrl → QModelIndex checkIndex = model->index(i, 0); Qt::CheckState checkState = static_castQt::CheckState( model->data(checkIndex, Qt::CheckStateRole).toInt());
最新发布
08-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值