1.基本概念
- 在C语言中,printf、scanf、strlen等是C语言库函数,而在Windows平台下,也有由Windows操作系统提供的各种各样的函数,方便开发Windows应用程序,这些函数就是由Windows提供给应用程序编程的接口,简称API函数,用MSDN手册进行查找使用API函数
- SDK是软件开发包,包含API函数库、帮助文档、使用手册、辅助工具等资源,实际就是一个资源的集合
- 窗口通常包含:标题栏、菜单栏、系统菜单、最小化框、最大化框等。分为客户区和非客户区
- 句柄是各种资源的标识号。Windows应用程序中,窗口通过窗口句柄来标识。Windows中有各种各样的资源(窗口、图标、光标等)创建这些资源时为他们分配内存,并返回各种各样的资源的标识号,这就是句柄。
2.第一个Win32应用程序
#include<Windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow)
{
int result = MessageBox(NULL, L"第一个win32窗口程序", L"xx的", MB_YESNOCANCEL | MB_ICONQUESTION);
//每个按钮都有一个ID值
if (IDYES == result)
{
MessageBox(NULL, L"press yes", L"hint", MB_OK);
}
else if (IDNO == result)
{
MessageBox(NULL, L"press no", L"hint", MB_OK);
}
if (IDCANCEL == result)
{
MessageBox(NULL, L"press cancel", L"hint", MB_OK);
}
return 0;
}
解释:
- WINAPI是函数的调用约定 实际上是一个宏定义–>即宏替换 替换__stdcall,Windows程序中遵守__stdcall调用约定,声明必须显示的加上,因为像C语言函数库默认的调用约定为__cdecl。这两种调用约定是不同的,但都定义了函数参数的入栈顺序:是由调用函数还是被调用函数弹出栈,以及产生函数名的修饰方法。参数的入栈方式:从右向左。
- 入口函数:WinMain,不能改其他名字
- HINSTANCE:应用程序实例句柄类型 是结构体指针
- hInstance:当前应用程序实例句柄 简单理解(代表当前exe
- hPreInstance:当前应用程序的前一个实例句柄 简单理解(代表当前exe的前一个exe) 32位系统已经废弃 所以是NULL 是16位机器上的
- LPSTR:CHAR型指针
- lpCmdLine:命令行参数
- nCmdShow:窗口的显示方式 最大化还是最小化、隐藏等等
- MessageBox函数:消息提示框。
第一个参数:HWND hWnd 窗口句柄 父窗口是NULL说明这是个独立窗口
第二个参数:字符串 LPCTSTR lpText 显示的文本 加L是告诉编译器这个字符串要用unicode编码
第三个参数:标题 LPCTSTR lpCaption
第四个参数:按钮 UINT uType 指定一组位标志来决定对话框的内容和行为等 可以是组合 图标等
3.第一个窗口程序
流程:
- 设计窗口类
//wParam:按下的是哪个键 lParam:按下的键代表的具体信息,状态等
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//第一个参数: 窗口句柄, 创建的这个窗口
//第二个参数: 消息编号, 数值
//第三个参数: 附加消息, 附加信息
//第四个参数: 附加消息, 附加信息
WNDCLASS wc = {0};
wc.style = CS_HREDRAW | CS_VREDRAW |CS_DBLCLKS; //窗口类的风格
wc.lpfnWndProc = WindowProc; //窗口处理函数
wc.cbClsExtra = 0; //窗口类这个结构体,额外拓展空间
wc.cbWndExtra = 0; //窗口实例额外空间大小,字节数
wc.hInstance = hInstance; //当前应用程序实例句柄
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON2)); //图标句柄
wc.hCursor = LoadCursor(NULL, IDC_HAND); //光标句柄
wc.hbrBackground= CreateSolidBrush(RGB(255,0,0)); //红,绿,蓝 , 0->255, 0:最暗,255:最亮//黄色背景
wc.lpszMenuName = NULL; //菜单名
wc.lpszClassName = L"xx"; //窗口类型名
//窗口处理函数(窗口过程函数/窗口回调函数)
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//一些消息,如WM_CREATE等
...
}
- 注册窗口类
if (RegisterClass(&wc) == 0)
{
MessageBox(NULL, L"注册不成功", L"提示", MB_OK | MB_ICONWARNING);
return 0;
}
- 创建窗口
HWND hWnd = CreateWindow(
L"DunkaiEDU", //窗口类型名
L"我的第一个Windows窗口程序", //窗口的标题
WS_BORDER | WS_CAPTION | WS_SYSMENU| WS_MAXIMIZEBOX | WS_MINIMIZEBOX, //窗口的风格
300, 200, //窗口左上角坐标
800, 600, //窗口的宽和高
NULL, //父窗口句柄
NULL, //菜单句柄
hInstance, //当前应用程序实例句柄类型
(LPVOID)3 //创建窗口传递的附加数据
);
//创建完后要判断是否成功 否则退出
if (hWnd == NULL)
{
MessageBox(NULL, L"窗口创建失败", L"温馨提示", MB_OK );
return 0;
}
- 显示以及更新窗口
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd); //也会发出WM_PAINT消息
4.消息循环
MSG msg;
//GetMessage函数的返回值要为 0 ,只有接收这个消息的时候:WM_QUIT
while (GetMessage(&msg, NULL, 0, 0))
{
//将虚拟键消息转化为字符消息WM_CHAR
TranslateMessage(&msg);
//将消息分发给窗口处理函数
DispatchMessage(&msg);
}
GetMessage函数:
- 第一个参数LPMSG lpMsg:指向一个消息MSG结构体
- 第二个参数HWND hWnd:指定接收属于哪个窗口的消息,通常设置为NULL,用于接收属于调用线程的所有窗口的窗口消息
- 第三个参数UINT wMsgFilterMin:获取消息的最小值,通常为0
- 第四个参数UINT wMsgFilterMax :获取消息的最大值,如果第三四个参数都为0则接受所有消息
- GetMessage函数接收到WM_QUIT消息返回0,如果出现错误返回-1,比如窗口句柄无效,lpMsg无效指针
- TranslateMessage:将虚拟键消息转换为字符消息。当我们敲击键盘上的某个字符时,系统产生 WM_KEYDOWN 和 WM_KEYUP 消息,这两个消息的附加参数包含的是虚拟键代码和扫描码等信息,而我们程序经常使用某个字符的 ASCII码,所以 TranslateMessage 能将 WM_KEYDOWN 和 WM_KEYUP 消息组合转化为 WM_CHAR消息(ASCII 码,并将这消息投递到消息队列
- DispatchMessage:将消息一个消息分发到窗口处理函数,由窗口处理函数对消息进行处理。
消息机制原理:
5.命名规范:
Window 命名约定遵循匈牙利命名法
前缀 | 含义 |
---|---|
a | 数组 |
b | 布尔值 |
by | 无符号字节字符 |
c | 字符字节 |
dw | 无符号长整型DWORD |
fn | 函数 |
h | 句柄 |
i | 整数 |
n | 短整型或整型 |
w | 无符号整型 |
p | 指针 |
s | 字符串 |
sz | 以零结束的字符串 |
m_ | 类的数据成员 |