C#和VC混合编程,C#调用VC窗口界面
前言
尽管C#在数据处理方面的界面编程比较方便,但在界面细节控制方面比VC还是差了一点。有时候已经在VC中做好的界面也需要在C#中展示。
一、制作界面DLL
C#要成功调用VC的窗口,VC代码必须以DLL方式提供。
1.先新建VC项目,选择MFC Dll,点击确定,新建一个dll工程。
在dll工程中新加各类,选MFC,点击确定后,给一个类名如下:
// CTestWnd
class CTestWnd : public CWnd
{
DECLARE_DYNAMIC(CTestWnd)
public:
CTestWnd();
virtual ~CTestWnd();
BOOL CreateWnd(HWND hWnd, CRect rect);
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnPaint();
};
2.添加对WM_PAINT消息的响应,并添加画图的代码:
void CTestWnd::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CWnd::OnPaint()
CRect rect;
GetClientRect(rect);
dc.FillSolidRect(rect, RGB(255, 0, 200));
rect.DeflateRect(10, 10);
dc.Rectangle(rect);
dc.MoveTo(rect.TopLeft());
dc.LineTo(rect.BottomRight());
dc.MoveTo(rect.left, rect.bottom);
dc.LineTo(rect.right, rect.top);
}
3.添加创建窗口函数
BOOL CreateTestWnd(HWND hWnd, int x, int y, int w, int h)
{
CTestWnd* pWnd = new CTestWnd();
return pWnd->Create(NULL, _T("自建窗口"), WS_VISIBLE | WS_CHILD, CRect(x,y,x+w,y+h), CWnd::FromHandle(hWnd), 1234);
}
4.导出函数,在def文件中加入CreateTestWnd导出声明
; MFCLibrary1.def : 声明 DLL 的模块参数。
LIBRARY
EXPORTS
; 此处可以是显式导出
CreateTestWnd
5.编译
二、测试DLL
1.建立一个VC的对话框工程,添加对MFCLibrary1.lib的引用,在对话的OnInitDialog()函数中添加:
CRect rect;
GetClientRect(rect);
rect.DeflateRect(10, 20);
BOOL CreateTestWnd(HWND hWnd, int x, int y, int w, int h);
CreateTestWnd(this->m_hWnd, rect.left, rect.top, rect.Width(), rect.Height());
2.测试运行效果:
Dll中的窗口可以正常显示
三、在C#的WinForm中显示
1.建立C#的工程,建立一个WinForm窗口。
2.复制MFCLibrary1.dll到C#工程的bin\Debug下
3.添加C#调用VC函数的声明
[DllImport("MFCLibrary1.dll", EntryPoint = "CreateTestWnd", CallingConvention = CallingConvention.Cdecl)]
public static extern int CreateTestWnd(IntPtr hWnd, int x, int y, int w, int h);
4.修改WinForm窗口代码:
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form5 : Form
{
[DllImport("MFCLibrary1.dll", EntryPoint = "CreateTestWnd", CallingConvention = CallingConvention.Cdecl)]
public static extern int CreateTestWnd(IntPtr hWnd, int x, int y, int w, int h);
public Form5()
{
InitializeComponent();
}
private void Form5_Load(object sender, EventArgs e)
{
IntPtr hwnd = this.Handle;
CreateTestWnd(hwnd, 10, 10, this.ClientSize.Width - 20, this.ClientSize.Height - 20);
}
}
}
5.运行效果:
VC程序的窗口在C#中成功调用。
Debug下,创建VC窗口时,会弹出两个Assert窗口,关闭即可,不影响运行。
四、Windows窗口创建问题总结
1.Windows的窗口不依赖于特定的程序,其资源有系统统一管理。
2.新的窗口需要通过父窗口句柄(handle)来控制应该显示在什么地方。