C语言集锦(三)Direct3D和GDI+的例子
0.前言
有些时候你可能想了解,如何用纯C语言来写Direct3D和GDI+的Demo。注意,下面的Direct3D例子不适用于TCC编译器,GDI+的例子是可以的。
1.Direct3D C语言的例子
几乎所有的D3D例子都是用COM和C++写的。C语言可以用D3D吗,StackOverflow上给出了答案:directx-programming-in-c。
hr = IDirect3D9_GetDeviceCaps(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps9);
hr = IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, game_window, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &d3dpp, &d3d_dev);
按照这种格式,可以用C语言写出Direct3D的Demo:
#include<d3d9.h> #pragma comment(lib, "d3d9.lib") #define WINDOW_CLASS "UGPDX"
#define WINDOW_NAME "Drawing Lines" // Function Prototypes...
BOOL InitializeD3D(HWND hWnd, BOOL fullscreen);
BOOL InitializeObjects();
void RenderScene();
void Shutdown(); // Direct3D object and device.
LPDIRECT3D9 g_D3D = NULL;
LPDIRECT3DDEVICE9 g_D3DDevice = NULL; // Vertex buffer to hold the geometry.
LPDIRECT3DVERTEXBUFFER9 g_VertexBuffer = NULL; // A structure for our custom vertex type
typedef struct
{
float x, y, z, rhw;
unsigned long color;
}stD3DVertex; // Our custom FVF, which describes our custom vertex structure.
#define D3DFVF_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage();
return ;
break; case WM_KEYUP:
if (wp == VK_ESCAPE) PostQuitMessage();
break;
} return DefWindowProc(hWnd, msg, wp, lp);
} int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prevhInst,
LPSTR cmdLine, int show)
{
// Register the window class
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc,
, , GetModuleHandle(NULL), NULL, LoadCursor(NULL,IDC_ARROW),
NULL, NULL, WINDOW_CLASS, NULL };
RegisterClassEx(&wc); // Create the application's window
HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME,
WS_OVERLAPPEDWINDOW, , ,
, , GetDesktopWindow(), NULL,
wc.hInstance, NULL); // Initialize Direct3D
if (InitializeD3D(hWnd, FALSE))
{
// Show the window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd); // Enter the message loop
MSG msg;
ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
RenderScene();
}
} // Release any and all resources.
Shutdown(); // Unregister our window.
UnregisterClass(WINDOW_CLASS, wc.hInstance);
return ;
} BOOL InitializeD3D(HWND hWnd, BOOL fullscreen)
{
D3DDISPLAYMODE displayMode; // Create the D3D object.
g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
if (g_D3D == NULL) return FALSE; // Get the desktop display mode.
if (FAILED(IDirect3D9_GetAdapterDisplayMode(g_D3D,D3DADAPTER_DEFAULT,
&displayMode))) return FALSE; // Set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp)); if (fullscreen)
{
d3dpp.Windowed = FALSE;
d3dpp.BackBufferWidth = ;
d3dpp.BackBufferHeight = ;
}
else
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = displayMode.Format; // Create the D3DDevice
if (FAILED(IDirect3D9_CreateDevice(g_D3D,D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp, &g_D3DDevice))) return FALSE; // Initialize any objects we will be displaying.
if (!InitializeObjects()) return FALSE; return TRUE;
} BOOL InitializeObjects()
{
unsigned long col = D3DCOLOR_XRGB(, , ); // Fill in our structure to draw an object.
// x, y, z, rhw, color.
stD3DVertex objData[] =
{
{ 420.0f, 150.0f, 0.5f, 1.0f, col, },
{ 420.0f, 350.0f, 0.5f, 1.0f, col, },
{ 220.0f, 150.0f, 0.5f, 1.0f, col, },
{ 220.0f, 350.0f, 0.5f, 1.0f, col, },
}; // Create the vertex buffer.
if (FAILED(IDirect3DDevice9_CreateVertexBuffer(g_D3DDevice,sizeof(objData), ,
D3DFVF_VERTEX, D3DPOOL_DEFAULT, &g_VertexBuffer,
NULL))) return FALSE; // Fill the vertex buffer.
void *ptr; if (FAILED(IDirect3DVertexBuffer9_Lock(g_VertexBuffer,, sizeof(objData),
(void**)&ptr, ))) return FALSE; memcpy(ptr, objData, sizeof(objData)); IDirect3DVertexBuffer9_Unlock(g_VertexBuffer); return TRUE;
} void RenderScene()
{
// Clear the backbuffer.
IDirect3DDevice9_Clear(g_D3DDevice,, NULL, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(, , ), 1.0f, ); // Begin the scene. Start rendering.
IDirect3DDevice9_BeginScene(g_D3DDevice); // Render object.
IDirect3DDevice9_SetStreamSource(g_D3DDevice,, g_VertexBuffer, ,
sizeof(stD3DVertex));
IDirect3DDevice9_SetFVF(g_D3DDevice,D3DFVF_VERTEX);
IDirect3DDevice9_DrawPrimitive(g_D3DDevice,D3DPT_LINELIST, , ); // End the scene. Stop rendering.
IDirect3DDevice9_EndScene(g_D3DDevice); // Display the scene.
IDirect3DDevice9_Present(g_D3DDevice,NULL, NULL, NULL, NULL);
} void Shutdown()
{
if (g_D3DDevice != NULL) IDirect3DDevice9_Release(g_D3DDevice);
if (g_D3D != NULL) IDirect3D9_Release(g_D3D);
if (g_VertexBuffer != NULL) IDirect3DVertexBuffer9_Release(g_VertexBuffer); g_D3DDevice = NULL;
g_D3D = NULL;
g_VertexBuffer = NULL;
}
这里只是画了两条平行的线段,作为一个例子:
2.GDI+ C语言的例子
参考来源:http://blog.csdn.net/zuishikonghuan/article/details/47251225
直接使用gdiplus的头文件,编译会报错。虽然gdiplus.dll本身是用C语言写的,但是官方只提供了C++的友好的接口,函数比较少的话,可以自己做函数声明,避免编译错误。
//tcc -run gdiplus.c
#include <windows.h>
#pragma comment(lib,"gdiplus") //GDI+Flat
typedef struct _GdiplusStartupInput
{
unsigned int GdiplusVersion;
unsigned int DebugEventCallback;
BOOL SuppressBackgroundThread;
BOOL SuppressExternalCodecs;
}GdiplusStartupInput; int WINAPI GdiplusStartup(int* token, GdiplusStartupInput *input, int *output);
void WINAPI GdiplusShutdown(int token);
int WINAPI GdipCreateFromHDC(HDC hdc, int* graphics);
int WINAPI GdipDeleteGraphics(int graphics);
//画笔
int WINAPI GdipCreatePen1(unsigned int argb_color, float width, int unit, int** pen);
int WINAPI GdipDeletePen(int* pen);
int WINAPI GdipDrawRectangle(int graphics, int* pen, float x, float y, float width, float height);
int WINAPI GdipDrawLine(int graphics, int* pen, float x1, float y1, float x2, float y2); int token;
int* pen; //*************************************************************
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); WNDCLASS wc;
const TCHAR* AppName = TEXT("MyWindowClass1");
HWND hwnd1; int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
//GDI+开启
GdiplusStartupInput StartupInput = { };
StartupInput.GdiplusVersion = ;
if (GdiplusStartup(&token, &StartupInput, NULL))MessageBox(, TEXT("GdiPlus开启失败"), TEXT("错误"), MB_ICONERROR); //这里是在构建窗口类结构
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;//窗口回调函数指针
wc.cbClsExtra = ;
wc.cbWndExtra = ;
wc.hInstance = hInstance;//实例句柄
wc.hIcon = LoadIcon(hInstance, TEXT("ICON_1"));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);//默认指针
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);//默认背景颜色
wc.lpszMenuName = NULL;
wc.lpszClassName = AppName;//窗口类名 //注册窗口类
if (!RegisterClass(&wc))
{
MessageBox(NULL, TEXT("注册窗口类失败!"), TEXT("错误"), MB_ICONERROR);
return ;
} //创建窗口
int style = WS_OVERLAPPEDWINDOW;
hwnd1 = CreateWindow(AppName, TEXT("窗口标题"), style, , , , , ,NULL, hInstance, );
if (hwnd1 == NULL)
{
MessageBox(NULL, TEXT("创建窗口失败!"), TEXT("错误"), MB_ICONERROR);
return ;
}
//无边框窗口
/*SetWindowLong(hwnd1, GWL_STYLE, WS_OVERLAPPED | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);*/ //显示、更新窗口
ShowWindow(hwnd1, nCmdShow);
UpdateWindow(hwnd1); //消息循环
MSG msg;
while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} //GDI+关闭
GdiplusShutdown(token);//可以把这个写在消息循环后面,程序退出就销毁,或者在不需要GDI+时调用,比如GDI+窗口的WM_DESTROY消息里调用
return msg.wParam;
} LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (uMsg)
{ case WM_PAINT: hdc = BeginPaint(hwnd, &ps); int graphics;
GdipCreateFromHDC(hdc, &graphics);//创建Graphics对象
GdipCreatePen1(0x60FF2015, , , &pen);//创建画笔
GdipDrawRectangle(graphics, pen, , , , );//画矩形
GdipDrawLine(graphics, pen, , , , );//画直线 GdipDeletePen(pen);//销毁画笔
GdipDeleteGraphics(graphics);//销毁Graphics对象 EndPaint(hwnd, &ps);
return ;//告诉系统,WM_PAINT消息我已经处理了,你那儿凉快哪儿玩去吧。
case WM_CREATE:
break;
case WM_DESTROY://窗口已经销毁
PostQuitMessage();//退出消息循环,结束应用程序
return ;
break;
case WM_LBUTTONDOWN://鼠标左键按下
//让无边框窗口能够拖动(在窗口客户区拖动)
PostMessage(hwnd, WM_SYSCOMMAND, , );
break;
/*case WM_MOUSEMOVE://鼠标移动
int xPos, yPos;
xPos = GET_X_LPARAM(lParam);//鼠标位置X坐标
yPos = GET_Y_LPARAM(lParam);//鼠标位置Y坐标
//不要用LOWORD和HIWORD获取坐标,因为坐标有可能是负的
break;*/
default:
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);//其他消息交给系统处理
}
C语言集锦(三)Direct3D和GDI+的例子的更多相关文章
- Swift语言指南(三)--语言基础之整数和浮点数
原文:Swift语言指南(三)--语言基础之整数和浮点数 整数 整数指没有小数的整数,如42,-23.整数可以是有符号的(正数,零,负数),也可以是无符号的(正数,零). Swift提供了8,16,3 ...
- ASP.NET MVC:多语言的三种技术处理策略
ASP.NET MVC:多语言的三种技术处理策略 背景 本文介绍了多语言的三种技术处理策略,每种策略对应一种场景,这三种场景是: 多语言资源信息只被.NET使用. 多语言资源信息只被Javascrip ...
- 基于C#程序设计语言的三种组合算法
目录 基于C#程序设计语言的三种组合算法 1. 总体思路 1.1 前言 1.2 算法思路 1.3 算法需要注意的点 2. 三种组合算法 2.1 普通组合算法 2.2 与自身进行组合的组合算法 2.3 ...
- UWP 多语言的三个概念
首先了解一下 RFC4646 和 BCP-47 是什么东西: RFC4646 The name is a combination of an ISO 639 two-letter lowercase ...
- 第二百五十九节,Tornado框架-模板语言的三种方式
Tornado框架-模板语言的三种方式 模板语言就是可以在html页面,接收逻辑处理的self.render()方法传输的变量,将数据渲染到对应的地方 一.接收值渲染 {{...}}接收self.re ...
- DirectX11笔记(三)--Direct3D初始化代码
原文:DirectX11笔记(三)--Direct3D初始化代码 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010333737/article ...
- DirectX11笔记(三)--Direct3D初始化2
原文:DirectX11笔记(三)--Direct3D初始化2 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010333737/article/ ...
- 第三章SignalR在线聊天例子
第三章SignalR在线聊天例子 本教程展示了如何使用SignalR2.0构建一个基于浏览器的聊天室程序.你将把SignalR库添加到一个空的Asp.Net Web应用程序中,创建用于发送消息到客户端 ...
- 深入研究C语言 第三篇
本篇研究TC2.0下其他几个工具.同时看看TC由源代码到exe程序的过程. 1. 用TCC将下面的程序编为.obj文件 我们知道,TCC在默认的编译连接一个C语言的源程序a.c的时候分为以下两步: ( ...
随机推荐
- 关于在namanode上编写脚本控制DataNode的...
脚本如下:(我的虚拟机名字分别为:wang201 wang 202 wang 203 wang 204) params=$@ i= ; i <= ; i++)) ; do echo ====== ...
- 想成长为一名年薪50万+的实战型架构师?必掌握这7大实战技能经验--阿里mike
想成为一名架构师,但是架构师对应的技能,我应该掌握哪些啊?以及掌握的程度是什么样的?如何成为一名真正的实战性架构师? 我简要分为以下7点来谈谈,从技能的角度抛砖引玉,希望你对你架构师之路有一定的参考. ...
- 01-Flutter移动电商实战-项目学习记录
一直想系统性的学习一下 Flutter,正好看到该课程<Flutter移动电商实战>的百度云资源,共 69 课时,由于怕自己坚持不下去(经常学着学着就不学了),故采用博客监督以记之. 1. ...
- 安装Mysql community server遇到计算机中丢失msvcr120.dll
一.下载community server版本 Mysql community server版本:https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7 ...
- vue --子父组件传值
1.父组件可以使用 props 把数据传给子组件. 2.子组件可以使用 $emit 触发父组件的自定义事件. vm.$emit( event, arg ) //触发当前实例上的事件 vm.$on( e ...
- ECMAScript5.1
http://lzw.me/pages/ecmascript/ ECMAScript5.1中文版 https://msdn.microsoft.com/zh-cn/library/dn656907. ...
- Your branch is ahead of 'origin/master' by 21 commits.
当切换到主分支后,准备 git pull 拉取远程 master 分支时,提示本地主分支显示有 21 个commits 问题原因: 因为你修改了 local master 本地的主分支,可以选择以下方 ...
- C# 序列化和反序列化 详解
什么是序列化以及如何实现序列化? 如何将对象数据写入 XML 文件? 如何从 XML 文件读取对象数据? 什么是序列化以及如何实现序列化? 序列化是通过将对象转换为字节流,从而存储对象或将对象传输到内 ...
- dijkstra 堆优化
#include <iostream> #include <vector> #include <cstring> #include <queue> us ...
- ROM+VGA 图片显示
内容 1.将一幅图片制成mif文件,初始化rom,图片像素为 120 * 60 2.驱动VGA,将图片显示在屏幕上 1.VGA 时序 下面是我的笔记截图,感觉更好理解. 2.640*480 60hz ...