void CreateTreeViewControl(HWND hMainWnd) { g_hTreeView = CreateWindow(WC_TREEVIEW, _T("Tree View"), WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_LINESATROOT, 5, 5, 320, 480, hMainWnd, NULL, hInst, NULL); TVINSERTSTRUCT tvInsertStruct = {0}; tvInsertStruct.hParent = NULL; tvInsertStruct.hInsertAfter = TVI_ROOT; tvInsertStruct.itemex.mask = TVIF_TEXT/* | TVIF_STATE */; tvInsertStruct.itemex.pszText = _T("根节点"); tvInsertStruct.itemex.state = TVIS_EXPANDED; //插入根节点 HTREEITEM hRoot = (HTREEITEM)SendMessage(g_hTreeView, TVM_INSERTITEM, 0, (LPARAM)(&tvInsertStruct)); DWORD dwErrorID = 0; if(hRoot == NULL) dwErrorID = GetLastError(); //不能在这里展开根节点,因为此时根节点还没有任何子项,这样SendMessage函数会调用失败,返回0! //msdn says: Attempting to expand or collapse a node that has no children is considered a failure and SendMessage returns zero. DWORD dwRet = SendMessage(g_hTreeView, TVM_EXPAND, TVE_EXPAND, (LPARAM)(hRoot)); //插入子节点 tvInsertStruct.hParent = hRoot; tvInsertStruct.hInsertAfter = TVI_LAST; tvInsertStruct.itemex.mask = TVIF_TEXT; tvInsertStruct.itemex.pszText = _T("子节点1"); HTREEITEM hSubitem1 = (HTREEITEM)SendMessage(g_hTreeView, TVM_INSERTITEM, 0, (LPARAM)(&tvInsertStruct)); tvInsertStruct.itemex.pszText = _T("子节点2"); HTREEITEM hSubitem2 = (HTREEITEM)SendMessage(g_hTreeView, TVM_INSERTITEM, 0, (LPARAM)(&tvInsertStruct)); tvInsertStruct.itemex.pszText = _T("子节点3"); HTREEITEM hSubitem3 = (HTREEITEM)SendMessage(g_hTreeView, TVM_INSERTITEM, 0, (LPARAM)(&tvInsertStruct)); tvInsertStruct.itemex.pszText = _T("子节点4"); HTREEITEM hSubitem4 = (HTREEITEM)SendMessage(g_hTreeView, TVM_INSERTITEM, 0, (LPARAM)(&tvInsertStruct)); tvInsertStruct.itemex.pszText = _T("子节点5"); HTREEITEM hSubitem5 = (HTREEITEM)SendMessage(g_hTreeView, TVM_INSERTITEM, 0, (LPARAM)(&tvInsertStruct)); tvInsertStruct.itemex.pszText = _T("子节点6"); HTREEITEM hSubitem6 = (HTREEITEM)SendMessage(g_hTreeView, TVM_INSERTITEM, 0, (LPARAM)(&tvInsertStruct)); //展开根节点 dwRet = SendMessage(g_hTreeView, TVM_EXPAND, TVE_EXPAND, (LPARAM)(hRoot)); //SetFocus(g_hTreeView); //选中某个节点 TVITEM tvItem = {0}; tvItem.mask = TVIF_STATE | TVIF_HANDLE; tvItem.hItem = hSubitem1; tvItem.stateMask |= TVIS_SELECTED; tvItem.state = TVIS_SELECTED; BOOL bRet = FALSE; //TODO: 这里为什么不成功? //bRet = SendMessage(g_hTreeView, TVM_SETITEM, 0, (LPARAM)(&tvItem)); //bRet = 0; //bRet = SendMessage(g_hTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM)(hSubitem4)); <span style="color:#ff0000;">bRet = SendMessage(g_hTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM)(hSubitem4));</span> //HTREEITEM hSelItem = NULL; //hSelItem = (HTREEITEM)SendMessage(g_hTreeView, TVM_GETNEXTITEM, TVGN_CARET, 0); //模拟鼠标点击 <span style="color:#3366ff;">RECT rc = {0}; *(HTREEITEM*)&rc = hSubitem6; SendMessage(g_hTreeView, TVM_GETITEMRECT, FALSE, (LPARAM)&rc); POINT pt = {(rc.right-rc.left)/2+rc.left, (rc.bottom-rc.top)/2+rc.top}; //ClientToScreen(g_hTreeView, &pt); //SetCursorPos(pt.x, pt.y); SendMessage(g_hTreeView, WM_LBUTTONDOWN, 0, MAKELONG(pt.x, pt.y));</span> g_OldTreeViewWndProc = (WNDPROC)GetWindowLong(g_hTreeView, GWL_WNDPROC); //if(SetWindowLong(g_hTreeView, GWL_WNDPROC, (long)newTreeViewWndProc) == 0) //MessageBox(hMainWnd, _T("子类化TreeView窗口失败!"), _T(""), MB_OK | MB_ICONERROR); } LRESULT CALLBACK newTreeViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { if(message == WM_LBUTTONDOWN) { //MessageBox(NULL, _T("鼠标按下消息!"), _T(""), MB_OK); return TRUE; } else return CallWindowProc(g_OldTreeViewWndProc, hWnd, message, wParam, lParam); }
我的意图是想【实现TreeView某个节点被点击选中的效果】,使用了两种方法来实现,都未成功:
方法一:给TreeView控件发送TVM_SELECTITEM,虽然能选中指定节点,但是该节点不会高亮显示。
方法二:给指定节点发送鼠标单击事件,但是显示效果位置总是不对,如上面代码中所示,我打算选中节点6,为何程序运行出来的效果是选中了节点4?(我也考虑了窗口坐标和全局桌面坐标的关系)如下图:
希望哪位大神路过看到此文,不吝赐教。特此感谢!!