C语言集锦(三)Direct3D和GDI+的例子
0.前言
有些时候你可能想了解,如何用纯C语言来写Direct3D和GDI+的Demo。注意,下面的Direct3D例子不适用于TCC编译器,GDI+的例子是可以的。
1.Direct3D C语言的例子
几乎所有的D3D例子都是用COM和C++写的。C语言可以用D3D吗,StackOverflow上给出了答案:directx-programming-in-c。
1 hr = IDirect3D9_GetDeviceCaps(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps9); 2 hr = IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm); 3 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, game_window, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &d3dpp, &d3d_dev);
按照这种格式,可以用C语言写出Direct3D的Demo:
1 #include<d3d9.h> 2 3 #pragma comment(lib, "d3d9.lib") 4 5 #define WINDOW_CLASS "UGPDX" 6 #define WINDOW_NAME "Drawing Lines" 7 8 // Function Prototypes... 9 BOOL InitializeD3D(HWND hWnd, BOOL fullscreen); 10 BOOL InitializeObjects(); 11 void RenderScene(); 12 void Shutdown(); 13 14 15 // Direct3D object and device. 16 LPDIRECT3D9 g_D3D = NULL; 17 LPDIRECT3DDEVICE9 g_D3DDevice = NULL; 18 19 // Vertex buffer to hold the geometry. 20 LPDIRECT3DVERTEXBUFFER9 g_VertexBuffer = NULL; 21 22 23 // A structure for our custom vertex type 24 typedef struct 25 { 26 float x, y, z, rhw; 27 unsigned long color; 28 }stD3DVertex; 29 30 // Our custom FVF, which describes our custom vertex structure. 31 #define D3DFVF_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) 32 33 34 LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) 35 { 36 switch (msg) 37 { 38 case WM_DESTROY: 39 PostQuitMessage(0); 40 return 0; 41 break; 42 43 case WM_KEYUP: 44 if (wp == VK_ESCAPE) PostQuitMessage(0); 45 break; 46 } 47 48 return DefWindowProc(hWnd, msg, wp, lp); 49 } 50 51 52 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prevhInst, 53 LPSTR cmdLine, int show) 54 { 55 // Register the window class 56 WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 57 0, 0, GetModuleHandle(NULL), NULL, LoadCursor(NULL,IDC_ARROW), 58 NULL, NULL, WINDOW_CLASS, NULL }; 59 RegisterClassEx(&wc); 60 61 // Create the application's window 62 HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME, 63 WS_OVERLAPPEDWINDOW, 100, 100, 64 640, 480, GetDesktopWindow(), NULL, 65 wc.hInstance, NULL); 66 67 // Initialize Direct3D 68 if (InitializeD3D(hWnd, FALSE)) 69 { 70 // Show the window 71 ShowWindow(hWnd, SW_SHOWDEFAULT); 72 UpdateWindow(hWnd); 73 74 // Enter the message loop 75 MSG msg; 76 ZeroMemory(&msg, sizeof(msg)); 77 78 while (msg.message != WM_QUIT) 79 { 80 if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) 81 { 82 TranslateMessage(&msg); 83 DispatchMessage(&msg); 84 } 85 else 86 RenderScene(); 87 } 88 } 89 90 // Release any and all resources. 91 Shutdown(); 92 93 // Unregister our window. 94 UnregisterClass(WINDOW_CLASS, wc.hInstance); 95 return 0; 96 } 97 98 99 BOOL InitializeD3D(HWND hWnd, BOOL fullscreen) 100 { 101 D3DDISPLAYMODE displayMode; 102 103 // Create the D3D object. 104 g_D3D = Direct3DCreate9(D3D_SDK_VERSION); 105 if (g_D3D == NULL) return FALSE; 106 107 108 // Get the desktop display mode. 109 if (FAILED(IDirect3D9_GetAdapterDisplayMode(g_D3D,D3DADAPTER_DEFAULT, 110 &displayMode))) return FALSE; 111 112 113 // Set up the structure used to create the D3DDevice 114 D3DPRESENT_PARAMETERS d3dpp; 115 ZeroMemory(&d3dpp, sizeof(d3dpp)); 116 117 118 if (fullscreen) 119 { 120 d3dpp.Windowed = FALSE; 121 d3dpp.BackBufferWidth = 640; 122 d3dpp.BackBufferHeight = 480; 123 } 124 else 125 d3dpp.Windowed = TRUE; 126 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 127 d3dpp.BackBufferFormat = displayMode.Format; 128 129 130 // Create the D3DDevice 131 if (FAILED(IDirect3D9_CreateDevice(g_D3D,D3DADAPTER_DEFAULT, 132 D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, 133 &d3dpp, &g_D3DDevice))) return FALSE; 134 135 136 // Initialize any objects we will be displaying. 137 if (!InitializeObjects()) return FALSE; 138 139 return TRUE; 140 } 141 142 143 BOOL InitializeObjects() 144 { 145 unsigned long col = D3DCOLOR_XRGB(255, 255, 255); 146 147 // Fill in our structure to draw an object. 148 // x, y, z, rhw, color. 149 stD3DVertex objData[] = 150 { 151 { 420.0f, 150.0f, 0.5f, 1.0f, col, }, 152 { 420.0f, 350.0f, 0.5f, 1.0f, col, }, 153 { 220.0f, 150.0f, 0.5f, 1.0f, col, }, 154 { 220.0f, 350.0f, 0.5f, 1.0f, col, }, 155 }; 156 157 // Create the vertex buffer. 158 if (FAILED(IDirect3DDevice9_CreateVertexBuffer(g_D3DDevice,sizeof(objData), 0, 159 D3DFVF_VERTEX, D3DPOOL_DEFAULT, &g_VertexBuffer, 160 NULL))) return FALSE; 161 162 // Fill the vertex buffer. 163 void *ptr; 164 165 if (FAILED(IDirect3DVertexBuffer9_Lock(g_VertexBuffer,0, sizeof(objData), 166 (void**)&ptr, 0))) return FALSE; 167 168 memcpy(ptr, objData, sizeof(objData)); 169 170 171 IDirect3DVertexBuffer9_Unlock(g_VertexBuffer); 172 173 return TRUE; 174 } 175 176 177 void RenderScene() 178 { 179 // Clear the backbuffer. 180 IDirect3DDevice9_Clear(g_D3DDevice,0, NULL, D3DCLEAR_TARGET, 181 D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); 182 183 // Begin the scene. Start rendering. 184 IDirect3DDevice9_BeginScene(g_D3DDevice); 185 186 // Render object. 187 IDirect3DDevice9_SetStreamSource(g_D3DDevice,0, g_VertexBuffer, 0, 188 sizeof(stD3DVertex)); 189 IDirect3DDevice9_SetFVF(g_D3DDevice,D3DFVF_VERTEX); 190 IDirect3DDevice9_DrawPrimitive(g_D3DDevice,D3DPT_LINELIST, 0, 2); 191 192 // End the scene. Stop rendering. 193 IDirect3DDevice9_EndScene(g_D3DDevice); 194 195 // Display the scene. 196 IDirect3DDevice9_Present(g_D3DDevice,NULL, NULL, NULL, NULL); 197 } 198 199 void Shutdown() 200 { 201 if (g_D3DDevice != NULL) IDirect3DDevice9_Release(g_D3DDevice); 202 if (g_D3D != NULL) IDirect3D9_Release(g_D3D); 203 if (g_VertexBuffer != NULL) IDirect3DVertexBuffer9_Release(g_VertexBuffer); 204 205 g_D3DDevice = NULL; 206 g_D3D = NULL; 207 g_VertexBuffer = NULL; 208 }
这里只是画了两条平行的线段,作为一个例子:
2.GDI+ C语言的例子
参考来源:http://blog.csdn.net/zuishikonghuan/article/details/47251225
直接使用gdiplus的头文件,编译会报错。虽然gdiplus.dll本身是用C语言写的,但是官方只提供了C++的友好的接口,函数比较少的话,可以自己做函数声明,避免编译错误。
1 //tcc -run gdiplus.c 2 #include <windows.h> 3 #pragma comment(lib,"gdiplus") 4 5 //GDI+Flat 6 typedef struct _GdiplusStartupInput 7 { 8 unsigned int GdiplusVersion; 9 unsigned int DebugEventCallback; 10 BOOL SuppressBackgroundThread; 11 BOOL SuppressExternalCodecs; 12 }GdiplusStartupInput; 13 14 15 int WINAPI GdiplusStartup(int* token, GdiplusStartupInput *input, int *output); 16 void WINAPI GdiplusShutdown(int token); 17 int WINAPI GdipCreateFromHDC(HDC hdc, int* graphics); 18 int WINAPI GdipDeleteGraphics(int graphics); 19 //画笔 20 int WINAPI GdipCreatePen1(unsigned int argb_color, float width, int unit, int** pen); 21 int WINAPI GdipDeletePen(int* pen); 22 int WINAPI GdipDrawRectangle(int graphics, int* pen, float x, float y, float width, float height); 23 int WINAPI GdipDrawLine(int graphics, int* pen, float x1, float y1, float x2, float y2); 24 25 int token; 26 int* pen; 27 28 //************************************************************* 29 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 30 31 WNDCLASS wc; 32 const TCHAR* AppName = TEXT("MyWindowClass1"); 33 HWND hwnd1; 34 35 int APIENTRY WinMain(HINSTANCE hInstance, 36 HINSTANCE hPrevInstance, 37 LPTSTR lpCmdLine, 38 int nCmdShow) 39 { 40 //GDI+开启 41 GdiplusStartupInput StartupInput = { 0 }; 42 StartupInput.GdiplusVersion = 1; 43 if (GdiplusStartup(&token, &StartupInput, NULL))MessageBox(0, TEXT("GdiPlus开启失败"), TEXT("错误"), MB_ICONERROR); 44 45 //这里是在构建窗口类结构 46 wc.style = CS_HREDRAW | CS_VREDRAW; 47 wc.lpfnWndProc = WndProc;//窗口回调函数指针 48 wc.cbClsExtra = 0; 49 wc.cbWndExtra = 0; 50 wc.hInstance = hInstance;//实例句柄 51 wc.hIcon = LoadIcon(hInstance, TEXT("ICON_1")); 52 wc.hCursor = LoadCursor(NULL, IDC_ARROW);//默认指针 53 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);//默认背景颜色 54 wc.lpszMenuName = NULL; 55 wc.lpszClassName = AppName;//窗口类名 56 57 //注册窗口类 58 if (!RegisterClass(&wc)) 59 { 60 MessageBox(NULL, TEXT("注册窗口类失败!"), TEXT("错误"), MB_ICONERROR); 61 return 0; 62 } 63 64 //创建窗口 65 int style = WS_OVERLAPPEDWINDOW; 66 hwnd1 = CreateWindow(AppName, TEXT("窗口标题"), style, 50, 50, 500, 500, 0,NULL, hInstance, 0); 67 if (hwnd1 == NULL) 68 { 69 MessageBox(NULL, TEXT("创建窗口失败!"), TEXT("错误"), MB_ICONERROR); 70 return 0; 71 } 72 //无边框窗口 73 /*SetWindowLong(hwnd1, GWL_STYLE, WS_OVERLAPPED | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);*/ 74 75 //显示、更新窗口 76 ShowWindow(hwnd1, nCmdShow); 77 UpdateWindow(hwnd1); 78 79 //消息循环 80 MSG msg; 81 while (GetMessage(&msg, NULL, 0, 0)) 82 { 83 TranslateMessage(&msg); 84 DispatchMessage(&msg); 85 } 86 87 //GDI+关闭 88 GdiplusShutdown(token);//可以把这个写在消息循环后面,程序退出就销毁,或者在不需要GDI+时调用,比如GDI+窗口的WM_DESTROY消息里调用 89 return msg.wParam; 90 } 91 92 LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 93 { 94 HDC hdc; 95 PAINTSTRUCT ps; 96 switch (uMsg) 97 { 98 99 case WM_PAINT: 100 101 102 hdc = BeginPaint(hwnd, &ps); 103 104 int graphics; 105 GdipCreateFromHDC(hdc, &graphics);//创建Graphics对象 106 GdipCreatePen1(0x60FF2015, 1, 2, &pen);//创建画笔 107 GdipDrawRectangle(graphics, pen, 20, 20, 120, 120);//画矩形 108 GdipDrawLine(graphics, pen, 50, 60, 170, 340);//画直线 109 110 GdipDeletePen(pen);//销毁画笔 111 GdipDeleteGraphics(graphics);//销毁Graphics对象 112 113 EndPaint(hwnd, &ps); 114 return 0;//告诉系统,WM_PAINT消息我已经处理了,你那儿凉快哪儿玩去吧。 115 case WM_CREATE: 116 break; 117 case WM_DESTROY://窗口已经销毁 118 PostQuitMessage(0);//退出消息循环,结束应用程序 119 return 0; 120 break; 121 case WM_LBUTTONDOWN://鼠标左键按下 122 //让无边框窗口能够拖动(在窗口客户区拖动) 123 PostMessage(hwnd, WM_SYSCOMMAND, 61458, 0); 124 break; 125 /*case WM_MOUSEMOVE://鼠标移动 126 int xPos, yPos; 127 xPos = GET_X_LPARAM(lParam);//鼠标位置X坐标 128 yPos = GET_Y_LPARAM(lParam);//鼠标位置Y坐标 129 //不要用LOWORD和HIWORD获取坐标,因为坐标有可能是负的 130 break;*/ 131 default: 132 break; 133 } 134 return DefWindowProc(hwnd, uMsg, wParam, lParam);//其他消息交给系统处理 135 }