本文要說的是混合C#和C/C++語言編程,在C#的Winform和WPF下使用原生的Direct和OpenGL進行繪圖。c++
因爲項目須要作一些圖形展現,因此就想到了使用Directx和OpenGL來繪圖,但項目準備使用C#來開發(你們比較熟悉C#),在網上看了相關的資料,有一些第三方的控件可用,試用了下,一運行就佔了幾百M的內存,並且編程
也不知道是否穩定,教程也少,還不如直接使用原生的。在網上看的Directx和OpenGL的教程基本上都是C/C++的,找了好久也就找到相關介紹,只能本身研究下。c#
我之前作過C#和C++混合語言編程相關的東西,在C++實現一些C#很差實現的功能,C#動態調用DLL文件,因此也想到了用C++的代碼來控制Winform控件的繪畫,這樣就可實現用Direct和OpenGL在Winform的控件上繪畫了。post
因爲我對Direct和OpenGL都不熟悉,沒有這方面的編程經驗,只能去瞎折騰,下面分別說說最近在Directx和OpenGL怎麼試驗的。this
Directx:.net
以前沒學過Directx,拿了同窗的代碼來看,也是霧裏看花啊,不過有一點啓示了我,在初始化的時候,要傳入一個句柄去建立設備(CreateDevice),一般都是傳入窗口的設備,我想若是傳入一個控件的句柄,那全部的繪畫都將在這個控件上實現,由於控件也是繼承自Window的。而Winform的控件在底層的實現應該和WIN32是同樣的。這樣的話只要把Winform的控件的句柄傳入C++代碼進行初始化,那麼繪畫的結果將顯示在這個控件上。結果一試,還真行。關鍵代碼以下:線程
extern "C" _declspec(dllexport) HRESULT InitD3D( HWND hWnd ); extern "C" _declspec(dllexport) VOID Render();
在InitD3D傳入控件的句柄進行初始化,C#再調用Render進行繪畫,如下是C#代碼:code
HWND handle = this.button1.Handle; InitD3D(handle); private void Draw() { for (; ; ) { Render(); } }
效果圖:orm
OpenGL:blog
查看了OpenGL的相關教程(推薦http://www.yakergong.net/nehe/),OpenGL是經過RC來執行的,建立RC時就必須指定一個DC,還要設置DC的像素格式。每一個線程有且只能擁有一個RC。
若是在初始化OpenGL的繪畫環境時傳入一個Winform的控件句柄,再經過這個句柄取到HDC,就可以使用這個HDC來建立RC,這樣OpenGL的繪畫環境就準備好了,而且這個RC關聯到Winform的控件上。
在給制前,先爲當前線程選擇RC(以前經過HDC建立的),再進行繪製,這樣繪製的結果將顯示在這個Winform控件上。
關鍵代碼以下:
extern "C" _declspec(dllexport) void Init( HWND hWnd); extern "C" _declspec(dllexport) void Render(); void Init(HWND hWnd) { int PixelFormat; int bits = 16; hDC = GetDC(hWnd); static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER, // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format bits, // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, // No Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; PixelFormat=ChoosePixelFormat(hDC,&pfd); SetPixelFormat(hDC,PixelFormat,&pfd); hRC=wglCreateContext(hDC); } void Render() { wglMakeCurrent(hDC, hRC); draw(); SwapBuffers(hDC); wglMakeCurrent(NULL, NULL); }
Init(this.pictureBox1.Handle); //開始繪製 var timer = new System.Timers.Timer(); timer.Interval = 100; timer.Elapsed += (tsender, te) => { Render(); }; timer.AutoReset = true; timer.Enabled = true;
WPF:WPF的控件沒有句柄,可是能夠換個思路,把繪畫代碼封裝在Winform控件上,在WPF使用自定義的Winform控件。
原文連接: http://zh.5long.me/2014/cs-C-directx-openGL/
版權聲明:自由轉載-非商用-保持署名 | Creative Commons BY-NC 4.0