Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 | 2 | 3 | 4 |

 

  Вопрос: Переопределение оконной процедуры Добавлено: 27.11.05 20:38  

Автор вопроса:  Sacred Phoenix | ICQ: 304238252 
Слышал, что влезать в чужое адресное пространство просто так нельзя, но можно "прикрепить" DLL.
lngOldWndProc = SetWindowLong(lngHandle, GWL_WNDPROC, AddressOf NewWndProc)

не катит, возвращает всегда 0. Если кто знает, объясните, плиз, как вторгнуться в Window Proc чужого окошка?

Ответить

  Ответы Всего ответов: 47  

Номер ответа: 1
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #1 Добавлено: 27.11.05 21:16
Можно просто повесить хук, и фильтровать сообщения, относящиеся к интересующему окну.

Если обязательно влезть в чужое пространство, то VirtualAllocEx, копируешь в выделенную им память свой код (только не VB :), который должен будет изнутри переопределить новую WndProc (которую тоже нужно принести с собой), заменить начало старой на jmp xxxxx (где xxxxx - начало твоей WndProc). В новой обработать интересующее сообщение, и вернуть управление Винде. Необрабатываемые сообщения вернуть в старую процедуру, предварительно вернув на место 5 байт, затёртые jmp xxxxx.

И всё.
Так что VB тут не поможет.

Ответить

Номер ответа: 2
Автор ответа:
 Sacred Phoenix



ICQ: 304238252 

Вопросов: 52
Ответов: 927
 Профиль | | #2 Добавлено: 27.11.05 22:11
Можно просто повесить хук, и фильтровать сообщения, относящиеся к интересующему окну
Если можешь, по-подробней. И можно ли будет в этом случае переопределить некоторые сообщения (н-р, мне нужно WM_USER + 100).

Ответить

Номер ответа: 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.
Какой способ выбрать - зависит от конкретной задачи.

Ответить

Номер ответа: 4
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #4 Добавлено: 28.11.05 09:02
WM_USER + 100, гы гы гы...

Часы в трее расширяем? :)
http://bbs.vbstreets.ru/viewtopic.php?t=10245

А потом bbs.vbstreets.ru/viewtopic.php?p=118850#118850

Ответить

Номер ответа: 5
Автор ответа:
 Sacred Phoenix



ICQ: 304238252 

Вопросов: 52
Ответов: 927
 Профиль | | #5 Добавлено: 28.11.05 20:48
2 GSerg: ага, все часики... :)
Ссылки у меня не пашут (SQL Error) :(

2 HOOLIGAN: а как создать не ActiveX'ную DLL? Насчет WM_USER + 100: как сказал GSerg, мне этот мессаг нужно не переопределить. Когда Taskbar посылает Trayclock'у WM_USER + 100, первому нужно вернуть размер часов.

Ответить

Номер ответа: 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 для линковки, думаю, что опции должны совпадать.

Ответить

Номер ответа: 7
Автор ответа:
 Sacred Phoenix



ICQ: 304238252 

Вопросов: 52
Ответов: 927
 Профиль | | #7 Добавлено: 28.11.05 21:49
Я тут одну фигню с Planet-Source-Code скачал для создания стандартных DLL на VB. Подходит?

Ответить

Номер ответа: 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
   ;DLLMain = 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

Код-то правильный? (Это мой первый опыт с хуками)

Ответить

Номер ответа: 10
Автор ответа:
 Sacred Phoenix



ICQ: 304238252 

Вопросов: 52
Ответов: 927
 Профиль | | #10 Добавлено: 28.11.05 22:26
Да, и есть различие между Standart DLL и DLL, которая может влезать в чужое пространство (или это одно и то же)?

Ответить

Номер ответа: 11
Автор ответа:
 ANDREY



Вопросов: 0
Ответов: 33
 Профиль | | #11 Добавлено: 29.11.05 00:11
ЛЮБАЯ dll влезает в чужое(для нее) адресное пространство. Так они устроены.
Ну я чувствую, что статья ходовая:
http://www.vbstreets.ru/VB/Articles/66227.aspx
Читай. Потом из созданной dll можно спокойно сабклассить окно.

Ответить

Номер ответа: 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


Ответить

Номер ответа: 13
Автор ответа:
 ANDREY



Вопросов: 0
Ответов: 33
 Профиль | | #13 Добавлено: 29.11.05 00:23
Из выше сказанного следует, что существуют Dll, которые (почти цитата)не может влезать в чужое пространство ???
Что считаеться "влезанием" в чужое АП? А что такое "свое" АП у dll?

Ответить

Номер ответа: 14
Автор ответа:
 ANDREY



Вопросов: 0
Ответов: 33
 Профиль | | #14 Добавлено: 29.11.05 00:31
СТОП. Или ты говоришь о dll-ах, которые могут быть загружены одним процессом, и при этом использоваться дургими(без предварительной загрузки тими самыми другими процессами)??

Ответить

Номер ответа: 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 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам