为轮子而生 2014-12-08 14:21 采纳率: 33.3%
浏览 4120
已采纳

跨进程控制SysTreeView32树状图控件的难题

最近公司在做一个智能化股票交易的项目,需要控制股票交易软件树状图进行翻页,刚开始我使用普通的WM_LBUTTONDOWN和WM_LBUTTONUP消息进行发送,发现只是实现了选择树状图节点,而没有达到实际效果,也就是控制页面跳转,遂怀疑是WM_NCHITTEST的问题,可是加入了WM_NCHITTEST消息,并把截获的消息全部依次发送后,仍无法成功。
后来发现在WM_LBUTTONUP消息后,有一个关键的TVM_HITTEST我没有进行处理,此时得知这个SysTreeView32的触发事件并不是ItemSelected,而是在鼠标点击时通过HitTest获取点击的节点,再触发下一步动作。
TVM_HITTEST消息向树状图发送了一个地址,这个地址指向一个TV_HITTESTINFO结构数据:
public struct TV_HITTESTINFO
{
    public POINTAPI pt;
    public int flags;
    public UInt32 hItem;
}
实际情况下发送的数据是这样的:
![](http://113.11.198.136:82/FileStore/1.jpg)
如果仅仅使用普通的鼠标模拟消息发送过去,pt的坐标值均为负数,显然达不到效果。可是我用WriteProcessMemory将有效的坐标值和节点句柄写入这个地址再发送过去发现,TVM_HITTEST消息中的pt坐标值会瞬间变为负值,仍然失败。如果新申请一个内存进行写入,结果相同。
![](http://113.11.198.136:82/FileStore/2.jpg)

以下是用spy++截获的关键消息:
![](http://113.11.198.136:82/FileStore/3.jpg)

以下是模拟点击的代码,其中一些十六进制数值已根据实际数值进行替换
class Test
{

    private int Handle, MainHandle, PID;

    public Test(int handle, int mainHandle, int pid)
    {
        this.Handle = handle; this.MainHandle = mainHandle; this.PID = pid;
        pHandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, PID);
    }

    public void SelectTreeItem()
    {
        int rtn;
        //windows鼠标消息
        rtn = SendMessage(Handle, WM_NCHITTEST, 0x0, 0xAB0068);  //0xAB0068是屏幕鼠标的坐标
        rtn = SendMessage(Handle, WM_MOUSEACTIVATE, MainHandle, 0x2010001);
        rtn = SendMessage(Handle, WM_SETCURSOR, Handle, 0x2010001);
        //左键按下
        rtn = PostMessage(Handle, WM_LBUTTONDOWN, 0x1, 0x9001D);  //0x9001D是树状图内鼠标点击的相对坐标
        //刷新树状图
        rtn = SendMessage(Handle, WM_GETDLGCODE, 0x0, 0x0);
        rtn = PostMessage(Handle, WM_PAINT, 0x0, 0x0);
        //左键弹起
        rtn = PostMessage(Handle, WM_LBUTTONUP, 0x0, 0x9001D);  //0x9001D是树状图内鼠标点击的相对坐标
        //改变节点
        rtn = SendMessage(Handle, WM_CAPTURECHANGED, 0x0, 0x0);
        //HitTest欺骗
        Hittest();
        rtn = SendMessage(Handle, TVM_HITTEST, 0x0, 0x18F2AC);  //0x18F2AC储存TV_HITTESTINFO结构数据
        //选择节点
        rtn = SendMessage(Handle, TVM_SELECTITEM, 0x9, 0x661770); //0x661770是目标节点的句柄(根据实际情况更改)
        rtn = SendMessage(Handle, WM_NCHITTEST, 0x0, 0xAB0068);
    }

    private void Hittest()
    {
        TV_HITTESTINFO NewItem = default(TV_HITTESTINFO);
        NewItem.pt = new POINTAPI(29, 9);
        NewItem.flags = TVHT_ONITEM | TVHT_ONITEMRIGHT | TVHT_BELOW | TVHT_TORIGHT | TVHT_TOLEFT | 0x77615080;
        NewItem.hItem = 0xF4F25FD0;
        WriteProcessMemory(pHandle, 0x18F2AC, NewItem, Marshal.SizeOf(typeof(TV_HITTESTINFO)), 0);
    }

}

地址0x18F2AC也尝试过自行申请内存,结果同样。 无论怎么控制TV_HITTESTINFO数据,它的pt坐标总会变成负数。
被这个问题困扰了很久,尝试过各种办法均告失败,请各位老师帮忙看看,还有没有成功的可能性。
  • 写回答

1条回答 默认 最新

  • 红牛工作室 2015-10-01 02:02
    关注

    打开进程
    申请内存
    填充结构
    发送消息 sendmessage TVM_HITTEST,0,内存地址
    读取内存
    这样就可以跨进程操作了 ,我目前只做到遍历节点信息和坐标,获取节点状态还不会,如果你研究出来了告诉我下

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条