Windows编程资源,菜单资源,图标资源,光标资源,上下文菜单,字符串资源,加速键资源

news2024/12/23 14:20:52

Windows资源是一种二进制数据,由链接器链接进程序成为程序的一部分,通过资源的方式可以很方便的对应用程序进行扩展。在Windows中资源可以是系统自定义的,也可以是用户自定义的。在本篇文章中为大家讲解菜单资源,上下文菜单,图标资源,光标资源,加速键资源的创建方法,这里我使用的编译器为visual studio2022版本。

文章目录

  • 一.菜单资源
    • 1.菜单分类
    • 2.如何创建菜单资源
    • 3.实操展示
  • 二.上下文菜单
    • 1.显示上下文菜单(右键菜单)
    • 2.上下文菜单中的WM_RBUTTONUP消息
    • 3.WM_CONTEXTMENU消息
  • 三.图标资源,光标资源
    • 1.添加图标资源
    • 2.加载图标资源
    • 3.添加光标资源
    • 4.加载光标资源
    • 5.设置资源
    • 5.WM_SETCURSOR消息
  • 三.字符串资源
  • 四.加速键资源
    • 1.添加加速键资源
    • 2.加速键资源的使用


一.菜单资源

1.菜单分类

  • 窗口顶层菜单
  • 弹出式菜单
  • 系统菜单
  • HMENU类型表示菜单,ID表示菜单项

2.如何创建菜单资源

对于目前的编译器,我们自己添加资源还是非常容易的,我们只需要使用可视化图形界面就可以。

  • 1.添加菜单资源
    • <1>.右键单击资源文件,选择添加–>资源
      添加菜单资源
    • <2>.选择添加Menu资源 添加Menu资源
    • <3>.添加想要的菜单资源,并且设置消息ID
      添加想要的菜单资源
  • 2.获取本进程菜单句柄
HMENU LoadMenu(
	HINSTANCE hInstance;         //包含要加载的菜单资源模块的句柄
	LPCSTR lpMenuName            //菜单资源的名称
);
  • 3.加载菜单资源
    • <1>.注册窗口类时设置菜单(lpszMenuName)
    • <2>.创建窗口时,传参设置菜单
    • <3>.在主窗口WM_CREATE消息中使用SetMenu函数设置菜单
SetMenu(
	HWND hWnd,        //窗口句柄
	HMENU hMenu,      //菜单句柄
);设置成功,返回非零

在这里对SetMenu函数不做过多的解释了,大家可以到MSDN官方文档解释SetMenu函数中查看该函数的详细介绍。

  • 4.处理菜单消息
    在学习处理菜单消息之前,我们来学习一种常见的消息类型:WM_COMMAND
    • 发出时间:当用户从菜单中选择命令项,空间将通知消息发送到其父窗口或翻译快捷键击时发送。
    • 附加信息
      • wParam:
        • HIWORD:对于菜单为0
        • LOWORD:菜单项的ID
      • lParam:对于菜单为0

3.实操展示

我们来使用WM_COMMAND消息来处理菜单按钮:
设置菜单:
菜单编辑
回调函数处理:

