APIでSysTreeView32のカレントアイテム名を得るには?

解決


25hプログラマー  2006-10-07 07:13:57  No: 96841

VB6 で他アプリ(例えばoutlookExpress)のSysTreeView32のアイテム名(例えばExpress のフォルダ名)を得ようとしていますが、SendMessage で他アプリが異常終了してしまいます。
ちなみに同じようなプログラムでSysListView32(例えばタスクマネージャー)はアイテム名が取れていますので仮想メモリを使った値の受け渡し方法には問題無いような気がします。
そもそもSysTreeView32のアイテム名は外のアプリから得る事はできないのでしょうか?
環境はXP(SP2)+VB6(SP6)です。
以下はSysTreeView32のハンドルを直に指定してアイテム名を得ようとしているプログラムです。識者の方のご意見をお聞かせ下さい。
---------------------------------------------------------
Option Explicit

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Const PROCESS_VM_OPERATION = &H8&
Private Const PROCESS_VM_READ = &H10&
Private Const PROCESS_VM_WRITE = &H20&
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function VirtualAlloc Lib "kernel32" (lpAddress As Any, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFree Lib "kernel32" (lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32.dll" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Const MEM_RESERVE = &H2000&
Private Const MEM_COMMIT = &H1000&
Private Const PAGE_READWRITE = &H4&
Private Declare Function VirtualFreeEx Lib "kernel32.dll" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Const MEM_RELEASE = &H8000&
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (destination As Any, source As Any, ByVal length As Long)
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Private Type TVITEM
    mask As Long
    hItem As Long
    state As Long
    stateMask As Long
    Text As String
    TextMax As Long
    iImage As Long
    iSelectedImage As Long
    Children As Long
    lParam As Long
End Type
Private Const MAX_PATH = 260
Public Const TVIF_TEXT     As Long = &H1
Public Const TV_FIRST      As Long = &H1100
Public Const TVM_GETITEM   As Long = (TV_FIRST + 12)
Public Const TVM_GETNEXTITEM  As Long = (TV_FIRST + 10)

Public Function GetCurrentTreeView(hSysWnd As Long) As String
    Dim pLocalShared As Long 'ファイルがマップされた自プロセスのビューの開始アドレス
    Dim tvi As TVITEM
    Dim pSysShared As Long 'ファイルがマップされた他のプロセスのビューの開始アドレス
    Dim hProcess As Long 'プロセスハンドル
    Dim dwPID As Long 'Process ID
    Dim dwNumberOfBytes As Long '読み書きされたバイト数
    Dim dwSize As Long
    Dim sBuffer As String
    Dim lItemWnd As Long

    dwSize = Len(tvi) + MAX_PATH '// 確保するサイズ

    'カレントのハンドル
    lItemWnd = SendMessageAny(hSysWnd, TVM_GETNEXTITEM, TVGN_CARET, ByVal 0)

    '共有メモリをオープン
    pLocalShared = VirtualAlloc(ByVal 0&, dwSize, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
    Call GetWindowThreadProcessId(hSysWnd, dwPID)
    hProcess = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, dwPID)
    pSysShared = VirtualAllocEx(hProcess, ByVal 0&, dwSize, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
    
    '共有メモリの初期化 ( 構造体の必要な個所を埋める )
    tvi.mask = TVIF_TEXT
    tvi.hItem = lItemWnd
    tvi.Text = (pSysShared + Len(tvi))
    tvi.TextMax = MAX_PATH

    'テキストを取得
    Call MoveMemory(ByVal pLocalShared, tvi, Len(tvi))
    Call WriteProcessMemory(hProcess, ByVal pSysShared, ByVal pLocalShared, dwSize, dwNumberOfBytes)
    Call SendMessage(hSysWnd, TVM_GETITEM, 0, ByVal pSysShared)
    Call ReadProcessMemory(hProcess, ByVal pSysShared, ByVal pLocalShared, dwSize, dwNumberOfBytes)
    
    '共有メモリから戻りを得る
    sBuffer = String$(MAX_PATH, 0)
    Call MoveMemory(ByVal sBuffer, ByVal (pLocalShared + Len(tvi)), MAX_PATH)
    
    MsgBox Left$(sBuffer, InStr(sBuffer, vbNullChar) - 1)

    '共有メモリをクローズ
    Call VirtualFree(ByVal pLocalShared, 0, MEM_RELEASE)
    Call VirtualFreeEx(hProcess, ByVal pSysShared, 0, MEM_RELEASE)
    Call CloseHandle(hProcess)
End Function

Sub test()
    'hWnd は、SysTreeView32 をspy++で探して直指定
    GetCurrentTreeView (&H30AB0)
End Sub


25hプログラマー  2006-10-10 20:26:53  No: 96842

Text As String  ではなく、Text As Long でした^^;
切羽詰ってると普段気が付くような所も気が付かないものですね。
お騒がせしました。

Private Type TVITEM
    mask As Long
    hItem As Long
    state As Long
    stateMask As Long
    Text As String      ←  ここ
    TextMax As Long
    iImage As Long
    iSelectedImage As Long
    Children As Long
    lParam As Long
End Type


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加