创建你的第一个Windows程序

第一个 Windows 程序

* 纯净版

#include<Windows.h>

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

* 注释版

#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") 也能自动变化

#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(如果列表中还没有的话)

* 纯净版

#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);
}

* 注释版

#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 指针

相关推荐

  1. 创建第一Windows程序

    2024-06-16 18:56:05       24 阅读
  2. 第一Vue程序

    2024-06-16 18:56:05       69 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-16 18:56:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-16 18:56:05       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-16 18:56:05       82 阅读
  4. Python语言-面向对象

    2024-06-16 18:56:05       91 阅读

热门阅读

  1. 【Python高级编程】用 Matplotlib 绘制迷人的图表

    2024-06-16 18:56:05       29 阅读
  2. 费曼的博士学位论文及下载

    2024-06-16 18:56:05       33 阅读
  3. 编程中的delete用法:深入探索与实战应用

    2024-06-16 18:56:05       34 阅读
  4. mybatis LambdaQueryWrapper之复杂与或非sql逻辑编写

    2024-06-16 18:56:05       31 阅读