Win32编程:创建属于你的第一个窗口

news2024/9/20 9:19:42

目录

一、Win32程序的运行过程

二、创建Windows窗口

1、分析

2、完整代码 


一、Win32程序的运行过程

        Win32编程,也称为Windows编程。运行步骤主要包含:加载程序(操作系统加载程序的可执行文件(exe格式)到内存中,创建进程的地址空间,并分配必要的系统资源。),初始化(查找程序的主函数WinMain函数),消息循环(消息也就是事件响应信息,这里会获取一段信息),消息处理(收到消息,放入消息队列,程序会根据消息调用相应函数,如果为WM_QUIT,则退出程序)。

Win32 应用特点:界面一致,操作便利,所见即所得,多任务。 

二、创建Windows窗口

1、分析

 首先要编写WinMain函数,它是窗口编程的入口函数,由操作系统调用填写参数。

int WINAPI WinMain(
    HINSTANCE hInstance,//操作系统使用此值来标识 EXE (加载到) 可执行文件。 某些函数需要实例句柄Windows例如,加载图标或位图。
	HINSTANCE hPrevInstance, //没有意义。 它用于 16 位Windows,但现在始终为零。
	LPSTR     lpCmdLine,//用于指定程序的命令行,是指向字符串的指针类型。
	int       nCmdShow//是一个标志,指示主应用程序窗口是最小化、最大化还是正常显示。
)
关键词解释
HINSTANCE程序实例句柄,用来标识唯一窗口。
PSTRCHAR*
WINAPIMicrosoft 定义的一种标准调用约定,主要用于 Windows API 函数

        在创建窗口之前,需要定义窗口结构体类WNDCLASS,并向Windows注册,它是Windows API 中用于定义窗口类的结构体

typedef struct tagWNDCLASS 
{
	UINT style;				//窗口的风格
	WNDPROC lpfnWndProc;	//指定窗口的消息处理函数的窗口过程函数
	int cbClsExtra :		//指定分配给窗口类结构之后的额外字节数
	int cbwndExtra;			//指定分配给窗口实例之后的额外字节数
	HINSTANCE hInstance :	//指定窗口过程所对应的实例句柄
	HICON hIcon;			//指定窗口的图标
	HCURSOR hCursor;		//指定窗口的鼠标指针
	HBRUSH hbrBackground;	//指定窗口的背景画刷
	LPCTSTR lpszMenuName;	//窗口的菜单资源名称
	LPCTSTR lpszClassName;	//该窗口类的名称
}WNDCLASS, * PWNDCLASS;
关键词解释
UINTunsigned int
WNDPROCWindows API 中定义窗口过程的函数指针类型。窗口过程是一个回调函数,用于处理与窗口相关的消息。
HBRUSH画刷句柄
HICON图标句柄
HCURSOR光标句柄
LPCTSTRchar* 长指针常量字符串

结构体填写完后,要向Windows系统去提交注册,成功返回true,失败返回false。

RegisterClass(&wndclass)

        由定义窗口结构体可得,需要一个消息处理函数WndProc,该函数也由Windows操作系统调用,但需要在定义窗口的结构体赋值。

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam)
{
	HDC hdc; // 设备上下文句柄,用于绘制图形  
	PAINTSTRUCT ps; // 用于存储绘制信息的结构体  
	RECT rect; // 矩形结构体,用于定义绘制区域  

	switch (message) {
	case WM_CREATE: // 当窗口被创建时接收到的消息  
		PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC); // 播放声音文件 "hellowin.wav"  
		return 0; // 处理完毕,返回0  

	case WM_PAINT: // 当窗口需要重绘时接收到的消息  
		hdc = BeginPaint(hwnd, &ps); // 开始绘制,获取设备上下文  
		GetClientRect(hwnd, &rect); // 获取窗口客户区的矩形区域  
		DrawText(hdc, TEXT("大家好"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); // 在客户区绘制文本 "大家好",居中显示  
		EndPaint(hwnd, &ps); // 结束绘制  
		return 0; // 处理完毕,返回0  

	case WM_DESTROY: // 当窗口被销毁时接收到的消息  
		PostQuitMessage(0); // 发送退出消息,结束应用程序  
		return 0; // 处理完毕,返回0  
	}

	// 对于未处理的消息,调用默认窗口过程  
	return DefWindowProc(hwnd, message, wParam, IParam);
}
关键词解释
CALLBACK这是一个调用约定,指示该函数是一个回调函数。Windows 在需要时会调用这个函数。
WPARAM这是一个无符号整数,通常用于传递消息的附加信息。
HWND这是一个句柄,表示窗口的句柄。
LPARAM这是一个长整型,通常用于传递消息的附加信息,具体内容也取决于消息类型。

