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));
bRet = SendMessage(g_hTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM)(hSubitem4));
//HTREEITEM hSelItem = NULL;
//hSelItem = (HTREEITEM)SendMessage(g_hTreeView, TVM_GETNEXTITEM, TVGN_CARET, 0);
//模拟鼠标点击
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));
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?(我也考虑了窗口坐标和全局桌面坐标的关系)如下图:
希望哪位大神路过看到此文,不吝赐教。特此感谢!!