一、基本概念
1.SDK和API的区别
SDK:软件开发工具包(外语首字母缩写:SDK、外语全称:Software Development Kit)一般都是一些软件工程师为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件时的开发工具的集合。
API:应用程序接口。
2.windows API
windows API是通过C语言来实现的,头文件为windows.h; MFC和QT是C++实现的,是C++的GUI开发框架。
3. 句柄
句柄是Windows资源的唯一标识:
HWND 窗口
HICON 图标
HCURSOR 光标
HBRUSH 画刷
4.消息
操作系统感知到我们在窗口中的某个操作时(鼠标左键),会将这个事件包装成一个消息,消息是由一个MSG结构体来表示的。
typedef struct tagMSG{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
hwnd -> 窗口句柄(索引内存当中的资源)
message -> 消息(事件);标准消息: WM_LBUTTONDOWN,虚拟消息:WM_KEYOWN WM_KEYUP
wParam -> 关于消息的附加参数,例如:按下一个键,具体是哪个按键
lParam -> 关于消息的附加参数
time -> 消息被传递时候的时间
pt -> 消息被传递时候,光标在屏幕上的位置
5.消息队列
每一个 Windows 应用程序开始执行后, 系统都会为该程序创建一个消息队列;应用程序通过消息循环从消息队列中取数据
while(msg)
{
...
...
}
二、WinMain 函数
Windows程序入口, WinMain函数结束,应用程序结束。
函数返回值: int
函数修饰符:WINAPI 规定了函数参数的入栈方式->从右向左入栈
参数: 4个
HINSTANCE hInstance:该程序当前运行的实例的句柄
HINSTANCE hInstance:当前实例的前一个实例的句柄,该参数已弃用,win32下永远为NULL
LPSTR lpCmdLine:传递给应用程序的命令行参数
int nCmdShow:指定程序的窗口应该如何显示
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR cmdLine, int nShow)
{
...
}
三、创建一个窗口的完整过程
1. 设计一个窗口类
窗口的特征就是由 WNDCLASS 结构体来定义的
typedef struct _WNDCLASS
{
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS, *PWNDCLASS;
style -> 窗口的样式
lpfnWndProc -> 函数指针,指向窗口过程函数
cbClsExtra -> 类的附加信息,一般设置为0
cbWndExtra -> 窗口附加内存,一般设置为 0
hInstance -> 包含窗口过程的程序的实例句柄
hIcon -> 窗口类的图标句柄
hCursor -> 窗口类的光标句柄
hbrBackground -> 窗口类的背景画刷句柄
lpszMenuName -> 指定菜单资源的名字
lpszClassName -> 指定窗口类的名字
2. 注册窗口类
函数: RegisterClass;参数: CONST WNDCLASS *lpWndClass。
作用:操作系统能够拿到回调函数的地址
3. 创建窗口
函数: CreateWindow
返回值:
HWND -> 该窗口的唯一标识
参数:
lpClassName -> 指定窗口类的名称
lpWindowName -> 指定窗口的名字
dwStyle -> 指定创建的窗口的样式
x -> 窗口左上角的x坐标
y -> 窗口左上角的y坐标
nWidth -> 窗口的宽度
nHeight -> 窗口的高度
hWndParent -> 指定被创建窗口的父窗口句柄
hMenu -> 指定窗口菜单的句柄
hInstance -> 指定窗口所属的应用程序实例的句柄
lpParam -> 指向一个值的指针,该值传递给窗口
4. 显示以及更新窗口
1.更新窗口
UpdateWindow
参数:
HWND hWnd -> 要显示的窗口的句柄
2.显示窗口
ShowWindow
参数:
HWND hWnd -> 要显示的窗口的句柄
int nCmdShow -> 窗口显示的状态
SW_HIDE
SW_HIDE
SW_SHOWNORMAL
四、消息循环
五、窗口过程函数
1. 作用:
用于处理发送给窗口的消息
2. 返回值:
LRESULT,实际上是 long
3.函数修饰符
CALLBACK,规定了函数参数的入栈方式:从右向左入栈
4.参数:
HWND hWnd:消息的窗口句柄
UINT uMsg:消息代码
WPARAM wParam:消息代码的两个附加参数一
LPARAM lParam:消息代码的两个附加参数二
5.默认窗口过程函数
DefWindowProc:应该将 DefWindowProc 函数的调用放到 default 语句中,并将该函数的返回值作为窗口过程函数的返回值,参数与窗口过程函数相同,对应用程序没有处理的其他消息提供默认处理
6. 函数体
switch(uMsg)
{
case WM_LBUTTONDOWN:
break;
case WM_DESTROY:
PostQuiteMessage(0);
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
……
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
六、完整案例代码
#include <windows.h>
LRESULT CALLBACK MyProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(10);
break;
case WM_LBUTTONDOWN:
MessageBox(hWnd, TEXT("aaa" ), TEXT("bbb"), MB_OKCANCEL);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int nShow)
{
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_CROSS);
wc.hIcon = LoadIcon(NULL, IDI_ERROR);
wc.hInstance = hInstance;
wc.lpfnWndProc = MyProc;
wc.lpszClassName = TEXT("ddd");
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
HWND hWnd = CreateWindow(TEXT("ddd"), TEXT("我是个窗口"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}