一、Windows窗口的创建过程
1.定义WinMain函数
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
WinMain函数是窗口程序的入口函数(类似于main函数),WinMain的第一个参数是当前应用程序的实例句柄,第二个参数是前一个实例,第三个参数是命令行参数,最后一个参数是主窗口显示方式。
2.设计并注册窗口类
typedef struct _WNDCLASS {
UINT style;// 窗口类的风格
WNDPROC lpfnWndProc;//窗口处理函数
int cbClsExtra;//窗口扩展
int cbWndExtra;//窗口实例扩展
HINSTANCE hInstance;//实例句柄
HICON hIcon;//窗口的最小化图标
HCURSOR hCursor;//窗口鼠标光标
HBRUSH hbrBackground;//窗口背景色
LPCTSTR lpszMenuName;//窗口菜单
LPCTSTR lpszClassName;// 窗口类名
} WNDCLASS, *LPWNDCLASS;
以上是窗口类的定义,用法如下
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmd, int nCmdShow)
{
WNDCLASS wc = { 0 };
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;//窗口处理函数
wc.lpszClassName = "Main";//窗口类名
wc.lpszMenuName = NULL;//菜单
wc.style = CS_HREDRAW | CS_VREDRAW;//窗口类的风格
}
示例中,将创建的窗口的hInstance = hIns,意思是将当前程序的实例句柄赋值给该窗口,窗口处理函数WndProc是个回调函数,稍后会讲解,wc.style = CS_HREDRAW | CS_VREDRAW,从名字就看出来了,就是同时具备水平重画和垂直重画。因为当我们的窗口显示的时候,被其他窗口挡住后重新显示,或者大小调整后,窗口都要发生绘制,就像我们在纸上涂鸦一样,每次窗口的变化都会“粉刷”一遍,并发送WM_PAINT消息。
窗口类设计完成后,不要忘了向系统注册,这样系统才能知道有这个窗口类的存在。向操作系统注册窗口类,使用RegisterClass函数,它的参数就是一个指向WNDCLASS结构体的指针,所以我们传递的时候,要加上&符号。
RegisterClass(&wc);//将以上所有赋值全部写入操作系统
3.创建并显示窗口
// 创建窗口
HWND hwnd = CreateWindow(
cls_Name, //类名,要和刚才注册的一致
L"我的应用程序", //窗口标题文字
WS_OVERLAPPEDWINDOW, //窗口外观样式
100, //窗口相对于父级的X坐标
100, //窗口相对于父级的Y坐标
500, //窗口的宽度
500, //窗口的高度
NULL, //没有父窗口,为NULL
NULL, //没有菜单,为NULL
hInstance, //当前应用程序的实例句柄
NULL); //没有附加数据,为NULL
if(hwnd == NULL) //检查窗口是否创建成功
return 0;
WS_OVERLAPPEDWINDOW,msdn中解释为Creates an overlapped window with the WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, and WS_MAXIMIZEBOX styles.也就是说WS_OVERLAPPEDWINDOW可以创建一个拥有各种窗口风格的窗体,包括标题,系统菜单,边框,最小化和最大化按钮等。
窗口创建后,就要显示它,用ShowWindow函数
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);//可选,更新窗口
SW_SHOW表示以当前大小激活运行后的程序窗口并显示它。
4.消息循环
当程序运行的时候,会不断产生新的信号,例如,按下鼠标左键会产生WM_LBUTTONDOWN的信号,我们需要对产生的信号不断用GetMessage获取到然后处理
BOOL WINAPI GetMessage(
_Out_ LPMSG lpMsg,
_In_opt_ HWND hWnd,
_In_ UINT wMsgFilterMin,
_In_ UINT wMsgFilterMax
);
第一个参数是一个指向MSG结构的指针。第二个参数是句柄,通常我们用NULL,因为我们会捕捉整个应用程序的消息。后面两个参数是用来过滤消息的,指定哪个范围内的消息我接收,在此范围之外的消息我拒收,如果不过滤就全设为0.。用法如下:
//消息循环
MSG nMsg = { 0 };
while (GetMessage(&nMsg, NULL, 0, 0)) {
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
死循环不断获取消息,用DispatchMessage函数将消息发给消息处理函数去处理,在这之前,当获取到消息时,对于键盘的大小写区分,还需要翻译一下,所以要 TranslateMessage。
5.消息响应
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
当按下退出键,程序会退出,其余情况按默认处理。
完整代码如下:(编码方式采用多字节字符集)
#define _CRT_SECURE_NO_WARNINGS 1
#include<windows.h>
//窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmd, int nCmdShow)
{
hInstance = hIns;
//注册窗口类
WNDCLASS wc = { 0 };
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = NULL;
wc.hIcon = NULL;
wc.hInstance = hIns;
wc.lpfnWndProc = WndProc;//窗口处理函数
wc.lpszClassName = "Main";//窗口类名
wc.lpszMenuName = NULL;//菜单
wc.style = CS_HREDRAW | CS_VREDRAW;//窗口类的风格
RegisterClass(&wc);//将以上所有赋值全部写入操作系统
//在内存创建窗口
HWND hWnd = CreateWindow("Main", "window", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hIns, NULL);
//显示窗口
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);//可选
//消息循环
MSG nMsg = { 0 };
while (GetMessage(&nMsg, NULL, 0, 0)) {
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
}
return 0;
}
二、字符串
在开发过程中,由于字符串的编码方式不同(ANSI,UNICODE),会导致每隔字符所占的大小不同,对应的字符串处理函数也不同。下面是一些常用字符串处理函数:
字符串长度:
● Ansi:strlen(char *str);
● Unicode:wcslen(wchar_t *str);
● 通用函数:_tcslen(TCHAR *str);
字符串转成数字
● Ansi:int atoi(const char *str);
● Unicode:int _wtoi(const wchar_t *str);
● 通用函数:_tstoi(const TCHAR *str);
字符串拷贝:
● Ansi:strcpy(char *strDestination, const char *strSource);
● Unicode:wcscpy(wchar_t *strDestination, const wchar_t *strSource);
● 通用函数:_tcscpy(TCHAR *strDestination, const TCHAR *strSource);
目录