搜索《Introduction to 3D Game Programming with DirectX 11》下载本书及代码
有的需要从VC++6.0的习惯中走出来
从VC++6.0到VS C++学习需要有一个适应的过程,这个过程可能是异常痛苦的,但本质是相同的,下边以经典的Win32 Applicationg演示说明下:
一、建立工程与文件的不同:
VC++ 6.0 | VS 2010 | |
新建工程 | 文件-》新建-》工程.Win32 Application | 文件-》新建-》三个选项:选择工程-》Win32 Application |
工程名 | -》自己起文件名(如“myproject”)-》确定 | 同左(推荐英文名,中文名后边很麻烦) |
生成工程 | -》默认 an ampty project | 点选下一步:应用程序默认 windows应用,附加项:空项目 |
创建完成 | -》完成 | 同左 |
文件视图 | 选择文件视图(file view)-》出现熟悉的:头文件、源文件及资源文件夹 | 默认或选择 视图-》解决方案资源管理器-》出现同左, 同左,多了一个外部依赖项 |
增加源文件.app | 选择 source files-》文件-》新建-》C++source files-》工程名下输入文件名(如:myproject)-》确定 | 源文件-》右击-》添加-》新建项-》C++文件-》输入文件名(如:myproject)-》添加 |
包含文件(本节可暂不设置) | 一般自动包含头文件和库文件,工具-》选择-》目录-》include files其实已经包含了一些头文件。其中有--\SDK\INCLUDE(没有的话可能没有下载,请搜索最新的directX sdk下载) -》在library files 其实已经包含了-:\SDK\LIB\X86,没有的请按如上下载。这些都是封装的功能,include引用头文件,以利用他们的功能,library释放。当然包含只是头一步,还要在代码中引用头文件(如:#include <d3d11.h>),释放可用预编译(如:#pragma comment(lib, "d3d11.lib") ),也可用衔接器。有些,如#include <windows.h>,个性化较强,设计代码时解决,没有windows.lib。当然,自己编写在工程同一个文件夹下的头文件不用目录包含,只需代码包含,如#include <----.h>,一旦设置目录包含,可能永久有效,不用反复操作。 | 2种方法:1.手工操作:右击解决方案下的工程(如:myproject)-》属性-》vc++目录-》增加包含目录中的SDK--include-》增加库目录中的SDK---lib---X86;2.一劳永逸的方法:视图-》属性管理器-》展开工程(如:myproject)-》展开debug|win32-》双击microsoft.cpp.win32.user-》如第一步更改VC++目录,以达到与VC++6.0相同的目的。(包含不同的头文件与库文件,请养成好习惯) |
释放文件功能(本节可暂不设置) | 接如上,2种方法:第一用#pragma comment(lib, ".lib")写在代码种,第二:工程-》设置-》link-》对象模块下-》拖到最后-》空格-》加入对应的.lib。也可在project options下, /nologo /subsystem前添加。 | 2种方法,第一种同左。第二种:又包括2种,同上两种方法,包含文件的方法,打开属性页选择衔接器-》输入。一劳永逸的方法用视图的属性管理器,如上 |
功能测试 | 请把下边的代码复制到建好的.cpp种,如myproject.cpp,前提知识,了解windows生成简单窗口的知识。 | 同左 |
二、VC++6.0与VS2010运行代码的不同:(通过上表设置环境,建立C++文件,复制下列代码分别运行)
#include <windows.h>
//回调函数,这个函数里的消息及消息处理我们下节再讲,这节大家先理解窗口创建显示的流程
LRESULT WINAPI WinProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg) //处理消息过程
{
case WM_DESTROY: //响应鼠标单击关闭按钮事件
PostQuitMessage(0); //退出消息队列
return 0; //退出函数
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
//主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
char *cName = "CWindowName"; //窗口类的名字
WNDCLASSEX wc;
HWND hWnd;
MSG Msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//通过函数来设置一个白色的背景.
wc.hCursor = NULL; //不设置
wc.hIcon = NULL; //不设置
wc.hIconSm = NULL; //不设置
wc.hInstance = hInstance; //当前程序的句柄,hInstance是有系统给传递的
wc.lpfnWndProc = WinProc; //窗口处理过程的回调函数,有关回调函数,下节再讲
wc.lpszClassName = cName; //窗口类的名字。
wc.lpszMenuName = NULL; //目录名,不设置
RegisterClassEx(&wc);//在系统中注册
//创建窗口,注意返回值是一个句柄。
hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, cName, "我的窗口", WS_OVERLAPPEDWINDOW,
200, 100, 600, 400, NULL, NULL, hInstance, NULL); //创建窗口,窗口标题为"我的窗口"
//创建窗口的容错处理
while (hWnd == NULL)
{
MessageBox(NULL, "There's an Error", "Error Title", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
//显示窗口
ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);
//下面是对消息的循环处理,关于消息及消息的处理我们下节在讲。
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg); //翻译消息
DispatchMessage(&Msg); //分派消息
}
return Msg.message;
}
先在VC++6.0中运行
复制完代码开始调试(编译-》开始调试):F5
VC++6.0编译一般无错,link时可能出错:
有可能出现 link2001类错误,.如:error LNK2001: unresolved external symbol _main Debug/....exe : fatal error LNK1120: 1 unresolved externals,不能解决的外部问题,
解决方法:1.暂时方法:(1)打开工程-》设置-link-》project options,如果是subsystem:console,请改为:subsystem:windows,原因是winmain的链接方法为windows,非console;
(2)也可以用预处理方法:#pragma comment( linker, "/subsystem:windows /entry:WinMainCRTStartup" )。
2.一劳永逸:但这不是根本更改,需要通过任务管理器修改,ctrl+alt+delete-》打开任务管理器-》服务-》打开服务-》若application informationg禁用,请启用。
复制代码在VS2010运行则出现了3个大错误:
(调试-》启用调试):F5
1.error C2440: “=”: 无法从“char *”转换为“LPCWSTR”;
对应: wc.lpszClassName = cName; 等同于wc.lpszClassName ="CWindowName";
cName的声明:char *cName = "CWindowName";
2.error C2664: “CreateWindowExW”: 不能将参数 2 从“char *”转换为“LPCWSTR”;
3.error C2664: “MessageBoxW”: 不能将参数 2 从“const char [17]”转换为“LPCWSTR”;
以上问题同根,VS函数对应的名字大多用wchar型的LPCWSTR,为长指针,32位,而VC++对应的函数对应的名字用char 8位,需将8位的char转化为32位的LPCWSTR,方法有N多:
1.#include “wchar.h”,把出问题的名字前加_T("");略麻烦;
2.用转化函数;麻烦
3.修改VS设置;麻烦,副作用大;
4.直接在名前加L进行转化;简单方便,如L“LPCWSTR”,注意L与“间不能有空格;
5.用其他函数:一般在函数名后加A或改为A;如:MessageBox(NULL, "There's an Error", "Error Title", MB_ICONEXCLAMATION | MB_OK);改为MessageBoxA(NULL, "There's an Error", "Error Title", MB_ICONEXCLAMATION | MB_OK);;略麻烦。
..................................................
总而言之,用第4、5个比较好。
修改后的VS2010代码如下:不用char*了,否则改不好出现乱码!
#include <windows.h>
//回调函数,这个函数里的消息及消息处理我们下节再讲,这节大家先理解窗口创建显示的流程
LRESULT WINAPI WinProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg) //处理消息过程
{
case WM_DESTROY: //响应鼠标单击关闭按钮事件
PostQuitMessage(0); //退出消息队列
return 0; //退出函数
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
//主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
// char *cName = "CWindowName"; //窗口类的名字
WNDCLASSEX wc;
HWND hWnd;
MSG Msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//通过函数来设置一个白色的背景.
wc.hCursor = NULL; //不设置
wc.hIcon = NULL; //不设置
wc.hIconSm = NULL; //不设置
wc.hInstance = hInstance; //当前程序的句柄,hInstance是有系统给传递的
wc.lpfnWndProc = WinProc; //窗口处理过程的回调函数,有关回调函数,下节再讲
wc.lpszClassName = L"CWindowName"; //窗口类的名字。
wc.lpszMenuName = NULL; //目录名,不设置
RegisterClassEx(&wc);//在系统中注册
//创建窗口,注意返回值是一个句柄。
hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"CWindowName", L"我的窗口", WS_OVERLAPPEDWINDOW,
200, 100, 600, 400, NULL, NULL, hInstance, NULL); //创建窗口,窗口标题为"我的窗口"
//创建窗口的容错处理
while (hWnd == NULL)
{
MessageBox(NULL, L"There's an Error", L"Error Title", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
//显示窗口
ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);
//下面是对消息的循环处理,关于消息及消息的处理我们下节在讲。
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg); //翻译消息
DispatchMessage(&Msg); //分派消息
}
return Msg.message;
}