.net 如何将控件强制转换为IOleObject

.net 如何将控件强制转换为IOleObject,.net,com,interop,ole,.net,Com,Interop,Ole,我想在.net控件上调用GetClientSite。为此,我尝试将一个控件(在示例Windows.Forms.Form中)强制转换为IOleObject,该控件返回null 我应该怎么做才能得到IOleObject using System; using System.Runtime.InteropServices; using System.Security; using System.Windows.Forms; namespace Test001 { public class F

我想在.net控件上调用GetClientSite。为此,我尝试将一个控件(在示例Windows.Forms.Form中)强制转换为IOleObject,该控件返回null

我应该怎么做才能得到IOleObject

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

namespace Test001
{
    public class Form001 : Form
    {
        public Form001()
        {
            InitializeComponent();
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            this.Name = "Form001";
            this.Text = "Form001";
            this.Load += new System.EventHandler(this.Form001_Load);
            this.ResumeLayout(false);
        }

        private void Form001_Load(object sender, EventArgs e)
        {
            IOleObject obj = (IOleObject) this;
            //IOleClientSite site = obj.GetClientSite();
        }
    }

    [ComImport, Guid("00000112-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), SuppressUnmanagedCodeSecurity]
    public interface IOleObject
    {
        [PreserveSig]
        int SetClientSite([In, MarshalAs(UnmanagedType.Interface)] IOleClientSite pClientSite);
        IOleClientSite GetClientSite();
        [PreserveSig]
        int SetHostNames([In, MarshalAs(UnmanagedType.LPWStr)] string szContainerApp, [In, MarshalAs(UnmanagedType.LPWStr)] string szContainerObj);
        [PreserveSig]
        int Close(int dwSaveOption);
        [PreserveSig]
        int SetMoniker([In, MarshalAs(UnmanagedType.U4)] int dwWhichMoniker, [In, MarshalAs(UnmanagedType.Interface)] object pmk);
        [PreserveSig]
        int GetMoniker([In, MarshalAs(UnmanagedType.U4)] int dwAssign, [In, MarshalAs(UnmanagedType.U4)] int dwWhichMoniker, [MarshalAs(UnmanagedType.Interface)] out object moniker);
        [PreserveSig]
        int InitFromData([In, MarshalAs(UnmanagedType.Interface)] IDataObject pDataObject, int fCreation, [In, MarshalAs(UnmanagedType.U4)] int dwReserved);
        [PreserveSig]
        int GetClipboardData([In, MarshalAs(UnmanagedType.U4)] int dwReserved, out IDataObject data);
        [PreserveSig]
        int DoVerb(int iVerb, [In] IntPtr lpmsg, [In, MarshalAs(UnmanagedType.Interface)] IOleClientSite pActiveSite, int lindex, IntPtr hwndParent, [In] object lprcPosRect);
        [PreserveSig]
        int EnumVerbs(out object e);
        [PreserveSig]
        int OleUpdate();
        [PreserveSig]
        int IsUpToDate();
        [PreserveSig]
        int GetUserClassID([In, Out] ref Guid pClsid);
        [PreserveSig]
        int GetUserType([In, MarshalAs(UnmanagedType.U4)] int dwFormOfType, [MarshalAs(UnmanagedType.LPWStr)] out string userType);
        [PreserveSig]
        int SetExtent([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, [In] object pSizel);
        [PreserveSig]
        int GetExtent([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, [Out] object pSizel);
        [PreserveSig]
        int Advise(object pAdvSink, out int cookie);
        [PreserveSig]
        int Unadvise([In, MarshalAs(UnmanagedType.U4)] int dwConnection);
        [PreserveSig]
        int EnumAdvise(out object e);
        [PreserveSig]
        int GetMiscStatus([In, MarshalAs(UnmanagedType.U4)] int dwAspect, out int misc);
        [PreserveSig]
        int SetColorScheme([In] object pLogpal);
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000118-0000-0000-C000-000000000046")]
    public interface IOleClientSite
    {
        [PreserveSig]
        int SaveObject();
        [PreserveSig]
        int GetMoniker([In, MarshalAs(UnmanagedType.U4)] int dwAssign, [In, MarshalAs(UnmanagedType.U4)] int dwWhichMoniker, [MarshalAs(UnmanagedType.Interface)] out object moniker);
        [PreserveSig]
        int GetContainer(out object container);
        [PreserveSig]
        int ShowObject();
        [PreserveSig]
        int OnShowWindow(int fShow);
        [PreserveSig]
        int RequestNewObjectLayout();
    }
}

IOleObject
接口是
System.Windows.Forms
程序集中内部
unsafentiveMethods
类中的嵌套接口。
System.Windows.Forms.Control
在内部显式地实现它

创建另一个具有相同名称和guid的接口不会使其成为托管级别上的“同一接口”

这条线

IOleObject obj = (IOleObject) this;
表示托管.net强制转换,与COM无关。此强制转换仅适用于winforms程序集中完全相同的接口,该接口不是公共的

您可以尝试通过结构使用反射来获得方法(但请注意,这是不推荐的):

现在,首先,您得到了一个封装在
System.Object
中的内部类型,由于原始接口是内部的,因此无法将其转换到您的接口,因此只要您打算使用该对象,您就可以从反射中获得更多乐趣

第二,我已经尝试过了,这种技术是有效的,但是在您的特定场景中,在windows窗体上调用此方法会引发一个异常-
“顶级windows窗体控件不能作为ActiveX控件公开。”

我正在使用此方法:

IOleClientSite pClientSite = (IOleClientSite)Site.GetService(new AntiMoniker().GetType());
例如,定义
AntiMoniker
。目前,不需要详细说明。只需获取系统的一个实例

[ComImport(), Guid("00000305-0000-0000-C000-000000000046")]
class AntiMoniker {
}
它将在.NET Framework 2.0/IE8/WinXP SP3上运行


感谢,使用
封送.CreateAggregatedObject
访问专用COM接口。

感谢提供更多信息,但这无助于我找到可能的解决方案。实际上,有一种在运行时获取内部接口的简单方法,但这也没有帮助。this.GetType().GetInterface(“IOleObject”);这可能与QueryInterface有关。我检查了一下,通过反射找到了一个解决方案,它不太友好,但很有效。
[ComImport(), Guid("00000305-0000-0000-C000-000000000046")]
class AntiMoniker {
}