SDK中操作TreeView通用控健的问题

APIer 2001-08-17 06:55:02
我为了形象的表示我写的一个n叉树,用TreeView控件来显示我的n叉树节点星系,但是我不喜欢用MFC,所以用的sdk,但在dialog的回调函数的时候我利用下面的notify消息来得到选择的节点的文字,失败了,不知道为什么,请高手指点:
错误是 lpTree->itemNew.pszText的值不是节点的文字
case WM_NOTIFY:
{
if((int) wParam==IDC_TREE_NODE)
{
NMHDR* pnmh = (LPNMHDR) lParam;
if(pnmh->idFrom==IDC_TREE_NODE)
{
if(pnmh->hwndFrom!=GetDlgItem(dialog, IDC_TREE_NODE))
{
return TRUE;
}
switch (pnmh->code)
{
case TVN_SELCHANGED:
NMTREEVIEW* lpTree=(LPNMTREEVIEW) lParam;
char Buffer[256];
/*TV_ITEM tvi;
ZeroMemory(&tvi,sizeof(TV_ITEM));
tvi.mask=TVIF_TEXT | TVIF_PARAM;
tvi.hItem=lpTree->itemNew.hItem;
TreeView_GetItem(pnmh->hwndFrom,&tvi);*/
strcpy(Buffer,lpTree->itemNew.pszText);
J3DINode* pNode=FindJ3DNode(pRoot3DNode,Buffer);
}
}
}
}
...全文
232 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
APIer 2001-08-18
  • 打赏
  • 举报
回复
dcz(dcz) :
你说得很对,刚才我也发现了这个问题,不过还是要多谢你:)
dcz 2001-08-18
  • 打赏
  • 举报
回复
You must set TVITEM structures pszText, cchTextMax for receive the node text, following is a sample:

TVITEM tvi;
TCHAR szText[MAX_LENGTH];
memset(&tvi, 0, sizeof(tvi));
tvi.mask = TVIF_TEXT | TVIF_PARAM;
tvi.hItem = the item handle;
tvi.pszText = szText;
tvi.cchTextMax = sizeof(szText);
BOOL bSuccess = TreeView_GetItem(hwndTreeView, &tvi);

Good Luck!
APIer 2001-08-18
  • 打赏
  • 举报
回复
tiongkohlang(SDK) :
我在mask中使用了tvi.mask=TVIF_TEXT¦TVIF_HANDLE;
后,仍然发现tvi.pszText是null,真的没有脾气了!这个问题应该不是很难,但是肯定是什么东西有点问题,你能够给我一个能够正常使用的例子代码么?让我对找看看问题的所在,我急着用啊:)
代码可以送到:APIer@china.com
APIer 2001-08-18
  • 打赏
  • 举报
回复
tiongkohlang(SDK):
不愧是sdk:)
我去看看行不行,总之多谢了!
tiongkohlang 2001-08-17
  • 打赏
  • 举报
回复
对不起,应该是NMTREEVIEW,第一行错了。
dcz 2001-08-17
  • 打赏
  • 举报
回复
tvi.mask=TVIF_TEXT ¦ TVIF_PARAM;
tvi.hItem=lpTree->itemNew.hItem;
TreeView_GetItem(pnmh->hwndFrom,&tvi);

在调用 TreeView_GetItem 函数前你是否设置了 TVITEM 中的 pszText 和 cchMaxText 两个成员?从你的代码中看不到这样的语句。它们是用于接收返回数据的。
tiongkohlang 2001-08-17
  • 打赏
  • 举报
