原帖及讨论:http://bbs.bccn.net/thread-211433-1-1.html 效果描述:该功能可使某义节点下的全部子节点按某种序列重新排列SortChildren是为该结点下面的所有子节点排序,注意只是子节点,不包括子节点的子节点。 SortChildrenCB是自定义排序方式。现给出大体例子 SortChildrenCB中的TVSORTCB需要用到一个回调函数常常是难点。 INT CHvrTree::SortItem(HTREEITEM hItem) { BOOL bRet; CHvrTree *ptree = this; TVSORTCB sortpage;
g_pLogger->Debug("<%s(%d)> SortItem(): Enter",D_PC_LOG_NAME_HVRTREE, __LINE__); ////////////////////////////////////////////////////////////////////////// // ソーティング情報 g_pLogger->Info("<%s(%d)> SortItem(): ソーティングノード,hItem - %08x" ,D_PC_LOG_NAME_HVRTREE, __LINE__,hItem );
sortpage.hParent = hItem; sortpage.lpfnCompare = MyCompareProc; sortpage.lParam = (LPARAM)ptree; bRet = SortChildrenCB(&sortpage); if ( bRet ) { g_pLogger->Debug("<%s(%d)> SortItem(): Leave",D_PC_LOG_NAME_HVRTREE, __LINE__);
return D_PC_SUCCESS; } else { g_pLogger->Debug("<%s(%d)> SortItem(): Leave",D_PC_LOG_NAME_HVRTREE, __LINE__);
return D_PC_FAILURE; } }
入口参数是两个在要排序的序列中的无序参数 INT CALLBACK CHvrTree::MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { CHvrTree* pTreeCtrl = (CHvrTree*) lParamSort;
HTREEITEM hItem1 = (HTREEITEM)lParam1; HTREEITEM hItem2 = (HTREEITEM)lParam2;
// ノードのアイコンに付けられた固有の番号によって、ノードタイプ取得 INT nKind1 = pTreeCtrl->GetItemType(hItem1); INT nKind2 = pTreeCtrl->GetItemType(hItem2); // 1.01 : カテゴリソーティングを機能修正 ////////////////////////////////////////////////////////////////////////// // ノードタイプ取得チェック if ( (nKind1<0)||(nKind2<0) ) { g_pLogger->Error( "<%s(%d)> MyCompareProc: 目標ノードノードタイプ情報取得できない, nType - %d", D_PC_LOG_NAME_HVRTREE, __LINE__, D_PC_FAILURE );
return D_PC_ERRCODE_HVRTREE_GETTREE_FAIL; } // 1.01 - END // ノード情報取得 BOOL bRet; ST_TREE_NODE *pnodeInfo1 = NULL; // ノード1の情報 ST_TREE_NODE *pnodeInfo2 = NULL; // ノード2の情報
bRet = pTreeCtrl->m_mapNode.Lookup(hItem1,(void*&)pnodeInfo1); // ノード1の情報取得 if(bRet == FALSE) { // 目標ノード情報取得できない g_pLogger->Error( "<%s(%d)> MyCompareProc: 目標ノード情報取得できない, hItem - %08x", D_PC_LOG_NAME_HVRTREE, __LINE__, hItem1 ); return D_PC_ERRCODE_HVRTREE_GETTREE_FAIL; } bRet = pTreeCtrl->m_mapNode.Lookup(hItem2,(void*&)pnodeInfo2); // ノード2の情報取得 if(bRet == FALSE) { // 目標ノード情報取得できない g_pLogger->Error( "<%s(%d)> MyCompareProc: 目標ノード情報取得できない, hItem - %08x", D_PC_LOG_NAME_HVRTREE, __LINE__, hItem2 ); return D_PC_ERRCODE_HVRTREE_GETTREE_FAIL; }
INT nRet = NULL; // 戻り値
if( nKind1 == nKind2) { // ノード1とノード2は同じノードタイプの場合
// ノード1とノード2はカテゴリーノードの場合 if( nKind1 == D_PC_NODE_CATE_1) { CString strItem1,strItem2; // カテゴリー名取得 strItem1 = pTreeCtrl->GetItemText(hItem1); strItem2 = pTreeCtrl->GetItemText(hItem2); // カテゴリー名比較 nRet = strcmp(strItem1, strItem2);
}
// 1.01 : カテゴリソーティングを機能修正 else if( nKind1 == D_PC_NODE_CATE_2) { CString strItem1,strItem2; // カテゴリー名取得 strItem1 = pTreeCtrl->GetItemText(hItem1); strItem2 = pTreeCtrl->GetItemText(hItem2); // カテゴリー名比較 nRet = strcmp(strItem1, strItem2);
} // 1.01 - END else if( nKind1 == D_PC_NODE_CAM ) { // ノード1とノード2はカメラノードの場合 // カメラ番号取得 INT nCamId1 = pnodeInfo1->Id; INT nCamId2 = pnodeInfo2->Id; // カメラ番号比較 nRet = nCamId1 - nCamId2; } else if( nKind1 == D_PC_NODE_HVR ) { // ノード1とノード2は物件ノードの場合 ST_HVR_INFO hvrInfo1, hvrInfo2; CString strItem1, strItem2; // 物件番号取得 INT nHvrId1 = pnodeInfo1->Id; INT nHvrId2 = pnodeInfo2->Id; // 物件情報取得 g_hvrUser.GetHvrInfo(nHvrId1, &hvrInfo1); g_hvrUser.GetHvrInfo(nHvrId2, &hvrInfo2); // 1.05 : 物件の順機能修正 // 物件カナ名取得 strItem1.Format("%s",hvrInfo1.szKana); strItem2.Format("%s",hvrInfo2.szKana); // 物件カナ名比較 nRet = CCheckWord::CompareValidKataName( strItem1, strItem2 );
if (nRet == 0) { if (nHvrId1 > nHvrId2) { nRet = 1; }else { nRet = -1; } } // 1.05 - END } else { // 他の場合 nRet = NULL; } } else { // ノード1とノード2は違いノードタイプの場合 nRet = nKind1 - nKind2; }
return nRet; }
GetItemType是获得结点状态即它的图标,主要是利用了GetItemImage得到其图标
复选重绘 有时可能会用到复选操作,即点击一个结点时该结点和另一个结点同时被选中(如其父结点) 可使用系统消息OnCustomDraw,该消息须手动添加 该功能的实质是:先把要选则的所有节点刷上颜色,再到调用时如单击或双击事件把不需要的颜色去掉
virtual void OnCustomDraw(NMHDR *pHdr, LRESULT *pResult);
BEGIN_MESSAGE_MAP(CHvrTree, CTreeCtrl) ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) //}}AFX_MSG_MAP END_MESSAGE_MAP()
void CHvrTree::OnCustomDraw(NMHDR *pHdr, LRESULT *pResult) { LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)pHdr; INT nState; switch(lplvcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: * pResult= CDRF_NOTIFYITEMDRAW; break; // アイテムが描画される前 case CDDS_ITEMPREPAINT: nState = lplvcd->nmcd.uItemState; if((nState == (CDIS_FOCUS|CDIS_SELECTED)) || (nState == CDIS_SELECTED) ) { lplvcd->clrTextBk = D_PC_DEV_ADD_BLACK_BRUSH; // アイテムの文字色を設定 lplvcd->clrText = D_PC_DEV_LIST_RUN_COLOR; * pResult= CDRF_DODEFAULT; break; } else { * pResult= 0; break; } default: * pResult = 0; break; } } 判断结点状态可使用GetItemState。如判断结点是否展开 UINT nState; nState = GetItemState( hItem,TVIS_EXPANDED ); if ( 0 == (nState & TVIS_EXPANDED) ) { // ノード非展開の場合 SetItemImage(hItem,D_PC_NODE_TREEROOT,D_PC_NODE_TREEROOT); } else { SetItemImage( hItem,D_PC_NODE_TREEROOTCOL,D_PC_NODE_TREEROOTCOL ); }
复选 INT CHvrTree::SetActiveItem( ULONG lHvrId,ULONG lCamId ) { HTREEITEM hHvrItem; // HTREEITEM hCamItem; // HTREEITEM hCam;
HTREEITEM hSelectItem; // ST_TREE_NODE *pCamNode; // BOOL bRet;
UINT nState = NULL; g_pLogger->Debug("<%s(%d)> SetActiveItem(): Enter",D_PC_LOG_NAME_HVRTREE, __LINE__); ////////////////////////////////////////////////////////////////////////// // 这部分主要是把原来的一些结点状态清空 SetItemState( m_hItem,0,TVIS_SELECTED );
for (int k=0;k<m_aryActiveItem.GetSize();k++) { SetItemState( m_aryActiveItem.GetAt(k),0,TVIS_SELECTED ); } m_aryActiveItem.RemoveAll(); ////////////////////////////////////////////////////////////////////////// // WM_LBUTTONDOWN消息让树控件获得焦点 m_pDeviceDlg->PostMessage(WM_LBUTTONDOWN,0,0); // 查找节点信息 bRet = m_mapHvrNode.Lookup((short)lHvrId,(void*&)hHvrItem); if ( bRet == FALSE ) { // 以下为错误处理 g_pLogger->Error("<%s(%d)> SetActiveItem(): m_mapHvrNode拞HVR僲乕僪枹敪尒丄lHvrId - %d", D_PC_LOG_NAME_HVRTREE, __LINE__ ,lHvrId ); g_pLogger->Debug("<%s(%d)> SetActiveItem(): Leave",D_PC_LOG_NAME_HVRTREE, __LINE__); return D_PC_FAILURE; }
// 便利子节点 hCamItem = GetChildItem( hHvrItem ); while ( hCamItem != NULL ) { bRet = m_mapNode.Lookup( hCamItem,(void*&)pCamNode ); if ( bRet == FALSE ) { // 错误处理 g_pLogger->Error("<%s(%d)> SetActiveItem(): 僇儊儔僲乕僪枹敪尒,hCamItem - %08x", D_PC_LOG_NAME_HVRTREE, __LINE__ ,hCamItem ); g_pLogger->Debug("<%s(%d)> SetActiveItem(): Leave",D_PC_LOG_NAME_HVRTREE, __LINE__); return D_PC_FAILURE; } // 如果找到了与入口参数相同的ID就退出。搜索结束 if ( pCamNode->Id == lCamId ) { hCam = pCamNode->hItem; break; } hCamItem = GetNextVisibleItem(hCamItem); } ////////////////////////////////////////////////////////////////////////// // 将符合条件的值粗如一个实现定义好的数组 INT i = 0; hSelectItem = hCamItem;
while ( hSelectItem != NULL ) { m_aryActiveItem.Add( hSelectItem ); // 向数组中添加值 i++;
hSelectItem = GetParentItem(hSelectItem); }
////////////////////////////////////////////////////////////////////////// // 为数组中的值设定状态 for (int j=0;j<m_aryActiveItem.GetSize();j++) { nState = GetItemState( m_aryActiveItem.GetAt(j), TVIS_EXPANDED);
if(0 != (nState & TVIS_EXPANDED)) { // 节点非展开的展开的场合 SetItemState( m_aryActiveItem.GetAt(j),0,TVIS_SELECTED); } else { SetItemState( m_aryActiveItem.GetAt(j),TVIS_SELECTED,TVIS_SELECTED); } } ////////////////////////////////////////////////////////////////////////// SetItemState( hHvrItem,TVIS_SELECTED,TVIS_SELECTED);
g_pLogger->Debug("<%s(%d)> SetActiveItem(): Leave",D_PC_LOG_NAME_HVRTREE, __LINE__);
return D_PC_SUCCESS; } 然后可在单击或双击事件中调用  
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
|