如何在 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 旨在帮助人们通过在 char
和 wchar_t
之间映射文字以及在 A
和W
变体。但那些日子早已一去不复返了。
在这种情况下正确的解决方案是完全忽略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::wstring
是 wchar_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 使用UNICODE
、TCHAR
和TEXT()
。 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的主要内容,如果未能解决你的问题,请参考以下文章