创建你的第一个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窗口风格

常用的变量名前缀

前缀数据类型
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指针

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/714111.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【vue3中使用$refs】

在使用uniapp官网里的uni-popup弹出层组件时&#xff0c;要将vue2转换成vue3,&#xff0c;这里遇到了一个问题&#xff1a;vue2可以通过this访问到绑定的ref&#xff0c;但是vue3没有了this,应该怎么办呢&#xff1f; 解决方法&#xff1a; !

Cocos Creator,Youtube 小游戏!

YouTube 官方前段时间发布了一则重磅通知&#xff0c;宣布平台旗下小游戏功能 Youtube Playables 正式登录全平台&#xff08;安卓、iOS、网页&#xff09;&#xff0c;并内置了数十款精选小游戏。 Youtube Playables 入口&#xff1a; https://www.youtube.com/playables Coco…

Digital电路仿真软件的安装

文章目录 1. Java环境的安装 2. Digital安装 3. 软件配置 1. Java环境的安装 电路仿真软件Digital是一款用于设计和仿真数字逻辑电路的工具。它可以帮助用户创建、测试和调试各种数字电路&#xff0c;提供可视化的电路编辑环境&#xff0c;使得设计过程更加直观和便捷。 D…

Sigir2024 ranking相关论文速读

简单浏览一下Sigir2024中与ranking相关的论文。不得不说&#xff0c;自从LLM大热后&#xff0c;传统的LTR方向的论文是越来越少了&#xff0c;目前不少都是RAG或类似场景下的工作了&#xff0c;比如查询改写、rerank等。 文章目录 The Surprising Effectiveness of Rankers Tr…

centos环境上:k8s 简单安装教程

本次演示安装3节点k8s环境&#xff0c;无需多言&#xff0c;直接上操作步骤&#xff1a; 1、环境准备 k8s部署前&#xff0c;首先需要准备好环境&#xff0c;除了1.4 步骤&#xff0c;其他步骤在所有&#xff08;3个&#xff09;节点上都要执行&#xff1a; 1.1 关闭防火墙 s…

CSS【详解】样式选择器的优先级(含提升优先级的方法)

数值越大&#xff0c;优先级越高&#xff0c;尽量保持较低的优先级&#xff0c;以便使用更高优先级的选择器重置样式 0级——通配选择器、选择符和逻辑组合伪类。逻辑组合伪类有:not()、:is()和:where等&#xff0c;这些伪类本身并不影响CSS优先级&#xff0c;影响优先级的是括…

C++初学者指南第一步---1. C++开发环境设置

C初学者指南第一步—1. C开发环境设置 目录 C初学者指南第一步---1. C开发环境设置1.1 工具1.1.1 代码编辑器和IDE1.1.2 Windows1.1.3 命令行界面 1.2 编译器1.2.1 gcc/g (支持Linux/Windows/MacOSX)1.2.2 clang/clang (支持Linux/Windows/MacOS)1.2.3 Microsoft Visual Studio…

C/C++李峋同款跳动的爱心代码

一、写在前面 在编程的世界里&#xff0c;代码不仅仅是冷冰冰的命令&#xff0c;它也可以成为表达情感、传递浪漫的工具。今天&#xff0c;就让小编带着大家用C语言打造出李峋同款跳动的爱心吧&#xff01; 首先&#xff0c;我们需要知道C作为一种高级编程语言&#xff0c;拥…

常见的宽基指数基金

指数基金投资指南 ❝ 这篇博客里面的内容主要来自于银行螺丝钉的《定投十年&#xff0c;财务自由》和《指数基金投资指南》这两本书中章“常见的宽基指数”&#xff0c;最近第三次读这本书&#xff0c;打算做一点笔记加深自己的印象。 博客中很多内容是从书中摘抄的&#xff0c…

二十六、办公用品管理系统

