Win32开发之Format MessageBox 详解
本文介绍在Windows程序开发中的MessageBox详解。
我们在在Windows程序设计中经常会涉及到一个格式化消息框,其代码如下:
#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 ; //GetSystemMetrics Api function --(SM_CXSCREEN),(SM_CYSCREEN) return weight and high,in pixles,of the screen 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 ; }
其中:
va_list arg_ptr:定义一个指向个数可变的参数列表指针;
va_start(arg_ptr, argN):使参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,说明:argN是位于第一个可选参数之前的固定参数,(或者说,最后一个固定参数;…之前的一个参数),函数参数列表中参数在内存中的顺序与函数声明时的顺序是一致的。如果有一va函数的声明是void va_test(char a, char b, char c, …),则它的固定参数依次是a,b,c,最后一个固定参数argN为c,因此就是va_start(arg_ptr, c)。
va_arg(arg_ptr, type):返回参数列表中指针arg_ptr所指的参数,返回类型为type,并使指针arg_ptr指向参数列表中下一个参数。
va_copy(dest, src):dest,src的类型都是va_list,va_copy()用于复制参数列表指针,将dest初始化为src。
va_end(arg_ptr):清空参数列表,并置参数指针arg_ptr无效。说明:指针arg_ptr被置无效后,可以通过调用va_start()、va_copy()恢复arg_ptr。每次调用va_start() / va_copy()后,必须得有相应的va_end()与之匹配。参数指针可以在参数列表中随意地来回移动,但必须在va_start() … va_end()之内。
下面是一个示例1,让我们看下示例1代码:
func( Type para1, Type para2, Type para3, ... ) { /****** Step 1 ******/ va_list ap; va_start( ap, para3 ); //一定要“...”之前的那个参数 /****** Step 2 ******/ //此时ap指向第一个可变参数 //调用va_arg取得里面的值 Type xx = va_arg( ap, Type ); //Type一定要相同,如: //char *p = va_arg( ap, char *); //int i = va_arg( ap, int ); //如果有多个参数继续调用va_arg /****** Step 3 ******/ va_end(ap); //For robust! }
一般的用法是:va_list args; //声明变量
va_start(args, fmt); //开始解析。args指向fmt后面的参数
TYPE var = va_arg(args, TYPE); //取下一个参数并返回。args指向下一个参数
va_end(args); //结束解析
示例2代码如下:
#include <stdio.h> #include <stdarg.h> #define SAMPLEFOOPARAM2DEFAULT 255 #define EOL -1 int samplefoo(int a, ……) { int param1, param2,param3; va_list num_ptr; param1 = a; va_start(num_ptr, a); /* 假定这里的第二个参数是int型,如果没有就用default值 */ param2 = va_arg(num_ptr, int); if ( param2 == EOL ) param2 = SAMPLEFOOPARAM2DEFAULT; param3=va_arg(num_ptr,int); if(param3==EOL) param3=SAMPLEFOOPARAM2DEFAULT; va_end(num_ptr); printf("The first parameter of function is: %d\n", param1); printf("The first parameter of function is: %d\n", param2); printf("The first parameter of function is: %d\n", param3); return 0; } int main() { printf("Output of samplefoo(10, 20, EOL):\n"); samplefoo(10, 20, 30, EOL); /* 使用的不是缺省值,注意最后的EOL是一个标记值 */ printf("Output of samplefoo(10, EOL):\n"); samplefoo(10, EOL,EOL); /* 使用的不是缺省值,注意最后的EOL是一个标记值 */ return 0; }
示例3代码如下:
#include <stdio.h> #include <stdlib.h> void myprintf(char* fmt, ……) //一个简单的类似于printf的实现,//参数必须都是int 类型 { char* pArg=NULL; //等价于原来的va_list char c; pArg = (char*) &fmt; //注意不要写成p = fmt !!因为这里要对//参数取址,而不是取值 pArg += sizeof(fmt); //等价于原来的va_start do{ c =*fmt; if (c != '%'){ putchar(c); //照原样输出字符 } else{ //按格式字符输出数据 switch(*++fmt) { case 'd': printf("%d",*((int*)pArg)); break; case 'x': printf("%#x",*((int*)pArg)); break; default: break; } pArg += sizeof(int); //等价于原来的va_arg } ++fmt; }while (*fmt != '\0'); pArg = NULL; //等价于va_end return; } int main(int argc, char* argv[]) { int i = 1234; int j = 5678; myprintf("the first test:i=%d\n",i,j); myprintf("the secend test:i=%d; %x;j=%d;\n",i,0xabcd,j); system("pause"); return 0; }
最后,希望转载的朋友能够尊重作者的劳动成果,加上转载地址:http://www.cnblogs.com/hanyonglu/archive/2011/04/19/2020738.html 谢谢。
完毕。^_^