Измените пользовательское имя подключаемого модуля Active-X, написанного на C#

#c# #user-controls #activex #ole

#c# #пользовательские элементы управления #activex #ole

Вопрос:

В настоящее время мне поручено создать подключаемый модуль Active-X для одного из наших клиентов. Теперь я успешно создал подключаемый модуль Active-X на C # / .NET (элемент управления Windows Form, который наследуется от System.Windows.Forms.UserControl класса), однако приложение, в котором размещен подключаемый модуль, показывает имя класса элемента управления в заголовке диалогового окна, в котором отображается подключаемый модуль Active-X.

После долгих поисков и разборки я обнаружил, что метод IOleObject.GetUserType вызывается хостом и что возвращаемое значение этого метода используется хостом в качестве заголовка диалогового окна. Посмотрев на System.Windows.Forms.UserControl класс, я обнаружил, что этот класс наследуется от System.Windows.Forms.Control класса, который, в свою очередь, явно реализует System.Windows.Forms.UnsafeNativeMethods.IOleObject интерфейс.

Что я хотел бы знать, так это то, есть ли какой-либо способ переопределить GetUserType метод в UserControl классе или есть другой способ выполнить то, что я хочу (возможно, решение очень простое, но я пока не смог его увидеть). До сих пор я уже пробовал различные «возможные» решения:

  1. Я пытался повторно реализовать IOleObject интерфейс, но поскольку System.Windows.Forms.UnsafeNativeMethods.IOleObject он является внутренним, это невозможно сделать (вы должны использовать точно такой же интерфейс, а переопределение интерфейса не приводит к точно такому же интерфейсу).

  2. Я пытался использовать внедрение CLR, как описано Зиадом Элмалки в CodeProject.

  3. Я пытался использовать какую-либо форму AOP. Поскольку Control класс наследуется от System.MarshalByRefObject через System.ComponentModel.Component , я подумал, что было бы возможно заставить мой пользовательский элемент управления возвращать какой-нибудь прокси, который перехватывал бы вызовы, отправляемые GetUserType методу.

К сожалению, я не смог заставить это работать. Что действительно работает, так это изменение имени класса, но поскольку в именах классов не допускается наличие пробелов или других специальных символов, это неприемлемое решение (подчеркивания просто не совпадают).

Чтобы уточнить, вот пример кода того, чего я хочу достичь (обратите внимание, что он не завершен):

 using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;

[ ComVisible(true)
, ClassInterface(ClassInterfaceType.AutoDual)
, Description("My Active-X plug-in")
, Guid("...")
]
public partial class MyControl : UserControl
{
    public override int GetUserType(int dwFromOfType, out string userType)
    {
        userType = "The caption to show in the host";
        // Return S_OK
        return 0;
    }
}
  

Надеюсь, кто-нибудь здесь сможет мне помочь.

Заранее спасибо!

Ответ №1:

Вы могли бы попытаться реализовать ICustomQueryInterface (.Net 4.0): http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.icustomqueryinterface.aspx

Когда система запрашивает IOleObject, вы могли бы вернуть свой собственный пользовательский объект, который реализует IOleObject , перенаправляет методы, которые вас не интересуют, в реализацию UserControl и надлежащим образом делегировать вызовы QueryInterface для пользовательского объекта обратно в UserControl (агрегирование).

Комментарии:

1. Хотя я смог реализовать ICustomQueryInterface и вернуть свою собственную реализацию интерфейса IOleObject, пересылка методов, которые меня не волнуют, в UserControl не является чем-то тривиальным. Проблема остается той же: некоторые интерфейсы / структуры, используемые реализацией IOleObject, предоставляемой классом Control, являются частными / внутренними и не могут быть использованы, поэтому вам нужно каким-то образом дублировать эти интерфейсы / структуры и преобразовать их во внутреннюю реализацию, используемую классом Control (что, насколько я могу судить, невозможно).

2. Я надеялся, что IOleObject и соответствующие интерфейсы и структуры, предоставляемые в сборке Microsoft.VisualStudio.OLE.Interop, каким-то образом совместимы с IOleObject, предоставляемым в System. Windows. Формирует сборку, но это не тот случай … к сожалению!