Win32窗口文本问题

3

我对Win32 API中的GetWindowTextA()函数有一些理解上的问题。

根据微软文档,nMaxCount是要复制到缓冲区lpString中的最大字符数,包括空字符。

那么,GetWindowTextA()函数是否会自动将空字符写入缓冲区lpString中,还是我需要手动将空字符添加到lpString中呢?

以下是来自微软文档的GetWindowTextA()定义:

int GetWindowTextA(
  [in]  HWND  hWnd,
  [out] LPSTR lpString,
  [in]  int   nMaxCount
);

这里是代码:

char M_Buff[20];

SetWindowTextA(M_SEND_EDIT_TEXT,"Hello World");

GetWindowTextA(M_SEND_EDIT_TEXT,M_Buff,20);  //Do i have to add  the null termination caracter into M_Buff myself  or it is put automatically ?

printf("String is %s\n",M_Buff);

实验表明,GetWindowText总是为您添加一个NULL。 GetWindowText返回返回的字符串长度,该长度可能在零到maxSize-1的范围内。 - Steve Valliere
1
@SteveValliere:标识符NULL(或nullptr)仅应用于指针,而不是字符。要指定空字符,通常会写成'\0' - Andreas Wenzel
1
“那么,GetWindowTextA()函数会自动将空终止字符写入缓冲区吗?” - 绝对是的。大多数Win32 API在多年前就已经加强了对字符串复制时的空终止保护。 - selbie
3个回答

3
如果GetWindowTextA()函数返回一个非零值以报告成功,则它还将在内存缓冲区中写入一个终止空字符。无需自己添加。
该函数的官方文档并没有明确指出它总是会向字符串写入空字符。它只明确指出了字符串被截断的边缘情况:
“如果字符串与缓冲区一样长或更长,则字符串将被截断并以空字符终止。”
但是,如果不对字符串进行截断,则此语句就没有意义。因此,可以安全地假定当字符串没有被截断时,它也会写入终止空字符。
此外,文档还声明如下:
“如果函数成功,则返回值是已复制字符串的字符数(不包括终止空字符)。”
此语句也暗示它将向缓冲区写入终止空字符。
此外,正如其他答案中指出的那样,参数类型LPSTR意味着在函数返回后缓冲区将以空字符结尾。

2
不幸的是,文档没有说明如果字符串比缓冲区短,结果是否以空终止。我知道它是这样的,如果它不是这样的话就很奇怪了。但我可以理解OP的困惑,因为这并没有明确说明。 - john
@john:是的,文档没有明确说明它会始终向字符串写入空字符。它只明确指出了当字符串被截断时的边缘情况。然而,如果在一般情况下字符串没有被截断,这个说法就没有意义了。因此,可以安全地假设它在字符串没有被截断时也会写入一个终止的空字符。 - Andreas Wenzel
1
@john:文档还指出:“如果函数成功,则返回值是已复制字符串的字符长度,不包括终止的空字符。”这也意味着正在写入空字符。我已经编辑了我的答案,包括这个参数。 - Andreas Wenzel

2
尽管 GetWindowTextA 函数的文档并没有完全明确如果返回的字符串没有被截断会发生什么(如果被截断了,则明确说明包括一个终止的空字符),但我们可以从 lpString 参数类型的定义推断出它应该始终以空字符结尾,这是因为它的定义是 LPSTR

该类型的文档 可得:

LPSTR      指向 8 位 Windows(ANSI)字符的以空字符结尾的字符串的指针。


2
只要查看正确的文档(特别是 SDK 头文件 winnt.h),就不需要太多猜测。有趣的部分在于,LPSTR 不仅是一个指针,它还带有一个SAL 注释
typedef _Null_terminated_ CHAR *NPSTR, *LPSTR, *PSTR;
自从GetWindowTextA使用LPSTR作为其_Out_参数类型,它也继承了SAL注释。如果在GetWindowTextA的实现中没有经过输出缓冲区的零结尾,那么将会产生构建错误,也就不会有User32.dll。如果您的系统中有User32.dll模块,则可以安全地假设其实现符合SAL注释。具体来说,传递给GetWindowTextA的缓冲区在返回时始终是以零结尾的(无论函数调用成功还是失败)。

如果传递的缓冲区是只读的且输入时未以null结尾,会怎样?或者如果它是一个无效的地址呢? - Adrian Mole
1
@adr 如果前提条件被违反,函数将不会做出任何承诺。形式参数 lpString 具有以下注释:_Out_writes_(nMaxSize)。它是一个输出参数(_Out_),因此输入时其内容被认为是不确定的。然而,整个缓冲区必须是可写的(_writes_(nMaxSize))。因此,缓冲区在输入时可能没有以 null 结尾,但需要是可写的,并且(显然)必须是有效的。 - IInspectable

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