文章目录

  • 起因
  • 经过
  • 结果
  • 收获
  • 后记

起因

namespace未定义标识符 未定义标识符i_控制变量

用Windows api写程序的时候,使用CreateWindow函数,用vs跑会报错,如上。 通过控制变量来排查错误,明白两点:

  1. 控制变量应该先从每个参数开始怀疑
  2. 未定义标识符其实说的是文本未定义【当第二个变量进行变化的时候,这个标识符会变化】

我的代码:

check_box[i] = CreateWindow(
	TEXT("button"), TEXT(&check_text[i]),
	WS_CHILD | WS_VISIBLE | BS_LEFT | BS_AUTOCHECKBOX/*复选框*/,
	x, y, 50, 26,
	hWnd, (HMENU)id_tmp, hInst, NULL
);

经过

微软中的定义:

void CreateWindowW(
   lpClassName,
   lpWindowName,
   dwStyle,
   x,
   y,
   nWidth,
   nHeight,
   hWndParent,
   hMenu,
   hInstance,
   lpParam
);

第二个参数,我开始把text当成了一个函数,然后只顾着传递参数了,现在踩了坑才知道这是个宏。

关于该宏

这个宏的作用是:标识一个字符串为宽字符字符串,Unicode

为什么要用这个宏呢?显然是要匹配第二个参数类型,第二个参数是LPCTSTR类型的,也就是CONST TCHAR *类型,关于微软的数据类型可以看它的官方文件

而我定义的变量是char类型的数组,我当然要转换一下,转换方法是使用swprintf函数【1】

与该函数类似的函数sprintf的使用方法有如下例子:

j  = sprintf( buffer,    "   String:    %s\n", s ); // C4996
   j = sprintf( buffer, "   Character: %c\n", c ); // C4996
   j = sprintf( buffer, "   Integer:   %d\n", i ); // C4996
   j = sprintf( buffer, "   Real:      %f\n", fp );// C4996

官网是这样说的

但是我的vs好像又不支持:

namespace未定义标识符 未定义标识符i_字符串_02

递归查询各种资料绕了一大圈(包括去找什么string到wchar_t的转换啦,去官网反复看sprintf、_sprintf_l、swprintf, _swprintf_l、__swprintf_l这些的定义啦等等,qswl)后才知道,在swprintf中要写成这样:"%S"【大写】,才可以转换字符串。而这一点,在本文中带有上标【1】的博客里已经写出来了。我反复去世。使我找到错误的是官方的另一个链接。这个链接详细阐述了printf和wprintf函数的输出格式问题,syntax……

结果

修改代码为:

TCHAR buffer[12];
swprintf(buffer, L"%S", check_text[i]);
check_box[i] = CreateWindow(
	TEXT("button"), buffer[i],
	WS_CHILD | WS_VISIBLE | BS_LEFT | BS_AUTOCHECKBOX/*复选框*/,
	x, y, 50, 26,
	hWnd, (HMENU)id_tmp, hInst, NULL
);

然后vs终于不报错了。我都不敢运行了,祝我好运……

收获

附上一个Windows api手册和微软中文官网

  1. 对syntax转换有了一定了解,深深记住了只要我想到的,别人就一定已经做过了,开发程序的人员一定做得比我需要得更普适
  2. 发现了微软的官网这个好东西,这个手册真棒!有很多开发相关的知识,但是用好它的前提是熟练它的结构和搜索引擎

后记

后来,我发现我的程序还是无法运行:

namespace未定义标识符 未定义标识符i_namespace未定义标识符_03

然后我想到了从定义的位置开始就用Unicode:

  1. 改前:
  2. 改后: