我目前正在研究WinAPI GUI(由Charles Petzold编写Windows第5版)和C(不是C ++)。我正在尝试并希望尽可能保持纯C,然后可能会跳转到C ++或C#。
我的问题依赖于使用可变参数***printf***()
版本。
项目:我想创建一个能够识别我是使用ASCII,UNICODE还是其他类型的多字节字符集(MBCS)的函数,然后相应地格式化输入并在MessageBox()中键入输出。
在我正在阅读的书中,作者正在使用下面的源代码来制作类似的东西: SCRNSIZE.C
/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
SCRNSIZE.C −− Displays screen size in a message box
(c) Charles Petzold, 1998
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ...)
{
TCHAR szBuffer [1024] ;
va_list pArgList ;
// The va_start macro (defined in STDARG.H) is usually equivalent to:
// pArgList = (char *) &szFormat + sizeof (szFormat) ;
va_start (pArgList, szFormat) ;
// The last argument to wvsprintf points to the arguments
_vsntprintf (szBuffer, sizeof (szBuffer) / sizeof (TCHAR),
szFormat, pArgList) ;
// The va_end macro just zeroes out pArgList for no good reason
va_end (pArgList) ;
return MessageBox (NULL, szBuffer, szCaption, 0) ;
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
int cxScreen, cyScreen ;
cxScreen = GetSystemMetrics (SM_CXSCREEN) ;
cyScreen = GetSystemMetrics (SM_CYSCREEN) ;
MessageBoxPrintf (TEXT ("ScrnSize"),
TEXT ("The screen is %i pixels wide by %i pixels high."),
cxScreen, cyScreen) ;
return 0 ;
}
程序使用获得的信息以像素为单位显示视频显示的宽度和高度 来自GetSystemMetrics函数。 GetSystemMetrics是获取信息的有用功能 关于Windows中各种对象的大小。
根据我的理解,他正在使用TCHAR,以便他的功能可以处理UNICODE或ASCII。 TCHAR定义为:
#ifdef UNICODE
typedef WCHAR TCHAR, * PTCHAR ;
typedef LPWSTR LPTCH, PTCH, PTSTR, LPTSTR ;
typedef LPCWSTR LPCTSTR ;
#else
typedef char TCHAR, * PTCHAR ;
typedef LPSTR LPTCH, PTCH, PTSTR, LPTSTR ;
typedef LPCSTR LPCTSTR ;
#endif
虽然MessageBox()
正在使用以下技巧来处理任一ASCII码UNICODE:
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif
在尝试编码我的项目之前(我开始但我有些问题我自己无法回答)我想解决一些我还没想到的难题。
1)他如何在int
中使用MessageBoxPrintf()
作为返回类型,并且能够返回像MessageBox()
这样的完整C对象?一般来说,我的返回类型应该是什么?当我返回像MessageBox()的完整函数?
2)作者使用的函数是_vsntprintf
。MSDN否认它存在,但我在源代码中找到了这个:
#define _vsntprintf _vsnwprintf
int _vsnwprintf(wchar_t *_Buffer, size_t _BufferCount, const wchar_t *_Format, va_list _ArgList)
他还在使用TCHAR的两个分区来获取缓冲区的实际大小 使用UNICODE。
2)根据您的经验或偏好,这个版本的printf仍然是最好用的吗?
因为搜索MSDN我发现了printf
这么多不同的可变版本。
3)您是否会更改代码中的任何内容以使其更具可移植性或更多&#34;正确&#34; ...我没有看到任何错误处理,并且从我所看到的内容总是更好使用作为黑盒子的va_
宏,以便您的代码可以更轻松。
如果有些问题听起来很愚蠢,我很抱歉,但是我从这个例子中感到不知所措。
提前谢谢。
答案 0 :(得分:1)
1)MessageBox
是一个函数。他正在返回方法MessageBox
的返回值。请查看此处的文档:https://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx
2)这是vsnwprintf https://msdn.microsoft.com/en-us/library/1kt27hek.aspx的所有现有变体。每种类型采用不同的统一大小(例如:byte,char,tchar,wchar等)。
此methot的第二个参数请求缓冲区中的元素数。鉴于sizeof (szBuffer)
为您提供bytes
中的缓冲区大小(而不是缓冲区内TCHAR
的数量),您必须将其除以TCHAR的大小({{1} })。因此,sizeof(TCHAR)
。
3)我在这一点上有点失落。会介意改进吗?