[原创](Modern C++)现代C++的字符串与Windows API交互的正确方式.

[简介]
常用网名: 猪头三
出生日期: 1981.XX.XX
QQ联系: 643439947
个人网站: 80x86汇编小站 https://www.x86asm.org
编程生涯: 2001年~至今[共22年]
职业生涯: 20年
开发语言: C/C++、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python
开发工具: Visual Studio、Delphi、XCode、Eclipse、C++ Builder
技能种类: 逆向 驱动 磁盘 文件
研发领域: Windows应用软件安全/Windows系统内核安全/Windows系统磁盘数据安全/macOS应用软件安全
项目经历: 磁盘性能优化/文件系统数据恢复/文件信息采集/敏感文件监测跟踪/网络安全检测

[序言]
在Windows系统中, 提供了大量的纯C接口的API, 比如最经典的SetWindowsText(), GetWindowsText(), 非常具有代表性, 因为它们涉及到了C语言的字符串指针的传递. 现在随着(Modern C++)现代C++的普及性, 为了代码更加纯粹和简单, 现在大多数都是用STL String的方式来处理指针的变换, 从而避免使用高损耗的CString类或者各种奇怪的ATL类. 

[第一种方式: std::wstring 处理]

​​​​​​std::wstring wstr_Test ;
::SetWindowTextW(hWnd, wstr_Test.c_str()) ;

[第二种方式: std::vector 分配字符串内存]

// +1 表示预留一个NUL结尾
const int int_Length = ::GetWindowsTextLength(hWnd) + 1 ;
std::vector<wchar_t> verctor_Buffer(int_Length) ;

[第三种方式: std::wstring 分配字符串内存]

// +1 表示预留一个NUL结尾
const int int_Length = ::GetWindowsTextLength(hWnd) + 1 ;
std::unique_ptr<wchar_t[]> whar_Buffer(new wchar_t[int_Length]) ;

//或者

// +1 表示预留一个NUL结尾
const int int_Length = ::GetWindowsTextLength(hWnd) + 1 ;
auto whar_Buffer = std::make_unique<wchar_t[]>(int_Length)

[std::vector, std::unique_ptr<wchar_t[]>如何接收字符串数据内容?]

1> std::vector<wchar_t> 方式接收, verctor_Buffer.data() 返回std::vector<wchar_t>管理的原始缓冲区起始指针

​​​​​​​::GetWindowTextW(hWnd, verctor_Buffer.data(), int_Length) ;

2> std::unique_ptr<wchar_t[]> 方式接收, whar_Buffer.get() 返回std::unique_ptr<wchar_t[]>管理的原始缓冲区起始指针

::GetWindowTextW(hWnd, whar_Buffer.get(), int_Length) ;

3> 接受到字符串数据之后, 可以使用深度复制, 赋值给其他变量

​​​​​​​std::wstring wstr_Text(verctor_Buffer.data()) ;
// 或者
std::wstring wstr_Text(whar_Buffer.get()) ;

[std::wstring如何接受字符串数据内容?][值得注意与学习]

const int int_Length = ::GetWindowsTextLength(hWnd) + 1 ;
std::wstring wstr_Text ;
wstr_Test.resize(int_Length) ;
::GetWindowTextW(hWnd, &wstr_Text[0], int_Length) ;
wstr_Test.resize(int_Length-1) ;

特别注意:
1> &wstr_Text[0], 表示获取std::wstring的原始缓冲区起始指针, 该缓冲区是具有可写权限
2> wstr_Test.resize(int_Length-1) ; 避免双NUL终止符号. 因为std::wstring的resize()会自动添加一个NUL终止符号, 由于之前::GetWindowsTextLength(hWnd) + 1代码已保证创建了一个NUL终止符号, 所以导致了双NUL终止符号, 因此需要通过wstr_Test.resize(int_Length-1)来去掉一个NUL终止符号.[另外一个细节: 通过std::unique_ptr类型, 可以方便的反复创建合适大小的内存, 而不用担心内存泄漏]
由于有些Windows API, 在传递参收之前需要预分配内存空间, 但是由于大小未知, 因此需要通过循环的方式去确认所需的内存大小, 比如经典的错误标志位: ERROR_MORE_DATA, 有了(Modern C++)现代C++的std::unique_ptr类型, 处理更加方便.

LONG long_error = ERROR_MORE_DATA;
auto whar_Buffer ;
DWORD dword_BufferLength =  /*根据当前实际情况初始化一个合理的大小*/
while (long_error == ERROR_MORE_DATA)
{
    // 分配内存
    whar_Buffer = std::make_unique<wchar_t[]>(dword_BufferLength);
    // 调用某个Windows API, 查询大小
    error = ::SomeApiCall(param1, param2, ..., whar_Buffer.get(), &dword_BufferLength);
}

// 成功获取字符串内容, 赋值到其他变量
std::wstring wstr_Text(whar_Buffer.get());

[总结]
上面的代码使用率是非常高的, 希望多大家有所帮助.

相关推荐

  1. 密码学:古老艺术现代科学交汇

    2024-05-12 20:32:03       15 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-05-12 20:32:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-12 20:32:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-12 20:32:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-12 20:32:03       20 阅读

热门阅读

  1. C++进阶——浅谈隐式转化

    2024-05-12 20:32:03       12 阅读
  2. 简述Redis过期策略及内存淘汰机制

    2024-05-12 20:32:03       10 阅读
  3. golang中三种线程安全的MAP

    2024-05-12 20:32:03       13 阅读
  4. SQL多表查询

    2024-05-12 20:32:03       8 阅读
  5. c++ 和c回调混合的一种实现

    2024-05-12 20:32:03       12 阅读
  6. Liunx软件包管理(上)

    2024-05-12 20:32:03       9 阅读
  7. 前端手写练习题及概念加深

    2024-05-12 20:32:03       9 阅读
  8. pip opencv-python其一失败原因解决方案

    2024-05-12 20:32:03       8 阅读
  9. C#中的隐式类型转换和显式类型转换

    2024-05-12 20:32:03       13 阅读