本文介绍在Windows程序开发中的MessageBox详解。

 

  我们在在Windows程序设计中经常会涉及到一个格式化消息框,其代码如下:

  1. #include <windows.h>
  2. #include <tchar.h>
  3. #include <stdio.h>
  4.  
  5. int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ……)
  6. {
  7. TCHAR szBuffer [1024] ;
  8. va_list pArgList ;
  9. // The va_start macro (defined in STDARG.H) is usually equivalent to:
  10. // pArgList = (char *) &szFormat + sizeof (szFormat) ;
  11. va_start (pArgList, szFormat) ;
  12. // The last argument to wvsprintf points to the arguments
  13. _vsntprintf (szBuffer, sizeof (szBuffer) / sizeof (TCHAR),
  14. szFormat, pArgList) ;
  15. // The va_end macro just zeroes out pArgList for no good reason
  16. va_end (pArgList) ;
  17. return MessageBox (NULL, szBuffer, szCaption, 0) ;
  18. }
  19. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  20. PSTR szCmdLine, int iCmdShow)
  21. {
  22. int cxScreen, cyScreen ;
  23. //GetSystemMetrics Api function --(SM_CXSCREEN),(SM_CYSCREEN) return weight and high,in pixles,of the screen
  24. cxScreen = GetSystemMetrics (SM_CXSCREEN) ;
  25. cyScreen = GetSystemMetrics (SM_CYSCREEN) ;
  26. MessageBoxPrintf (TEXT ("ScrnSize"),
  27. TEXT ("The screen is %i pixels wide by %i pixels high."),
  28. cxScreen, cyScreen) ;
  29. return 0 ;
  30. }

 

  其中:

     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代码:

  1. func( Type para1, Type para2, Type para3, ... )
  2. {
  3.    /****** Step 1 ******/
  4.    va_list ap;
  5.    va_start( ap, para3 ); //一定要“...”之前的那个参数
  6.    /****** Step 2 ******/
  7.  
  8.    //此时ap指向第一个可变参数
  9.    //调用va_arg取得里面的值
  10.    Type xx = va_arg( ap, Type );
  11.    //Type一定要相同,如:
  12.    //char *p = va_arg( ap, char *);
  13.    //int i = va_arg( ap, int );
  14.    //如果有多个参数继续调用va_arg
  15.  
  16.    /****** Step 3 ******/
  17.    va_end(ap); //For robust!
  18.   }

 

  一般的用法是:va_list args; //声明变量

  va_start(args, fmt); //开始解析。args指向fmt后面的参数

  TYPE var = va_arg(args, TYPE); //取下一个参数并返回。args指向下一个参数

      va_end(args); //结束解析

  

  示例2代码如下:

  1. #include <stdio.h>
  2. #include <stdarg.h>
  3.  
  4. #define SAMPLEFOOPARAM2DEFAULT 255
  5. #define EOL -1
  6.  
  7. int samplefoo(int a, ……)
  8.  {
  9. int param1, param2,param3;
  10. va_list num_ptr;
  11. param1 = a;
  12. va_start(num_ptr, a);
  13. /* 假定这里的第二个参数是int型,如果没有就用default值 */
  14. param2 = va_arg(num_ptr, int);
  15. if ( param2 == EOL )
  16. param2 = SAMPLEFOOPARAM2DEFAULT;
  17. param3=va_arg(num_ptr,int);
  18. if(param3==EOL)
  19. param3=SAMPLEFOOPARAM2DEFAULT;
  20. va_end(num_ptr);
  21. printf("The first parameter of function is: %d\n", param1);
  22. printf("The first parameter of function is: %d\n", param2);
  23. printf("The first parameter of function is: %d\n", param3);
  24. return 0;
  25. }
  26. int main()
  27.  {
  28. printf("Output of samplefoo(10, 20, EOL):\n");
  29. samplefoo(10, 20, 30, EOL); /* 使用的不是缺省值,注意最后的EOL是一个标记值 */
  30. printf("Output of samplefoo(10, EOL):\n");
  31. samplefoo(10, EOL,EOL); /* 使用的不是缺省值,注意最后的EOL是一个标记值 */
  32.  
  33. return 0;
  34. }

 

  示例3代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void myprintf(char* fmt, ……) //一个简单的类似于printf的实现,//参数必须都是int 类型
  5. {
  6. char* pArg=NULL; //等价于原来的va_list
  7.  
  8. char c;
  9. pArg = (char*) &fmt; //注意不要写成p = fmt !!因为这里要对//参数取址,而不是取值
  10. pArg += sizeof(fmt); //等价于原来的va_start
  11.  
  12. do{
  13. c =*fmt;
  14. if (c != \'%\'){
  15. putchar(c); //照原样输出字符
  16. }
  17. else{
  18. //按格式字符输出数据
  19.  
  20. switch(*++fmt) {
  21. case \'d\':
  22. printf("%d",*((int*)pArg));
  23. break;
  24. case \'x\':
  25. printf("%#x",*((int*)pArg));
  26. break;
  27. default:
  28. break;
  29. }
  30. pArg += sizeof(int); //等价于原来的va_arg
  31. }
  32. ++fmt;
  33. }while (*fmt != \'\0\');
  34. pArg = NULL; //等价于va_end
  35.  
  36. return;
  37. }
  38. int main(int argc, char* argv[])
  39. {
  40. int i = 1234;
  41. int j = 5678;
  42. myprintf("the first test:i=%d\n",i,j);
  43. myprintf("the secend test:i=%d; %x;j=%d;\n",i,0xabcd,j);
  44. system("pause");
  45. return 0;
  46. }

 

  最后,希望转载的朋友能够尊重作者的劳动成果,加上转载地址:http://www.cnblogs.com/hanyonglu/archive/2011/04/19/2020738.html  谢谢。

 

  完毕。^_^
 

版权声明:本文为hanyonglu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/hanyonglu/archive/2011/04/19/2020738.html