接着是创建窗口函数CreateWindow函数

HWND WINAPI CreateWindow(	//返回值是窗口句柄
	LPCTSTR lpClassName,		//窗口类名,要与注册时指定的名称相同
	LPCTSTR lpWindowName,		//窗口标题
	DWORD dwStyle,				//窗口样式
	int X,						//窗口最初的x位置
	int y,						//窗口最初的y位置
	int nWidth,					//窗口最初的x大小
	int nHeight,				//窗口最初的y大小
	HWND hWndParent,			//父窗口句柄
	HMENU hMenu,				//窗口菜单句柄
	HINSTANCE hInstance,		//应用程序实例句柄
	LPVOID lpParam				//指向一个传递给窗口的参数值的指针,以便后续在程序中加以引用
);
关键词解释
HWND句柄,它是窗口的唯一标识符
LPCTSTRchar* 长指针常量字符串
HMENU指向窗口菜单的唯一标识符
DWORD双字节32位无符号整数
LPVOID指向任何类型的指针,通常用于表示通用数据指针,允许函数接受不同类型的数据。

2、完整代码 

        总结来说,先编写一个入口函数WinMain,然后在入口函数里,进行窗口结构体的定义和注册,定义好了后进行创建窗口CreateWindow,只是创建并没有显示,使用ShowWindow和UpdateWindow显示并更新窗口,然后进行消息循环,GetMessage和DispatchMessage获取并分发消息到消息处理函数WndProc(自己编写,系统调用),这样一个简单的窗口程序便结束了,以下是完整代码。

#include<Windows.h>
#pragma comment(lib, "winmm")
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam)
{
	HDC hdc; // 设备上下文句柄,用于绘制图形  
	PAINTSTRUCT ps; // 用于存储绘制信息的结构体  
	RECT rect; // 矩形结构体,用于定义绘制区域  

	switch (message) {
	case WM_CREATE: // 当窗口被创建时接收到的消息  
		PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC); // 播放声音文件 "hellowin.wav"  
		return 0; // 处理完毕,返回0  

	case WM_PAINT: // 当窗口需要重绘时接收到的消息  
		hdc = BeginPaint(hwnd, &ps); // 开始绘制,获取设备上下文  
		GetClientRect(hwnd, &rect); // 获取窗口客户区的矩形区域  
		DrawText(hdc, TEXT("大家好"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); // 在客户区绘制文本 "大家好",居中显示  
		EndPaint(hwnd, &ps); // 结束绘制  
		return 0; // 处理完毕,返回0  

	case WM_DESTROY: // 当窗口被销毁时接收到的消息  
		PostQuitMessage(0); // 发送退出消息,结束应用程序  
		return 0; // 处理完毕,返回0  
	}

	// 对于未处理的消息,调用默认窗口过程  
	return DefWindowProc(hwnd, message, wParam, IParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
	// 定义应用程序名称  
	static TCHAR szAppName[] = TEXT("HelloWorld!");
	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_ARROW); // 加载默认箭头光标  
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 设置背景画刷为白色  
	wndclass.lpszMenuName = NULL; // 此窗口没有菜单  
	wndclass.lpszClassName = szAppName; // 将类名设置为应用程序名称  

	// 注册窗口类  
	if (!RegisterClass(&wndclass)) {
		// 如果注册失败,显示错误消息  
		MessageBox(NULL, TEXT("此程序的 RegisterClass 出错!"), szAppName, MB_ICONERROR);
		return 0; // 退出程序  
	}

	// 创建主窗口  
	hwnd = CreateWindow(szAppName, // 类名  
		TEXT("Hello 程序"), // 窗口标题  
		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); // 将消息分发到窗口过程WndProc  
	}

	// 返回消息的 wParam 作为退出代码  
	return msg.wParam;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录刷题day30丨452. 用最少数量的箭引爆气球, 435. 无重叠区间,763.划分字母区间

