创建你的第一个Windows程序

第一个 Windows 程序

* 纯净版

cpp 复制代码
#include<Windows.h>

int WINAPI WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int iShowCmd
)
{
	MessageBox(NULL, TEXT("Hello, Windows!"), TEXT("HelloMsg"), 1);
	return 0;
}

* 注释版

cpp 复制代码
#include<Windows.h>

int WINAPI WinMain(
	HINSTANCE hInstance,		// 当前实例的句柄,唯一标识了我们这个程序(在Windows程序中,句柄就是一个数值,用来标识某个东西)
	HINSTANCE hPrevInstance,	// 前一个实例的句柄(在Win32中,此概念已弃用,因此该参数总是NULL)
	LPSTR lpCmdLine,			// 命令行参数
	int iShowCmd				// 指明程序最初如何显示(正常显示、最大化到全屏、最小化到任务栏)
)
{
	MessageBox(					// 函数作用:弹出一个小窗口,主要用来显示一些短消息
		NULL,					// 窗口句柄,唯一标识这个窗口
		TEXT("Hello, Windows!"),// 要在信息框里面出现的文本字符串
		TEXT("HelloMsg"),		// 要在标题栏上显示的文本字符串
		1						// 选择按钮的类型
	);
	return 0;
}

/*
Windows API 中"类型"的命名规则:

	HINSTANCE: H + INSTANCE == handle + instance == 实例句柄
	LPSTR: L + P + STR == long + pointer + str == 长字符指针
	i == int
	sz == 以零结尾的字符串
	c == const == 常量
	s == static == 静态

*/

编码问题

  • 早期 Windows 使用 ASCII 进行编码,对于美国自己来用,基本上足够了

  • 随着计算机的发展,世界各国都想要自己的文字能够在计算机上表示

  • 为了统一世界各国的字符编码问题,Unicode 诞生了

  • 它是通过增加位的方式来扩充,由原来的7位,变成现在的16位(方案不同,会有所出入,但只会更多,不会更少)

  • 可容纳的符号,由原来的27=128,变成现在的216=65536(方案不同,会有所出入,但只会更多,不会更少)

  • 使用 Unicode 也有缺点:就是用 Unicode 写的字符占用的空间,会比用 ASCII 写的字符所占用的空间大2倍

  • 为此,人们希望最好能够创建两个版本的程序,让不同需求的人,拿最适合自己的那一个版本即可

  • 于是,有了以下的设计:

使用 TCHAR.H 头文件,这个头文件提供了一系列的类型或函数的替代名称

一个命名为 _UNICODE 的标识符被定义了,在生成代码时

TCHAR 就自动变成 wchar_t_tprintf 就自动变成 wprintf(w:width)

一个名为 _UNICODE 的标识符没有被定义,在生成代码时

TCHAR 就自动变成 char_tprintf 就自动变成 printf

同样的道理,对于字符串而言,使用 _T("hello world")_TEXT("hello world") 也能自动变化

cpp 复制代码
#include<Windows.h>
#include<tchar.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	MessageBox(NULL, _T("你好,窗口!"), _T("信息窗口"), 0);
	return 0;
}

创建窗口

运行代码的时候:

  • 打开项目属性。
  • 导航到"链接器">"输入">"附加依赖项"。
  • 在"附加依赖项"字段中添加 winmm.lib(如果列表中还没有的话)

* 纯净版

