声明:纯粹出于个人兴趣,打算开始对DX开始一次系统的学习。欢迎拍砖,不对的地方望各位看官给予指正,感激不尽!!!
要开始搞DX,当然少不了DX SDK。从微软官网下最新的SDk,速度真是没的说(啥时候下爱情动作片也能有这速度!)。下好后,安装就是了,开发环境依个人习惯了,我是用的VS2005。刚整了套 WIN 7,就尝尝鲜,直接选择从DX10入手了,废话不多说,开始XX吧,吼吼。
既然是从头系统学习,又没有项目进度压力,慢慢抠代码了,绝不放过一切不明白的地方!!以这个宗旨来整,果真是相当的~~~~~~~慢,不过收获也不少。先从第一个例子:Win32 Basics开始。
顾名思义,Basics,还是Win32的,这是基础之中的基础了,好比万丈高楼的地基,一定要打好,所以一行一行来吧。
Win32 Baiscs其实就是创建一个空白的Win32窗口。直接创建一个默认设置的Win32项目,我们就可以得到一个包含菜单项的空白窗口,很简单,但内部代码不见得都是一看就能明白,反正我是遇到了几个不太明白的地方,后面我会着重指出。
先来看创建窗口的过程:
1.注册窗口类,以下是摘取的系统自动生成的代码:
// 函数: MyRegisterClass()
// 目的: 注册窗口类。
// 注释:
// 仅当希望
// 此代码与添加到Windows 95 中的"RegisterClassEx"
// 函数之前的Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,
// 这样应用程序就可以获得关联的
// "格式正确的"小图标。
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_BASICWIN32));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);//为了区分COLOR_SCROLLBAR,+1保证了不会定义为和COLOR_SCROLLBAR相同的颜色
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_BASICWIN32);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
其他部分可以直接看msdn,讲解很详细,我英文也很烂,所以不用指望我去翻译了,不会的就查词霸吧。这里要说一下红色标记的部分:wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1),这里是设置窗口背景色的,但是为什么自动生成的代码要将笔刷设置为COLOR_WINDOW+1,而不是直接写成COLOR_WINDOWFRAME呢(COLOR_WINDOWFRAME的宏定义是6, COLOR_WINDOW的宏定义是5)?这点让我很费解,根据查到的一些解释,貌似这样做是为了区分COLOR_SCROLLBAR,因为COLOR_SCROLLBAR的宏定义为0,如果我们不小心把笔刷定义为了COLOR_SCROLLBAR,那我们可能就难以区分窗口和滚动条了,+1的话我们就不必担心这种情况出现了,因为即使你将笔刷定义成了COLOR_SCROLLBAR,实际上用的笔刷却是下一个:COLOR_BACKGROUND。这个解释似乎比较牵强,但貌似就是因为这个,所以微软的工程师就异想天开的用了这样一种方法,真是有够微软风格的。不过我觉得大可不必遵循这样难以理解的规则,你想用哪个颜色直接写哪个就是了,不过记住不写COLOR_SCROLLBAR就是了。
2.创建主程序窗口,以下是系统生成的代码:
// 函数: InitInstance(HINSTANCE, int)
// 目的: 保存实例句柄并创建主窗口
// 注释:
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
RECT rc = { 0, 0, 640, 480 };
AdjustWindowRect(&rc,WS_OVERLAPPEDWINDOW,TRUE);//第二个参数为窗口风格,第三个参数代表是否//有菜单栏,对于第三个参数:如果设置为TRUE,无论是否有菜单栏,都会将菜单栏所占空间考虑在内,//rc设置的是除了菜单栏和边框外的大小如果设置为FALSE,无论是否有菜单栏,都不将菜单栏的空间考虑//在内,rc设置的就是除了边框外的大小
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
同上,我们只来讨论红色代码部分AdjustWindowRect(&rc,WS_OVERLAPPEDWINDOW,TRUE)只通过我添加的注释可能不太好理解,为什么要着重提这个呢,因为刚开始用这个函数的时候我对最后一个变量bMenu有误解,以为如果设为TRUE就表示有菜单栏,设为FALSE就表示没有菜单栏,但尝试过之后发现并不是这么回事,查阅资料后才知道错在哪里了。其实通过这个函数的名字就应该意识到,这是调整窗口框架区域的函数,它不会去操作控制菜单栏的有还是没有。如果把第三个参数设置为TRUE,无论是否有菜单栏,都会将菜单栏所占空间考虑在内,rc设置的是除了菜单栏和边框外的大小;如果把第三个参数设置为FALSE,无论是否有菜单栏,都不将菜单栏的空间考虑在内,rc设置的就是除了边框外的大小。所以要正确设置窗口区域的大小,必须要保证此参数与实际情况相符,有菜单栏就要设置为TRUE,没有的话就要设置为FALSE。
其他部分可以很清楚的理解,记不住的话查一下msdn也会有详细的讲解,好了,今天就搞到这里,第一次写BLOG,还真是有够累,明天继续DX10 Basics。