LRESULT CALLBACK WindowProc(
	IN  HWND hwnd,
	IN  UINT uMsg,
	IN  WPARAM wParam,
	IN  LPARAM lParam
)
{
	char output[256] = { 0 };
	switch (uMsg)
	{
	//常见消息
	case WM_DESTROY: {
		PostQuitMessage(0);
		break;
		}
	case WM_SYSCOMMAND: {
		sprintf(output, TEXT("检测到WM_COMMAND消息\n"));
		WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
		break;
	}
	case WM_CREATE: {
	sprintf(output, "检测到WM_CREATE消息,将创建窗口。\n");
		WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
		break;
	}
	case WM_SIZE: {
		sprintf(output, "lParam:窗口宽变化为:%d,窗口高变化为:%d \n", HIWORD(lParam), LOWORD(lParam));
		WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
		break;
	}
	//菜单命令消息
	case WM_COMMAND: {
		switch(LOWORD(wParam)) {
			case MY_OPEN: {
				sprintf(output, "打开按钮被点击,请到回调函数中做具体处理。\n");
				WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
				break;
			}
			case MY_QUIT: {
				sprintf(output, "退出按钮被点击,请到回调函数中做具体处理。\n");
				WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
				break;
			}
			case IDM_ABOUT: {
				sprintf(output, "帮助按钮被点击,请到回调函数中做具体处理。\n");
				WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
			}
			case MY_NEWFILE: {
				sprintf(output, "打开新文件按钮被点击,请到回调函数中做具体处理。\n");
				WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
				break;
			}
			case MY_LASTTIMEFILE: {
				sprintf(output, "上次打开文件按钮被点击,请到回调函数中做具体处理。\n");
				WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
				break;
			}
		}
		break;
	}
	//键盘消息
	case WM_KEYDOWN: {
		sprintf(output, "检测到WM_KEYDOWN消息,键码值:%d.\n", wParam);
		WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
		break;
	}
	case WM_KEYUP: {
		sprintf(output, "检测到WM_KEYUP消息,键码值:%d.该按键被放开\n", wParam);
		WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
		break;
	}
	//鼠标消息
	case WM_LBUTTONDOWN: {
		sprintf(output, "检测到WM_LBUTTONDOWN消息,鼠标左键被按下。\n");
		WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
		break;
	}
	case WM_LBUTTONUP: {
		sprintf(output, "检测到WM_LBUTTONUP消息,鼠标左键被放开。\n");
		WriteConsole(g_hOUTPUT, output, strlen(output),0,0);
		break;
	}
	case WM_RBUTTONDOWN: {
		sprintf(output, "检测到WM_RBUTTON消息,鼠标右键被按下。\n");
		WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
		break;
	}
	case WM_RBUTTONUP: {
		sprintf(output, "检测到WM_RBUTTON消息,鼠标右键被放开。\n");
		WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
	}
	case WM_MOUSEMOVE: {
		sprintf(output, "检测到WM_MOUSEMOVE消息,鼠标移动中,鼠标位置(%d,%d).\n", LOWORD(lParam), HIWORD(lParam));
		WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
		break;
	}
	case WM_MOUSEWHEEL: {
		sprintf(output, "鼠标滚轮滚动中,偏移量:%d,鼠标当前位置(%d,%d)\n",HIWORD(wParam), LOWORD(lParam), HIWORD(lParam));
		WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0);
		break;
	}
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

我们来看看处理效果:
WM_COMMAND消息处理

二.上下文菜单

1.显示上下文菜单(右键菜单)

MSDN官方文档解释TrankPopupMensu函数

BOOL TrankPopupMenu(
	HMENU hMenu,      //要显示的快捷菜单的句柄。
	UINT nFlags,      //指定显示方式
	int x,
	int y,            //x,y分别为快捷菜单位置,x为水平位置,y为垂直位置(屏幕坐标系)
	int nReserved,    //保留,必须为0
	HWND hWnd,        //拥有快捷菜单的窗口句柄
	const RECT* prcRext  //已忽略
	);

注意: 这里的第一个参数hMenu,可以通过CreatePopopMenu函数来创建一个新的快捷菜单,也可以通过GetSubMenu函数来检索与现有菜单项关联的子菜单句柄来获取句柄。
这个函数是阻塞函数

2.上下文菜单中的WM_RBUTTONUP消息

鼠标右键被放开为窗口坐标系坐标,如果要转化为屏幕坐标系的话,请使用ClientToScreen函数。

3.WM_CONTEXTMENU消息

MSDN官方文档结束WM_CONTEXTMENU消息

  • 产生时间:鼠标右键被放开时
  • 附加信息
    • wParam:右键点击的窗口句柄
    • lParam:
      • LOWORD:x
      • HIWORD:y (注意是屏幕坐标系)

我们在讲解鼠标消息的时候,鼠标右键被放开时会产生WM_RBUTTONUP消息,这里的WM_CONTEXTMENU消息是在WM_RBUTTONUP消息之后产生的。

三.图标资源,光标资源

1.添加图标资源

像我们添加菜单资源一样,添加Icon资源
添加图标资源
添加好之后,我们可以选择自己画一个图标或者从外部添加图标,注意图标大小,一个图形文件中,可以有多个大小不同的图标。

2.加载图标资源

将图标资源设置好之后,我们需要拿到图标资源句柄
我们可以使用LoadIcon函数来获取图标句柄:
MSDN官方文档解释LoadIcon函数

HICON LoadIcon(
	HINSTANCE hInstance,     //图标资源的实例句柄
	LPCTSTR lpIconName       //要加载的图标资源的名称
);

获取到图标资源句柄之后,我们只需要在注册窗口时将图标资源句柄传给hIcon参数即可。

3.添加光标资源

像前文讲到的添加菜单资源,图标资源一样,我们只需要选择Coursor
添加光标资源
添加好光标资源后,每个光标还有FotSpot,是当前鼠标的热点,只有在这一点上,光标才起作用。

4.加载光标资源

添加好光标资源后,我们还是需要拿到光标资源句柄,我们可以使用HCURSOR函数来获取光标资源句柄。
MSDN官方文档解释LoadCursor函数

HCURSOR LoadCursor(
	HINSTANCE hInstance,        //光标资源句柄可以为0
	LPCTSTR lpCursorName        //光标资源名称
	);

当hInstance参数为0时,获取系统默认的光标资源

5.设置资源

  • 我们拿到光标资源句柄后,在注册窗口时,设置hCursor参数为我们拿到的光标资源句柄即可。
  • 我们也可以在创建窗口时,显示窗口之前,使用SetCursor函数来设置光标资源。

5.WM_SETCURSOR消息

  • 产生时间:如果鼠标导致光标在窗口移动,并且未捕获鼠标输入,则发送到窗口
  • 附加消息:
    • wParam:包含光标的窗口句柄
    • lParam:
      • LOWORD:当前区域代码(指定触发此消息的窗口,当进入菜单模式时,此字段为0)
      • HIWORD:当前鼠标消息ID

三.字符串资源

在这里我们讲一下,字符串资源到底有什么作用呢?
我们在做开发的时候,客户可能有时候让我们做中文版界面,有时候又想让我们改为英文版界面,这时候字符串资源就显得特别重要了,不让我们要改很多源码。
同样,我们到可视化图形界面来添加字符串资源
字符串资源

  • 获取字符串资源句柄
int LoadString(
	HINSTANCE hInstance,     //包含字符串资源的可执行文件的实例句柄
	UINT uID,      //要加载的字符串标识符
	LPTSTR lpBuffer,    //存放字符串的Buff
	int nBufferMax     //字符串Buff长度
	);

四.加速键资源

加速键资源这里定义的有点抽象了,其实就是快捷键。

1.添加加速键资源

我们还是添加资源–>添加Accelerator资源
添加加速键资源

2.加速键资源的使用

  • 加载加速键表

MSDN官方文档解释LoadAccelerstors函数
加载指定的加速器表。

HACCEL LoadAccelerators(
	HINSTANCE hInstance,      //模块的实例句柄
	LPCTSTR lpTableName       //要加载的加速表的名称
	);

这里注意,我们加载完加速表后,不能直接使用加速键表,我们还需要翻译加速键,
MSDN官方文档解释TranslateAccelerator函数,函数作用:处理菜单命令的快捷键。

int TranslateAccelerator(
	HWND hWnd,         //要翻译其消息的窗口句柄
	HACCEL hAccTable,  //加速器表的句柄
	LPMSG lpMsg        //指向Msg结构的指针,其中包括检索得到的消息
	);

那么加速器到底是怎么工作的?我们来写一段伪代码为大家讲解:

TranslateAcceleator(hWnd,hAccTable,&Msg){
	if(Msg.message != WM_KEYDOWN) return 0;
	根据Msg.wParam获知按键到底是哪个
	查表,到hAccelTable中比对是否存在该加速键
	if(没找到) return 0;
	else{
	SendMesage(hWnd,WM_COMMAND,ID_NEW....);
	return 0;
	}

今天的分享就到这里,如果文章中有错误之处,还请大家指出来,我会非常虚心得学习,希望我们共同进步!!!

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

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

相关文章

【LeetCode】617. 合并二叉树

1.问题 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新二叉树。合并的规则是&#xff1a;如果两个节点重…

Win11系统更新后网络速度变的很慢怎么办?

Win11系统更新后网络速度变的很慢怎么办&#xff1f;有用户将自己的电脑系统升级到了Win11之后&#xff0c;出现了一些问题。电脑在使用中出现了网络速度变慢的情况。而且其它的设备在连接网络后速度是正常的&#xff0c;那么这个问题要怎么解决&#xff1f;来看看以下的方法分…

SpringBoot+RXTXcomm实现Java串口通信 读取串口数据以及发送数据

记录一下使用SpringBootRXTXcomm实现Java串口通信&#xff0c;使用Java语言开发串口&#xff0c;对串口进行读写操作。 RXTXcomm.jar这个包支持的系统较多&#xff0c;但是更新太慢&#xff0c;在win系统下使用没有问题&#xff0c;但是在centos的工控机系统里使用读取和发送有…

vmstat 粗查系统判断瓶颈

vmstat 1 5 每 1 秒显示一次 &#xff0c; 一共显示 5 次后结束 memory 内存 swap 虚拟磁盘&#xff0c;交换分区 io 磁盘 system 系统进程 rrun 多少个进程在跑&#xff0c;包括在排队等待cpu处理的进程b block 多少个进程处于卡死状态。 除CPU外的资源如网络、…

视频播放方案

video插件播放m3u8格式视频(存原生) 这里使用原生的javascript实现m3u8格式视频播放。 使用了包括video.min.js库和HLS插件。 1-基础使用 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>Video.js HLS Example</title…

MYSQL高级语句

实验用表 create table location (Region char(20),Store_Name char(20)); insert into location values(East,Boston); insert into location values(East,New York); insert into location values(West,Los Angeles); insert into location values(West,Houston); location…

如何解决请求参数为JSON时,采用IO流读取,只能请求一次的问题?

如何解决请求参数为JSON时&#xff0c;采用IO流读取&#xff0c;只能请求一次的问题&#xff1f; 一、错误演示1. 创建项目&#xff0c;添加所需依赖2. 配置redis环境3. 写一个简单的测试请求4. 写一个拦截器&#xff0c;拦截请求5. WebConfig 注册拦截器6. 测试请求 二、问题解…

vue问题

一、路由 hash模式&#xff08;location.hash hashchange 事件&#xff09; hash 模式的实现方式就是通过监听 URL 中的 hash 部分的变化&#xff0c;触发haschange事件&#xff0c;页面做出不同的响应。但是 hash 模式下&#xff0c;URL 中会带有 #&#xff0c;不太美观。 h…

【多线程初阶三】简单了解wait和notify方法~

目录 &#x1f31f;1、wait() &#x1f31f;2、notify() &#x1f31f;1、wait() &#xff08;1&#xff09;wait()方法与notify()方法都是Object类中的方法。 &#xff08;2&#xff09;wait()是让线程等待一段时间&#xff0c;死等——>状态WAITING:没有时间限制的等待.…

MySQL 高级(进阶) SQL 语句一

一、高级SQL语句&#xff08;进阶查询&#xff09; 先准备2个表 一个location表&#xff1a; use kgc; create table location (Region char(20),Store_Name char(20)); insert into location values(East,Boston); insert into location values(East,New York); insert int…

如何判断CRM软件的好坏?2023年CRM系统排行榜前三名是什么?

CRM客户管理系统经过20余年的发展&#xff0c;收获了越来越多企业的认可&#xff0c;成为企业数字化转型必不可少的一环。很多企业都有上线CRM软件的计划&#xff0c;但精准的找到一款适合自身的产品十分不易&#xff0c;今天我们就来盘点2023年CRM软件排行榜。 一、CRM的含义…

Intellij中使用Spotless 格式化代码

Spotless简介 在一些大型项目或开源项目&#xff0c;由于开发人员太多&#xff0c;导致各个代码格式不统一。会让整体项目的代码可读性变差。统一代码格式使用maven中的Spotless插件就是不错的选择。 Spotless 是一个代码格式化工具&#xff0c;它有以下功能&#xff1a; 支…

300. 最长递增子序列

300. 最长递增子序列 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子…

tp6 对接阿里云短信

1、获取AccessKey ID,AccessKey Secret&#xff0c;第一次会提示需要创建 2、添加签名 3、创建模板 composer版本太老了&#xff0c;可能会导致下载失败&#xff0c;建议升级下版本 官方提供的最新依赖版本&#xff0c;我的会报错&#xff0c;下载不了&#xff0c;提示用2.0.…

Android Studio 下真机调试

文章目录 一、开启真机调试二、断开真机调试 一、开启真机调试 准备USB调试线&#xff0c;一端插在电脑USB接口上&#xff0c;另一端插在手机充电口上。 下面以自己的手机&#xff08;huawei nova 5 &#xff09;为例&#xff1a;点击手机界面上的设置应用。 然后往下找到 【关…

经典神经网络(1)LeNet及其在Fashion-MNIST数据集上的应用

经典神经网络(1)LeNet 1、卷积神经网络LeNet 之前对于Fashion-MNIST服装分类数据集&#xff0c;为了能够应⽤softmax回归和多层感知机&#xff0c;我们⾸先将每个大小为28 28的图像展平为⼀个784维的固定⻓度的⼀维向量&#xff0c;然后⽤全连接层对其进⾏处理&#xff0c;此…

函数式接口的介绍和使用(FunctionInterface)——Consumer,Supplier,Predicate、Function

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法&#xff0c;但是可以有多个非抽象方法的接口。 函数式接口可以被隐式转换为 lambda 表达式。 函数式接口都添加了 FunctionalInterface 注解&#xff0c;这个是jdk1.8才引进的。例如 因为函数式接口里面只是…

【C++】| 01——泛型编程 | 模板

系列文章目录 【C】| 01——泛型编程 | 模板 文章目录 1. 认识泛型编程2. 函数模板1.1 函数模板的语法1.1.1 定义模板1.1.2 应用模板实现函数1.1.3 使用模板函数(实例化)1.1.3.1 隐式使用(实例化)1.1.3.2 显式使用(实例化)1.1.3.3 使用函数模板的注意事项(实例化) 2. 类模板2.…

第1章 Nginx简介

基于 Nginx版本 1.14.2 &#xff0c;Tomcat版本 9.0.0 演示 第1章 Nginx简介 1.1 Nginx发展介绍 Nginx &#xff08;engine x&#xff09; 是一个高性能的Web服务器和反向代理服务器&#xff0c;也可以作为邮件代理服务器。 Nginx 特点是占有内存少&#xff0c;并发处理能力…

南京邮电大学数据库实验二(DBMS的数据库保护)

文章目录 一、实验目的和要求二、实验环境(实验设备)三、实验原理及内容(1) DBMS的数据库保护功能(2) 安全控制中的访问控制机制(3) 事务的提交与回滚(4) 并发控制的锁机制 三、实验内容1.以root账户登录数据库管理系统&#xff0c;创建用户U1和U2&#xff0c;密码自定。2.创建…