要写游戏嘛,首先肯定要有个窗口,今天我会跟大家分析窗口的编写,以及分享一些我的错误经验,(*^__^*) 嘻嘻
在这里我们写的是Windows应用程序,所以要要建立的工程是Win32 Application,注意不是以前的Win32 Console Application。由于使用Windows API,建议大家下一个MSDN Library,用来查看各种Windows库函数。在Windows应用程序里我们的程序入口不是以前在学C/C++基础时写的main函数了,而是WinMain函数,下面贴出WinMain函数原型
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
);
hInstance是应用程序实例句柄,标识当前运行的程序
hPrevInstance是上一个窗口的实例,目前暂时用不到,就先不说啦
lpCmdLine是一个指向应用程序命令行的指针,暂时也用不到
nCmdShow是窗口运行一开始的显示状态,比如:最大化、还原、最小化
下面就要在WinMain函数里写窗口,这要经历6个步骤,即设计窗口类(看下面其实是结构体,我也纳闷为什么微软的函数里要说是窗口类,这些不管了,意会就好了)、注册窗口类、创建窗口、更新窗口、显示窗口、消息循环响应
因为微软已经给我们写好了窗口类,所以所谓的设计窗口类就是初始化一个窗口类对象
typedef struct _WNDCLASSEX {
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
} WNDCLASSEX, *PWNDCLASSEX;
cbSize是指这个结构体的大小,用sizeof(WMDCLASSES)赋值
style是窗口的类型,一般选用CS_HREDRAW | CS_VREDRAW或者CS_CLASSDC赋值
lpfnWndProc指向窗口的回调函数,Windows编程是采用消息响应机制,所以需要一个回调函数来响应消息,让俺开心的是微软已经帮我们写好了回调函数的原型,如下:
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
hwnd是一个窗口句柄,以为一个进程对应好多好多个窗口,我们需要一个句柄来标识当前窗口
uMsg是系统接收的消息(前面已经说过Windows是消息响应机制)
wParam是第一个消息参数,一般用来存储键盘按下的消息
lParam是第二个消息参数,一般用来存储鼠标的位置
好了,我们继续回到WNDCLASSEX
cbClsExtra和cbWndExtra是注册窗口类需要的额外的空间,一般不需要,我们设置为0
hInstance没啥好说的,直接用WinMain参数里的hInstance赋值,表示当前应用程序句柄
hIcon是图标资源句柄,表示进程在任务栏里的图标,可以用LoadImage函数来载入图片资源
hCursor是鼠标句柄,可以用LoadImage来给鼠标换个图标
hbrBackground是个画刷句柄,设置窗口的背景颜色
lpszMenuName是菜单名字,我们暂时用不到,先设为NULL
lpszClassName是窗口类的名字
hIconSm是窗口做上角图标句柄,同样可以用LoadImage来载入图标资源
为窗口结构体的各个属性赋值完之后我们就要调用RegisterClassEx函数来注册窗口类了
注册完窗口类,接下来就是创建窗口句柄了(也就是创建窗口),用CreateWindow函数
然后呢就是调用ShowWindow和UpdateWndow函数来显示和更新窗口了
最后就是写一下查看消息队列的代码啦, 用PeekMessage函数,要注意PeekMessage和GetMessage的区别哦o(∩_∩)o
一下区别摘自http://www.cnblogs.com/faceang/archive/2010/05/25/1743757.html
无论应用程序消息队列是否有消息,PeekMessage函数都立即返回,程序得以继续执行后面的语句(无消息则执行其它指令,有消息时一般要将消息派发出去,再执行其它
指令)。GetMessage函数只有在消息对立中有消息时返回,队列中无消息就会一直等,直至下一个消息出现时才返回。在等的这段时间,应用程序不能执行任何指令。
以下贴出建立窗口示例代码
#include
#define WINDOW_CLASS "Demo" //用宏来定义窗口类的名字
#define WINDOW_NAME "CreateWindow" //定义窗口实例的名字
#define WINDOW_WIDTH 640 //定义窗口的宽度
#define WINDOW_HEIGHT 480 //定义窗口的高度
HWND hWnd; //窗口实例句柄
//定义回调函数
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
switch(uMsg)
{
//如果接收到用户点窗口右上角的x
case WM_CLOSE:
MessageBox(hWnd, "您点击了关闭图标,即将关闭窗口诶~~", "你好哇", MB_OK);
DestroyWindow(hWnd);
break;
//如果接收到销毁窗口的消息就调用PostQuitMessage来销毁窗口
case WM_DESTROY:
PostQuitMessage(0);
break;
//如果没有消息就调用系统默认的回调函数
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
)
{
WNDCLASSEX wcex;
wcex.cbClsExtra = 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.cbWndExtra = 0;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); //如果使用微软提供鼠标图标,第一个参数要设为NULL
wcex.hIcon = NULL;
wcex.hIconSm = NULL;
wcex.hInstance = hInstance;
wcex.lpfnWndProc = WindowProc;
wcex.lpszClassName = WINDOW_CLASS;
wcex.lpszMenuName = NULL;
wcex.style = CS_CLASSDC;
RegisterClassEx(&wcex);
hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
350, 120, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) //捕获消息
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
UnregisterClass(WINDOW_CLASS, wcex.hInstance); //注销窗口类
return 0;
}
注意return DefWindowProc(hwnd, uMsg, wParam, lParam);这句代码,里面的窗口句柄一定要用回调函数参数里的窗口句柄参数哦,虽然全局变量hWnd已赋值,但是不能用在这里啊,不信你试试,窗口是显不出来滴,好了,说到这里我也累了,各位小伙伴有兴趣的话可以根据msdn自己试试窗口类里的各个变量的不同赋值哦,见证奇迹的时候到了