З.Ы. Как ты мог читать мою статью, если я её только что написал?
Видишь ли, то, что я читал подобную статью - очень уловно. Поскольку большую часть я просто не понимаю, можно сказать, что скорее я проглядывал по диагонали. Что-то из того, что понятно, остаётся в памяти. Основной контекст - что в копимемери очень много кода, а гетМем совсем простая - я понял. Я это уже знал, и знал, кажется, как раз от тебя - поэтому, наверное, и сработало в памяти, что уже читал.
Вот (если конечно я правильно тебя понял):
- Код: Выделить всё
Option Explicit
Public Event KeyDown(ByVal KeyCode As Long)
Private Const WM_KEYDOWN As Long = &H100
Private Const cNull As Long = &H0
Private Const GWL_WNDPROC = -4
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private OldCtl As Long
Private ASM() As Byte 'эталон
Private asmPrc() As Byte
Dim p1 As Long, p2 As Long
Dim mHwnd As Long
Public Function WinProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case uMsg
Case WM_KEYDOWN
RaiseEvent KeyDown(wParam)
End Select
WinProc = CallWindowProc(OldCtl, hWnd, uMsg, wParam, lParam)
End Function
Public Function Hook(ByVal hWnd As Long)
mHwnd = hWnd
Call StartSubclass(hWnd, OldCtl, cNull)
End Function
Public Sub Unhook()
If OldCtl Then Call SetWindowLong(mHwnd, &HFFFC, OldCtl)
End Sub
Private Sub StartSubclass(ByVal hWnd As Long _
, ByRef OldWndProc As Long _
, ByVal ProcNumber As Long)
Dim lng As Long
Dim tPtr As Long
asmPrc = ASM
Call CopyMemory(tPtr, ByVal ObjPtr(Me), 4&)
Call CopyMemory(lng, ByVal tPtr + &H1C + (4& * ProcNumber), 4&)
Call CopyMemory(asmPrc(p1), ObjPtr(Me), 4&)
' Относительное - [адрес метода] минус [адрес следующего байта после синего лонга].
Call CopyMemory(asmPrc(p2), lng - VarPtr(asmPrc(p2 + 4)), 4&)
OldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, VarPtr(asmPrc(0)))
End Sub
Private Sub Class_Initialize()
' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
' -------------------------------------------------
' 31 C0 50 54 8D 48 04 FF 74 24 18 E0 FA 68 хх хх
' хх хх E8 хх хх хх хх 58 C2 10 00
ReDim ASM(26)
ASM(c) = &H31
ASM(c) = &HC0
ASM(c) = &H50
ASM(c) = &H54
ASM(c) = &H8D
ASM(c) = &H48
ASM(c) = &H4
ASM(c) = &HFF
ASM(c) = &H74
ASM(c) = &H24
ASM(c) = &H18
ASM(c) = &HE0
ASM(c) = &HFA
ASM(c) = &H68
p1 = c(4) 'если я, конечно, правильно тебя понял
'ASM(c) = &H0
'ASM(c) = &H0
'ASM(c) = &H0
'ASM(c) = &H0
ASM(c) = &HE8
p2 = c(4)
'ASM(c) = &H0
'ASM(c) = &H0
'ASM(c) = &H0
'ASM(c) = &H0
ASM(c) = &H58
ASM(c) = &HC2
ASM(c) = &H10
ASM(c) = &H0
End Sub
Private Sub Class_Terminate()
Call Unhook
End Sub
Private Function c(Optional n As Long = 1) As Long
Static cnt As Long
c = cnt
cnt = cnt + n
End Function