创建你的第一个Windows程序

作者 : admin 本文共6020个字,预计阅读时间需要16分钟 发布时间: 2024-06-16 共1人阅读

第一个 Windows 程序

* 纯净版

#include

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

* 注释版

#include

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
#include

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

创建窗口

运行代码的时候:

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

* 纯净版

#include
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 回调用的,它必须遵循规定的格式
对窗口过程的子程序名并没有规定,对 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窗口风格

常用的变量名前缀

前缀数据类型
cchar 或 WCHAR 或 TCHAR
byBYTE(无符号字符)
nshort
iint
x, yint, 表示 x 坐标和 y 坐标
cx, cyint, 表示 x 或 y 的长度,c 表示 count (计数)
B 或 fBOOL(int); f 表示 flag
wWORD(无符号短整型)
lLONG(长整型)
dwDWORD(无符号长整型)
fn函数
s字符串
sz以零结束的字符串
h句柄
p指针
本站无任何商业行为
个人在线分享 » 创建你的第一个Windows程序
E-->