随着计算机技术的迅猛发展,相关技术进入商业和社会应用阶段,设备的种类、数量越来越多,如何有效利用先进的互联网技术和日新月异的计算机设备来有效地收集、处理这些设备,建立以信息化为核心的管理体制,减轻管理人员和业务人员的数据处理负担,极大地提高设备管理效率和管…

Jmeter多个请求按照比例并发压测的几种方式

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、需求 在压测的过程中&#xff0c;为了能够压测整个链路&#xff0c;通常需要多个接口进行并…

HarmongOS打包[保姆级]

创建应用 首先进入 华为开发者联盟-HarmonyOS开发者官网 然后进行登录。 登录成功后&#xff0c;鼠标悬停在在登录右上角那个位置后再点击管理中心&#xff0c;进入下面这个界面。 再点击&#xff1a;应用服务–>应用发布–>新建–>完善信息 构建和生成私钥和证书请求…

SQL Server Management Studio (SSMS) 20.1 - 微软数据库管理工具

SQL Server Management Studio (SSMS) 20.1 - 微软数据库管理工具 请访问原文链接&#xff1a;https://sysin.org/blog/ssms/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 笔者注&#xff1a;SQL Server 2014 及之前版本内置…

[Linux] UDP协议介绍:UDP协议格式、端口号在网络协议栈那一层工作...

TCP/IP网络模型, 将网络分为了四层: 之前的文章中以HTTP和HTTPS这两个协议为代表, 简单介绍了应用层协议. 实际上, 无论是HTTP还是HTTPS等应用层协议, 都是在传输层协议的基础上实现的 而传输层协议中最具代表性的就是: UDP和TCP协议了. 以HTTP为例, 在使用HTTP协议通信之前, …

调度算法(SSTF,SCAN,CSCAN)c语言

假定当前磁头位于100号磁道&#xff0c;有9个进程先后提出了磁盘I/O请求&#xff1a;55 58 39 18 90 160 150 38 184&#xff0c;如果采用扫描算法或循环扫描算法&#xff0c;则磁头向磁道号增加的方向访问。 设计一个磁盘调度模拟系统&#xff0c;编程序演示下述算法的具体实…

线程池ThreadPoolExecutor源码分析

一、线程池基本概念和线程池前置知识 1.1 Java中创建线程的方式有哪些 传统答案&#xff1a; 继承Thread类 通过继承Thread类并重写其run方法来创建线程。具体步骤包括定义Thread类的子类&#xff0c;在子类中重写run方法以实现线程的具体逻辑&#xff0c;然后创建子类的实例…

举例说明 如何通过SparkUI和日志定位任务莫名失败?

有一个Task OOM&#xff1a; 通过概览信息&#xff0c;发现Stage 10的Task 36失败了4次导致Job失败。概览信息中显示最后一次失败的退出代码&#xff08;exit code&#xff09;是143&#xff0c;意味着发生了内存溢出&#xff08;OOM&#xff0c;即Out of Memory&#xff09;。…

QQ登录测试用例

QQ登录测试用例 常见测试方法&#xff08;可参考软件测试<用例篇>&#xff09; 等价类&#xff1a; 1、有效等价类 &#xff1a;满足需求的数据集合 2、无效等价类&#xff1a;不满足需求的数据集合 边界值错误猜测法场景法 QQ测试用例设计&#xff1a;xmind 需要完整…

C++ 55 之 多继承

#include <iostream> #include <string> using namespace std;class Base08_1{ public:int m_a;Base08_1(){this->m_a 10;} };class Base08_2{ public:// int m_b;int m_a;Base08_2(){// this->m_b 20;this->m_a 30;} };// 多继承 继承的类型都要…

九、BGP路由属性和选路

目录 一、属性分类 1.1、公认属性 1.2、可选属性 二、选路原则 0、丢弃不可达 取值越大越优 1、Preferred-Value 2、Local_Preference 取值越小越优 3、路由优先级 4、AS_Path 5、Origin 6、MED 7、路由来源 8、Next_Hop的IGP度量值 BGP路由等价负载分担&#…
最新文章