Страница: 1 | 2 | 3 | 4 |
|
Вопрос: Переопределение оконной процедуры
|
Добавлено: 27.11.05 20:38
|
|
Автор вопроса: Sacred Phoenix | ICQ: 304238252
|
Слышал, что влезать в чужое адресное пространство просто так нельзя, но можно "прикрепить" DLL.
lngOldWndProc = SetWindowLong(lngHandle, GWL_WNDPROC, AddressOf NewWndProc)
не катит, возвращает всегда 0. Если кто знает, объясните, плиз, как вторгнуться в Window Proc чужого окошка?
Ответить
|
Номер ответа: 3 Автор ответа: HOOLIGAN
Вопросов: 0 Ответов: 1066
|
Профиль | | #3
|
Добавлено: 27.11.05 23:21
|
Делаешь .dll. Не ActiveX. Она должна быть с разделяемыми секциями.
В ней вызываешь SetWindowsHookEx с параметрами WH_CALLWNDPROC и адресом твоей хучащей процедуры CallWndProc (она тоже должна быть в этой .dll). Это так называемая инсталляция хука. После этого сообщения, адресуемые в WndProc, будут сначала передаваться в твою CallWndProc в виде указателя на структуру CWPSTRUCT, в которой содержится hWnd окна, кому адресовано данное сообщение, само сообщение, lParam и wParam.
Если сообщение тебе не интересно, пропускаешь его в дефолтную WndProc вызывая CallNextHookEx.
Если интересно - можешь по этому сообщению выполнить какие-то свои действия. Если nCode, передаваемое вместе с указателем в CallWndProc, < 0, то ты не должен обрабатывать данное сообщение, и должен передать его в WndProc и затем вернуть её результат.
Это примерная схема. Подробнее можно найти в msdn по ключевым словам SetWindowsHookEx и т.д.
А что значит переопределить WM_USER+100, я не понял. Зачем менять константу? Можно обработать, если соответствующий nCode.
Если вызвать SetWindowsHookEx с WH_CALLWNDPROCRET, то сообщения дойдут до твоей CallWndProc уже после их обработки в WndProc.
Какой способ выбрать - зависит от конкретной задачи.
Ответить
|
Номер ответа: 6 Автор ответа: HOOLIGAN
Вопросов: 0 Ответов: 1066
|
Профиль | | #6
|
Добавлено: 28.11.05 21:18
|
Создать dll можно как угодно, хоть на с++, хоть на асме, хоть на дельфи.
Пишется код dll (твои функции), а затем компилируется в .obj-файл. После этого его нужно линковать таким образом, чтобы можно было dll подгружать в адресное пространство других приложений, т.е. с разделяемыми секциями.
Как на с++ и дельфи не знаю, на ассемблере делал для линкера командную строку так:
C:\masm32\bin\Link /SECTION:.bss,S /DLL /DEF:mydll.def /SUBSYSTEM:WINDOWS /LIBPATH:\masm32\lib mydll.obj
В принципе с++ тоже использует Link для линковки, думаю, что опции должны совпадать.
Ответить
|
Номер ответа: 8 Автор ответа: HOOLIGAN
Вопросов: 0 Ответов: 1066
|
Профиль | | #8
|
Добавлено: 28.11.05 21:54
|
Попробую стать телепатом: фигня для VB, скачанная откуда бы то ни было, вряд ли подойдёт для этого.
Скачай лучше VC++ 2003 (30Мб) или пакет masm32v8 (3Мб).
Это точно подойдёт
Ответить
|
Номер ответа: 9 Автор ответа: Sacred Phoenix
ICQ: 304238252
Вопросов: 52 Ответов: 927
|
Профиль | | #9
|
Добавлено: 28.11.05 22:24
|
Ну, не фигня. Кстати, код DLL, который я щас написал:
Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" ( ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" ( ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" ( ByVal hHook As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Const WH_CALLWNDPROC = 4
Private Const WM_USER = &H400
Private Const WM_TIMER = &H113
Private Type EVENTMSG
wMsg As Long
lParam As Long
hParam As Long
hWnd As Long
End Type
Private Type DWORD
pLow As Long
pHigh As Long
End Type
Private lngHHook&, lngHTrayclock&
Option Explicit
Public Function DLLMain( ByVal A&, ByVal B&, ByVal C& As Boolean
  LLMain = True
End Function
Public Sub Main()
'Dummy
End Sub
Public Function SetHook() As Boolean
On Local Error Resume Next
lngHTrayclock = FindWindow("Shell_TrayWnd", vbNullString)
lngHTrayclock = FindWindowEx(lngHTrayclock, 0, "TrayNotifyWnd", vbNullString)
lngHTrayclock = FindWindowEx(lngHTrayclock, 0, "TrayClockWClass", vbNullString)
lngHHook = SetWindowsHookEx(WH_CALLWNDPROC, AddressOf CallWndProc, 0, 0)
SetHook = ( Not Err.Number) And lngHHook
End Function
Public Function UnsetHook() As Boolean
On Local Error Resume Next
Call UnhookWindowsHookEx(lngHHook)
UnsetHook = Not Err.Number
End Function
Public Function CallWndProc( ByVal nCode&, ByVal wParam&, ByVal lParam& As Long
Dim typMsg As EVENTMSG, typRes As DWORD
Dim lngRes&
If nCode < 0 Then
CallWndProc = CallNextHookEx(lngHHook, nCode, wParam, lParam)
Exit Function
End If
Call CopyMemory(typMsg, ByVal lParam, Len(typMsg))
If typMsg.hWnd = lngHTrayclock Then
Select Case typMsg.wMsg
Case WM_USER + 100
'Здеся код. На мессагу возвращаем width/height:
typRes.pLow = ClockWidth
typRes.pHigh = ClockHeight
Call CopyMemory(lngRes, typRes, Len(typRes))
CallWndProc = lngRes
Case WM_TIMER
'Не даем получить Trayclock'у этот мессаг.
Exit Function
End Select
End If
Call CallNextHookEx(lngHHook, nCode, wParam, lParam)
End Function
Код-то правильный? (Это мой первый опыт с хуками)
Ответить
|
Номер ответа: 12 Автор ответа: HOOLIGAN
Вопросов: 0 Ответов: 1066
|
Профиль | | #12
|
Добавлено: 29.11.05 00:12
|
Есть, именно поэтому несколько раз повторил: dll должна быть с разделяемыми секциями, что достигается указанием определенных ключей линкеру.
Каких-то ошибок я не вижу, пробуй
Для сравнения хук на мышиные сообщения на асме. На оконные нету (на vb тоже). Но принцип тот же.
;==============================================================================
DllEntry proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD
.if reason==DLL_PROCESS_ATTACH
mov eax, TRUE
.endif
ret
DllEntry endp
;=============================================================================
InstallHook proc hwnd:DWORD,hwndFrom:DWORD
push hwnd
pop hWnd
push hwndFrom
pop hWndFrom
invoke SetWindowsHookEx,WH_MOUSE,addr MouseProc,hInstance,NULL
mov hHook,eax
ret
InstallHook endp
;=============================================================================
MouseProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD
LOCAL MStruct :MOUSEHOOKSTRUCT
LOCAL hWin :DWORD
mov ecx,wParam
cmp ecx,WM_MOUSEWHEEL ;если сообщение WM_MOUSEWHEEL
jne _no_wheel
invoke RtlMoveMemory,ADDR MStruct,lParam,sizeof crMOUSEHOOKSTRUCT
invoke WindowFromPoint,MStruct.xCoord,MStruct.yCoord
mov hWin,eax
invoke PostMessage,hWnd,WM_USER+111,hWin,MStruct.mouseData
xor eax,eax
ret
_no_wheel:
invoke CallNextHookEx,hHook,nCode,wParam,lParam
xor eax,eax
ret
MouseProc endp
;============================================================================
UninstallHook proc
invoke UnhookWindowsHookEx,hHook
ret
UninstallHook endp
Ответить
|
Номер ответа: 15 Автор ответа: HOOLIGAN
Вопросов: 0 Ответов: 1066
|
Профиль | | #15
|
Добавлено: 29.11.05 00:47
|
Сейчас ради интереса перекомпилил свою dll, которая хучит мышиные сообщения, удалив ключ, позволяющий создавать разделяемые секции. Оставил такой ключ:
C:\masm32\bin\Link /DLL /DEF:mydll.def /SUBSYSTEM:WINDOWS /LIBPATH:\masm32\lib mydll.obj
Т.е. без /SECTION:.bss,S
Компилируется и линкуется обычная стандартная dll, а работать - хрен. Мышиные сообщения (WM_MOUSEWHEEL) перестали ловиться.
Так что нужна dll с разделяемыми секциями.
Влезание в чужой процесс и вылезание оттуда не совсем корректные термины, поэтому скажем так: разделяемые секции.
Ответить
|
Страница: 1 | 2 | 3 | 4 |
Поиск по форуму