怎么发送消息选择wxpython treectrll的某个节点,并触发TVN

MDI程序中怎样在APP类中关闭已经打开的文档解决方法 - VC/MFC当前位置:& &&&MDI程序中怎样在APP类中关闭已经打开的文档解决方法MDI程序中怎样在APP类中关闭已经打开的文档解决方法&&网友分享于:&&浏览:48次MDI程序中怎样在APP类中关闭已经打开的文档VC6
app类:CMyA
文档类:CMyD
怎样在APP类中关闭已经打开的文档?------解决方案--------------------CWinApp::GetFirstDocTemplatePosition/CWinApp::GetNextDocTemplate遍历文档模板;
CDocTemplate::GetFirstDocPosition/CDocTemplate::GetNextDoc遍历文档
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有树结点没用改变时,我使用sendmessage发送TVN_SELCHANGED(树结点改变的消息),可是为什么还是触发不了OnSelchanged函数啊
树结点没用改变时,我使用sendmessage发送TVN_SELCHANGED(树结点改变的消息),可是为什么还是触发不了OnSelchanged函数啊
发布时间: 23:54:22
编辑:www.fx114.net
本篇文章主要介绍了"树结点没用改变时,我使用sendmessage发送TVN_SELCHANGED(树结点改变的消息),可是为什么还是触发不了OnSelchanged函数啊
20lewice]",主要涉及到树结点没用改变时,我使用sendmessage发送TVN_SELCHANGED(树结点改变的消息),可是为什么还是触发不了OnSelchanged函数啊
20lewice]方面的内容,对于树结点没用改变时,我使用sendmessage发送TVN_SELCHANGED(树结点改变的消息),可是为什么还是触发不了OnSelchanged函数啊
20lewice]感兴趣的同学可以参考一下。
树结点没用改变时,我使用sendmessage发送TVN_SELCHANGED(树结点改变的消息),可是为什么还是触发不了OnSelchanged函数啊
问题如上,谢了,你是怎么发的呢??????用SetItemState来改变节点你的参数有误就是这样发的,m_TreeCtrl.PostMessage(TVN_SELCHANGED);
m_TreeCtrl.SendMessage(TVN_SELCHANGED);
2个我都试了,不行用WM_NOTIFY&发消息:
CTreeCtrl&&ctrl&=&GetTreeCtrl();
NMTREEVIEW&
memset((void*)&vi,0,sizeof(NMTREEVIEW));
vi.hdr.hwndFrom&=&ctrl.m_hW
vi.hdr.idFrom&=&::GetWindowLong(ctrl.m_hWnd,GWL_ID);
vi.hdr.code&=&TVN_SELCHANGED;
vi.action&=&TVN_SELCHANGED;
//vi.itemOld&=&hO
//vi.itemNew&=&hN
::SendMessage(ctrl.m_hWnd,WM_NOTIFY,(WPARAM)vi.hdr.idFrom,(LPARAM)&vi);恩,楼上的大虾,谢了,可以了,不过要用postmessage来发
问下,为什么不能直接m_TreeCtrl.PostMessage(TVN_SELCHANGED);
这样发了?在MSG结构中,TVN_SELCHANGED不是消息,只是WM_NOTIFY消息中的一个参数用POS发,在接收消息的过程中要把pvi&free掉,这样做不是很安全,还要区分是系统发的还是你发的消息,因为系统发的是SendMessag,不能把它的结构指针free掉
CTreeCtrl&&ctrl&=&GetTreeCtrl();
NMTREEVIEW*&pvi&=&(NMTREEVIEW*)calloc(1,sizeof(NMTREEVIEW));
pvi-&hdr.hwndFrom&=&ctrl.m_hW
pvi-&hdr.idFrom&=&::GetWindowLong(ctrl.m_hWnd,GWL_ID);
pvi-&hdr.code&=&TVN_SELCHANGED;
pvi-&action&=&TVN_SELCHANGED;
//pvi-&itemOld&=&hO
//pvi-&itemNew&=&hN
::PostMessage(ctrl.m_hWnd,WM_NOTIFY,(WPARAM)vi.hdr.idFrom,(LPARAM)pvi);??我只知道post是发送后一定要等到消息响应才会返回,而send只是负责发送出去,
这段话,能再详细点吗,不懂
用POS发,在接收消息的过程中要把pvi&free掉,这样做不是很安全,还要区分是系统发的还是你发的消息,因为系统发的是SendMessag,不能把它的结构指针free掉****.SendMessage(WM_NOTIFY,...);******
我只知道post是发送后一定要等到消息响应才会返回,而send只是负责发送出去,
意思反了,SendMessage是发送后一定要等到消息响应才会返回,PostMessage把消息添加到消息队列即返回,NMTREEVIEW结构需要用户自己分配和释放,因此用PostMessage,栈变量不行(NMTREEVIEW&
),发送消息的过程结束后,栈变量释放,相应消息的过程访问不到栈变量。用堆变量可以(NMTREEVIEW*&),但在响应消息的过程中,要把它释放楼上的大虾,你说的意思,我有点明白了,
你是说send是发送后必须返回,所以内存结构它自动帮你释放了,
而post是只是添加到消息队列,以后就不管了,这样NMTREEVIEW会造成内存泄漏
我理解的正确吗,是这个意思吗,??
可是问题出现了,我用这段代码,也就是你说的栈变量,它是可以的;
CTreeCtrl&&ctrl&=&m_TreeC
NMTREEVIEW&
memset((void*)&vi,0,sizeof(NMTREEVIEW));
vi.hdr.hwndFrom&=&ctrl.m_hW
vi.hdr.idFrom&=&::GetWindowLong(ctrl.m_hWnd,GWL_ID);
vi.hdr.code&=&TVN_SELCHANGED;
vi.action&=&TVN_SELCHANGED;
//vi.itemOld&=&hO
//vi.itemNew&=&hN
::PostMessage(ctrl.m_hWnd,WM_NOTIFY,(WPARAM)vi.hdr.idFrom,(LPARAM)&vi);
反而,是这段代码不行了,也就是你说的堆变量,
CTreeCtrl&&ctrl&=&m_TreeC
NMTREEVIEW*&pvi&=&(NMTREEVIEW*)calloc(1,sizeof(NMTREEVIEW));
pvi-&hdr.hwndFrom&=&ctrl.m_hW
pvi-&hdr.idFrom&=&::GetWindowLong(ctrl.m_hWnd,GWL_ID);
pvi-&hdr.code&=&TVN_SELCHANGED;
pvi-&action&=&TVN_SELCHANGED;
//pvi-&itemOld&=&hO
//pvi-&itemNew&=&hN
::PostMessage(ctrl.m_hWnd,WM_NOTIFY,(WPARAM)pvi-&hdr.idFrom,(LPARAM)pvi);
还有为什么这2种情况我用send发送反而不行了?你说的意思我也明白了,NMTREEVIEW&是局部变量,出了函数,vi就没了,不保险
NMTREEVIEW*&pvi&=&(NMTREEVIEW*)calloc(1,sizeof(NMTREEVIEW));是分配堆内存,不free它是会保存的,可是实际为什么不是那么回事呢?
本文标题:
本页链接:1. 标准消息(队列消息)
除WM_COMMAND之外,所有以WM_开头的消息都是标准消息,如WM_MOUSEMOVE、WM_LBUTTONUP、
WM_KEYDOWN、WM_CHAR。
从CWnd派生的类都可以接收到这类消息。
Windows每次从系统消息队列移走一个消息,确定它是送给哪个窗口的和这个窗口是由哪个线程创建的,然后,把它放进窗口
创建线程的线程消息队列。线程消息队列接收送给该线程所创建窗口的消息。线程从消息队列取出消息,通过Windows 把它送
给适当的窗口过程来处理。除了键盘、鼠标消息以外,队列消息还有WM_PAINT、WM_TIMER 和WM_QUIT。
注意:标准消息并不需要我们指定处理函数名称,是默认的对应关系。
宏名称                        对应消息                消息处理函数
ON_WM_CHAR           WM_CHAR                OnChar
ON_WM_CLOSE          WM_CLOSE              OnClose
ON_WM_CREATE        WM_CREATE             OnCreate
ON_WM_DESTROY      WM_DESTROY           OnDestroy
ON_WM_LBUTTONDO  WM_LBUTTONDOWN  OnLButtonDown
ON_WM_LBUTTONUP   WM_LBUTTONUP       OnLButtonUp
ON_WM_MOUSEMOVE  WM_MOUSEMOVE      OnMouseMove
ON_WM_PAINT           WM_PAINT               OnPaint
.........  ............ .......
2.命令消息
来自菜单、加速键或工具栏按钮的消息均是命令消息。
这类消息都以WM_COMMAND形式呈现。在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息
的wParam参数识别。从CCmdTarget派生的类都可以接收到这类消息,其wParam 记录着该消息来自哪一个菜单项目。
ON_COMMAND(IDM_ABOUT,  OnAbout)
ON_COMMAND(IDM_FILENEW, OnFileNew)
ON_COMMAND(IDM_FILEOPEN, OnFileOpen)
ON_COMMAND(IDM_FILESAVE, OnFileSave)
...........
3.通告消息
由控件产生的消息,例如按钮,列表框的选择等都会产生通告消息,目的是为了向其父窗口(通常是对话框)通知事件的发
这类消息是以WM_COMMAND或WM_NOTIFY形式呈现的。从CCmdTarget派生的类(如CDocument可以接受命令消息和
通告消息,但不能接收标准消息(队列消息)),都可以接收到这类消息。
注意:由于CWnd类派生于CCmdTarget类,所以凡是从CWnd派生的类,他们既可以接收标准消息,也可以接收命令消息和
通告消息。而对于从CCmdTarget类派生的类只能接收命令消息和通告消息,不能接受标准消息。
例如: 
控件                     宏                                  消息处理函数
Button  ON_BN_CLICKED(&id&,&memberFxn&)  memberFxn
ComboBox  ON_CBN_DBLCLK(&id&,&memberFxn&)  memberFxn
Edit  ON_EN_SETFOCUS(&id&,&memberFxn&)  memberFxn
ListBox  ON_LBN_DBLCLK(&id&,&memberFxn&)  memberFxn
.........  ......................  ...........
标准消息和非标准消息的区分:
标准消息:代有控制后后续操作;
非标准消息:只是简单提示。
MFC命令消息的路由:
AfxWndProc(替换了窗口过程函数)-&AfxCallWndProc-&WindowProc-&OnWnddMsg-&(如果是命令消息则调用O如果是
通告消息则调用OnNotify)-&OnCmdMsg
那么通告消息到底是WM_COMMAND还是WM_NOTIFY呢?
解释一:WM_NOTIFY比WM_COMMAND 功能更强大,可以存储一些额外的信息,WM_COMMAND 并不被所有的控件所支
解释二:Edit,Button,ListBox等发送WM_COMMAND消息,ListView,Toolbar,Tree等编译时如果不联接comctl32.lib就通
不过的。Common Controls发送WM_NOTIFY消息,因为需要提供的信息更多。
给对话框中的控件发送消息:
想要给CTreeCtrl控件模拟发送一个TCN_SELCHANGE消息。
想要给CButton控件模拟发送一个BN_CLICKED消息。
★  由上面对windows消息的分类,我们得知,这两个消息都是通告消息。那是用 WM_COMMAND还是WM_NOTIFY呢?
根据上面的解释,我们使用 TCN_SELCHANGE--WM_NOTIFY ,BN_CLICKED--WM_COMMAND。
是不是这样呢?咱们参看MSDN:
TCN_SELCHANGE
lpnmhdr = (LPNMHDR) lP
Notifies a tab control's parent window that the currently selected tab has changed. This message is sent in the form of
No return value.
lpnmhdrAddress of an
structure. The hwndFrom member is the handle to the tab control. The idFrommember is the child window identifier of the tab control. The code member is TCN_SELCHANGE.
由上看出TCN_SELCHANGE确实是以呈现的,它包含以一个结构体指针的形式包含在lParam中:
typedef struct tagNMHDR { HWND hwndF UINT idF UINT } NMHDR;
Contains information about a notification message.
hwndFromWindow handle to the control sending a message. idFromIdentifier of the control sending a message. codeNotification code. This member can be a control-specific notification code or it can be one of the common notification codes.
注:关于NMHDR以及ON_NOTIFY(转自:)
NMHDR结构的引进就是消息统一起来,利用它可以传递复杂的信息。这个结构的布局如下:
HWnd hWndF 相当于原WM_COMMAND传递方式的lParam
UINT idF  相当于原WM_COMMAND传递方式的wParam(low-order)
UINT 相当于原WM_COMMAND传递方式的Notify Code(wParam&s high-order)
对于这个结构的应用于WM_NOTIFY信息结构,结果WM_NOTIFY就变成了:
A、无附加信息。结构变得很简单,就是一个NMHDR结构。
B、有附加信息。定义一个大的结构,它的第一个元素就是NMHDR结构,它的后面放置附加信息。
WM_NOTIFY结构的好处:
由于在大结构中,第一个成员为NMHDR,这样一来,我们就可以利用指向NMHDR的指针来传递结构地址,根据指针的特性,无论消息有没有附加信息,这个指针都适用,也能够很方便的进行强制转换。
分析ON_NOTIFY:
   类向导可以创建ON_NOTIFY消息映射入口并提供一个处理函数的框架,来处理 WM_NOTIFY类型的消息。ON_NOTIFY消息映射宏有如下语法:
