您的位置:首页 > 其它

windows程序设计:第二章:Unicode简介

2014-04-21 19:02 295 查看
本文是我学习《windows程序设计》(第5版)的笔记,方便以后查阅。如果被您看到并且对您有用的话,那再好不过了。本文不涉及具体的讲解,详细的讲解请看《windows程序设计》(第5版)这本书,它才是经典之作!

这本书是1998年出的,当时Unicode还没有成为国际标准,现在肯定是标准了。Unicode的作用:能够使计算机实现跨语言、跨平台的文本转换及处理。
先看代码:

#include <windows.h>
#include <tchar.h>     
#include <stdio.h>     

int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ...)
{
	TCHAR   szBuffer [1024] ; //定义缓冲区大小
	va_list pArgList ;//定义一个va_list型的变量,这个变量是指向参数的指针

	// The va_start macro (defined in STDARG.H) is usually equivalent to:
	// pArgList = (char *) &szFormat + sizeof (szFormat) ;

	va_start (pArgList, szFormat) ;//用va_start宏初始化变量,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数.

	// 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) ;//用va_end宏结束可变参数的获取,将指针置为无效

	return MessageBox (NULL, szBuffer, szCaption, 0) ;//把变量在消息框显示
}

//windows入口函数
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
	PSTR szCmdLine, int iCmdShow) 
{
	int cxScreen, cyScreen ;

	//获取屏幕的分辨率
	cxScreen = GetSystemMetrics (SM_CXSCREEN) ;//横向
	cyScreen = GetSystemMetrics (SM_CYSCREEN) ;//纵向

	//调用MessageBoxPrintf,这里参数变成了四个
	MessageBoxPrintf (TEXT ("ScreenSize"), 
		TEXT ("The screen is %i pixels wide by %i pixels high."),
		cxScreen, cyScreen) ;
	return 0 ;
}


运行结果如下:



本章的重点是如何实现MessageBoxPrintf函数,使用这个函数可以将变量在MessageBox中输出出来。并且程序中用到了C语言的变参技术(va_start, va_end)。首先看程序中的MessageBoxPrintf函数,如下:

intCDECLMessageBoxPrintf(TCHAR*szCaption,TCHAR*szFormat,...),可以看到这个函数的参数是变长的。类似于C语言中的print函数, int printf(constchar *format, ...);

那三个连续的点就代表大于或等于0个参数,再加上前面的format参数,所以printf函数至少要接受一个字符串,后面就随便了。

关于_vsnprintf()函数:

函数声明:
int vsnprintf(char*str,size_tsize,constchar*format,va_listap);
参数说明:

1. char *str [out],把生成的格式化的字符串存放在这里.
2. size_t size [in],str可接受的最大字节数,防止产生数组越界.
3. const char *format[in], 指定输出格式的字符串,它决定了你需要提供的可变参数的类型、个数和顺序。
4. va_list ap [in],va_list变量.
函数功能:将可变参数格式化输出到一个字符数组。
用法类似于vsprintf,不过加了size的限制,防止了内存溢出(size为str所指的存储空间的大小)。
返回值:执行成功,返回写入到字符数组str中的字符个数(不包含终止符),最大不超过size;执行失败,返回负值,并置errno.
备注:
linux环境下是:vsnprintf
VC6环境下是:_vsnprintf
通过_vsnprintf()函数就把MessageBoxPrintf函数第二个参数的字符串值存入了第一的缓冲区szBuffer

关于宏va_list,va_start,va_end:

这里要知道两个事情:

⑴在intel+windows的机器上,函数栈的方向是向下的,栈顶指针内存地址低于栈底指针,所以先进栈的数据是存放在内存的高地址处。

(2)在VC等绝大多数C编译器中,默认情况下,参数进栈的顺序是由右向左的,因此,参数进栈以后的内存模型如下图所示:最后一个固定参数的地址位于第一个可变参数之下,并且是连续存储的。

|-----------------------------------------|

|-------最后一个可变参数----------| ->高内存地址处

|-----------------------------------------|

|-----------------------------------------|

|--------第N个可变参数-------------|

|-----------------------------------------|

|-----------------------------------------|

|--------第一个可变参数------------| ->va_start(pArgList,szFormat)后pArgList所指的地方

|-----------------------------------------|

|--------最后一个固定参数---------|

|-----------------------------------------|

|-----------------------------------------|

|-----------------------------------------|

|---------第一个固定参数-----------| -> 低内存地址处

|-----------------------------------------|

|-----------------------------------------|

va_start,函数名称,读取可变参数的过程其实就是在堆栈中,使用指针,遍历堆栈段中的参数列表,从低地址到高地址一个一个地把参数内容读出来的过程·

在进程中,堆栈地址是从高到低分配的.当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码,这个入栈过程,堆栈地址不断递减.
总之,函数在堆栈中的分布情况是:地址从高到低,依次是:函数参数列表,函数返回地址,函数执行代码段.
堆栈中,各个函数的分布情况是倒序的.即最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分.




GetSystemMetrics ()函数:用于得到被定义的系统数据或者系统配置信息.
参数SM_CYSCREEN :以像素为单位计算的屏幕尺寸

(第4章中作者将具体讲解)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: