SetWindowSubclass пропускает пользовательские объекты - PullRequest
1 голос
/ 13 июля 2009

Я использую Bear для проверки пользовательских объектов, и счетчик WindowProc никогда не уменьшается при RemoveWindowSubclass. Так же, как и сумма в USER, которая является объектами пользователя в диспетчере задач.

Я прочитал комментарий Раймонда Безопасные подклассы о том, как удалить подклассы перед разрушением окна, но мой тест завершен без его уничтожения.

Тот же API подклассов используется внутренне классом всплывающих подсказок comctl для инструментов TTF_SUBCLASS, поэтому при использовании несовместимых всплывающих подсказок возникает больше утечек.

Вот код VB6

'--- Form1.frm '
Option Explicit

Private Declare Function SetWindowSubclass Lib "comctl32" (ByVal hwnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, ByVal dwRefData As Long) As Long
Private Declare Function DefSubclassProc Lib "comctl32" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function RemoveWindowSubclass Lib "comctl32" (ByVal hwnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long

Private Sub Command1_Click()
    Call SetWindowSubclass(hwnd, AddressOf RedirectTabPaneEditWndProc, 10, ObjPtr(Me))
End Sub

Private Sub Command2_Click()
    Call RemoveWindowSubclass(hwnd, AddressOf RedirectTabPaneEditWndProc, 10)
End Sub

Friend Function frWndProc(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    frWndProc = DefSubclassProc(hwnd, wMsg, wParam, lParam)
End Function

'--- Module1.bas '
Option Explicit

Public Function RedirectTabPaneEditWndProc( _
            ByVal hwnd As Long, _
            ByVal wMsg As Long, _
            ByVal wParam As Long, _
            ByVal lParam As Long, _
            ByVal uIdSubclass As Long, _
            ByVal This As Form1) As Long
    #If uIdSubclass Then '--- touch args
    #End If
    RedirectTabPaneEditWndProc = This.frWndProc(hwnd, wMsg, wParam, lParam)
End Function

Если кто-то может оставить комментарий, что происходит и как устранить утечки, будет здорово.

Кто-нибудь еще будет предупрежден, если вы делаете интенсивное создание подклассов с помощью API SetWindowSubclass.

ура

Ответы [ 2 ]

2 голосов
/ 23 июля 2009

Я думаю, что называть это "утечкой" немного гиперболично. Правда, пользовательский объект не восстанавливается при вызове RemoveWindowSubclass, но и другой объект не выделяется при повторном вызове SetWindowSubclass. Вы можете многократно устанавливать и удалять зацепку, и один и тот же пользовательский объект, кажется, будет снова и снова использоваться снова и снова в течение всего процесса.

Я провел еще несколько тестов, которые расширили ваш простейший сценарий. Просто для справки, каждый экземпляр вашей формы с двумя командными кнопками и без оконных хуков потребляет шесть пользовательских объектов. Вызов SetWindowSubclass действительно потребляет еще один объект User на класс окна . То есть я могу загрузить несколько экземпляров этой формы и перехватить поток сообщений для самой формы, а также для обеих содержащихся командных кнопок и использовать в общей сложности два объекта User. Они, как вы заметили, не перерабатываются на протяжении всего процесса.

Может ли внутренний дизайн быть чище? Возможно. С другой стороны, возможно, нет. Я не вижу в этом особой причины для беспокойства. Более серьезной причиной для беспокойства могло бы стать приложение, разработанное таким образом, чтобы это могло иметь отношение. В этом случае может потребоваться фундаментальное пересмотр всей конструкции пользовательского интерфейса. Я просто не могу себе представить, когда вы будете создавать подклассы так много оконных классов в одном процессе, что этот дополнительный объект для каждого класса может иметь значение.

1 голос
/ 14 июля 2009

Это необычный способ создания подклассов в VB6. Возможно, вам повезет больше с SetWindowLong (GWL_WNDPROC) - смотрите этот код VB6 от Карла Петерсона.

Интересно, похоже, что Карл сейчас экспериментирует с теми же функциями comctl32, которые вы используете. РЕДАКТИРОВАТЬ: да, он опубликовал статью . РЕДАКТИРОВАТЬ: о, и ответ на этот вопрос :)

...