ON_NOTIFY(wNotifyCode,id,memberFxn)
     wNotifyCode:要处理的通知消息通知码。比如上面我们提到的LVN_KEYDOWN;
     Id:控件标识ID;
     MemberFxn:处理此消息的成员函数。
此成员函数有如下的原型声明:
afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result);
比如:假设你想成员函数OnKeydownList1处理ClistCtrl(标识ID=IDC_LIST1)的 LVN_KEYDOWN消息,你可以使用类向导添加如下的消息映射:
ON_NOTIFY( LVN_KEYDOWN, IDC_LIST1, OnKeydownList1 )
在上面的例子中,类向导提供如下函数:
void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult)
LV_KEYDOWN* pLVKey= (LV_KEYDOWN*)pNMHDR;
*pResult = 0;
这时类向导提供了一个适当类型的指针,你既可以通过pNMHDR,也可以通过 pLVKey来访问这个通知结构。
ON_NOTIFY_RANGE:
有时我们可能需要为一组控件处理相同的WM_NOTIFY消息。这时需要使用ON_NOTIFY_RANGE而不是ON_NOTIFY。不过,很不幸的是,VC6的ClassWizard并不支持这个消息,所以我们必须手工添加。方法和一般的手工添加的消息一样,不过需要注意的是:
(1)当你使用 ON_NOTIFY_RANGE时,你需要指定控件的ID范围.其消息映射入口及函数原型如下:
ON_NOTIFY_RANGE( wNotifyCode, id, idLast, memberFxn )
其中:wNotifyCode:消息通知码.比如:LVN_KEYDOWN。id: 第一控件的标识ID。
idLast:最后一个控件的标识ID。(标识值一定要连续)memberFxn: 消息处理函数。
(2)成员函数必须有如下原型申明:afx_msg void memberFxn( UINT id, NMHDR * pNotifyStruct, LRESULT * result );
BN_CLICKED
The BN_CLICKED notification message is sent when the user clicks a button. The parent window of the button receives
this notification message through the WM_COMMAND message.
BN_CLICKED
idButton = (int) LOWORD(wParam); // identifier of button
hwndButton = (HWND) lP // handle to button
由上看出BN_CLICKED确实是包含在WM_COMMAND 中的。
★  怎样把通告消息溶到WM_COMMAND 和 中呢?
idCtrl = (int) wP
pnmh = (LPNMHDR) lP
idCtrlIdentifier of the common control sending the message. pnmhAddress of an
structure that contains the notification code and additional information.
WM_COMMAND
wNotifyCode = HIWORD(wParam); // notification code
wID = LOWORD(wParam);  // item, control, or accelerator identifier
hwndCtl = (HWND) lP  // handle of control
组装参数:
LPARAM MAKELPARAM(
WORD wLow, // low-order word
WORD wHigh // high-order word
DWORD MAKELONG(
WORD wLow, // low-order word of long value
WORD wHigh // high-order word of long value );
★  向控件发消息我们可以使用以下两个方法: 
LONG SendDlgItemMessage(
HWND hDlg,  // handle of dialog box
int nIDDlgItem, // identifier of control
UINT Msg,  // message to send
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
LRESULT SendMessage(
HWND hWnd,  // handle of destination window
UINT Msg,  // message to send
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
★  实例,验证成功:
//模拟发送TCN_SELCHANGE消息
NMHDR 
nmhdr.code = TCN_SELCHANGE;  nmhdr.hwndFrom = g_pMainDlg-&m_TabCtrl.GetSafeHwnd();  nmhdr.idFrom= g_pMainDlg-&m_TabCtrl.GetDlgCtrlID();
::SendDlgItemMessage(g_pMainDlg-&m_hWnd,IDC_TAB1,WM_NOTIFY,MAKELONG(TCN_SELCHANGE,0),(LPARAM)(&nmhdr)); 
//发送BN_CLICKED消息
::SendMessage(g_pMainDlg-&m_VNOnLine.m_hWnd,WM_COMMAND,MAKELPARAM(IDC_RANG_OFF,BN_CLICKED),(LPARAM)(::GetDlgItem(g_pMainDlg-&m_VNOnLine.m_hWnd,IDC_RANG_OFF)));
阅读(...) 评论()TreeCtrl控件使用经验总结
VC/MFC之TreeCtrl控件使用经验总结
树形控件可以用于树形的结构,其中有一个根接点(Root)然后下面有许多子结点,而每个子结点上有允许有一个或多个或没有子结点。MFC中使用CTreeCtrl类来封装树形控件的各种操作。通过调用
Create( DWORD dwStyle, const RECT& rect, CWnd*
pParentWnd, UINT nID
);创建一个窗口,dwStyle中可以使用以下一些树形控件的专用风格:
TVS_HASLINES 在父/子结点之间绘制连线
TVS_LINESATROOT 在根/子结点之间绘制连线
TVS_HASBUTTONS
在每一个结点前添加一个按钮,用于表示当前结点是否已被展开
TVS_EDITLABELS 结点的显示字符可以被编辑
TVS_SHOWSELALWAYS
在失去焦点时也显示当前选中的结点
TVS_DISABLEDRAGDROP
不允许Drag/Drop
TVS_NOTOOLTIPS
不使用ToolTip显示结点的显示字符
在树形控件中每一个结点都有一个句柄(HTREEITEM),同时添加结点时必须提供的参数是该结点的父结点句柄,(其中根Root结点只有一个,既不可以添加也不可以删除)利用
InsertItem( LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT,
HTREEITEM hInsertAfter = TVI_LAST
);可以添加一个结点,pszItem为显示的字符,hParent代表父结点的句柄,当前添加的结点会排在hInsertAfter表示的结点的后面,返回值为当前创建的结点的句柄。
下面的代码会建立一个如下形式的树形结构:
+--- Child1_1
+--- Child1_2
+--- Child1_3
hItem,hSubI
m_tree.InsertItem("Parent1",TVI_ROOT);在根结点上添加Parent1
m_tree.InsertItem("Child1_1",hItem);//在Parent1上添加一个子结点
m_tree.InsertItem("Child1_2",hItem,hSubItem);//在Parent1上添加一个子结点,排在Child1_1后面
= m_tree.InsertItem("Child1_3",hItem,hSubItem);
m_tree.InsertItem("Parent2",TVI_ROOT,hItem);&&&
m_tree.InsertItem("Parent3",TVI_ROOT,hItem);&&&
如果你希望在每个结点前添加一个小图标,就必需先调用CImageList*
SetImageList( CImageList * pImageList, int nImageListType
CImageList指向一个CImageList对象,如果这个值为空,则CTreeCtrl中的Image将被移除。
nImageListType有两种,TVSIL_NORMAL-包含选择和被选择两个状态的Image,TVSIL_STATE-用户定义状态的Image。
在调用完成后控件中使用图片以设置的ImageList中图片为准。然后调用
InsertItem( LPCTSTR lpszItem, int nImage, int nSelectedImage,
HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter =
TVI_LAST);添加结点,
nImage为结点没被选中时所使用图片序号,nSelectedImage为结点被选中时所使用图片序号。
下面的代码演示了ImageList的设置。
m_list.Create(IDB_TREE,16,4,RGB(0,0,0));
m_tree.SetImageList(&m_list,TVSIL_NORMAL);
m_tree.InsertItem("Parent1",0,1);//添加,选中时显示图标1,未选中时显示图标0
CBitmap&&&&
imglist.Create(16, 16, ILC_MASK, 1,
bitmap.LoadBitmap( IDB_COMPUTER
imglist.Add(&bitmap,
(COLORREF)0xFFFFFF);
bitmap.DeleteObject();
treectrl.SetImageList(&m_imgList,
TVSIL_NORMAL);
此外CTreeCtrl还提供了一些函数用于得到/修改控件的状态。
GetSelectedItem( );将返回当前选中的结点的句柄。BOOL SelectItem( HTREEITEM hItem
);将选中指明结点。
GetItemImage( HTREEITEM hItem, int& nImage,
int& nSelectedImage ) / BOOL SetItemImage(
HTREEITEM hItem, int nImage, int nSelectedImage
)用于得到/修改某结点所使用图标索引。
GetItemText( HTREEITEM hItem ) /BOOL SetItemText( HTREEITEM hItem,
LPCTSTR lpszItem );用于得到/修改某一结点的显示字符。
DeleteItem( HTREEITEM hItem );用于删除某一结点,BOOL DeleteAllItems(
);将删除所有结点。
此外如果想遍历树可以使用下面的函数:
GetRootItem( );得到根结点。
GetChildItem( HTREEITEM hItem );得到子结点。
GetPrevSiblingItem/GetNextSiblingItem( HTREEITEM hItem
);得到指明结点的上/下一个兄弟结点。
GetParentItem( HTREEITEM hItem );得到父结点。
树形控件的消息映射使用ON_NOTIFY宏,形式如同:ON_NOTIFY(
wNotifyCode, id, memberFxn
),wNotifyCode为通知代码,id为产生该消息的窗口ID,memberFxn为处理函数,函数的原型如同void
OnXXXTree(NMHDR* pNMHDR, LRESULT*
pResult),其中pNMHDR为一数据结构,在具体使用时需要转换成其他类型的结构。对于树形控件可能取值和对应的数据结构为:
TVN_SELCHANGED
在所选中的结点发生改变后发送,所用结构:NMTREEVIEW
TVN_ITEMEXPANDED
在某结点被展开后发送,所用结构:NMTREEVIEW
TVN_BEGINLABELEDIT
在开始编辑结点字符时发送,所用结构:NMTVDISPINFO
TVN_ENDLABELEDIT
在结束编辑结点字符时发送,所用结构:NMTVDISPINFO
TVN_GETDISPINFO
在需要得到某结点信息时发送,(如得到结点的显示字符)所用结构:NMTVDISPINFO
关于ON_NOTIFY有很多内容,将在以后的内容中进行详细讲解。
关于动态提供结点所显示的字符:首先你在添加结点时需要指明lpszItem参数为:LPSTR_TEXTCALLBACK。在控件显示该结点时会通过发送TVN_GETDISPINFO来取得所需要的字符,在处理该消息时先将参数pNMHDR转换为LPNMTVDISPINFO,然后填充其中item.pszText。但是我们通过什么来知道该结点所对应的信息呢,我的做法是在添加结点后设置其lParam参数,然后在提供信息时利用该参数来查找所对应的信息。下面的代码说明了这种方法:
szOut[8][3]={"No.1","No.2","No.3"};
//添加结点
m_tree.InsertItem(LPSTR_TEXTCALLBACK,...)
m_tree.SetItemData(hItem, 0
m_tree.InsertItem(LPSTR_TEXTCALLBACK,...)
m_tree.SetItemData(hItem, 1
//处理消息
CParentWnd::OnGetDispInfoTree(NMHDR* pNMHDR, LRESULT*
TV_DISPINFO* pTVDI =
(TV_DISPINFO*)pNMHDR;
pTVDI-&item.pszText=szOut[pTVDI-&item.lParam];//通过lParam得到需要显示的字符在数组中的位置
关于编辑结点的显示字符:首先需要设置树形控件的TVS_EDITLABELS风格,在开始编辑时该控件将会发送TVN_BEGINLABELEDIT,你可以通过在处理函数中返回TRUE来取消接下来的编辑,在编辑完成后会发送TVN_ENDLABELEDIT,在处理该消息时需要将参数pNMHDR转换为LPNMTVDISPINFO,然后通过其中的item.pszText得到编辑后的字符,并重置显示字符。如果编辑在中途中取消该变量为NULL。下面的代码说明如何处理这些消息:
//处理消息
TVN_BEGINLABELEDIT
CParentWnd::OnBeginEditTree(NMHDR* pNMHDR, LRESULT*
TV_DISPINFO* pTVDI =
(TV_DISPINFO*)pNMHDR;
if(pTVDI-&item.lParam==0);//判断是否取消该操作
&& *pResult =
&& *pResult =
//处理消息
TVN_BEGINLABELEDIT
CParentWnd::OnBeginEditTree(NMHDR* pNMHDR, LRESULT*
TV_DISPINFO* pTVDI =
(TV_DISPINFO*)pNMHDR;
if(pTVDI-&item.pszText==NULL);//判断是否已经取消取消编辑
m_tree.SetItemText(pTVDI-&item.hItem,pTVDI-&pszText);//重置显示字符
上面讲述的方法所进行的消息映射必须在父窗口中进行(同样WM_NOTIFY的所有消息都需要在父窗口中处理)。
1.树视图风格:
TVS_HASBUTTONS;&&&
//在父项旁边显示(+)和(-)
TVS_HASLINES;&&&&
//使用线条显示各项之间的层次
TVS_LINESATROOT;//使用线条链接树视图控件根部各项
2.处理单击事件:TVN_SELCHANGED
CTreeCtrlDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT
LPNMTREEVIEW pNMTreeView =
reinterpret_cast&LPNMTREEVIEW&(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
HTREEITEM ht=m_treeCtrl.GetSelectedItem();
CString strSelect=m_treeCtrl.GetItemText(ht);
m_strTreeVal=strS
UpdateData(FALSE);
*pResult = 0;
3.同时让自己派生的CMyTreeCtrl类和对话框处理TVN_SELCHANGED消息:
只须在CMyTreeCtrl中处理以下消息,并返回FALSE就OK了ON_NOTIFY_REFLECT_EX(TVN_SELCHANGED,
OnTvnSelchanged)
OnTvnSelchanged的签名如下
CMyTreeCtrl::OnTvnSelchanged(NMHDR *pNMHDR,LRESULT
4.编辑标签:要允许编辑树视图控件中的文本,可以设置以下三个步骤
(1).设置树视图的TVS_EDITLABELS风格
TVS_EDITLABE可以通过资源编辑框内部修改(Edit
labels),也可以用代码的方式修改,如下
lStyle=::GetWindowLong(m_treeCtrl.GetSafeHwnd(),GWL_STYLE);
lStyle|=TVS_EDITLABELS;
::SetWindowLong(m_treeCtrl.GetSafeHwnd(),GWL_STYLE,lStyle)
(2).处理TVN_BEGINLABELEDIT通知消息
//设置相关限制,如限制编辑框字符串长度
CEdit*pEdit=GetEditControl();&&&&
//获取当前选中结点编辑框
ASSERT(pEdit);
if (pEdit)
pEdit-&LimitText(15);//设置编辑框文本长度为15个字符串
*pResult =
(3).处理TVN_ENDLABLEEDIT通知消息
hParent=GetParentItem(pTVDispInfo-&item.hItem);
//获取父结点&
HTREEITEM hChild=GetChildItem(hParent?hParent:TVI_ROOT);
//获取第一个根结点
hChild=GetNextSiblingItem(hChild);&&&&&&&&&&&
//获取下一个兄弟节点
(pTVDispInfo-&item.hItem!=hChild)&&&&&&&&&
//判断是否与当前节点相同
pTVDispInfo-&item.pszText&&&&&&&&&&&&&&&&&&&&
//获取当前节点的字符串
strText=GetItemText(hChild);&&&&&&&&&
//获取节点的字符串
5.让树视图处理Esc和Enter键
重载PreTranslateMessage函数
bHandleMsg=FALSE;
switch(pMsg-&message) {
case VK_ESCAPE:
case VK_RETURN:
(::GetKeyState(VK_CONTROL)&0x8000)
&&&&&&&&&&&&&
if (GetEditControl())
&&&&&&&&&&&&&
::TranslateMessage(pMsg);
&&&&&&&&&&&&&
::DispatchMessage(pMsg);
&&&&&&&&&&&&&
bHandleMsg=TRUE;
4.实现上下文菜单
在WM_RBUTTONDOWN消息处理函数上实现上下文菜单
5.展开和收起树视图结点:
hItem=GetRootItem();&&&&&&&&&&&&&&&
//获取根结点,可能会有多个根结点
ItemHasChildren(hParent)&&&&&&&&&&&&&&&&&&&&&
//判断结点是否有孩子结点
hItem=GetChildItem(hParent);&&&&&&&&&&&&&&&&&
//获取第一个子结点
hItem=GetNextSiblingItem(hItem));&&&&&&&&&&&&
//获取下一个兄弟结点结点
Expand(hItem,bExpand?TVE_EXPAND:TVE_COLLAPSE);//展开/叠起结点
Select(hItem,TVGN_FIRSTVISIBLE);&&&&&&&&&&&&&&&&&
//设置选中结点
str=GetItemText(hChild);&&&&&&&&&&&&&
//获取结点字符串信息
hCurrSel =
GetSelectedItem();&&&&&&
//获取当前选中结点
SelectItem(hNewSel);
hNewSel = HitTest(pt,
&nFlags);&&&&&&&&
//判断坐标是否在当前结点范围内
hItem=InsertItem(dlg.m_strItemText,hItemParent);&&&
//插入结点
//定义文件MyTreeCtrl.h
CMyTreeCtrl
CMyTreeCtrl : public CTreeCtrl
DECLARE_DYNAMIC(CMyTreeCtrl)
CMyTreeCtrl();
virtual ~CMyTreeCtrl();
protected:
DECLARE_MESSAGE_MAP()
void ExpandBranch(HTREEITEM hItem,BOOL bExpand
void ExpandAllBranches(BOOL bExpand =TRUE);
BOOL DoesItemExist(HTREEITEM hItemParent, CString
const& strItem);
afx_msg void OnRButtonDown(UINT nFlags, CPoint
afx_msg void OnAddItem();
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnTvnBeginlabeledit(NMHDR *pNMHDR, LRESULT
*pResult);
afx_msg void OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT
*pResult);
afx_msg BOOL OnTvnSelchanged(NMHDR *pNMHDR, LRESULT
*pResult);
MyTreeCtrl.cpp : 实现文件
"stdafx.h"
"TreeCtrl.h"
"MyTreeCtrl.h"
".mytreectrl.h"
"AddItemDlg.h"
CMyTreeCtrl
IMPLEMENT_DYNAMIC(CMyTreeCtrl,
CTreeCtrl)
CMyTreeCtrl::CMyTreeCtrl()
CMyTreeCtrl::~CMyTreeCtrl()
BEGIN_MESSAGE_MAP(CMyTreeCtrl,
CTreeCtrl)
ON_WM_RBUTTONDOWN()
ON_COMMAND(IDR_ADD_ITEM, OnAddItem)
ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT,
OnTvnEndlabeledit)
ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT,
OnTvnBeginlabeledit)
ON_NOTIFY_REFLECT_EX(TVN_SELCHANGED,
OnTvnSelchanged)
END_MESSAGE_MAP()
CMyTreeCtrl 消息处理程序
CMyTreeCtrl::ExpandBranch(HTREEITEM hItem,BOOL bExpand
(ItemHasChildren(hItem))&&&
//判断是否有孩子结点
Expand(hItem,bExpand?TVE_EXPAND:TVE_COLLAPSE);
//展开/叠起结点
hItem=GetChildItem(hItem);//获取第一个子结点
&&&&&&&&&&&&&
ExpandBranch(hItem);
while(hItem=GetNextSiblingItem(hItem));//获取兄弟结点
CMyTreeCtrl::ExpandAllBranches(BOOL bExpand )
HTREEITEM hItem=GetRootItem();//获取根结点,可能会有多个根结点
ExpandBranch(hItem,bExpand);
} while(hItem=GetNextSiblingItem(hItem));
Select(hItem,TVGN_FIRSTVISIBLE);//设置选中结点
CMyTreeCtrl::DoesItemExist(HTREEITEM
hItemParent,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
CString const& strItem)
BOOL bDoesItemExist=FALSE;
ASSERT(strItem.GetLength());
hChild=GetChildItem(hItemParent?hItemParent:TVI_ROOT);
(NULL!=hChild&&!bDoesItemExist)
CString str=GetItemText(hChild);//获取结点字符串信息
if (0==pareNoCase(strItem))
&&&&&&&&&&&&&
bDoesItemExist=TRUE;
&&&&&&&&&&&&&
hChild=GetNextSiblingItem(hChild);
return bDoesItemE
CMyTreeCtrl::OnRButtonDown(UINT nFlags, CPoint
在此添加消息处理程序代码和/或调用默认值&&&
// set focus to the tree control
SetFocus();
// map the point that is passed to the
// function from client coordinates
// to screen coordinates
ClientToScreen(&point);
// Get the currently selected item
HTREEITEM hCurrSel =
GetSelectedItem();//获取当前选中结点
// Figure out which item was right clicked
CPoint pt(0, 0);
::GetCursorPos(&pt);
ScreenToClient (&pt);
HTREEITEM hNewSel = HitTest(pt,
// Set the selection to the item that the
// mouse was over when the user right
// clicked
if (NULL == hNewSel)
SelectItem(NULL);
else if (hCurrSel != hNewSel)
SelectItem(hNewSel);
SetFocus();
// Load the context menu
if (Menu.LoadMenu(IDM_CONTEXT_MENU))
CMenu* pSubMenu = Menu.GetSubMenu(0);
if (pSubMenu!=NULL)
&&&&&&&&&&&&&
// Display the context menu
&&&&&&&&&&&&&
pSubMenu-&TrackPopupMenu(
&&&&&&&&&&&&&&&&&
TPM_LEFTALIGN | TPM_RIGHTBUTTON,
&&&&&&&&&&&&&&&&&
point.x, point.y, this);
CMyTreeCtrl::OnAddItem()
//添加上下文菜单
// TODO: 在此添加命令处理程序代码
HTREEITEM hItemParent=GetSelectedItem();
//获取当前选中结点
if (dlg.DoModal()==IDOK)
(!DoesItemExist(hItemParent,dlg.m_strItemText))
&&&&&&&&&&&&&
hItem=InsertItem(dlg.m_strItemText,hItemParent);
&&&&&&&&&&&&&
//插入结点
&&&&&&&&&&&&&
SelectItem(hItem);
&&&&&&&&&&&&&
AfxMessageBox("已存在相同结点");
CMyTreeCtrl::PreTranslateMessage(MSG* pMsg)
// TODO: 在此添加专用代码和/或调用基类
BOOL bHandledMsg = FALSE;
switch (pMsg-&message)
case WM_KEYDOWN:
&&&&&&&&&&&&&
switch (pMsg-&wParam)
&&&&&&&&&&&&&
&&&&&&&&&&&&&
case VK_ESCAPE:
&&&&&&&&&&&&&
VK_RETURN:&&&
&&&&&&&&&&&&&&&&&
if (::GetKeyState(VK_CONTROL) &
&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&
if (GetEditControl())
&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&
::TranslateMessage(pMsg);
&&&&&&&&&&&&&&&&&&&&&
::DispatchMessage(pMsg);
&&&&&&&&&&&&&&&&&&&&&
bHandledMsg = TRUE;
&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&
&&&&&&&&&&&&&
} // switch (pMsg-&wParam)
} // WM_KEYDOWN
} // switch
(pMsg-&message)&&&&&&&&&&&&&&&&&&
// continue normal translation and
dispatching&&&&&&&&&&&&&
return (bHandledMsg ?TRUE :
CTreeCtrl::PreTranslateMessage(pMsg));
CMyTreeCtrl::OnTvnBeginlabeledit(NMHDR *pNMHDR, LRESULT
LPNMTVDISPINFO pTVDispInfo =
reinterpret_cast&LPNMTVDISPINFO&(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult=1;
CEdit*pEdit=GetEditControl();
ASSERT(pEdit);
if (pEdit)
pEdit-&LimitText(15);
*pResult=0;
CMyTreeCtrl::OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT
LPNMTVDISPINFO pTVDispInfo =
reinterpret_cast&LPNMTVDISPINFO&(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
BOOL bValidItem=FALSE;
strItem=pTVDispInfo-&item.pszT
if (0&strItem.GetLength())
hParent=GetParentItem(pTVDispInfo-&item.hItem);
bValidItem=!DoesItemExist(hParent,strItem);&&&&
*pResult = bValidI
CMyTreeCtrl::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT
LPNMTREEVIEW pNMTreeView =
reinterpret_cast&LPNMTREEVIEW&(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
TRACE(GetItemText(pNMTreeView-&itemNew.hItem));
TRACE(" ");
*pResult = 0;
FALSE;&&&&&&&&
//返回FALSE可以让父窗口进行进一步的处理
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 mfc treectrl隐藏节点 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信