开发过程优化·自定义鼠标右键菜单

news2025/1/4 5:49:05

为了改善日常工作中的开发体验,我希望在某个项目目录下点击鼠标右键的快捷菜单,让程序自动为该项目引入一个内部的工具库文件并挂载到项目中。

        实现该功能需要组装一些零碎的电脑应用知识,下面徐徐渐进依次说明:

1、在右键菜单中添加一级菜单

        1)运行“regedit”打开注册表编辑器;

        2)找到“HKEY_CLASSES_ROOT\Directory\Background\shell(针对文件夹空白处右键菜单)”,在左侧树shell下新建一个子项(例如:front_tools),并设置该子项右侧的默认值(该值是右键菜单中显示的文案,缺省则会使用子项的左侧树名称);

        3)在上述子项(front_tools)下新建一个子项“command”,在其右侧的默认值中设置想要调用的程序(例如:此处设置nodejs程序,若要执行JS脚本,可在程序后跟上脚本的绝对路径)。

        虽然上述方法可以实现添加菜单,但实际工作中,我们更需要的其实是个二级菜单,就像图中的“新建”菜单,里面可以包含很多子菜单。

2、在右键菜单中添加二级菜单

        1)添加二级菜单数据

        在注册表编辑器中找到“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell”,新建子项(例如:importCosUtil),并在其右侧默认数据中设置该二级菜单对应的中文文案(例如:引入腾讯云公共函数)。然后再在importCosUtil下新建子项command,并在其右侧设置要调用的应用程序(图例中我创建了两个二级菜单);

        2)创建一级菜单并与二级菜单建立关联

        在“HKEY_CLASSES_ROOT\Directory\Background\shell”下创建子项(例如:前端便捷工具),并在其右侧新建“字符串值”SubCommands,该字符串值对应的数据设置为想要关联的二级菜单的名称(例如:“importCosUtil;importOssUtil;”);

        此时,在文件夹中点击鼠标右键,即可看到自定义的菜单了。

        需要注意的是:一级菜单(即示例中的“前端便捷工具”)右侧的默认数据不要做修改,应保持显示“(数据未设置)”,否则当点击鼠标右键时,二级菜单无法显示。

3、编写脚本来添加右键菜单

        之前两节都是手动操作注册表,比较繁琐,我们需要编写一个安装脚本,双击运行脚本后自动添加右键菜单。因为注册表的部分内容与业务相关,所以我们结合整体方案思路来说明:

        1)使用批处理进行一键安装

        设置一个名为install.bat的批处理文件,用来一键安装程序,安装过程中会构建注册表脚本来实现添加右键菜单的操作;

        install.bat代码:

node install.js

        install.js代码:

const path = require('path');
const Registry = require('winreg');
let nodePath = path.join(process.env.NVM_SYMLINK, 'node.exe');
let copyPath = path.join(__dirname, 'commands', 'copy.js');
const methodToPromise = function (host, method) {
  return new Promise((resolve, reject) => {
    if (!host || !method) {reject('宿主名和方法名不能为空')}
    host[method](function (err) {
      if (err) {reject(err)}
      else {resolve(...arguments)}
    });
  })
}
let ret = (async function () {
  let regKey = new Registry({
    hive: Registry.HKCR,
    key: '\\Directory\\Background\\shell\\前端便捷工具'
  });
  await methodToPromise(regKey, 'create');
  // create方法创建的“(默认)”值不是“(数值未设置)”,需要用clear清空。
  await methodToPromise(regKey, 'clear');
  regKey.set('SubCommands', 'REG_SZ', 'importCosUtil;importOssUtil;', function (err) {
    if (err) {console.log(err)}
  });
  let regKey1 = new Registry({
    hive: Registry.HKLM,
    key: '\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CommandStore\\shell\\importCosUtil'
  });
  let regKey2 = new Registry({
    hive: Registry.HKLM,
    key: '\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CommandStore\\shell\\importOssUtil'
  });
  let regKey3 = new Registry({
    hive: Registry.HKLM,
    key: '\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CommandStore\\shell\\importCosUtil\\command'
  });
  let regKey4 = new Registry({
    hive: Registry.HKLM,
    key: '\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CommandStore\\shell\\importOssUtil\\command'
  });
  // let regVal3 = "\"\\\"C:\\Users\\Administrator\\AppData\\Roaming\\nvm\\v10.4.1\\node.exe\\\" \\\"E:\\public\\commands\\copy.js\\\" cosUtil.js \\\"%V\\\"\"";
  let regVal3 = `\"\\\"${nodePath}\\\" \\\"${copyPath}\\\" cosUtil.js \\\"%V\\\"\"`;
  let regVal4 = `\"\\\"${nodePath}\\\" \\\"${copyPath}\\\" ossUtil.js \\\"%V\\\"\"`;
  await methodToPromise(regKey1, 'create');
  await methodToPromise(regKey2, 'create');
  await methodToPromise(regKey3, 'create');
  await methodToPromise(regKey4, 'create');
  regKey1.set(Registry.DEFAULT_VALUE, 'REG_SZ', '引入腾讯云公共函数', function (err) {console.log(err)});
  regKey2.set(Registry.DEFAULT_VALUE, 'REG_SZ', '引入阿里云公共函数', function (err) {console.log(err)});
  regKey3.set(Registry.DEFAULT_VALUE, 'REG_SZ', regVal3, function (err) {console.log(err)});
  regKey4.set(Registry.DEFAULT_VALUE, 'REG_SZ', regVal4, function (err) {console.log(err)});
})();

        上述代码中,我是通过“winreg”这个依赖包来操作注册表的,因为操作注册表需要管理员权限,所以要以管理员身份运行批处理。

        其中一个难点在regVal3和regVal4的内容上,需要多层字符转义。其最终写入注册表的内容是:

