如何投出控制的IOleObject投出、IOleObject

由网友(꧁墨.꧂)分享简介:我要调用的 GetClientSite 在.NET控件。为此我想投的控制(在例子Windows.Forms.Form)为的IOleObject 它返回null。我应该怎么做才能获得的IOleObject?使用系统;使用了System.Runtime.InteropServices;使用System.Security...

我要调用的 GetClientSite 在.NET控件。为此我想投的控制(在例子Windows.Forms.Form)为的IOleObject 它返回null。

我应该怎么做才能获得的IOleObject?

 使用系统;
使用了System.Runtime.InteropServices;
使用System.Security程序;
使用System.Windows.Forms的;

命名空间Test001
{
    公共类Form001:表
    {
    公共Form001()
    {
    的InitializeComponent();
    }

    私人无效的Ini​​tializeComponent()
    {
    this.SuspendLayout();
    this.Name =Form001;
    this.Text =Form001;
    this.Load + =新System.EventHandler(this.Form001_Lo​​ad);
    this.ResumeLayout(假);
    }

    私人无效Form001_Lo​​ad(对象发件人,EventArgs的)
    {
    的IOleObject OBJ =(的IOleObject)这一点;
    //的IOleClientSite网站= obj.GetClientSite();
    }
    }

    [ComImport中GUID(00000112-0000-0000-C000-000000000046),InterfaceType(ComInterfaceType.InterfaceIsIUnknown),燮pressUnmanaged codeSecurity]
    公共接口的IOleObject
    {
    [preserveSig]
    INT SetClientSite([中,的MarshalAs(UnmanagedType.Interface)的IOleClientSite pClientSite);
    的IOleClientSite GetClientSite();
    [preserveSig]
    INT SetHostNames([中,的MarshalAs(UnmanagedType.LPWStr)字符串szCont​​ainerApp,[在,的MarshalAs(UnmanagedType.LPWStr)字符串szCont​​ainerObj);
    [preserveSig]
    INT关闭(INT dwSaveOption);
    [preserveSig]
    INT SetMoniker([中,的MarshalAs(UnmanagedType.U4)诠释dwWhichMoniker,[在,的MarshalAs(UnmanagedType.Interface)对象PMK);
    [preserveSig]
    INT GetMoniker([中,的MarshalAs(UnmanagedType.U4)INT dwAssign,[在,的MarshalAs(UnmanagedType.U4)诠释dwWhichMoniker,[的MarshalAs(UnmanagedType.Interface)] out对象的绰号);
    [preserveSig]
    INT InitFromData([中,的MarshalAs(UnmanagedType.Interface)的IDataObject pDataObject,INT fCreation,[在,的MarshalAs(UnmanagedType.U4)诠释dwReserved);
    [preserveSig]
    INT GetClipboardData([中,的MarshalAs(UnmanagedType.U4)INT dwReserved,出IDataObject的数据);
    [preserveSig]
    INT DoVerb(INT iVerb,[在] IntPtr的LPMSG,[在,的MarshalAs(UnmanagedType.Interface)的IOleClientSite pActiveSite,INT LINDEX,IntPtr的hwndParent,[在]对象lprcPosRect);
    [preserveSig]
    INT EnumVerbs(out对象E);
    [preserveSig]
    INT OleUpdate();
    [preserveSig]
    INT IsUpToDate();
    [preserveSig]
    INT GetUserClassID([输入,输出]裁判的Guid pClsid);
    [preserveSig]
    INT GetUserType([中,的MarshalAs(UnmanagedType.U4)INT dwFormOfType,[的MarshalAs(UnmanagedType.LPWStr)出字符串的用户类型);
    [preserveSig]
    INT SetExtent([中,的MarshalAs(UnmanagedType.U4)诠释dwDrawAspect,[在]对象pSizel);
    [preserveSig]
    INT GetExtent([中,的MarshalAs(UnmanagedType.U4)诠释dwDrawAspect,[OUT]对象pSizel);
    [preserveSig]
    INT提醒(对象pAdvSink,OUT INT饼干);
    [preserveSig]
    INT的Unadvise([中,的MarshalAs(UnmanagedType.U4)INT dwConnection);
    [preserveSig]
    INT EnumAdvise(out对象E);
    [preserveSig]
    INT GetMiscStatus([中,的MarshalAs(UnmanagedType.U4)INT dwAspect,OUT INT MISC);
    [preserveSig]
    INT SetColorScheme([IN]的对象pLogpal);
    }

    [ComImport,InterfaceType(ComInterfaceType.InterfaceIsIUnknown)的Guid(00000118-0000-0000-C000-000000000046)]
    公共接口的IOleClientSite
    {
    [preserveSig]
    INT SaveObject();
    [preserveSig]
    INT GetMoniker([中,的MarshalAs(UnmanagedType.U4)INT dwAssign,[在,的MarshalAs(UnmanagedType.U4)诠释dwWhichMoniker,[的MarshalAs(UnmanagedType.Interface)] out对象的绰号);
    [preserveSig]
    INT GetContainer(出对象容器);
    [preserveSig]
    INT ShowObject();
    [preserveSig]
    INT OnShowWindow(INT fShow);
    [preserveSig]
    INT RequestNewObjectLayout();
    }
}
 

解决方案

的IOleObject 界面里面嵌套接口内部 UnsafeNativeMethods System.Windows.Forms的类组装。该 System.Windows.Forms.Control的实现它的内部和明确的。

创建具有相同的名称和GUID另一个接口不会在管理层面使相同的接口。

这行

 的IOleObject OBJ =(的IOleObject)这一点;
 
商业银行不良率连升 快投机器独创STS风控体系

再presents管理.NET铸造,并有无关,与COM。该投将只使用在完全一样从WinForms的组件,这是不公开的接口。

您可以尝试使用通过 InterfaceMapping 结构来获取方法(但请注意,这是我们不推荐):

 键入thisType = this.GetType();

键入oleInterface = thisType.GetInterface(的IOleObject);

MethodInfo的getSiteMethod = oleInterface.GetMethod(GetClientSite);

// InterfaceMapping用来获取更复杂的界面的场景
InterfaceMapping地图= thisType.GetInterfaceMap(oleInterface);

//在该指数明确落实
INT指数= Array.IndexOf(map.InterfaceMethods,getSiteMethod);
MethodInfo的actualExplicitMethod = map.TargetMethods [指数]

//后期绑定调用(慢)
对象o = actualExplicitMethod.Invoke(这一点,新的对象[] {});
 

现在,第一,你包裹在 System.Object的内部类型,不能转换到你的接口,因为原来的界面是内部的,所以你能有更多的乐趣与思考,只要你打算使用该对象。

二,我已经试过了,技术是可行的,但在特定情况下这种方法要求在Windows窗体抛出一个异常 - 顶级Windows窗体控件不能暴露作为ActiveX的控制。

I want to invoke GetClientSite on a .net control. For this purpose I am trying to cast a control (in example Windows.Forms.Form) to IOleObject which returns null.

What should I do to get 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();
    }
}

解决方案

The IOleObject interface is a nested interface inside the internal UnsafeNativeMethods class in the System.Windows.Forms assembly. The System.Windows.Forms.Control implements it internally, and explicitly.

Creating another interface with the same name and guid will not make it "the same interface" on a managed level.

This line

IOleObject obj = (IOleObject) this;

represents managed .net casting, and has nothing to do with COM. This cast will work only with the exact same interface from the winforms assembly, which isn't public.

You could try to use reflection via the InterfaceMapping structure to get the method (but note that this is not recommendable):

Type thisType = this.GetType();

Type oleInterface = thisType.GetInterface("IOleObject");

MethodInfo getSiteMethod = oleInterface.GetMethod("GetClientSite");

//InterfaceMapping is used to get more complex interface scenarios
InterfaceMapping map = thisType.GetInterfaceMap(oleInterface);

//at which index is the explicit implementation
int index = Array.IndexOf(map.InterfaceMethods, getSiteMethod);
MethodInfo actualExplicitMethod = map.TargetMethods[index];

//late-bound call (slow)
object o = actualExplicitMethod.Invoke(this, new object[] { });

Now, first, you get an internal type wrapped in System.Object which cannot be cast to your interface since the original interface is internal, so you get to have more fun with reflection as long as you intend to use that object.

Second, I've tried it, the technique works, but in your specific scenario this method called on a windows Form throws an exception - "Top-level Windows Forms control cannot be exposed as an ActiveX control.".

阅读全文

相关推荐

最新文章