• 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  谢谢。

      完毕。^_^
     

  • 相关阅读:
    golang中channels的本质详解,经典!
    Vim tips——Working with external commands
    go语言中log包的使用
    vue自定义轮播图组件 swiper
    Nerv --- React IE8 兼容方案
    微信小程序实战之 pay(支付页面)
    微信小程序实战之 goods(订餐页)
    微信小程序 自定义组件(stepper)
    微信小程序 自定义组件(modal) 引入组件
    微信小程序之 Swiper(轮播图)
  • 原文地址:https://www.cnblogs.com/hanyonglu/p/2020738.html
Copyright © 2020-2023  润新知