VBA + WinAPI: WM_NCHITTEST вызывает бесконечный цикл

Обсуждения по программированию для ОС Windows безотносительно используемого языка программирования. Windows NT, Win32, Windows API, ядро и драйверы.
grunger
Начинающий
Начинающий
 
Сообщения: 11
Зарегистрирован: 01.06.2002 (Сб) 17:25
Откуда: Нью-Йорк

VBA + WinAPI: WM_NCHITTEST вызывает бесконечный цикл

Сообщение grunger » 07.08.2012 (Вт) 18:49

Здравствуйте, друзья!

Я - совершеннейший профан в 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.

Спасите, помогите.

grunger
Начинающий
Начинающий
 
Сообщения: 11
Зарегистрирован: 01.06.2002 (Сб) 17:25
Откуда: Нью-Йорк

Re: VBA + WinAPI: WM_NCHITTEST вызывает бесконечный цикл

Сообщение grunger » 07.08.2012 (Вт) 19:37

Сам пошутил - сам посмеялся. Решил проблему:

Код: Выделить всё
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
        wnd.Unhook
        DoEvents
        wnd.Hook
    End If
   
     Window_OnMessage = CallWindowProc(wnd.PrevWndProc, hwnd, Msg, wParam, lParam)
End Function


нашёл тут - http://www.xtremevbtalk.com/archive/index.php/t-297317.html

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: VBA + WinAPI: WM_NCHITTEST вызывает бесконечный цикл

Сообщение Хакер » 08.08.2012 (Ср) 16:20

grunger писал(а):нужно отслеживать их перемещение по экрану и запоминать координаты, чтобы в следующий раз открыть окно на том же месте.

По-моему гигантский overkill.
Чтобы в следующий раз открыть в том же месте, достаточно просто запоминать координаты и размер в момент закрытия. То есть отслеживать надо закрытие, а не перемещение.

Отслеживать перемещение имеет смысл только в том случае, если в следующий раз нужно было бы воспроизвести точную траекторию движения окна. Но это не нужно.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 08.08.2012 (Ср) 19:32

Хакер писал(а):Отслеживать перемещение имеет смысл только в том случае, если в следующий раз нужно было бы воспроизвести точную траекторию движения окна.

А ещё, в случае, когда достаточно вероятным является использование кнопки Reset :)

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: VBA + WinAPI: WM_NCHITTEST вызывает бесконечный цикл

Сообщение Хакер » 08.08.2012 (Ср) 20:43

1) Почему использование кнопки Reset является достаточно вероятным?
2) Даже если так, это можно решить делая периодически (раз в минуту, раз в 30 секунд, в 10 секунд, в 4 секунды, раз в секнду) проверку положения и запоминания. Ибо всё равно нельзя по каждому WM_MOVE начинать сохранение настроек.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 08.08.2012 (Ср) 22:39

1. Я просто привёл пример. А причина, например, если он виснет намертво...
2. А насколько часто оно происходит?

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: VBA + WinAPI: WM_NCHITTEST вызывает бесконечный цикл

Сообщение Хакер » 08.08.2012 (Ср) 22:53

1. Это стандартная логика. Практически весь софт, котоый запоминает подобные вещи, запоминает их при закрытии.
2. Что именно?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

grunger
Начинающий
Начинающий
 
Сообщения: 11
Зарегистрирован: 01.06.2002 (Сб) 17:25
Откуда: Нью-Йорк

Re: VBA + WinAPI: WM_NCHITTEST вызывает бесконечный цикл

Сообщение grunger » 08.08.2012 (Ср) 23:40

причина была простой, но не помню, если честно, какой, как это часто бывает %-) а так как это не единственное сообщение, которое я перехватываю, решил для единообразия, но да, Вы безусловно правы про закрытие окна.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 09.08.2012 (Чт) 7:42

Хакер писал(а):1. Это стандартная логика. Практически весь софт, котоый запоминает подобные вещи, запоминает их при закрытии.
2. Что именно?

1. Некоторые программы сохраняют настройки по таймеру.
2. Сообщение WM_MOVE.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: VBA + WinAPI: WM_NCHITTEST вызывает бесконечный цикл

Сообщение Хакер » 09.08.2012 (Чт) 15:29

Qwertiy писал(а):2. Сообщение WM_MOVE.

Разумеется невероятно часто, если только не включено «не живое» перетаскивание (когда тащится не окно, а рамочка, рисуемая с помощью DrawFocusRect, а перемещение окна происходит только при отпускании кнопки). Зависит от производительности машины, наличия других сообщений, загруженности процессора.

В хороших условиях — одно сообщение WM_MOVE при каждом перемещении на 1px.

Кому-то нужно хрюканье жесткого диска при перемещении окон? Сомневаюсь.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 09.08.2012 (Чт) 15:35

Хакер писал(а):В хороших условиях — одно сообщение WM_MOVE при каждом перемещении на 1px.

А вот про это я не подумал :)


Вернуться в Windows-программирование

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

    TopList