Я - совершеннейший профан в WinAPI. Но задача простая: есть n окон типа Window (UserForm), нужно отслеживать их перемещение по экрану и запоминать координаты, чтобы в следующий раз открыть окно на том же месте.
Решение: создаётся класс WindowManager (объект gWindowManager), который держит коллекцию открытых окон. UserForm имеет метод Hook:
- Код: Выделить всё
Public Sub Hook()
If Not mIsHooked Then
mPrevWndProc = SetWindowLong(mHwnd, GWL_WNDPROC, AddressOf API.Window_OnMessage)
mIsHooked = True
End If
End Sub
И Unhook:
- Код: Выделить всё
Private Sub Unhook()
If mIsHooked Then
Dim tmp As Long: tmp = SetWindowLong(mHwnd, GWL_WNDPROC, mPrevWndProc)
mIsHooked = False
End If
End Sub
А это код обработчика сообщений окна:
- Код: Выделить всё
Private Const WM_MOVE As Long = &H3
Private Const WM_NCHITTEST As Long = &H84
Private Declare Function CallWindowProc Lib "user32" 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 Declare Sub RtlMoveMemory Lib "kernel32" (ByRef Target As Any, ByRef Source As Any, ByVal length As Long)
Public Function Window_OnMessage(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim wnd As Window: Set wnd = gWindowManager.Windows.Item(hwnd)
If Msg = WM_MOVE Then
Debug.Print wnd.Caption & " x: " & (lParam And &HFFFF) & " y:" & (lParam \ &H10000 And &HFFFF&)
ElseIf Msg = WM_NCHITTEST Then
'Debug.Print "bla"
End If
Window_OnMessage = CallWindowProc(wnd.PrevWndProc, hwnd, Msg, wParam, lParam)
End Function
К сожалению, если мышку подносить к окну, программа вводится в бесконечный цикл и Window_OnMessage получает сообщение WM_NCHITTEST, времени ничего обработать нет. Если использую DoEvents, всё виснет, если использую Debug.Print при получении WM_NCHITTEST, то программа не успевает свалиться в цикл, так как тратит время собственно на сам Debug.Print.
Спасите, помогите.