起因
用Windows api写程序的时候,使用CreateWindow函数,用vs跑会报错,如上。
通过控制变量来排查错误,明白两点:
- 控制变量应该先从每个参数开始怀疑
- 未定义标识符其实说的是文本未定义【当第二个变量进行变化的时候,这个标识符会变化】
我的代码:
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好像又不支持:
递归查询各种资料绕了一大圈(包括去找什么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手册和微软中文官网
- 对syntax转换有了一定了解,深深记住了只要我想到的,别人就一定已经做过了,开发程序的人员一定做得比我需要得更普适
- 发现了微软的官网这个好东西,这个手册真棒!有很多开发相关的知识,但是用好它的前提是熟练它的结构和搜索引擎
后记
后来,我发现我的程序还是无法运行:
然后我想到了从定义的位置开始就用Unicode:
- 改前:
- 改后: