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 }

  

原文地址:https://www.cnblogs.com/wurui1994/p/6785036.html