混合語言編程:C#使用原生的Directx和OpenGL


本文要說的是混合C#和C/C++語言編程,在C#的Winform和WPF下使用原生的Direct和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) HRESULT InitD3D( HWND hWnd );

extern "C" _declspec(dllexport) VOID Render();

在InitD3D傳入控件的句柄進行初始化,C#再調用Render進行繪畫,以下是C#代碼:

HWND handle = this.button1.Handle;
InitD3D(handle);
private void Draw()
  {
         for (; ; )
            {
                Render();
            }
        }

效果圖:

Directx

OpenGL:

查看了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;

OpenGL

WPF:WPF的控件沒有句柄,但是可以換個思路,把繪畫代碼封裝在Winform控件上,在WPF使用自定義的Winform控件。

WPF

原文鏈接: http://zh.5long.me/2014/cs-C-directx-openGL/
版權聲明:自由轉載-非商用-保持署名 | Creative Commons BY-NC 4.0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM