如何在 Windows 上将 Qt QString 转换为 LPCTSTR

Posted

技术标签:

【中文标题】如何在 Windows 上将 Qt QString 转换为 LPCTSTR【英文标题】:How to convert a Qt QString into an LPCTSTR on Windows 【发布时间】:2018-06-25 15:34:48 【问题描述】:

我试图打开注册表并修改它。这就是我打开注册表的方式:

HKEY hKey;
LPCTSTR subKey = TEXT("a registry subkey to be opened");
RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_ALL_ACCESS , &hKey);

但是这里有一个问题,我想使用QString 务实地更改子键。并把QString 像这样:

QString subKeyString = QString("%1").arg(subKeyName);
LPCTSTR subKey = TEXT(subKeyString); //but it's not working here

我以为是因为我没有将QString 更改为LPCTSTR,我尝试了这个解决方案,但我仍然无法找到将自定义QString 放入TEXT 宏的方法。我不太确定引擎盖下的 WinApi,我只是尝试了我可能做的事情。 有什么办法可以解决这个问题吗?

编辑: 这是我将QString 转换为LPCTSTR 的方法:

QString testString = "converting QString to LPCSTR";
QByteArray testStringArr = testString.toLocal8Bit();
LPCSTR lp = LPCSTR(testStringArr.constData()); //the QString is converted to LPCTSTR
//but when I put the LPCSTR to the TEXT macro, the error is still there, like the next line below will not complie
LPCSTR lp = TEXT(LPCSTR(testStringArr.constData())); //This line will not work

【问题讨论】:

看***.com/questions/28090577/… @infixed 我确实看到了一些类似的解决方案,但我认为只需将QString 转换为LPCTSTR,我的问题仍然存在。我将编辑我的问题,以便您更清楚地知道我遇到了什么错误。 仅供参考,QSettings 类提供了 Qt 和 Windows 注册表之间的一些集成,尽管它可能适用于您的情况。 @walkingTarget 我尝试使用QSettings 将注册表修改为我需要的,但不工作,除了我使用本机WinApi。所以当我使用windows api时,我遇到了这个问题。我编辑了我的问题,有什么解决方案吗? TEXT 就像 QStringLiteral... 在相同的情况下使用:当您传入字符串时。 【参考方案1】:

TEXT() 宏仅适用于编译时文字,不适用于运行时数据。 TCHAR 和相关 API 旨在帮助人们通过在 charwchar_t 之间映射文字以及在 AW 变体。但那些日子早已一去不复返了。

在这种情况下正确的解决方案是完全忽略TCHAR,只关注Unicode。 QString 是 Unicode 字符串的包装器。因此,请仅使用基于 Unicode 的注册表 API 函数并假装 TCHAR 不存在。

在 Windows 上,基于 Unicode 的 API 需要 UTF-16 编码的 wchar_t 字符串。使用QString::toStdWString() 方法获取std::wstring,它是wchar_t 字符串的C++ 包装器:

QString subKeyString = QString("%1").arg(subKeyName);
std::wstring subKey = subKeyString.toStdWString();
HKEY hKey;
RegOpenKeyExW(HKEY_LOCAL_MACHINE, subKey.c_str(), 0, KEY_ALL_ACCESS, &hKey);

或者,您可以使用QString::utf16() 方法。但是,它返回一个 const ushort* 指针,因此您必须将其类型转换为 const wchar_t*

QString subKeyString = QString("%1").arg(subKeyName);
LPCWSTR subKey = reinterpret_cast<LPCWSTR>(subKeyString.utf16());
HKEY hKey;
RegOpenKeyExW(HKEY_LOCAL_MACHINE, subKey, 0, KEY_ALL_ACCESS, &hKey);

【讨论】:

Paul 的回答是否避免了构建std::wstring 的需要? (在想要调用 Windows API 的特定情况下,当然,这可能是您想要 std::wstring 的其他原因。 @PaulSanders Win32 Unicode API 需要 wchar_t* 字符串。 std::wstringwchar_t* 字符串包装器,因此它“正常工作”。 utf16() 也可以工作,只是因为 Win32 API 在 Windows 上使用 wchar_t* 来表示 UTF-16。 当然,但仍然。无论如何,发表我自己的微薄贡献。【参考方案2】:

TEXT 宏应该有助于维护应用程序的非 Unicode 和 Unicode 版本。取决于是否定义了_UNICODE(或UNICODE,不记得了)。 TEXT("foo") 将扩展为 L"foo" 或只是 "foo"。同样,CreateWindow 将是采用 WCHAR* 参数的 CreateWindowW 或采用 CHAR* 参数的 CreateWindowA

考虑到现在是 2018 年,我建议您忘记应用程序的 TEXT 宏和非 Unicode 版本。 QString::utf16() 将返回 WinAPI 期望的 UTF16 字符串。如果使用“Native wchar_t”编译器设置进行编译,则需要将utf16() 返回的内容转换为WCHAR*。如果“Native wchar_t` 被关闭,它将照原样工作。

【讨论】:

Win32 API 使用UNICODETCHARTEXT()。 C 运行时库分别使用_UNICODE_TCHAR_T() @Remy 我不确定我是否理解这一点。正如保罗所说,您需要做的(取决于您的编译器(标志)是将QString::utf16()返回的指针转换为WCHAR *。然后您可以将它传递给任何Win32 API调用,就像您自己在编辑中显示的那样(我会转换为WCHAR * 而不是wchar_t *,因为这是声明这些 API 的方式,尽管实际上这并不重要)。 @PaulSanders 该评论与“取决于是否定义了_UNICODE(或UNICODE,不记得已经定义)”部分有关保罗关于TEXT 宏的回答。该评论与Qt无关。关于 Qt,如果您使用 QString::utf16(),则必须对返回的指针进行类型转换,因为它返回为 const ushort* 而不是 const wchar_t*,这是 Win32 API 所期望的。虽然这两种类型都适用于 Windows 上的 UTF-16。 @PaulSanders 至于“Native wchar_t”,Paul 指的是 MSVC 的 /Zc:wchar_t parameter。 QString::utf16() 返回一个 const ushort* 指针。如果启用了/Zc:wchar_t,则wchar_t 是一种不同的数据类型,因此您必须将const ushort* 类型转换为const wchar_t* 才能将其与Win32 API 一起使用。但是如果/Zc:wchar_t 被禁用,wchar_t 只是ushort 的别名,因此您可以将const ushort* 原样与 Win32 API 一起使用。 @Remy 哦,对了,对不起。我以为你的第一条评论是写给我的,但显然不是。我将发布几个实用函数,它们可以消除类型转换的痛苦。【参考方案3】:

也许我参加聚会有点晚了,但要建立在其他两个答案的基础上,这样简单的事情就会给车轮上油:

inline const WCHAR *QStoWCHAR (const QString& qs)

    return (const WCHAR *) qs.utf16 ();

然后你可以做(​​例如):

RegOpenKeyExW (HKEY_LOCAL_MACHINE, QStoWCHAR (my_qstring), 0, KEY_ALL_ACCESS, &hKey);

【讨论】:

以上是关于如何在 Windows 上将 Qt QString 转换为 LPCTSTR的主要内容,如果未能解决你的问题,请参考以下文章

在windows下的QT编程中的_TCHAR与QString之间的转换

如何在 Mac OSX 上将 DCMTK 与 Qt 链接

关于在QT中使用<windows.h> 的Sleep的问题

QTcpSocket如何返回QString

在 Linux 机器上将 Qt 部署到 Windows

在 Windows 上将 TagLib 编译成 Qt C++ 项目