Требуется событие LostFocus для WinForms UserControl, размещенного в MS Office VBA через COM Interop

Мы реализовали элемент управления ActiveX на основе WinForms UserControl в VB.NET 2010. Он используется в пользовательских формах VBA через COM-взаимодействие. Все работает нормально - кроме одного. Когда фокус ввода перемещается с ActiveX на другой собственный элемент управления VBA в UserForm (например, Command Button), мы не можем обнаружить это. Такие стандартные управляющие события WinForms, такие как Leave или Validating, в этом случае не запускаются.

Как это отследить (лучше "управляемым" способом, без уловок WinAPI)?

Обратите внимание, что наш UserControl содержит другие элементы управления WinForms, такие как кнопки или текстовые поля, поэтому нам нужно событие LostFocus для всего элемента управления, представленного как ActiveX, независимо от того, какая составляющая часть была выбрана.


person TecMan    schedule 08.10.2013    source источник


Ответы (1)


Я не думаю, что это можно исправить с помощью управляемого API. Если вас устраивает P / invoke, SetWindowsHookEx / _1 _ / _ 2_.

Возможно, у вас есть еще одна причуда. Попробуйте поместить текстовый курсор (курсор) в любое из редактируемых полей в управляемом элементе управления, а затем переключитесь на другое приложение с помощью Alt-Tab. Затем вернитесь в свое приложение с помощью Alt-Tab. Курсор все еще на месте или исчез? В последнем случае вам нужно HCBT_ACTIVATE.

Реализация COM-интерфейсов элемента управления ActiveX в .NET Framework для UserControl ожидает некоторых вызовов протокола от узла ActiveX. Например, ожидается, что IOleInPlaceObject::UIDeactivate будет вызываться, когда фокус перемещается в другое место за пределами UserControl, или IOleInPlaceActiveObject::OnFrameWindowActivate method, который будет вызываться с фреймом хоста, станет неактивным, потому что пользователь переключился на другое приложение. Вы можете изучить исходный код Framework для получения дополнительных сведений.

К сожалению, не все контейнеры ActiveX строго следуют этому протоколу; по-видимому, VBA этого не делает. Конечным решением является реализация промежуточного уровня (предпочтительно на C ++ / ATL), который будет служить элементом управления ActiveX для хоста VBA и контейнером ActiveX для управляемого элемента управления .NET, исправляя все эти причуды между ними. Это выполнимо, но довольно утомительно.

person noseratio    schedule 08.10.2013