cpp 复制代码
#include<Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	PSTR szCmdLine,
	int iCmdShow
)
{
	static TCHAR szAppName[] = TEXT("HelloWin");
	HWND		hwnd;
	MSG			msg;
	WNDCLASS	wndclass;

	wndclass.style			= CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc	= WndProc;
	wndclass.cbClsExtra		= 0;
	wndclass.cbWndExtra		= 0;
	wndclass.hInstance		= hInstance;
	wndclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor		= LoadCursor(NULL, IDC_APPSTARTING);
	wndclass.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName	= NULL;
	wndclass.lpszClassName	= szAppName;

	if (!RegisterClass(&wndclass))
	{
		MessageBox(NULL, TEXT("This program requires Windwos!"), szAppName, MB_ICONERROR);
		return 0;
	}

	hwnd = CreateWindow(
		szAppName,
		TEXT("The Hello Program"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL
	);

	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;

	switch (message)
	{
	case WM_CREATE:
		PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
		return 0;

	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);

		GetClientRect(hwnd, &rect);

		DrawText(hdc, TEXT("Hello, Windows!"), -1, &rect,
			DT_SINGLELINE | DT_CENTER | DT_VCENTER);

		EndPaint(hwnd, &ps);
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

* 注释版

cpp 复制代码
#include<Windows.h>

/* ------------------------------------------------------------------
	要创建窗口,首先需要注册一个窗口类,而窗口类又需要"窗口过程"来处理窗口消息
	名词解释:窗口过程,是一个函数,用于处理发送到类的所有窗口或发布到所有窗口的所有消息
	窗口过程是给 Windows 回调用的,它必须遵循规定的格式
	对窗口过程的子程序名并没有规定,对 Windows 来说,窗口过程的地址才是惟一需要的
------------------------------------------------------------------ */


// 声明"窗口过程"(窗口处理函数),用于处理窗口消息
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  // 窗口过程的名字,是可以自定义命名的


// Windows 程序的入口点
int WINAPI WinMain(
	HINSTANCE hInstance,		// 当前实例的句柄
	HINSTANCE hPrevInstance,	// 前一个实例的句柄(在Win32中,此参数总是NULL)
	PSTR szCmdLine,				// 命令行参数
	int iCmdShow				// 控制窗口如何显示
)
{
	static TCHAR szAppName[] = TEXT("HelloWin");	// 窗口类名
	HWND		hwnd;								// 窗口句柄
	MSG			msg;								// 消息结构体
	WNDCLASS	wndclass;							// 窗口类结构体

	// 设置窗口类的属性
	wndclass.style			= CS_HREDRAW | CS_VREDRAW;				// 窗口重绘风格
	wndclass.lpfnWndProc	= WndProc;								// 窗口过程(窗口处理函数)
	wndclass.cbClsExtra		= 0;									// 窗口类额外内存大小
	wndclass.cbWndExtra		= 0;									// 窗口实例额外内存大小
	wndclass.hInstance		= hInstance;							// 应用实例句柄
	wndclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);		// 加载默认图标
	wndclass.hCursor		= LoadCursor(NULL, IDC_APPSTARTING);	// 加载默认光标
	wndclass.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);	// 背景画刷
	wndclass.lpszMenuName	= NULL;									// 菜单名(这里没有使用)
	wndclass.lpszClassName	= szAppName;							// 窗口类名

	// 注册窗口类
	if (!RegisterClass(&wndclass))
	{
		MessageBox(
			NULL,
			TEXT("This program requires Windwos!"),
			szAppName,
			MB_ICONERROR
		);
		return 0;
	}

	// 创建窗口
	hwnd = CreateWindow(
		szAppName,					// 窗口类名
		TEXT("The Hello Program"),	// 窗口标题
		WS_OVERLAPPEDWINDOW,		// 窗口风格
		CW_USEDEFAULT,				// x坐标(使用默认值)
		CW_USEDEFAULT,				// y坐标(使用默认值)
		CW_USEDEFAULT,				// 宽度(使用默认值)
		CW_USEDEFAULT,				// 高度(使用默认值)
		NULL,						// 父窗口句柄(无父窗口)
		NULL,						// 菜单句柄(无菜单)
		hInstance,					// 应用实例句柄
		NULL						// 创建参数(这里不使用)
	);

	// 显示并更新窗口
	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);

	// 消息循环
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);		// 翻译消息(如键盘消息到字符消息)
		DispatchMessage(&msg);		// 分发消息到窗口过程(窗口处理函数)
	}
	return msg.wParam;
}


