关于使用C++ QT 写注册表中包含\或者/的问题 设置程序兼容win8

首先,稍微介绍注册表:

1.什么是注册表:

简单来说,就是系统的配置文件,通过这些配置去管理软件硬件之类的。比如开机自启,你就可以通过修改注册表的某些项达到开机自启的效果。

2.长什么样:

在这里插入图片描述
注册表就是一个又一个的键值对,类似文件系统一样,一个键(文件夹)下面有许多的子健(文件),而注册表中的一条记录就是一个键值对,包括名称,值,以及这个值的类型。

值类型有以下几种:
在这里插入图片描述
有了这些基础(想更加深入的可以去百度或者wiki看)我们就可以开始对注册表进行操作了,windowsAPI提供了操作注册表的接口,当然,QT也同样提供了。

下面主要介绍我在工作中遇到的一个问题。
问题描述:设置某一个程序为兼容win8。
解决方式:在注册表HKEY_CURRENT_USER\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers下添加程序路径并且设置兼容模式(当然,你可以手动去设置=。=,不过你老大可能会请你喝茶)。结果如下图:
在这里插入图片描述

实现方式:

1.QT去读写注册表:QSetting类

优点:方便(qt已经帮你做了关于编码问题的处理,你只需要传入一个QString就ok了!)
缺点:面对一些特殊情况,你会很头疼
针对上面一个问题,如果你用QSetting去完成,你只会,fk,QT!
为什么呢了,想想我们要设置的名称是什么,是E:\tantou\Release\DeviceSimulator.exe,看源码:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
坑爹▄█▀█●啊,他会把你的用\\作为分隔符,把分隔出来的东西作为一个键(文件夹)而不是一条记录(文件) 你会见到类似下面的东西:
在这里插入图片描述
我相信,这绝对不是你想要的结果!!
当然,你用\或者/会出现其他情况(/可以写入,但是没效果,讲道理E:\tantou\Release\DeviceSimulator.exe和E:/tantou/Release/DeviceSimulator.exe在window中都是可以访问到这次程序的,但是在注册表中不行,可能也是和win内核调用的dll有关系吧,暂时没深入研究,而\的话==会被转义了,所以会乱码)。
总之,你没办法通过单纯的只使用QSettings来完成这个操作(你也可以去改源码再自己编译出一个dll使用,但是没必要),所以windowsAPI也就体现了他的威力。

2.windowsAPI去读写注册表:#include<atlbase.h >

优点:更加自由的操作方式
缺点:会遇到许多莫名其妙的乱码或者error

设置一个键值RegSetValueEx
函数定义:

LONG RegSetValueEx(HKEY hKey,//要设置的键的句柄
                                 LPCTSTR lpValueName,//要访问的键值的名称
                                 LPDWORD lpReserved,//保留值
                                 DWORD dwType,//要设置的数据的类型
                                 const BYTE *lpData,//要设置的健值
                                 DWORD cbData//数据的长度
                                );//这就是最主要的函数

继续上面的话题,当我们使用windowsAPI去操作的时候,当然也会有相应的麻烦,主要集中在转码问题上。首先,清楚一个东西:LPCTSTR就是一个字符指针,只是这个字符指针指向的字符串的编码不确定。
所以在使用windowsAPI提供的接口时(不仅仅是注册表方面,基本都有)我们会遇到很多类似这种报错:
在这里插入图片描述
遇到这种报错时,你可以通过以下步骤解决:
1.
改变项目的字符集。右击项目,在属性-》常规-》字符集中可以设置。改为unicode,或者多字节。
但是这样可行,为什么呢?其实,RegSetValueEx不是最底层的实现,他底层实现是依赖两个函数,通过不同的预处理定义去实现切换,其他源码中你也可以看见这种东西:
在这里插入图片描述
在这里插入图片描述
那么你改变字符集其实就是在你预处理定义中多了个UNICODE的定义。
2.
如果你是使用的是文本直接初始化LPCTSTR,比如:

LPCTSTR lpValue = “test”;

那么你可以直接改为:

LPCTSTR lpValue = _T(“test”);

当然,也可能你是使用一个char*去初始化,比如:

char* chStr = “test”;

那么这时候你可以通过MultiByteToWideChar去转换,以下代码就可以直接完成转换。也有其他转换方式,暂未比较差别,有兴趣可以去了解一下:

char* chRegistry = “test”;
 WCHAR wszClassName[256];   
 memset(wszClassName,0,sizeof(wszClassName));     
 MultiByteToWideChar(CP_ACP,0,chRegistry,strlen(chRegistry)+1,wszClassName,         sizeof(wszClassName)/sizeof(wszClassName[0]));    
 LPCTSTR lpRegistry = wszClassName;

如果以上两步还不能解决问题,那么看具体报错的位置,看使用的函数,看他到底想要什么。

敲重点

解决这种报错的思路最主要的还是打断点,多写几个变量暂存转换时的值,去查看到底是哪一步导致的乱码,再对症下药。

多说一点

使用这种方式还有一个地方需要注意的就是:
const BYTE lpData,//要设置的健值
DWORD cbData//数据的长度

这两个参数,大多数博客上面都是这样的:
在这里插入图片描述
对,没错,这样就基本可以完成我们的需求了,0或1,一些数值,但有些却不行。比如这次的兼容问题,要兼容win8的话,这个值需要设置为~ WIN8RTM。那么就涉及到char*到BYTE*的转换。其实包括上面的char*到LPCTSTR的转换你都可以强转,但是,会乱码。不过,这次你可以直接强转,而且强转之后的BYTE*并没有乱码,但是你写到注册表中的值却是乱码。如下图:
在这里插入图片描述
这里,我只能猜测他在函数内部其实是进行了到LPCTSTR的转换的。那么好,我也用LPCTSTR去赋值,使用LPCTSTR去强转到BYTE
,也不会有乱码。所以,在这种情况下,我这样去使用该函数:
在这里插入图片描述
在这里插入图片描述
虽然结果导向告诉我,这样的结果是乱码消失了,但是我仍然不能很确定的是因为他内部做了转到LPCTSTR的原因。

感想:

在工作中,很多时候我们都会遇到转码的问题,而且也是个大问题,看来是时候找个机会去集中整理一下编码的问题相关资料了。

8198qwy,第一次写博客,有不足或者错误之处,请各位严厉的支出并且批评@-@

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值