混合语言编程—C#使用原生的Directx和OpenGL绘图的方法
由于项目需要做一些图形展示,所以就想到了使用Directx和OpenGL来绘图,但项目准备使用C#来开发(大家比较熟悉C#),在网上看了相关的资料,有一些第三方的控件可用,试用了下,一运行就占了几百M的内存,而且也不知道是否稳定,教程也少,还不如直接使用原生的。在网上看的Directx和OpenGL的教程基本上都是C/C++的,找了很久也就找到相关介绍,只能自己研究下。
我以前做过C#和C++混合语言编程相关的东西,在C++实现一些C#不好实现的功能,C#动态调用DLL文件,所以也想到了用C++的代码来控制Winform控件的绘画,这样就可实现用Direct和OpenGL在Winform的控件上绘画了。
由于我对Direct和OpenGL都不熟悉,没有这方面的编程经验,只能去瞎折腾,下面分别说说最近在Directx和OpenGL怎么试验的。
Directx:
之前没学过Directx,拿了同学的代码来看,也是雾里看花啊,不过有一点启示了我,在初始化的时候,要传入一个句柄去创建设备(CreateDevice),通常都是传入窗口的设备,我想如果传入一个控件的句柄,那所有的绘画都将在这个控件上实现,因为控件也是继承自Window的。而Winform的控件在底层的实现应该和WIN32是一样的。这样的话只要把Winform的控件的句柄传入C++代码进行初始化,那么绘画的结果将显示在这个控件上。结果一试,还真行。关键代码如下:
extern"C"_declspec(dllexport)HRESULTInitD3D(HWNDhWnd);
extern"C"_declspec(dllexport)VOIDRender();
在InitD3D传入控件的句柄进行初始化,C#再调用Render进行绘画,以下是C#代码:
HWNDhandle=this.button1.Handle;
InitD3D(handle);
privatevoidDraw()
{
for(;;)
{
Render();
}
}
效果图:
OpenGL:
查看了OpenGL的相关教程(推荐http://www.yakergong.net/nehe/),OpenGL是通过RC来执行的,创建RC时就必须指定一个DC,还要设置DC的像素格式。每个线程有且只能拥有一个RC。
如果在初始化OpenGL的绘画环境时传入一个Winform的控件句柄,再通过这个句柄取到HDC,就可使用这个HDC来创建RC,这样OpenGL的绘画环境就准备好了,并且这个RC关联到Winform的控件上。
在给制前,先为当前线程选择RC(之前通过HDC创建的),再进行绘制,这样绘制的结果将显示在这个Winform控件上。
关键代码如下:
C++:
extern"C"_declspec(dllexport)voidInit(HWNDhWnd);
extern"C"_declspec(dllexport)voidRender();
voidInit(HWNDhWnd)
{
intPixelFormat;
intbits=16;
hDC=GetDC(hWnd);
static PIXELFORMATDESCRIPTORpfd= //pfdTellsWindowsHowWeWantThingsToBe
{
sizeof(PIXELFORMATDESCRIPTOR), //SizeOfThisPixelFormatDescriptor
1, //VersionNumber
PFD_DRAW_TO_WINDOW| //FormatMustSupportWindow
PFD_SUPPORT_OPENGL| //FormatMustSupportOpenGL
PFD_DOUBLEBUFFER, //MustSupportDoubleBuffering
PFD_TYPE_RGBA, //RequestAnRGBAFormat
bits, //SelectOurColorDepth
0,0,0,0,0,0, //ColorBitsIgnored
0, //NoAlphaBuffer
0, //ShiftBitIgnored
0, //NoAccumulationBuffer
0,0,0,0, //AccumulationBitsIgnored
16, //16BitZ-Buffer(DepthBuffer)
0, //NoStencilBuffer
0, //NoAuxiliaryBuffer
PFD_MAIN_PLANE, //MainDrawingLayer
0, //Reserved
0,0,0 //LayerMasksIgnored
};
PixelFormat=ChoosePixelFormat(hDC,&pfd);
SetPixelFormat(hDC,PixelFormat,&pfd);
hRC=wglCreateContext(hDC);
}
voidRender()
{
wglMakeCurrent(hDC,hRC);
draw();
SwapBuffers(hDC);
wglMakeCurrent(NULL,NULL);
}
C#:
Init(this.pictureBox1.Handle);
//开始绘制
vartimer=newSystem.Timers.Timer();
timer.Interval=100;
timer.Elapsed+=(tsender,te)=>
{
Render();
};
timer.AutoReset=true;
timer.Enabled=true;
效果图:
WPF:WPF的控件没有句柄,但是可以换个思路,把绘画代码封装在Winform控件上,在WPF使用自定义的Winform控件。
相关文章
- C#的WinForm窗体程序中如何设置TextBox为密码文本框
- c# mysql executenonquery_C#与数据库访问技术总结(八)之ExecuteNonQuery方法
- C# md5 算法实现代码的案例分享
- C# json 传参发送 post 请求例子
- c#打包发布时出现错误的解决方法总结详解编程语言
- C助力MySQL源代码分析(c# mysql 源代码)
- C#OWC生成图表
- C#中让控件全屏显示的实现代码(WinForm)
- C#数据导入/导出Excel文件及winForm导出Execl总结
- C#将字节流转换为图片的实例方法
- c#冒泡排序算法(BubbleSort)附实例代码
- c#文件操作示例带详细注释
- C#随机生成不重复字符串的两个不错方法
- C#中使用ADOMD.NET查询多维数据集的实现方法
- C#中float的取值范围和精度分析
- C#动态执行批处理命令的方法
- C#使用smtp发送带附件的邮件实现方法
- C#中的IEnumerable接口深入研究
- 初步认识C#中的Lambda表达式和匿名方法
- C#实现一键换IP、重置DNS、网关及掩码的方法
- C#运用FileInfo类实现拷贝文件的方法
- C#实现绘制面形图表的方法详解
- C#实现移除字符串末尾指定字符的方法
- C#实现洗牌游戏实例
- C#实现根据指定容器和控件名字获得控件的方法
- C#实现中英文混合字符串截取的方法
- C#简单多线程同步和优先权用法实例
- C#实现下载网页HTML源码的方法