// 实现窗口过程(窗口处理函数)
LRESULT CALLBACK WndProc(
	HWND hwnd,			// 窗口句柄
	UINT message,		// 消息ID
	WPARAM wParam,		// 消息参数(对于某些消息,它表示特定的信息)
	LPARAM lParam		// 消息参数(对于某些消息,它通常是一个指向结构体的指针)
)
{
	HDC hdc;			// 设备上下文句柄,用于绘图操作
	PAINTSTRUCT ps;		// 绘图结构体,用于 BeginPaint 和 EndPaint 函数
	RECT rect;			// 矩形区域,用于描述窗口的绘图区域

	switch (message)
	{
	case WM_CREATE:						// 窗口创建消息
		PlaySound(						// 播放声音文件
			TEXT("hellowin.wav"),		// 声音文件的路径
			NULL,
			SND_FILENAME | SND_ASYNC	// SND_FILENAME表示通过文件名播放声音,SND_ASYNC表示异步播放(不阻塞程序)
		);
		return 0;

	case WM_PAINT:						// 窗口绘图消息
		hdc = BeginPaint(hwnd, &ps);	// 开始绘图

		GetClientRect(hwnd, &rect);		// 获取窗口客户区大小

		DrawText(
			hdc,
			TEXT("Hello, Windows!"),	// TEXT("Hello, Windows!"): 要绘制的文本字符串
			-1,							// -1: 字符串中的字符数。如果为-1,则函数会自动计算字符串长度 
			&rect,						// &rect: RECT结构体的指针,指定文本绘制的区域。文本将在这个矩形区域内被格式化
			DT_SINGLELINE | DT_CENTER | DT_VCENTER
			// DT_SINGLELINE | DT_CENTER | DT_VCENTER: 文本绘制选项
			// DT_SINGLELINE 表示文本将被格式化为单行
			// DT_CENTER 表示文本将在指定的矩形区域内水平居中
			// DT_VCENTER 表示文本将在指定的矩形区域内垂直居中
		);

		EndPaint(hwnd, &ps);			// 结束绘图
		return 0;

	case WM_DESTROY:					// 窗口销毁消息
		PostQuitMessage(0);				// 发出退出消息到消息队列
		return 0;
	}

	// 如果消息没有被窗口过程(WndProc)显式处理,则调用默认的窗口处理函数(DefWindowProc)来处理它
	return DefWindowProc(
		hwnd,		// hwnd: 窗口句柄,表示哪个窗口接收到了消息
		message,	// message: 消息ID,标识了要处理的消息类型
		wParam,		// wParam: 消息的参数之一,它的具体含义取决于消息类型
		lParam		// lParam: 消息的参数之二,它的具体含义也取决于消息类型
	);
}

常见的标识符前缀

前缀 常量
CS 类风格选项
CW 创建窗口选项
DT 文本绘制选项
IDI 图标的 ID 号
IDC 光标的 ID 号
MB 消息框选项
SND 声音选项
WM 窗口消息
WS 窗口风格

常用的变量名前缀

前缀 数据类型
c char 或 WCHAR 或 TCHAR
by BYTE(无符号字符)
n short
i int
x, y int, 表示 x 坐标和 y 坐标
cx, cy int, 表示 x 或 y 的长度,c 表示 count (计数)
B 或 f BOOL(int); f 表示 flag
w WORD(无符号短整型)
l LONG(长整型)
dw DWORD(无符号长整型)
fn 函数
s 字符串
sz 以零结束的字符串
h 句柄
p 指针
相关推荐
武藤一雄4 小时前
C# 关于多线程如何实现需要注意的问题(持续更新)
windows·后端·microsoft·c#·.net·.netcore·死锁
coding消烦员7 小时前
在 Windows 内网搭建 Git 仓库:共享普通仓库 vs 中心 bare 仓库
windows·git
xiaoliuliu1234511 小时前
IE8-WindowsXP-x86-CHS_23253_BDdl.exe 安装步骤(XP 32位简体中文版)
windows
百事牛科技11 小时前
文件不想再加密了?取消Word 打开密码的方法
windows·word
love530love13 小时前
EPGF 新手教程 13在 PyCharm(中文版 GUI)中创建 Hatch 项目环境,并把 Hatch 做成“项目自包含”(工具本地化为必做环节)
开发语言·ide·人工智能·windows·python·pycharm·hatch
峰上踏雪13 小时前
Go(Golang)Windows 环境配置关键点总结
开发语言·windows·golang·go语言
lusasky14 小时前
在Windows上编译、安装Rust
开发语言·windows·rust
麻辣长颈鹿Sir14 小时前
CMAKE指令集
linux·运维·windows·cmake·cmake指令集
Alice102915 小时前
如何在windows本地打包python镜像
开发语言·windows·python
北京流年15 小时前
windows安装jenkins并且编译app
运维·windows·jenkins