by THEREMIN » 2007年2月22日(木) 21:34
ここのアドバイスや他の掲示版での情報も参考にして、なんとか
フォルダウィンドウのハンドルと ウィンドウの並んでいる順は取得することができました。
結構前に取得自体はできていたのですが、Unicodeテキストファイルの扱いで悪戦苦闘していて返事が遅れてしまいました。
イグトランス様のアドバイスを参考に、ToolbarWindow32クラスのウィンドウハンドルを取得して
そこからタブボタンの情報をSendMessage()で取得していったところ、
うまくフォルダウィンドウのハンドルを取得することができました。一応ソースを示しておきます。
[ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]コード: 全て選択
Type WindowInfo ' 取得したウィンドウ情報
Handle As HWND ' ウィンドウハンドル
ID As DWord ' ウィンドウID
Index As DWord ' ウィンドウが左から何番目にあるか
End Type
Sub GetWindowInfo()
' hTaskBarにToolbarWindow32クラスのウィンドウハンドルを取得
Dim hTaskBar As HWND
hTaskBar = FindWindow("Shell_TrayWnd",NULL)
hTaskBar = FindWindowExA(hTaskBar, NULL,"ReBarWindow32", NULL)
hTaskBar = FindWindowExA(hTaskBar, NULL,"MSTaskSwWClass", NULL)
hTaskBar = FindWindowExA(hTaskBar, NULL,"ToolbarWindow32",NULL)
' 共有メモリをオープン
Dim pSysShared As BytePtr ' ファイルがマップされた他のプロセスのビューの開始アドレス
Dim hProcess As HWND ' プロセスハンドル
Dim dw As DWord
Dim dwPID As DWord ' Process ID
Dim dwSize As DWord
dwSize = sizeof(TBBUTTON) + sizeof(TCHAR) * MAX_PATH '確保するサイズ
GetWindowThreadProcessId(hTaskBar, VarPtr(dwPID))
hProcess = OpenProcess(PROCESS_VM_OPERATION + PROCESS_VM_READ + PROCESS_VM_WRITE,FALSE, dwPID)
pSysShared = VirtualAllocEx(hProcess, NULL, dwSize, MEM_RESERVE + MEM_COMMIT, PAGE_READWRITE)
Dim tb As TBBUTTON
Dim hTaskBtn As HWND
Dim WinText[MAX_PATH] As Byte
Dim winID As DWord
Dim BtnNo As DWord
Dim nBtnIndex As DWord
Dim nBtnCount As DWord
' タブボタン(開いているフォルダウィンドウ)の数を取得
nBtnCount = SendMessage(hTaskBar,TB_BUTTONCOUNT,0,0)
Dim t_info As *WindowInfo ' タブボタンの情報
t_info = calloc(nBtnCount*SizeOf(WindowInfo))
/* TB_BUTTONCOUNT で得られる値は実際に表示されているボタンの数の2倍になっている
つまり、ウィンドウごとに2つのボタンが割り当てられている。その内奇数番号が有効なハンドル */
For nBtnIndex=1 To nBtnCount-1 Step 2
/* nBtnIndex 番目のボタンの情報を取得 */
SendMessage(hTaskBar, TB_GETBUTTON, nBtnIndex, pSysShared As LPARAM)
/* 取得した情報を自分のプロセス領域へコピー */
ReadProcessMemory(hProcess, pSysShared, VarPtr(tb), Len(tb), VarPtr(dw))
/* nBtnIndex 番目のボタンのIndexを取得 */
/* 指定するのはボタンの番号ではなくてコマンドID */
BtnNo = SendMessage(hTaskBar, TB_COMMANDTOINDEX, tb.idCommand, 0)
/* tb.dwDataの先頭メンバがウィンドウのハンドルになっているので、取得する */
ReadProcessMemory(hProcess,tb.dwData As VoidPtr,VarPtr(hTaskBtn),Len(hTaskBtn),VarPtr(dw))
/* そのウィンドウのテキストを普通に拾う */
GetWindowText(hTaskBtn,WinText,Len(WinText))
/* ウィンドウIDを取得することにより、一意のウィンドウを指定できる */
winID = GetWindowLong(hTaskBtn,GWL_ID)
/* ClassNameはちゃんと"CabinetWClass"になっている */
GetClassName(hTaskBtn, WINDOW_INFO, MAX_PATH)
/* 自作のWindowInfo構造体にタブボタンの情報を設定 */
t_info[nBtnIndex].Handle = hTaskBtn ' ウィンドウのハンドル
t_info[nBtnIndex].ID = winID ' ウィンドウのID(不要)
t_info[nBtnIndex].Index = BtnNo ' ボタン番号
End If
Next nBtnIndex
' 共有メモリをクローズ
VirtualFreeEx(hProcess, pSysShared, 0, MEM_RELEASE)
CloseHandle(hProcess)
End Sub
見にくくてすみません。
SendMessage()の他にも色々処理がいるようで、あんまり理解してはいないのですが、要するに
ToolBarコントロールは別プロセスなので、共有メモリをオープンし、
それを利用してメッセージの受け渡しをしなければならないようです。
http://techtips.belution.com/ja/vc/0001/
http://forums.belution.com/ja/vc/000/271/11s.shtml
http://hongliang.seesaa.net/article/7851680.html
http://www.atmarkit.co.jp/bbs/phpBB/vie ... forum=7&11
ここのアドバイスや他の掲示版での情報も参考にして、なんとか
フォルダウィンドウのハンドルと ウィンドウの並んでいる順は取得することができました。
結構前に取得自体はできていたのですが、Unicodeテキストファイルの扱いで悪戦苦闘していて返事が遅れてしまいました。
イグトランス様のアドバイスを参考に、ToolbarWindow32クラスのウィンドウハンドルを取得して
そこからタブボタンの情報をSendMessage()で取得していったところ、
うまくフォルダウィンドウのハンドルを取得することができました。一応ソースを示しておきます。
[hide][code]Type WindowInfo ' 取得したウィンドウ情報
Handle As HWND ' ウィンドウハンドル
ID As DWord ' ウィンドウID
Index As DWord ' ウィンドウが左から何番目にあるか
End Type
Sub GetWindowInfo()
' hTaskBarにToolbarWindow32クラスのウィンドウハンドルを取得
Dim hTaskBar As HWND
hTaskBar = FindWindow("Shell_TrayWnd",NULL)
hTaskBar = FindWindowExA(hTaskBar, NULL,"ReBarWindow32", NULL)
hTaskBar = FindWindowExA(hTaskBar, NULL,"MSTaskSwWClass", NULL)
hTaskBar = FindWindowExA(hTaskBar, NULL,"ToolbarWindow32",NULL)
' 共有メモリをオープン
Dim pSysShared As BytePtr ' ファイルがマップされた他のプロセスのビューの開始アドレス
Dim hProcess As HWND ' プロセスハンドル
Dim dw As DWord
Dim dwPID As DWord ' Process ID
Dim dwSize As DWord
dwSize = sizeof(TBBUTTON) + sizeof(TCHAR) * MAX_PATH '確保するサイズ
GetWindowThreadProcessId(hTaskBar, VarPtr(dwPID))
hProcess = OpenProcess(PROCESS_VM_OPERATION + PROCESS_VM_READ + PROCESS_VM_WRITE,FALSE, dwPID)
pSysShared = VirtualAllocEx(hProcess, NULL, dwSize, MEM_RESERVE + MEM_COMMIT, PAGE_READWRITE)
Dim tb As TBBUTTON
Dim hTaskBtn As HWND
Dim WinText[MAX_PATH] As Byte
Dim winID As DWord
Dim BtnNo As DWord
Dim nBtnIndex As DWord
Dim nBtnCount As DWord
' タブボタン(開いているフォルダウィンドウ)の数を取得
nBtnCount = SendMessage(hTaskBar,TB_BUTTONCOUNT,0,0)
Dim t_info As *WindowInfo ' タブボタンの情報
t_info = calloc(nBtnCount*SizeOf(WindowInfo))
/* TB_BUTTONCOUNT で得られる値は実際に表示されているボタンの数の2倍になっている
つまり、ウィンドウごとに2つのボタンが割り当てられている。その内奇数番号が有効なハンドル */
For nBtnIndex=1 To nBtnCount-1 Step 2
/* nBtnIndex 番目のボタンの情報を取得 */
SendMessage(hTaskBar, TB_GETBUTTON, nBtnIndex, pSysShared As LPARAM)
/* 取得した情報を自分のプロセス領域へコピー */
ReadProcessMemory(hProcess, pSysShared, VarPtr(tb), Len(tb), VarPtr(dw))
/* nBtnIndex 番目のボタンのIndexを取得 */
/* 指定するのはボタンの番号ではなくてコマンドID */
BtnNo = SendMessage(hTaskBar, TB_COMMANDTOINDEX, tb.idCommand, 0)
/* tb.dwDataの先頭メンバがウィンドウのハンドルになっているので、取得する */
ReadProcessMemory(hProcess,tb.dwData As VoidPtr,VarPtr(hTaskBtn),Len(hTaskBtn),VarPtr(dw))
/* そのウィンドウのテキストを普通に拾う */
GetWindowText(hTaskBtn,WinText,Len(WinText))
/* ウィンドウIDを取得することにより、一意のウィンドウを指定できる */
winID = GetWindowLong(hTaskBtn,GWL_ID)
/* ClassNameはちゃんと"CabinetWClass"になっている */
GetClassName(hTaskBtn, WINDOW_INFO, MAX_PATH)
/* 自作のWindowInfo構造体にタブボタンの情報を設定 */
t_info[nBtnIndex].Handle = hTaskBtn ' ウィンドウのハンドル
t_info[nBtnIndex].ID = winID ' ウィンドウのID(不要)
t_info[nBtnIndex].Index = BtnNo ' ボタン番号
End If
Next nBtnIndex
' 共有メモリをクローズ
VirtualFreeEx(hProcess, pSysShared, 0, MEM_RELEASE)
CloseHandle(hProcess)
End Sub[/code]
見にくくてすみません。[/hide]
SendMessage()の他にも色々処理がいるようで、あんまり理解してはいないのですが、要するに
ToolBarコントロールは別プロセスなので、共有メモリをオープンし、
それを利用してメッセージの受け渡しをしなければならないようです。
http://techtips.belution.com/ja/vc/0001/
http://forums.belution.com/ja/vc/000/271/11s.shtml
http://hongliang.seesaa.net/article/7851680.html
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=24958&forum=7&11