Страницы: 1
RSS
Универсальный обработчик событий контролов юзерформы
 
Всем привет,

Пытаюсь сделать универсальный обработчик событий (Change) для определенных контролов (комбобокс и текстбокс) на форме, по аналогии с рабочим кодом (закомментирован) обработчика для одного контрола, но возникает ошибка.

Подскажите, пожалуйста, как лучше это реализовать в одном классе это, не плодить же по классу на каждый тип контрола.

класс clsEventHandler_Universal
Код
Option Explicit

Private WithEvents mControl As MSForms.Control    '<-- тут ошибка возникает

Public Sub AssignControl(c As MSForms.Control)
    Set mControl = c
End Sub

Private Sub mControl_Change()
Debug.Print TypeName(mControl)
    Select Case True
        Case TypeName(mControl) = "TextBox"
            Debug.Print "txt", mControl.Name
        Case TypeName(mControl) = "ComboBox"
            Debug.Print "cbo", mControl.Name
    End Select
End Sub
юзер форма
Код
Private eventHandlerCollection As New Collection

Private Sub UserForm_Initialize()
    Dim c As Control

    Dim handler As clsEventHandler_Universal
    For Each c In Controls
        If TypeName(c) = "ComboBox" Or _
           TypeName(c) = "TextBox" Then
            Set handler = New clsEventHandler_Universal
            handler.AssignControl c
            eventHandlerCollection.Add handler
        End If
    Next    
End Sub
Изменено: user0 - 24.08.2022 09:53:02
 
Почитайте тему "Работа с модулями классов" на сайте Дмитрия Щербакова.
Изменено: sokol92 - 24.08.2022 13:41:41
Владимир
 
Цитата
user0 написал:
не плодить же по классу на каждый тип контрола
а придется для нормальной работы с каждым типом(благо не так уж их и много). Притом совершенно не обязательно плодить именно классы - обработки всех типов можно записать в одном классе без проблем. А универсальный для всех типов через Control не сделать потому, что у каждого типа могут быть свои методы и события, которых нет у других типов. Например, у ComboBox-ов есть событие click, которого нет у TextBox-ов. Поэтому для типа Control вообще нет таких событий - только Enter и Exit, AfterUpdate и BeforeUpdate, которые используются весьма редко. Следовательно, Ваше событие Private Sub mControl_Change() вообще никогда не будет запущено, т.к. оно просто не зарегистрировано для этого типа объекта. А значит нет и смысла создавать обработку по Вашей схеме :)
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Здравствуйте user0, как-то интересовался этой темой, не скажу что я её до конца понял, но рабочий код нашел(переписал с книги) и сохранил.
Правда некоторых событий характерных для тексбокса в модуле класса не хватает.
Список событий текстбокса в модуле класса:

Обычный список событий текстбокса:
 
сделаете  - обязательно покажите
лично я тяготею к универсальности ( чтобы один раз написал и забыл н всю жизнь (осталось не так много)
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
sokol92, там в общем написано и, к сожалению, не дает ответа на мой вопрос.
Дмитрий(The_Prist) Щербаков, спасибо за развернутое объяснение, стало понятнее.
DANIKOLA, спасибо за пример.
Ігор Гончаренко, не, мне хватило объяснений Дмитрия про Control чтобы не копать дальше, а сделать обработки пары нужных типов в одном классе (как в примере от DANIKOLA). KISS, YAGNI, вот эта вот вся фигня )
Изменено: user0 - 25.08.2022 01:48:38
 
Ваш подход может быть реализован следуюшим образом (см. вложение) - об этом же писал и Дмитрий.
Включена обработка событий Change и DblClick элементов управления TextBox и Combobox, но каким же образом можно обработать и все остальные события этих элементов управления, кроме Enter, Exit, AfterUpdate, BeforeUpdate.
События Enter и Exit могут быть обработаны косвенно, через анализ событий клавиатуры и мыши. Недавно (по меркам Excel) было предложено универсальное решение для обработки события Enter (через Windows API).

Приложенный пример должен обрабатывать и события динамически добавляемых элементов управления TextBox и Combobox.
Изменено: sokol92 - 25.08.2022 13:29:29
Владимир
 
Прилагаю пример универсального обработчика всех событий всех элементов управления пользовательской формы (включая Enter, Exit, ...).

Вся основная работа производится в модуле класса CatchEvents2, который взят из этого замечательного сообщения.

Этот модуль класса нельзя редактировать в встроенном редакторе кода VBA (VBE), поскольку текст модуля содержит директивы "Attribute ...", которые не показываются VBE. Перемещать модуль из проекта в проект можно. Для изменения текста необходимо в редакторе VBE экспортировать файл (Menu / File / Export file...), откорректировать выгруженный текстовый файл (в любом редакторе), импортировать обратно (Menu / File / Import file...).

В приложенном примере макрос Event_Handler выводит в окно Immediate наименования элементов управления и событий, кроме событий мыши и клавиатуры (хотя  сами события мыши и клавиатуры перехватываются).

При динамическом (на лету) добавлении элементов управления в форму их события так же будут обработаны.

Откройте прилагаемый файл, нажмите кнопку для открытия формы. Поработайте с элементами управления (вводите данные, щелкайте, ...) и затем проанализируйте в окне Immediate (Ctrl+G), какие события были обработаны.
Изменено: sokol92 - 28.08.2022 20:02:10
Владимир
 
sokol92, сохранил в закладки и потом обязательно разберу  :idea:
Спасибо!  ;)
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Владимир, обалденный код!
 
Цитата
sokol92 написал: Прилагаю пример универсального обработчика
Владимир, спасибо - шикарный метод!  :)
 
Друзья, спасибо этому гению, который про себя пишет: "Финансовый менеджер со склонностью к Excel и VBA".

Эх, знать бы это лет 20 назад.  ;)
Владимир
 
Это да. Тот человек, кстати, честно написал, что метод изначально он увидел когда-то на японском сайте.
Страницы: 1
Наверх