您的位置:首页 > 其它

用于树控件消息处理的几个结构

2009-12-12 19:48 309 查看

from:http://blog.csdn.net/kdwangzi/archive/2008/12/02/3422845.aspx

用于树控件消息处理的几个结构

众所周知,Windows程序是消息驱动模式,各种消息由Windows操作系统侦测得到,并由用户创建的窗口所取得。这时,操作系统将消息的具体信息包含在两个典型的消息参数里:LPARAMWPARAM,它们都是32位无符号整型参数UINT类型。其实,奥妙就在这两个参数当中。它们依据不同的消息,包含不同的参数格式。比如,当用户在窗口中点击鼠标左键时,就会发送WM_LBUTTIONDOWN消息。想想看,点击消息一定要包含点击的鼠标位置,那么自然地,这个消息中的LPARAM中包含了POINT数据类型。其中,低字节是X轴坐标,高字节是Y轴坐标,可以通过LOWORDHIWORD宏取得:

             POINT pt;

             pt.x = LOWORD(lParam);

             pt.y = HIWORD(lParam);

同时,消息参数WPARAM包含一些标志位flags,用于确定在点击鼠标的同时是否还按下了键盘上的功能键等等。

而有时候,有些消息需要传递一些比较大的结构struct,这时32位的无符号整数UINT肯定是装不下的。那么,就把传递的结构指针(地址)放在消息参数当中。当窗口接收到这种消息时,用户负责把消息参数转换成适当的指针类型即可。比如下面将要说明的NMHDR结构。当控件向其父窗口发送通知消息WM_NOTIFY时,消息参数LPARAM就是一个结构的地址指针。那么使用时,可以这样处理:

         NMHDR *pnmhdr = (NMHDR *)lParam;

此外,对于控件来说,当控件上发生什么事件时(产生了相应的消息),那么控件会向其父窗口发送通知消息WM_NOTIFY,其中的lParam是NMHDR结构地址。给出这个结构还要进一步确定究竟是什么通知消息,这时code字段包含具体的消息类型。它可以是通用控件的通知消息,以NM_XXX形式命名,也可以是具体控件的通知消息。对于树控件来说它们以TVN_XXX形式命名。

另外,还要对控件进行控制,这些控制操作是通过向控件发送消息来实现。这些消息以TVM_XXX形式命名。

好了,可以简单地说,树控件上发生了某种事件时,树控件会向其父窗口发送通知消息WM_NOTIFY, 它们是TVN_XXX;当需要控制树控件时,通过SendMessage向它发送通知消息,它们是TVM_XXX。

1.NMHDR结构

typedef struct tagNMHDR {

    HWND hwndFrom;

    UINT idFrom;

    UINT code;

} NMHDR;

该结构包含有关通知消息的信息。

hwndFrom

发送消息的控件窗口句柄。

idFrom

发送消息的控件标识符(ID)

code

通知码。此成员可以是特殊控件的通知码,例如,TVN_ITEMEXPANDING.。也可以是通用控件的通知码之一。

通用通知码列表如下:

通知码
发送原因
NM_CLICK
用户在控件上单击鼠标左键
NM_DBLCLK
用户在控件上双击鼠标左键
NM_RCLICK
用户在控件上单击鼠标右键
NM_RDBLCLK
用户在控件上双击鼠标右键
NM_RETURN
当控件具有输入焦点时,用户按下回车键
NM_SETFOCUS
控件已经具有输入焦点
NM_KILLFOCUS
控件已经失去焦点
NM_OUTOFMEMORY
因为没有足够的内存可用,控件不能完成指定的操作
此结构一般作为控件通知消息处理函数的参数,例如上面代码中的通知消息处理函数:

afx_msg void OnTreeDblClk(NMHDR * pNMHDR, LRESULT *pResult);

――――――――――――――――――――――――――――――――――――――



2.NM_TREEVIEW结构

typedef struct _NM_TREEVIEW {

NMHDR hdr;

UINT action;

TV_ITEM itemOld;

TV_ITEM itemNew;

POINT ptDrag; }

NM_TREEVIEW;

typedef NM_TREEVIEW FAR *LPNM_TREEVIEW;



此结构包含树控件消息的信息。

此结构中action成员是特定的通知消息位。它表明是由鼠标动作引起的选择操作的改变,还是由键盘动作引起的。比如,当在树控件的小加号/减号(+/-)上点击鼠标左键时,带有子节点的项就要展开或者合拢。那么究竟是展开还是合拢,就要通过这个action字段来区分。当action == TVE_EXPAND时,就展开;当action == TVE_COLLAPSE时就合拢。 而itemOlditemNew分别是旧结点的状态和新结点的状态。ptDrag是引起消息发送的事件发生时的鼠标在客户区上的坐标。

在通知消息处理函数中一般使用HMHDR指针,例如:

afx_msg void OnTreeDblClk(NMHDR * pNMHDR, LRESULT *pResult);

而有时,甚至是大多数时候,在消息处理函数需要使用NM_TREEVIEW对象,这时可以将消息处理函数传进来的NMHDR指针强制转换为NM_TREEVIEW指针。例如:

void CComDlg::OnSelchangedTreeview(NMHDR* pNMHDR, LRESULT* pResult)

{

       NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

       CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_TREEVIEW1);

    HTREEITEM hSelected = pNMTreeView->itemNew.hItem;

    if (hSelected != NULL) {

        char text[31];

        TV_ITEM item;

        item.mask = TVIF_HANDLE | TVIF_TEXT;

        item.hItem = hSelected;

        item.pszText = text;

        item.cchTextMax = 30;

        VERIFY(pTree->GetItem(&item));

                     SetDlgItemText(IDC_STATIC_TREEVIEW1

pTree->GetItemText(hSelected));

    }

    

       *pResult = 0;

}



――――――――――――――――――――――――――――――――――――

此函数处理了NM_SELCHANGED消息,在树控件中某项的选择状态被改变后,在一个静态文本框中显示改变后新项的项标签文本。其实这段代码也可以用如下代码代替:

CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_TREEVIEW1);

HTREEITEM hSelected = pTree->GetSelectedItem();

if (hSelected != NULL) {

              SetDlgItemText(IDC_STATIC_TREEVIEW1

pTree->GetItemText(hSelected));

     }

     pResult = 0;

――――――――――――――――――――――――――――――――――――

区别是前一段代码中选择在程序栈中为项标签文本缓冲区分配内存,而后一段代码中选择在程序堆中为项标签文本分配内存。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  action struct windows null