在 C++ 中将 HWND 转换为十六进制字符串

3

在C++中将HWND转换为十六进制字符串,最好的方法是什么?我的意思是同时带有"0x"前缀。

HWND hWnd = FindWindow(L"Notepad", L"Untitled - Notepad");
MessageBox(nullptr, LPCWSTR(hWnd), L"Hello World!", MB_ICONINFORMATION | MB_OK | MB_DEFBUTTON1);

但是我希望输出结果为0x00000000(假设未打开记事本窗口),但它总是返回一个空字符串。我也尝试了这个答案,但最终返回的是0000000000000000。是否有人能帮我解决这个转换问题?
3个回答

4

这是:

HWND hwnd = FindWindowW(NULL, L"Untitled - Notepad");
std::wostringstream ss;
ss << std::hex << hwnd;
std::wstring strTitle = ss.str();
MessageBoxW(NULL, L"Caption message", strTitle.c_str(), MB_OK);

2
为了获得十六进制数的字符串表示,需要在stringstream中插入0x字面量,后跟一个句柄:
#include <Windows.h>
#include <sstream>
#include <iostream>

int main(){
    HWND hWnd = FindWindow(L"Notepad", L"Untitled - Notepad");
    std::stringstream ss;
    ss << "0x" << hWnd;
    std::cout << ss.str();
}

如果您需要在消息框中打印结果,请使用宽字符串流:
#include <Windows.h>
#include <sstream>

int main(){
    HWND hWnd = FindWindow(L"Notepad", L"Untitled - Notepad");
    std::wstringstream wss;
    wss << "0x" << hWnd;
    MessageBox(NULL, wss.str().c_str(), L"Hello World!", MB_ICONINFORMATION | MB_OK | MB_DEFBUTTON1);
}

以上建议在记事本未打开时给我返回 0x0000000000000000,打开时返回 0x0000000000xxxxxx,但我期望它返回 0x000000000x00xxxxxx。 :-) - Blueeyes789

1
你所做的不是转换。你只是将 hWnd 强制转换为字符串指针。几乎总是它不会指向有效的字符串,当你尝试将其作为字符串打印时会产生未定义的行为。
要正确地执行此操作,您应将 hWnd 的位视为整数,并在显示在消息框中之前将其打印到某个缓冲区中作为十六进制数。
#include <sstream>
#include <cstdint>
#include <iomanip>

//.....

std::wstringstream ss;
ss << std::hex << L"0x" << std::setw(16) << std::setfill(L'0') << 
    *reinterpret_cast<uint64_t*>(&hWnd) << std::endl;
MessageBox(nullptr, ss.str().c_str(), L"Hello World!",
    MB_ICONINFORMATION | MB_OK | MB_DEFBUTTON1);

注意:

1)stringstream是C++风格的sprintf。它的str()方法返回std::string,所以要获取C风格指针,你应该在其上调用c_str

2)我没有Windows来检查HWND实际上是什么。因此,请检查它的大小并使用适当的整数类型代替uint64_t。这很重要,因为如果你使用了太宽的类型,你将得到垃圾或甚至访问冲突。更好的方法是使用像这里讨论的整数类型模板。

3)可能,你需要std::wstringstream,因为你正在使用MessageBox的宽字符版本。

4)装饰。 ss << *reinterpret_cast<uint64_t*>(&hWnd)只是向ss打印原始十六进制数字,因此要获得正确的格式,你应该进行微调,设置适当的填充和填充字符。例如,这将导致所有整数被打印为带有前导零的16位数字:

ss << std::setw(16) << std::setfill(L'0') ...

其中setwsetfill函数来自于iomanip头文件。同时,打印0x前缀是你的职责,而不是stringstream的。还需要查看std::showbase


我将尝试通过将uint64_t更改为另一种类型来再次尝试...... :-},现在当记事本打开时,我接近预期的结果。它输出了一个六位数的十六进制数,但我希望输出一个八位数的十六进制数,如0x00000000 - Blueeyes789
@Blueeyes789 我更新了我的答案。同时在Windows上进行了检查,它可以正常工作。 - Sergey
这个可能有效,但是我现在无法编译它,C++ 给出了两个 E0135 错误,告诉我 namespace "std" 没有成员 "setw"namespace "std" 没有成员 "setfill"。我只包含了你在这里展示的头文件。 - Blueeyes789
不用了,谢谢。我忘了它,我现在会把它包含进去。 - Blueeyes789
1
@Blueeyes789 如果你想用正则表达式解决问题,那么你就有两个问题 :) 这可以更容易地完成:http://en.cppreference.com/w/cpp/io/manip/uppercase - Sergey
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接