• wndows程序设计之书籍知识与代码摘录-封装一个类似printf的messagebox


    //-----------------------------------------
    //本程序展示了如何实现MessageBoxPrintf函数
    //本函数能像printf那样格式化输出
    //摘录自:《windows程序设计第五版》
    //-----------------------------------------
    #include<windows.h>
    #include<tchar.h>
    #include<stdio.h>
    
    int CDECL MessageBoxPrintf(TCHAR * szCaption, TCHAR * szFormat, ...)
    {
        TCHAR szBuffer[1024];
        
        va_list pArgList;
        
        va_start (pArgList, szFormat);
        
        _vsntprintf_s(szBuffer,sizeof(szBuffer)/sizeof(TCHAR), sizeof(szBuffer) / sizeof(TCHAR),szFormat, pArgList);
        //---------------------------------------------------------------------------------------------------------------------------------
        //原文使用_vsntprintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR),szFormat, pArgList); vs认为此函数具有安全性问题 因此我替换成上边的函数
        //---------------------------------------------------------------------------------------------------------------------------------
        
        va_end(pArgList);
        return MessageBox(NULL,szBuffer,szCaption,0);
    }
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        int cxScreen;
        int cyScreen;
        cxScreen = GetSystemMetrics(SM_CXSCREEN);
        cyScreen = GetSystemMetrics(SM_CYSCREEN);
        MessageBoxPrintf(TEXT("SCREEN SIZE"),TEXT("您的视屏显示器:
    WIDE:%i
    HIGH: %i"),cxScreen,cyScreen);
        
        return 0;
    }

    这个函数使用了可变参数 这样就出现了一些陌生的东西,解释如下

    CDECL

    __cdecl __fastcall与__stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数弹出栈,3)以及产生函数修饰名的方法。
    1、__stdcall调用约定:函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈。
    2、_cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。注意:对于可变参数的成员函数,始终使用__cdecl的转换方式。
    3、__fastcall调用约定:它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈)。

     va_start va_end等

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

    #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址
    #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址
    #define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效

    在学习windows程序设计时此函数可以给c/c++程序员一份熟悉感。。。。。。。。。。。

  • 相关阅读:
    初学HTML_3
    初学HTML_2
    初学HTML_1
    VScode中的Java配置
    JAVA中访问控制和继承的规则
    Java中的变量
    minishift 部署postgresql
    sydnsis 把数据库做成api
    sydnsis接口 数据库到mq
    sydnsis 推送和消费amq消息
  • 原文地址:https://www.cnblogs.com/xdblog/p/4821517.html
Copyright © 2020-2023  润新知