回复
faint!再贴一遍。
sclzmbie(梦里红尘)不太了解SDK的通用控件编程,人家这么干基本没有问题。sclzmbie(梦里红尘)应该仔细看看NMTREEVIRE和NMHDR的定义。
APIer的问题并不复杂。请看:
switch (pnmh->code)
{
case TVN_SELCHANGED:
NMTREEVIEW* lpTree=(LPNMTREEVIEW) lParam;
char Buffer[256];
/*TV_ITEM tvi;
ZeroMemory(&tvi,sizeof(TV_ITEM));
tvi.mask=TVIF_TEXT|TVIF_PARAM;
tvi.hItem=lpTree->itemNew.hItem;
TreeView_GetItem(pnmh->hwndFrom,&tvi);*/
strcpy(Buffer,lpTree->itemNew.pszText);
J3DINode* pNode=FindJ3DNode(pRoot3DNode,Buffer);
}
首先我不赞成这么组织代码,最好写成这样
switch (pnmh->code)
{
case TVN_SELCHANGED:
{
NMTREEVIEW* lpTree=(LPNMTREEVIEW) lParam;
char Buffer[256];
TV_ITEM tvi;
ZeroMemory(&tvi,sizeof(TV_ITEM));
tvi.mask=TVIF_TEXT|TVIF_PARAM;
tvi.hItem=lpTree->itemNew.hItem;
TreeView_GetItem(pnmh->hwndFrom,&tvi);*/
strcpy(Buffer,lpTree->itemNew.pszText);
J3DINode* pNode=FindJ3DNode(pRoot3DNode,Buffer);
}
}
下面说一下问题的关键所在。
tvi.mask=TVIF_TEXT|TVIF_PARAM;
应该是:
tvi.mask=TVIF_TEXT|TVIF_HANDLE;
APIer的用意很明显,就是要文字,就是pszText。把我说的改了,就可以解决问题。SDK编程就是这样。按理说调用TreeView_GetItem宏肯定要填写hItem,但是就是必须在mask里边加上TVIF_HANDLE,要不然不行。
在顺便说一个事情。
1,不要用TV_ITEM了。现在应该用TVITEM。如果你的SDK头文件比较新,那么应该用这个结构名。完全和TV_ITEN一样,但是它遵守新的命名约定。
tiongkohlang 2001-08-17
  • 打赏
  • 举报
回复
对不起,应该是NMTREEVIEW,第一行错了。
tiongkohlang 2001-08-17
  • 打赏
  • 举报
回复
sclzmbie(梦里红尘)不太了解SDK的通用控件编程,人家这么干基本没有问题。sclzmbie(梦里红尘)应该仔细看看NMTREEVIRE和NMHDR的定义。
APIer的问题并不复杂。请看:
switch (pnmh->code)
{
case TVN_SELCHANGED:
NMTREEVIEW* lpTree=(LPNMTREEVIEW) lParam;
char Buffer[256];
/*TV_ITEM tvi;
ZeroMemory(&tvi,sizeof(TV_ITEM));
tvi.mask=TVIF_TEXT ¦ TVIF_PARAM;
tvi.hItem=lpTree->itemNew.hItem;
TreeView_GetItem(pnmh->hwndFrom,&tvi);*/
strcpy(Buffer,lpTree->itemNew.pszText);
J3DINode* pNode=FindJ3DNode(pRoot3DNode,Buffer);
}
首先我不赞成这么组织代码,最好写成这样
switch (pnmh->code)
{
case TVN_SELCHANGED:
{
NMTREEVIEW* lpTree=(LPNMTREEVIEW) lParam;
char Buffer[256];
TV_ITEM tvi;
ZeroMemory(&tvi,sizeof(TV_ITEM));
tvi.mask=TVIF_TEXT ¦ TVIF_PARAM;
tvi.hItem=lpTree->itemNew.hItem;
TreeView_GetItem(pnmh->hwndFrom,&tvi);*/
strcpy(Buffer,lpTree->itemNew.pszText);
J3DINode* pNode=FindJ3DNode(pRoot3DNode,Buffer);
}
}
下面说一下问题的关键所在。
tvi.mask=TVIF_TEXT ¦ TVIF_PARAM;
应该是:
tvi.mask=TVIF_TEXT ¦ TVIF_HANDLE;
APIer的用意很明显,就是要文字,就是pszText。把我说的改了,就可以解决问题。SDK编程就是这样。按理说调用TreeView_GetItem宏肯定要填写hItem,但是就是必须在mask里边加上TVIF_HANDLE,要不然不行。
在顺便说一个事情。
1,不要用TV_ITEM了。现在应该用TVITEM。如果你的SDK头文件比较新,那么应该用这个结构名。完全和TV_ITEN一样,但是它遵守新的命名约定。
sclzmbie 2001-08-17
  • 打赏
  • 举报
回复
你在case语句里能这么写吗:
  NMTREEVIEW* lpTree=(LPNMTREEVIEW) lParam;
编译器不提示出错?!!
-------------------
不管错不错,你把 lpTree也设为指向lParam的指针,你的
  NMHDR* pnmh = (LPNMHDR) lParam;
