Страница: 1 |
|
Вопрос: Работать с окнами класса ToolBarWindow32
|
Добавлено: 11.12.08 13:20
|
|
Автор вопроса: GDK
|
Есть "чужое" приложение. В нём есть окно, класс которого ToolBarWindow32. Это панель инструментов. Нужно узнавать состояние её кнопочек (нажата или отпущена), нажимать и отпускать их, узнавать состояние всего окошка панели (отображается или нет на экране). Ну и неплохо было бы узнавать её место расположения на экране относительно гланого окна "чужой" программы и относительно экрана.
HWnd панели получить могу. Может быть кто-нибудь делал подобное? Если не трудно покажите примеры. Ну хотя бы объясните как/где искать инф. по этому поводу.
Ответить
|
Номер ответа: 2 Автор ответа: GDK
Вопросов: 13 Ответов: 348
|
Профиль | | #2
|
Добавлено: 15.12.08 12:42
|
TB_PRESSBUTTON как раз и хотел заслать чтобы нажать кнопку.
Не вышло. Почему - не понятно. Пробовал посылать и через SendMessage и через PostMessage. Другие сообщения тоже посылал, Например, получилось удалять кнопки. Но это мне не надо. Вот что нарыл по TB_PRESSBUTTON:
TB_PRESSBUTTON
The TB_PRESSBUTTON message presses or releases the specified button in a toolbar.
TB_PRESSBUTTON
wParam = (WPARAM) idButton;
lParam = (LPARAM) MAKELONG(fPress, 0);
Parameters
idButton
Command identifier of the button to press or release.
fPress
Press flag. If this parameter is TRUE, the button is pressed. If it is FALSE, the button is released.
Return Values
Returns TRUE if successful or FALSE otherwise.
TB_PRESSBUTTON
Сообщение TB_PRESSBUTTON нажимает или выпускает определенную кнопку в toolbar.
TB_PRESSBUTTON wParam = (WPARAM) idButton;
lParam = (LPARAM) MAKELONG(fPress, 0);
Параметры
idButton
Командный идентификатор кнопки, чтобы нажимать или выпускаться.
fPress
Корреспондентский флаг. Если этот параметр является ИСТИНОЙ, кнопка нажата. Если это - ЛОЖЬ, кнопка выпущена.
Обратные Величины
Возвращается ВЕРНО если успешный или ЛОЖНЫЙ в противном случае.
Думал, что дело в MAKELONG(fPress, 0). Пробовал вместо этого выражения просто писать 0. Кнопка при этом всё равно не становится отжатой(не реагирует).
Да, кстати в данном ToolBare есть несколько кнопочек, причём нажатой может быть только одна или ни одной. Может дело в этом(не то сообщение посылаю)?
Ответить
|
Номер ответа: 3 Автор ответа: Father
Вопросов: 0 Ответов: 159
|
Профиль | | #3
|
Добавлено: 15.12.08 22:47
|
Во-первых не забывай, что idButton - командный идентификатор кнопки, а не порядковый индекс.
Чтобы найти его по индексу пошли TB_GETBUTTON.
Во-вторых, ты имеешь дело с чужим процессом, поэтому пример c проводником:
-
- Option Explicit
- Private hwntbr As Long
-
- Private Sub Command1_Click()
- Dim Tbn As TBBUTTON
- Dim procid As Long
- Dim hProcess As Long
- Dim vptrTbn As Long
- Dim vptrStr As Long
- Dim rwbytes As Long
-
-
- Call GetWindowThreadProcessId(hwntbr, procid)
- hProcess = OpenProcess(PROCESS_ALL_ACCESS Or PROCESS_DUP_HANDLE, True, procid)
- vptrTbn = VirtualAllocEx(hProcess, 0, LenB(Tbn), MEM_COMMIT Or MEM_TOP_DOWN, PAGE_READWRITE)
- Call SendMessage(hwntbr, TB_GETBUTTON, 4, vptrTbn)
- Call ReadProcessMemory(hProcess, vptrTbn, Tbn, LenB(Tbn), rwbytes)
- Call SendMessage(hwntbr, WM_COMMAND, Tbn.idCommand, hwntbr)
- Call VirtualFreeEx(hProcess, vptrTbn, LenB(Tbn), MEM_RELEASE)
- Call CloseHandle(hProcess)
-
- End Sub
-
- Private Sub Form_Load()
-
-
- Dim hwmain As Long
-
- Call EnumChildWindows(FindWindow("ExploreWClass", vbNullString), AddressOf EnumChildProc, VarPtr(hwntbr))
- If Not CBool(hwntbr) Then Debug.Print "ToolbarWindow32 не найден"
- End Sub
-
- Option Explicit
-
- Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
- Public Declare Sub PutMem4 Lib "msvbvm60" (ByVal dest As Long, ByVal Value As Long)
- Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
- Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
- Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
- Public Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
- Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
- Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
- Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
- Public Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
- Public Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
- Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
-
- Public Const MEM_RELEASE = &H8000
- Public Const MEM_COMMIT = &H1000
- Public Const MEM_TOP_DOWN = &H100000
- Public Const PAGE_READWRITE = &H4
-
- Public Const PROCESS_ALL_ACCESS = &H1F0FFF
- Public Const PROCESS_DUP_HANDLE = &H40
-
- Public Const WM_COMMAND = &H111
- Public Const WM_USER = &H400
-
- Public Const TB_GETBUTTON = (WM_USER + 23)
- Public Const TB_BUTTONCOUNT = (WM_USER + 24)
-
- Public Type TBBUTTON
- iBitmap As Long
- idCommand As Long
- fsState As Byte
- fsStyle As Byte
- dwData As Long
- iString As Long
- End Type
-
- Public Function EnumChildProc(ByVal hwnd As Long, ByVal lParam As Long) As Long
- Dim st As String * 512
- Dim ls As Long
- ls = GetClassName(hwnd, st, 512)
- If Left(st, ls) = "ToolbarWindow32" Then
- If SendMessage(hwnd, TB_BUTTONCOUNT, 0, 0) > 6 Then
- Call PutMem4(ByVal lParam, ByVal hwnd)
- EnumChildProc = 0
- Exit Function
- End If
- End If
- EnumChildProc = 1
- End Function
-
- Public Function MAKELONG(ByVal hiword As Integer, ByVal loword As Integer) As Long
- MAKELONG = (hiword * &H10000) Or (loword And &HFFFF&)
- End Function
Ответить
|
Номер ответа: 4 Автор ответа: Father
Вопросов: 0 Ответов: 159
|
Профиль | | #4
|
Добавлено: 16.12.08 00:50
|
P/S/
Не факт, что TB_PRESSBUTTON будет вызывать обработку нажатия, поэтому можно послать мышиные сообщения:
-
- Private Sub Command1_Click()
- Dim rwb As Long
- Dim procid As Long
- Dim rc As RECT
- Dim prc As Long
-
- Call GetWindowThreadProcessId(hwntbr, procid)
- hProcess = OpenProcess(PROCESS_ALL_ACCESS Or PROCESS_DUP_HANDLE, True, procid)
- prc = VirtualAllocEx(hProcess, 0, LenB(rc), MEM_COMMIT Or MEM_TOP_DOWN, PAGE_READWRITE)
- Call SendMessage(hwntbr, TB_GETITEMRECT, 4, prc)
- Call ReadProcessMemory(hProcess, prc, rc, LenB(rc), rwb)
- Call VirtualFreeEx(hProcess, prc, LenB(rc), MEM_RELEASE)
- Call SendMessage(hwntbr, WM_LBUTTONDOWN, 0, MAKELONG(rc.Top, rc.Left))
- Call SendMessage(hwntbr, WM_LBUTTONUP, 0, MAKELONG(rc.Top, rc.Left))
- CloseHandle (hProcess)
- End Sub
-
Ответить
|
Номер ответа: 6 Автор ответа: GDK
Вопросов: 13 Ответов: 348
|
Профиль | | #6
|
Добавлено: 16.12.08 17:45
|
И ещё. В том варианте кроме класса должен был обязательно присутствовать дополнительный модуль, в котором была фукция, создающая объект этого класса. Причём получалось доставать координаты кнопок только если код находился в форме. Пробовал скопировать его в стандартный модуль и получить координаты - возвращается 0 во всех членах переменной типа RECT. Пробовал в модуле писать Option Explicit, процедуру делать типа Private - результат отрицательный. Короче, полный писец. А я то хотел всю работу с ToolBar-ом чужого приложения оформить в виде класса. Получалось бы для работы этого класса необходимы: дополнительный класс для работы с памятью чужого процесса, модуль для создания объекта этого класса, дополнительная форма для корректной работы. Теперь же благодаря вам попробую разобраться как работать с памятью чужого процесса и организовать всё же работу с ToolBar-ом чужого приложения в виде ОДНОГО класса. Хотя работаю в VBA Word, думаю получится разобраться.
И ещё, к сведению. При поисках по интернету с целью решения этой задачи, наткнулся на следующее: в каком то форуме было выяснено, что поле dwData структуры TBBUTTON содержит в первых четырёх байтах HWnd кнопки, хотя в MSDN об этом ничего не сказано. А выяснилось это при экспериментировании. Да, кстати, EnumChildWindows при поисках дочерних окон чужой проги вызывает ошибку, от которой VBA закрывается вместе с Word-ом. Причём функция обратного вызова (в вашем первом варианте это EnumChildProc), может вызваться один или два или три раза, а потом бац-ошибка. Может быть это особенность VBA, но в любом случае уважение ко всем API типа Enum... после этого поубавилось. Короче пользуюсь GetNextWindow и GetChildWindow.
Ответить
|
Номер ответа: 8 Автор ответа: Father
Вопросов: 0 Ответов: 159
|
Профиль | | #8
|
Добавлено: 19.12.08 22:47
|
поле dwData структуры TBBUTTON содержит в первых четырёх байтах HWnd кнопки,
Поле dwData имеет тип DWORD и состоит всего из 4-х байт и если вдруг и содержит hwnd самого окна (для чего бы?), то не сильно ориентируйся на это, т.к. разработчик имет право засунуть туда хоть телефон своей бабушки.
На EnumChildWindows плюнь, делай как удобно.
Ответить
|
Номер ответа: 9 Автор ответа: GDK
Вопросов: 13 Ответов: 348
|
Профиль | | #9
|
Добавлено: 26.12.08 17:15
|
Да я и не ориентируюсь. Так, к сведению написал. Теперь ещё вопросик: Можно ли использовать как шаблон следующий код -
- Dim rwb As Long
-
- Dim procid As Long
-
- Dim rc As RECT
-
- Dim prc As Long
-
-
-
- Call GetWindowThreadProcessId(hwntbr, procid)
-
- hProcess = OpenProcess(PROCESS_ALL_ACCESS Or PROCESS_DUP_HANDLE, True, procid)
-
- prc = VirtualAllocEx(hProcess, 0, LenB(rc), MEM_COMMIT Or MEM_TOP_DOWN, PAGE_READWRITE)
-
- Call SendMessage(hwntbr, TB_GETITEMRECT, 4, prc)
-
- Call ReadProcessMemory(hProcess, prc, rc, LenB(rc), rwb)
-
- Call VirtualFreeEx(hProcess, prc, LenB(rc), MEM_RELEASE)
-
для извлечения информации других типов (не RECT).
В качестве примера - попытался получить текст из любой строки панели состояния чужой проги(класс окна msctls_statusbar32)
вот как изменил код:
-
- Dim BufStr As String
- Dim i As Long
-
- Dim rwb As Long
- Dim procid As Long
- Dim rc As String
- Dim prc As Long
- Dim hwntbr As Long
- Dim hProcess As Long
-
-
- hwntbr = HWndObjm
-
- rc = Space(10)
- Call GetWindowThreadProcessId(hwntbr, procid)
-
- hProcess = OpenProcess(PROCESS_ALL_ACCESS Or PROCESS_DUP_HANDLE, True, procid)
-
- prc = VirtualAllocEx(hProcess, 0, LenB(rc), MEM_COMMIT Or MEM_TOP_DOWN, PAGE_READWRITE)
-
- Call SendMessage(hwntbr, WM_GETTEXT, 1, prc)
-
- Call ReadProcessMemory(hProcess, prc, rc, LenB(rc), rwb)
-
- Call VirtualFreeEx(hProcess, prc, LenB(rc), MEM_RELEASE)
-
- Call CloseHandle(hProcess)
в Call SendMessage(hwntbr, WM_GETTEXT, 1, prc) wParam (=1) - номер панели в статусбаре.
Вместо WM_GETTEXT в Call SendMessage(hwntbr, WM_GETTEXT, 1, prc) пытался также ставить SB_GETTEXTA.
Вот. VBA и весь WORD рушится при выполнении этого кода. Причём на строке
-
- Call ReadProcessMemory(hProcess, prc, rc, LenB(rc), rwb)
-
И ещё вопрос. Почему prc всегда получается =0. Так и должно быть. Выяснил при отладке. В примере с ToolBar тоже prc=0, но всё работает ведь.
Ответить
|
Номер ответа: 11 Автор ответа: Father
Вопросов: 0 Ответов: 159
|
Профиль | | #11
|
Добавлено: 26.12.08 19:32
|
Почему prc всегда получается =0
Нет конечно же, ты ошибся. Скорее всего ты после остановки в отладке нажал reset и Pubic-переменная HWndObjm заново инициализировалась в ноль.
Call SendMessage(hwntbr, WM_GETTEXT, 1, prc) wParam (=1) - номер панели в статусбаре.
Для панелей статусбара WM_GETTEXT не прокатит т.к. wparam хочет видеть ко-во получаемых символов а не zero-index панели.
Надо бы:
Private Const SB_GETTEXTA = (WM_USER + 2)
Private Const SB_GETTEXTLENGTHA = (WM_USER + 3)
В качестве примера - получить текст из строки панели состояния чужой проги(класс окна msctls_statusbar32):
-
- Dim rwb As Long
- Dim procid As Long
- Dim hProcess As Long
- Dim L As Long
- Dim prc As Long
-
- Call GetWindowThreadProcessId(hwntbr, procid)
- hProcess = OpenProcess(PROCESS_ALL_ACCESS Or PROCESS_DUP_HANDLE, True, procid)
- L = SendMessage(hwntbr, SB_GETTEXTLENGTHA, 0, 0)
- Dim s() As Byte
- ReDim s(L - 1)
- prc = VirtualAllocEx(hProcess, 0, L, MEM_COMMIT Or MEM_TOP_DOWN, PAGE_READWRITE)
- Call SendMessage(hwntbr, SB_GETTEXTA, 0, prc)
- Call ReadProcessMemory(hProcess, prc, ByVal VarPtr(s(0)), L, rwb)
- MsgBox StrConv(s, vbUnicode)
- Call VirtualFreeEx(hProcess, prc, L, MEM_RELEASE)
- Call CloseHandle(hProcess)
У меня сегодня судьба со строками воевать.
Ответить
|
Номер ответа: 14 Автор ответа: Father
Вопросов: 0 Ответов: 159
|
Профиль | | #14
|
Добавлено: 02.01.09 11:50
|
Смотря, как декларирована ReadProcessMemory.
-
- Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
- Call ReadProcessMemory(hProcess, prc, s(0), L, rwb)
или так
-
- Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As Long, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
- Call ReadProcessMemory(hProcess, prc, ByVal VarPtr(s(0)), L, rwb)
Ответить
|
Страница: 1 |
Поиск по форуму