"C:\Users\Administrator\AppData\Roaming\nvm\v10.4.1\node.exe" "e:\public\commands\copy.js" cosUtil.js "%V"

        2)点击右键菜单时的响应脚本

        当点击右键菜单时,系统会执行注册表command项中设置的命令,此处以“引入腾讯云公共函数”为例,command内容为

"C:\Users\Administrator\AppData\Roaming\nvm\v10.4.1\node.exe" "E:\public\commands\copy.js" cosUtil.js "%V"

        意即点击菜单后会执行copy.js这个本地脚本(将某个公共函数库拷贝到当前文件夹中)。

        copy.js代码:

const fs = require('fs');
const path = require('path');
const toolsNode = require('../libs/tools-node');
// 获取传递给脚本的参数(排除前两个默认参数)
const args = process.argv.slice(2);
let from = path.join(__dirname, '../resources/', args[0]);
let to = path.join(args[1], args[0]);
if (fs.existsSync(from) && fs.existsSync(args[1])) {
  toolsNode.copyFile(from, to);
}

        完成上述代码后,直接以管理员身份运行install.bat便可以自动添加右键菜单了。

4、结语

        上文示例中我只是把指定文件拷贝到当前目录,更多便捷操作可以自行编写相应脚本实现。本项目的目录结构设计如图所示:

5、附注

        上文中只用到了“文件夹空白处的右击菜单”,其它场景相关的注册表路径如下:

        1)只在文件右键菜单中添加菜单,相关的注册表路径为“HKEY_CLASSES_ROOT\*\shell”;

        2)只在桌面右击菜单中显示,路径为“HKEY_CLASSES_ROOT\DesktopBackground\Shell”;

        3)在桌面和文件夹空白处右击菜单都显示,路径为“HKEY_CLASSES_ROOT\Directory\Background\shell”;

        4)在选中文件夹的右击菜单中显示,路径为“HKEY_CLASSES_ROOT\Directory\shell”;

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

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

相关文章

搭建ZooKeeper分布式集群

ZooKeeper分布式集群部署旨在通过多节点协作实现高可用性和容错能力。本次实战以三台服务器(master、slave1、slave2)为例,详细介绍了从下载安装到配置启动的全过程。首先,下载并解压ZooKeeper安装包至/usr/local目录,…

elasticsearch-java客户端jar包中各模块的应用梳理

最近使用elasticsearch-java客户端实现对elasticsearch服务的Api请求,现对elasticsearch-java客户端jar包中各模块的应用做个梳理。主要是对co.elastic.clients.elasticsearch路径下的各子包的简单说明。使用的版本为:co.elastic.clients:elasticsearch-…

【AIGC】使用Java实现Azure语音服务批量转录功能:完整指南

文章目录 引言技术背景环境准备详细实现1. 基础架构设计2. 实现文件上传功能3. 提交转录任务crul4. 获取转录结果 使用示例结果示例最佳实践与注意事项总结 引言 在当今数字化时代,将音频内容转换为文本的需求越来越普遍。无论是会议记录、视频字幕生成&#xff0c…

InstructGPT:基于人类反馈训练语言模型遵从指令的能力

大家读完觉得有意义记得关注和点赞!!! 大模型进化树,可以看到 InstructGPT 所处的年代和位置。来自 大语言模型(LLM)综述与实用指南(Amazon,2023) 目录 摘要 1 引言 …

kafka开机自启失败问题处理

前言:在当今大数据处理领域,Kafka 作为一款高性能、分布式的消息队列系统,发挥着举足轻重的作用。无论是海量数据的实时传输,还是复杂系统间的解耦通信,Kafka 都能轻松应对。然而,在实际部署和运维 Kafka 的…

在Linux上获取MS(如Media Server)中的RTP流并录制为双轨PCM格式的WAV文件

在Linux上获取MS(如Media Server)中的RTP流并录制为双轨PCM格式的WAV文件 一、RTP流与WAV文件格式二、实现步骤三、伪代码示例四、C语言示例代码五、关键点说明六、总结在Linux操作系统上,从媒体服务器(如Media Server,简称MS)获取RTP(Real-time Transport Protocol)流…