代码随想录刷题day30丨452. 用最少数量的箭引爆气球&#xff0c; 435. 无重叠区间&#xff0c;763.划分字母区间 1.题目 1.1用最少数量的箭引爆气球 题目链接&#xff1a;452. 用最少数量的箭引爆气球 - 力扣&#xff08;LeetCode&#xff09; 视频讲解&#xff1a;贪心算法…

ColorThief的介绍与使用

概述 colorThief是一个 Javascript 插件&#xff0c;支持在浏览器端或 Node 环境中使用。Thief的中文意思是偷窃、小偷。colorThief的作用就是通过算法去获取图片的色源。 API 介绍与示例 colorThief提供两个方法&#xff0c;getColor和getPalette&#xff0c;这两个方法在 …

类和对象(c++)

欢迎来到本期频道&#xff01; 类和对象 类定义&#xff1a;格式&#xff1a;类域&#xff1a;访问限定符友元内部类this指针静态与非静态成员关系类型转换六大默认成员函数&#xff08;C98&#xff09;1️⃣构造函数2️⃣拷贝构造函数浅拷贝与深拷贝 3️⃣赋值重载拷贝函数4️…

x-cmd pkg | superfile: 终端文件管理器,界面精致美观

目录 简介快速上手功能特点竞品和相关项目进一步阅读 简介 superfile 是 github.com/yorukot 用 Go 开发的终端文件管理器&#xff0c;相比于其他终端文件管理器&#xff0c;它最显著的特点是 UI 精致美观。 Tip Superfile 采用了特殊的 Unicode 符号来标识各种类型的文件&…

【我的 PWN 学习手札】Unsortedbin Leak

前言 从前都是野路子学习&#xff0c;学校时间也比较紧张&#xff0c;没有能够好好总结。一直有做个人笔记的习惯&#xff0c;但是学习路线比较分散盲目&#xff0c;虽然跟着wiki做&#xff0c;但是也面临知识点不全的窘境。近期开始跟着课程系统的学习&#xff0c;对于老的知…

mp3转文字要怎么处理?使用这4个工具就对了

MP3是音频当中比较常用的格式&#xff0c;如果像将其转换成文字内容&#xff0c;一般的语音转文字工具都是可以完成的。但是音频转换成文字的过程中&#xff0c;它的准确率是会受到像口音&#xff0c;语言&#xff0c;环境音等因素的影响的。所以大家如果想将自己的mp3语音转成…

en造数据结构与算法C# 用数组实现个栈还不简单???看我一秒破之!!!(unity演示)

实现效果 线性表&#xff0c;线性表是指数据元素按顺序排列的一种数据结构&#xff0c;下面这些东西可以说都是线性表&#xff0c;所以用array实现三者一点问题都没有 分别是List动态数组&#xff0c;stack栈和queue队列&#xff0c;今天就秒掉stack 栈&#xff1a;先进后出 实…

Vue邮件发送:如何有效集成邮件发送功能?

vue邮件发送功能实现方法&#xff1f;Vue邮件发送性能怎么优化&#xff1f; 无论是用户注册验证、密码重置&#xff0c;还是通知提醒&#xff0c;邮件发送功能都能提供重要的支持。本文将详细探讨如何在Vue项目中有效集成邮件发送功能&#xff0c;确保邮件能够准确、及时地送达…

万龙觉醒免费辅助:VMOS云手机辅助巴克尔阵容搭配攻略!

《万龙觉醒》是一款策略类手游&#xff0c;选择合适的英雄阵容搭配能够极大提升战斗效果。而借助VMOS云手机的辅助功能&#xff0c;玩家可以更加轻松地管理游戏进程&#xff0c;优化操作体验。以下是VMOS云手机的三大核心功能&#xff0c;帮助你更好地掌控《万龙觉醒》战局。 V…

