混合語言編程—C#使用原生的Directx和OpenGL繪圖的方法
由于項(xiàng)目需要做一些圖形展示,所以就想到了使用Directx和OpenGL來繪圖,但項(xiàng)目準(zhǔn)備使用C#來開發(fā)(大家比較熟悉C#),在網(wǎng)上看了相關(guān)的資料,有一些第三方的控件可用,試用了下,一運(yùn)行就占了幾百M(fèi)的內(nèi)存,而且也不知道是否穩(wěn)定,教程也少,還不如直接使用原生的。在網(wǎng)上看的Directx和OpenGL的教程基本上都是C/C++的,找了很久也就找到相關(guān)介紹,只能自己研究下。
我以前做過C#和C++混合語言編程相關(guān)的東西,在C++實(shí)現(xiàn)一些C#不好實(shí)現(xiàn)的功能,C#動(dòng)態(tài)調(diào)用DLL文件,所以也想到了用C++的代碼來控制Winform控件的繪畫,這樣就可實(shí)現(xiàn)用Direct和OpenGL在Winform的控件上繪畫了。
由于我對(duì)Direct和OpenGL都不熟悉,沒有這方面的編程經(jīng)驗(yàn),只能去瞎折騰,下面分別說說最近在Directx和OpenGL怎么試驗(yàn)的。
Directx:
之前沒學(xué)過Directx,拿了同學(xué)的代碼來看,也是霧里看花啊,不過有一點(diǎn)啟示了我,在初始化的時(shí)候,要傳入一個(gè)句柄去創(chuàng)建設(shè)備(CreateDevice),通常都是傳入窗口的設(shè)備,我想如果傳入一個(gè)控件的句柄,那所有的繪畫都將在這個(gè)控件上實(shí)現(xiàn),因?yàn)榭丶彩抢^承自Window的。而Winform的控件在底層的實(shí)現(xiàn)應(yīng)該和WIN32是一樣的。這樣的話只要把Winform的控件的句柄傳入C++代碼進(jìn)行初始化,那么繪畫的結(jié)果將顯示在這個(gè)控件上。結(jié)果一試,還真行。關(guān)鍵代碼如下:
extern "C" _declspec(dllexport) HRESULT InitD3D( HWND hWnd );
extern "C" _declspec(dllexport) VOID Render();
在InitD3D傳入控件的句柄進(jìn)行初始化,C#再調(diào)用Render進(jìn)行繪畫,以下是C#代碼:
HWND handle = this.button1.Handle;
InitD3D(handle);
private void Draw()
{
for (; ; )
{
Render();
}
}
效果圖:
OpenGL:
查看了OpenGL的相關(guān)教程(推薦http://www.yakergong.net/nehe/),OpenGL是通過RC來執(zhí)行的,創(chuàng)建RC時(shí)就必須指定一個(gè)DC,還要設(shè)置DC的像素格式。每個(gè)線程有且只能擁有一個(gè)RC。
如果在初始化OpenGL的繪畫環(huán)境時(shí)傳入一個(gè)Winform的控件句柄,再通過這個(gè)句柄取到HDC,就可使用這個(gè)HDC來創(chuàng)建RC,這樣OpenGL的繪畫環(huán)境就準(zhǔn)備好了,并且這個(gè)RC關(guān)聯(lián)到Winform的控件上。
在給制前,先為當(dāng)前線程選擇RC(之前通過HDC創(chuàng)建的),再進(jìn)行繪制,這樣繪制的結(jié)果將顯示在這個(gè)Winform控件上。
關(guān)鍵代碼如下:
C++:
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);
}
C#:
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的控件沒有句柄,但是可以換個(gè)思路,把繪畫代碼封裝在Winform控件上,在WPF使用自定義的Winform控件。
相關(guān)文章
C#將DataGridView中的數(shù)據(jù)保存到CSV和Excel中
這篇文章介紹了C#將DataGridView中的數(shù)據(jù)保存到CSV和Excel中的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04C#實(shí)現(xiàn)將32位MD5摘要串轉(zhuǎn)換為128位二進(jìn)制字符串的方法
這篇文章主要介紹了C#實(shí)現(xiàn)將32位MD5摘要串轉(zhuǎn)換為128位二進(jìn)制字符串的方法,涉及C#字符串遍歷、加密與轉(zhuǎn)換相關(guān)操作技巧,需要的朋友可以參考下2017-04-04C# AE之返回上一級(jí)和下一級(jí)的實(shí)戰(zhàn)操作
這篇文章主要介紹了C# AE之返回上一級(jí)和下一級(jí)的實(shí)戰(zhàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01Unity Shader實(shí)現(xiàn)徑向模糊效果
這篇文章主要為大家詳細(xì)介紹了Unity Shader實(shí)現(xiàn)徑向模糊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08C#實(shí)現(xiàn)學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08