我已经能够成功包装我的非托管Borland C ++ dll,并从C#.NET 4.0应用程序启动它的表单。是否可以将表单从dll直接嵌入到.NET应用程序中?
为了澄清,原始表单已经在Borland C ++项目中用作嵌入式控件。它基本上看起来像一个自定义控件,坐在应用程序的面板上。
当我说'嵌入'时,我的意思是将INTO放入表单中,就像将按钮,面板等放到表单上一样。我不打算只做一个孩子。
如果这是不可能的,那么或许更好的问题是如何将无人管理的自定义控件嵌入到.Net应用程序中?
答案 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项目中?