程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程綜合問答 >> systreeview32-跨進程控制SysTreeView32樹狀圖控件的難題

systreeview32-跨進程控制SysTreeView32樹狀圖控件的難題

編輯:編程綜合問答
跨進程控制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坐標總會變成負數。
被這個問題困擾了很久,嘗試過各種辦法均告失敗,請各位老師幫忙看看,還有沒有成功的可能性。

最佳回答:


打開進程
申請內存
填充結構
發送消息 sendmessage TVM_HITTEST,0,內存地址
讀取內存
這樣就可以跨進程操作了 ,我目前只做到遍歷節點信息和坐標,獲取節點狀態還不會,如果你研究出來了告訴我下

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved