如何将非托管C ++表单嵌入到.NET应用程序中?

时间:2011-03-01 15:48:28

标签: c# .net c++ unmanaged

我已经能够成功包装我的非托管Borland C ++ dll,并从C#.NET 4.0应用程序启动它的表单。是否可以将表单从dll直接嵌入到.NET应用程序中?

为了澄清,原始表单已经在Borland C ++项目中用作嵌入式控件。它基本上看起来像一个自定义控件,坐在应用程序的面板上。

当我说'嵌入'时,我的意思是将INTO放入表单中,就像将按钮,面板等放到表单上一样。我不打算只做一个孩子。

如果这是不可能的,那么或许更好的问题是如何将无人管理的自定义控件嵌入到.Net应用程序中?

2 个答案:

答案 0 :(得分:4)

是的,您只需要使用user32.dll中的一些低级win32函数:SetParent,GetWindowLog,SetWindowLong,MoveWindow。您可以创建一个空的.NET容器控件,将本机窗口的父级设置为.NET控件,然后(可选)修改窗口样式(即删除本机窗口的边框),并注意将其与.NET控件。请注意,在托管级别,.NET控件将不会意识到它有任何子级。

在.NET控件中执行类似

的操作
public void AddNativeChildWindow(IntPtr hWndChild){

        //adjust window style of child in case it is a top-level window
        int iStyle = GetWindowLong(hWndChild, GWL_STYLE);
        iStyle = iStyle & (int)(~(WS_OVERLAPPEDWINDOW | WS_POPUP));
        iStyle = iStyle | WS_CHILD;
        SetWindowLong(hWndChild, GWL_STYLE, iStyle);


        //let the .NET control  be the parent of the native window
        SetParent((IntPtr)hWndChild, this.Handle);
         this._childHandle=hWndChild;

        // just for fun, send an appropriate message to the .NET control 
        SendMessage(this.Handle, WM_PARENTNOTIFY, (IntPtr)1, (IntPtr)hWndChild);

}

然后覆盖.NET控件的WndProc,使其适当调整本机表单的大小 - 例如填充客户区。

 protected override unsafe void WndProc(ref Message m)
    {

        switch (m.Msg)
        {
            case WM_PARENTNOTIFY:
                   //... maybe change the border styles , etc
                   break;
              case WM_SIZE:
                iWid =(int)( (int)m.LParam & 0xFFFF);
                iHei= (int) (m.LParam) >> 16;
                if (_childHandle != (IntPtr)0)
                {

                    MoveWindow(_childHandle, 0, 0, iWid, iHei, true);

                }
                break;

        }

 }

答案 1 :(得分:1)

注意 我写了这个回应,假设OP想要在.NET应用程序中嵌入包含该表单的本机DLL,而不仅仅是修改它的显示方式。

简而言之,没有。您需要将C ++ DLL与您的发行版打包在一起,并以与您现在相同的方式导入/包装其功能。

我似乎记得从我的Delphi(它使用与Borland C ++相同的编译器后端)的日子,表单设计器生成C ++代码,为表单中的每个资产创建一个winproc / message循环等。 Win32 API。

由于所有代码都是不受管理的,因此无法将其编译为托管程序集。你可以把它移植到托管C ++,但是这会破坏在C ++中开始使用它的大部分好处,并且你会遇到一个糟糕的异常模型和C ++的所有其他很棒的部分。在这种情况下,你可能最好只用C#重写它。

但是,由于这是软件,几乎一切皆有可能,这是一个非常蹩脚的解决方案:将DLL作为二进制资源嵌入.NET应用程序中,并在运行时将其内容拉入二进制流,保存到磁盘然后加载它(我不确定是否有办法从内存中执行非托管DLL,除了通过将其放在RAM磁盘上作弊)。

唯一能让你隐藏DLL的能力,但我真的不明白这一点。

修改 您是指将show作为子窗口嵌入,还是将代码嵌入到.NET项目中?