通信工程学习:什么是QoS服务质量

QoS服务质量 在通信工程中&#xff0c;QoS&#xff08;Quality of Service&#xff0c;服务质量&#xff09;是一个至关重要的概念&#xff0c;它关乎网络性能的提升和用户体验的优化。QoS是网络的一种安全机制&#xff0c;旨在通过一系列技术和策略来优化网络资源的分配&#…

代码随想录打卡Day30

今天的题目还可以&#xff0c;第一题看了视频&#xff0c;看卡哥把问题转化成数学问题&#xff0c;把图画出来以后就会了&#xff0c;剩下两题没看视频直接AC的。 452. 用最少数量的箭引爆气球 这个题主要是画完图以后就很好理解了&#xff0c;需要先对区间按照区间左值进行排…

飞速了解Conda的作用和安装使用教程

当我们想要在github上克隆不同的项目下来运行时&#xff0c;会发现项目的语言环境或包的版本不同&#xff0c;出现版本冲突问题会导致程序无法运行、兼容性问题频出。我们常常需要管理多个项目&#xff0c;每个项目可能依赖于不同的包版本或编程语言环境。如果不加以管理&#…

华为OD机试 - 报文响应时间 - 贪心算法、位运算(Java 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

基于SpringBoot的准妈妈孕期交流平台

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架 工具&#xff1a;IDEA/Eclipse、Navicat 系统展示 首页 管理员登录 用户管理 早教…

C++ STL关联容器Set与集合论入门

1. 简介 Set&#xff08;集合&#xff09;属于关联式容器&#xff0c;也是STL中最实用的容器&#xff0c;关联式容器依据特定的排序准则&#xff0c;自动为其元素排序。Set集合的底层使用一颗红黑树&#xff0c;其属于一种非线性的数据结构&#xff0c;每一次插入数据都会自动…

【F的领地】项目拆解:小学教辅资料

项目介绍 虚拟资料项目的赛道其实一直可以做&#xff0c;实际上就是一个信息差项目。 知识付费是常青树&#xff0c;人天生有为知识付费的倾向。 而且虚拟资料通常一份 19~99 的资料有这方面需求很容易就能付款。 主要是产附属的流量再提问题。 我有个同乡&#xff0c;18年…

DDOS攻击学习-scapy使用python编写SYN拒绝服务攻击

文章目录 启动&配置发送数据怎么查看回答查看详细的数据sinff()hexdump() 使用python进行SYN拒绝服务攻击 安装npcap可以查看此教程 启动&配置 scapy#控制台输入如图所示可以查看IP等, 格式是 变量名 IP()/TCP()你可以查看相关信息 变量名.show()以上的值都可以进行…

2024第三届大学生算法大赛 真题训练2 解题报告 | 珂学家 | FFT/NTT板子

前言 题解 D是FFT板子题&#xff0c;这么来看&#xff0c;其实处于ACM入门题&#xff0c;哭了T_T. D. 行走之谜 思路: FFT 如果你知道多项式乘法&#xff0c;继而知道FFT&#xff0c;那题纯粹就是板子题&#xff0c;可惜当时比赛的时候&#xff0c;无人AC。 这题来简单抽象…

最好磁吸充电宝是哪个牌子?目前公认好用磁吸充电宝排行榜!

在现代生活中&#xff0c;移动设备的普及使得充电宝成为了人们日常出行必备的工具。尤其是磁吸充电宝&#xff0c;以其便捷的使用体验和高效的充电速度&#xff0c;逐渐受到消费者的青睐。然而&#xff0c;在选择充电宝时&#xff0c;安全性能是不可忽视的重要因素。一个好的充…

Redis入门1

Redis简介 Redis是一个基于内存的 key-value 结构数据库。 基于内存存储&#xff0c;读写性能高 适合存储热点数据(热点商品、资讯、新闻) 企业应用广泛 官网:https://redis.io 中文网:https://www.redis.net.cn/ window版启动命令 redis-server.exe redis.windows.con…