也指向lParam,重复引用有什么意思?! 
是不是要指向wParam而写错了?
APIer 2001-08-17
  • 打赏
  • 举报
回复
再顶,高手们,等你帮忙呢!
APIer 2001-08-17
  • 打赏
  • 举报
回复
这么快就被压到2页了?顶!
APIer 2001-08-17
  • 打赏
  • 举报
回复
jiangsheng(蒋晟):
多谢你的帮助,但这里这么多MFC,我很少用MFC的,而且我想知道我上面的处理方法到底错在什么地方,请你帮我看看号么?
蒋晟 2001-08-17
  • 打赏
  • 举报
回复
如果节点文本和节点数据有关的话,建议使用回调节点(callback item)根据节点数据显示文本内容。
插入节点时,每个节点的lParam是一个指向节点数据的指针。
HTREEITEM CCWDeptTree::InsertItem( HTREEITEM hParent, CRecordBase* pRecord)
{
ASSERT(IsWindow(m_hWnd));
TVINSERTSTRUCT InsertStruct;
memset(&InsertStruct,0,sizeof(TVINSERTSTRUCT));
if(hParent==NULL)
InsertStruct.hParent=TVI_ROOT;
else
InsertStruct.hParent=hParent;
InsertStruct.hInsertAfter =TVI_LAST;

InsertStruct.item.mask=TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM;
InsertStruct.item.pszText =LPSTR_TEXTCALLBACK ;
InsertStruct.item.iImage =I_IMAGECALLBACK ;
InsertStruct.item.iSelectedImage =I_IMAGECALLBACK ;
InsertStruct.item.lParam=(LPARAM)pRecord;
HTREEITEM hItem=CTreeCtrl::InsertItem(&InsertStruct);
ASSERT(hItem!=NULL);
m_mapItemToRecord.SetAt(hItem,pRecord);
}

我这里使用一个HTREEITEM到数据的映射来存储数据,当然你也可以用其他方法,比如
InsertStruct.item.lParam=(LPARAM)new CMyObject;分配一块内存来存储数据。

然后截获TVN_GETDISPINFO,来显示信息
void CCWDeptTree::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
// TODO: Add your control notification handler code here
TVITEM* pItem=&pTVDispInfo ->item;
CRecordBase* pItemRecord=(CRecordBase*)pItem->lParam;
if(pItemRecord->IsKindOf(RUNTIME_CLASS(CCWDeptRecord))){
CCWDeptRecord* pDept=DYNAMIC_DOWNCAST(CCWDeptRecord,pItemRecord);
if(pDept){
if(pItem->mask&TVIF_TEXT){
StrCpyN(pItem->pszText,pDept->m_strName,pItem->cchTextMax);
}
if(pItem->mask&TVIF_IMAGE){
pItem->iImage=IMAGE_DEPT;
}
if(pItem->mask&TVIF_SELECTEDIMAGE){
pItem->iSelectedImage=IMAGE_DEPT;
}
}
}
if(pItemRecord->IsKindOf(RUNTIME_CLASS(CCWCardRecord))){
CCWCardRecord* pCard=DYNAMIC_DOWNCAST(CCWCardRecord,pItemRecord);
if(pCard){
if(pItem->mask&TVIF_TEXT){
StrCpyN(pItem->pszText,pCard->Format(),pItem->cchTextMax);
}
if(pItem->mask&TVIF_IMAGE){
pItem->iImage=IMAGE_CARD;
}
if(pItem->mask&TVIF_SELECTEDIMAGE){
pItem->iSelectedImage=IMAGE_CARD;
}
}
}
*pResult = 0;
}
要访问一个HTREEITEM对应的数据就很简单了
CRecordBase* CCWDeptTree::GetRecord(HTREEITEM hItem)
{
if(hItem==NULL)return NULL;
TVITEM tvi;
tvi.mask=TVIF_PARAM|TVIF_HANDLE;
tvi.hItem=hItem;
GetItem(&tvi);
return (CRecordBase*)tvi.lParam;
}
如果你的节点数据是插入时分配的
InsertStruct.item.lParam=(LPARAM)new CMyObject;
那么在退出的时候要手动删除
TVITEM tvi;
tvi.mask=TVIF_PARAM|TVIF_HANDLE;
tvi.hItem=hItem;
GetItem(&tvi);
delete (CMyObject*)tvi.lParam

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