Вот соответствующие шаги , которые документированы внешне . Это суммировано, оставляя некоторые изложения, но не необходимые шаги.
Этот пример также очень похож на статью Использование управляемых элементов управления в качестве элементов управления ActiveX , автор Garry Trinder, 25 ноября 2008 г., и я также включил некоторые заметки из этой статьи.
Предоставление элементов управления Windows Forms в качестве элементов управления ActiveX
В этой статье описывается, как использовать элементы управления Windows Forms.
за пределами .NET.
Написание элемента управления
- Создайте новый проект элемента управления из Visual Studio - все мои примеры написаны на C #, но VB.NET также можно использовать.
[Здесь статья Гарри предлагает: " Во-первых, создайте управляемый проект usercontrol - либо библиотеку классов Windows Forms, либо проект библиотеки управления. Используйте конструктор usercontrol, чтобы создать свой пользовательский контроль пользователя так, как вы этого хотите (используя любой стандарт вам нравится)."]
Добавить элементы управления и т. Д. В форму, ввести код и т. Д.
Добавьте следующие пункты, используя пункты ...
using System.Runtime.InteropServices;
using System.Text;
using System.Reflection;
using Microsoft.Win32;
- Атрибут вашего класса, чтобы он получил ProgID. Это не обязательно, так как он будет сгенерирован, но почти всегда лучше
Явный.
[ProgId("Prisoner.PrisonerControl")]
[ClassInterface(ClassInterfaceType.AutoDual)]
Это назначает ProgID, а также определяет, что интерфейс
должен быть «AutoDual» - это портит интерфейс по умолчанию для
Вы из всех публичных, нестатичных членов класса. Если это не так
что вы хотите, используйте один из других вариантов.
- Обновите свойства проекта, чтобы ваша сборка была зарегистрирована для взаимодействия COM.
Если вы используете VB.NET, вам также нужна сборка со строгим именем.
Любопытно, что в C # вы этого не сделаете - и это, кажется, особенность
среда, а не особенность компилятора или CLR.
- Добавьте следующие два метода в ваш класс.
[ComRegisterFunction()]
public static void RegisterClass ( string key )
{
// Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it
StringBuilder sb = new StringBuilder ( key ) ;
sb.Replace(@"HKEY_CLASSES_ROOT\","") ;
// Open the CLSID\{guid} key for write access
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);
// And create the 'Control' key - this allows it to show up in
// the ActiveX control container
RegistryKey ctrl = k.CreateSubKey ( "Control" ) ;
ctrl.Close ( ) ;
// Next create the CodeBase entry - needed if not string named and GACced.
RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;
inprocServer32.SetValue ( "CodeBase" , Assembly.GetExecutingAssembly().CodeBase ) ;
inprocServer32.Close ( ) ;
// Finally close the main key
k.Close ( ) ;
}
Функция RegisterClass приписывается ComRegisterFunction -
этот статический метод будет вызываться при регистрации сборки на
COM Interop. Все, что я здесь делаю, это добавляю ключевое слово «Control» к
реестра, а также добавить в запись CodeBase.
CodeBase интересен - не только для элементов управления .NET. Он определяет URL
путь к тому, где можно найти код, который может быть сборкой на
диск как в этом случае, или удаленная сборка на веб-сервере
где-то. Когда среда выполнения пытается создать элемент управления, он будет
проверьте этот URL и загрузите элемент управления по мере необходимости. Это очень
полезно при тестировании компонентов .NET, как обычное предостережение о проживании
в том же каталоге (и т. д.), что и .EXE, не применяется.
[ComUnregisterFunction()]
public static void UnregisterClass ( string key )
{
StringBuilder sb = new StringBuilder ( key ) ;
sb.Replace(@"HKEY_CLASSES_ROOT\","") ;
// Open HKCR\CLSID\{guid} for write access
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);
// Delete the 'Control' key, but don't throw an exception if it does not exist
k.DeleteSubKey ( "Control" , false ) ;
// Next open up InprocServer32
RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;
// And delete the CodeBase key, again not throwing if missing
k.DeleteSubKey ( "CodeBase" , false ) ;
// Finally close the main key
k.Close ( ) ;
}
Вторая функция удалит записи реестра, добавленные, когда (если)
класс не зарегистрирован - это всегда хорошее предложение привести в порядок
по ходу дела.
Теперь вы готовы скомпилировать и протестировать свой элемент управления.
Дополнительные заметки из блога Гарри:
[The] дополнительные записи реестра: Control
, MiscStatus
, TypeLib
и
Version
[можно создать] с помощью .REG
скрипта, но обычно лучше
написать функции, которые будут вызываться при регистрации / отмене регистрации
Он описывает ключи реестра в некоторых деталях:
Control
- пустой подраздел. TypeLib
сопоставляется с GUID
TypeLib (это GUID уровня сборки в assemblyinfo.cs).
Version
старшие и младшие номера версий из сборки
версия. Единственный слегка интересный подраздел - MiscStatus
. Это необходимо
быть установленным на значение, состоящее из (побитовых) значений в OLEMISC
ан задокументировано здесь . Чтобы сделать это перечисление доступным, добавьте
ссылка на Microsoft.VisualStudio.OLE.Interop
(и подходящий
Оператор «using» для пространства имен).
Его последняя нота является предупреждением:
Примечание: кажется, что это работает нормально для Excel (с очень ограниченным тестированием
Я сделал), частично работает с PowerPoint, но терпит неудачу с
Слово. Возможно, некоторые дополнительные значения OLEMISC
могут улучшить это;
возможно, есть некоторые сообщения, которые нам нужно перехватить; возможно есть
еще несколько интерфейсов, которые мы должны реализовать ... Тот факт, что я только
едва заставить его работать очень ограниченным образом должен сказать вам, что это
вероятно, это не та техника, которую вы хотите использовать каким-либо серьезным образом.