蓝桥杯(Java)(ing)

Java前置知识 输入流: (在Java面向对象编程-CSDN博客里面有提过相关知识------IO流) // 快读快写 static BufferedReader in new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter out new BufferedWriter(new…

python钉钉机器人

上代码 #coding:utf-8 import sys import time import hmac import hashlib import base64 import urllib.parse import requeststimestamp str(round(time.time() * 1000)) secret 你的secret secret_enc secret.encode(utf-8) string_to_sign {}\n{}.format(timestamp, …

「Mac畅玩鸿蒙与硬件50」UI互动应用篇27 - 水果掉落小游戏

本篇教程将带你实现一个水果掉落小游戏,掌握基本的动态交互逻辑和鸿蒙组件的使用,进一步了解事件处理与状态管理。 关键词 UI互动应用水果掉落状态管理动态交互游戏开发 一、功能说明 水果掉落小游戏包含以下交互功能: 随机生成水果&#…

用 vue3 实现新年快乐

提前祝福大家新年快乐,今天用一个新年快乐的教程来结束这一年。 看下效果 在这个案例中,我们使用了 vue3 ,有一个浮动的新年快乐的字体,然后有一堆从下到上的小粒子,在文字背后有一个模拟烟花绽放的效果。 环境搭建…

QT集成IntelRealSense双目摄像头2,集成OpenGL

上一篇文章写了如何把IntelRealSense摄像头的SDK集成到QT项目,并成功采集数据,在没有用OpenCV的情况下完成色彩数据,以及深度数据的显示。 具体地址:https://blog.csdn.net/qujia121qu/article/details/144734163 本次主要写如何…

【模块一】kubernetes容器编排进阶实战之kubernetes pod Affinity与pod antiaffinity

pod Affinity与pod antiaffinity Pod Affinity与anti-affinity简介: Pod亲和性与反亲和性可以基于已经在node节点上运行的Pod的标签来约束新创建的Pod可以调度到的 目的节点,注意不是基于node上的标签而是使用的已经运行在node上的pod标签匹配。 其规则…

从百度云网盘下载数据到矩池云网盘或者服务器内

本教程教大家如何快速将百度云网盘数据集或者模型代码文件下载到矩池云网盘或者服务器硬盘上。 本教程使用到了一个开源工具 BaiduPCS-Go,官方地址 : https://github.com/qjfoidnh/BaiduPCS-Go 这个工具可以实现“仿 Linux shell 文件处理命令的百度网…

使用maven-mvnd替换maven大大提升编译打包速度

先上结论!!! 多模块清理并打包提升:约3.5倍 多模块不清理打包提升:约5.5倍 单模块提升:约2倍 从计算结果来看,多模块提升的效率更高。在使用mvnd package打包多模块式,可在控制台…

LeetCode - 初级算法 数组(删除排序数组中的重复项)

免责声明:本文来源于个人知识与公开资料,仅用于学术交流。 删除排序数组中的重复项 这篇文章讨论如何从一个非严格递增的数组 nums 中删除重复的元素,使每个元素只出现一次,并返回新数组的长度。因为数组是排序的,只要是相同的肯定是挨着的,所以我们需要遍历所有数组,然…

2024 年度总结

时光荏苒,2024 年即将画上句号,回顾这一年的写博历程,有付出、有收获、有成长,也有诸多值得回味与反思的瞬间。 一、内容创作 主题涉猎:这一年,我致力于探索多样化的主题,以满足不同读者群体的…

基于STM32位单片机的腕式运动体力监测装置设计

本设计基于STM32位单片机的腕式运动体力状态诊断系统装置。本系统内的使用的STM32单片机包含了心率检测电路、呼吸频率检测电路、OLED液晶显示电路、电源电路、蓝牙电路。通过心率传感器以及手指脉搏波动放大过后发送给比较器,结果处理后发送给单片机进行信息的收集…

LunarVim安装

LunarVim以其丰富的功能和灵活的定制性,迅速在Nvim用户中流行开来。它不仅提供了一套完善的默认配置,还允许用户根据自己的需求进行深度定制。无论是自动补全、内置终端、文件浏览器,还是模糊查找、LSP支持、代码检测、格式化和调试&#xff…

前端超大缓存IndexDB、入门及实际使用

文章目录 往期回顾项目实战初始化表获取列表新增表的数据项获取详情根据ID获取详情根据其他字段获取详情 删除数据 总结 往期回顾 在之前的文章中,我们介绍了IndexDB vs Cookies vs Session这几个的对比,但是没有做实际项目的演示,今天我们用…

面试题解,JVM的运行时数据区

一、请简述JVM运行时数据区的组成结构及各部分作用 总览 从线程持有的权限来看 线程私有区 虚拟机栈 虚拟机栈是一个栈结构,由许多个栈帧组成,一个方法分配一个栈帧,线程每执行一个方法时都会有一个栈帧入栈,方法执行结束后栈帧…