Win32 API向外部程序TreeView选中项发双击消息及获取其句柄
如何获取TreeView选中项并发送双击消息
嘿,这个场景我熟!既然你已经拿到了TreeView的窗口句柄,接下来分两步走就能搞定:
第一步:获取选中项的HTREEITEM
TreeView的选中项并不是一个窗口句柄(HWND),而是它内部维护的一个HTREEITEM标识——可以理解为TreeView给每个节点分配的“身份证号”。要拿到它,只需要给TreeView发送TVM_GETNEXTITEM消息,指定TVGN_CARET作为wParam(这个参数专门用来获取当前选中的项):
// hTreeView是你通过Spy++拿到的TreeView窗口句柄 HTREEITEM hSelectedItem = (HTREEITEM)SendMessage(hTreeView, TVM_GETNEXTITEM, TVGN_CARET, NULL);
注意先判断hSelectedItem是否为NULL,如果是,说明当前TreeView没有选中任何项,后续操作就没必要做了。
第二步:发送双击消息到选中项
模拟双击有两种常见方式,选哪种取决于目标程序的处理逻辑:
方式1:发送鼠标双击消息(WM_LBUTTONDBLCLK)
这种方式更贴近真实用户操作,但需要先拿到选中项在TreeView客户区的坐标:
- 用
TVM_GETITEMRECT获取项的矩形区域:
RECT itemRect; // 最后一个参数传TRUE表示获取整个节点的点击区域,传FALSE只获取文本部分 BOOL gotRect = SendMessage(hTreeView, TVM_GETITEMRECT, TRUE, (LPARAM)&itemRect);
- 计算矩形中心作为双击位置,然后构造消息发送:
if (gotRect && hSelectedItem != NULL) { POINT ptClick = { itemRect.left + (itemRect.right - itemRect.left) / 2, itemRect.top + (itemRect.bottom - itemRect.top) / 2 }; // 构造鼠标消息的参数:wParam是左键按下标记,lParam是坐标(低16位x,高16位y) LPARAM lParam = MAKELPARAM(ptClick.x, ptClick.y); SendMessage(hTreeView, WM_LBUTTONDBLCLK, MK_LBUTTON, lParam); }
方式2:发送NM_DBLCLK通知给父窗口
很多程序是通过TreeView发送给父窗口的NM_DBLCLK通知来处理双击逻辑的,这时候需要构造完整的NMTREEVIEW结构体发送:
if (hSelectedItem != NULL) { NMTREEVIEW nmTreeMsg = {0}; nmTreeMsg.hdr.hwndFrom = hTreeView; nmTreeMsg.hdr.idFrom = GetDlgCtrlID(hTreeView); nmTreeMsg.hdr.code = NM_DBLCLK; nmTreeMsg.item.hItem = hSelectedItem; // 把刚才计算的点击位置也填上,更贴近真实场景 nmTreeMsg.ptAction = ptClick; // 发送给TreeView的父窗口 SendMessage(GetParent(hTreeView), WM_NOTIFY, nmTreeMsg.hdr.idFrom, (LPARAM)&nmTreeMsg); }
注意事项
- 如果你不确定目标程序用哪种方式处理双击,可以两种都试试,一般总有一种能生效。
- 确保你的程序有足够的权限发送消息给目标窗口(比如目标程序是管理员权限运行的,你的程序也需要管理员权限)。
内容的提问来源于stack exchange,提问作者Iichi Kohuro
相关产品推荐
相关产品推荐

