求助:程序如何模拟鼠标点击一个TreeView节点?

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?(我也考虑了窗口坐标和全局桌面坐标的关系)如下图:

求助:程序如何模拟鼠标点击一个TreeView节点?_第1张图片


希望哪位大神路过看到此文,不吝赐教。特此感谢!!

你可能感兴趣的:(Windows应用层编程)