读取MFC资源中的版本信息

起因

  记得刚接触MFC的时候就发现在资源部分有一个Version的东西,当时由于刚刚入门,写些程序都是有的没的,所以也没有很关注版本之类的东西。现在使用SVN维护程序还是挺方便的,但是慢慢发现了由于有的时候版本更新的较快,发给客户的程序他们也不知道是什么版本,这样一出错就比较糗了,无从着手,所以开始注意这个项,本以为这个Version可以象字符表一样方便使用,结果还是挺麻烦的。

实现

  还是查阅相关的MSDN之类,以及一些论坛,终于找到了方法。我的设计是这样的,在关于对话框的标题上标识下一个版本号(原有系统的版本号是美工直接嵌入到图像中的,现在美工转走了。。。),该版本号可以与SVN中的更新号相关联,这样用户只要给我一个关于框的截图,我就可以找到对应版本的源码,方便调试。

BOOL CAboutDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    /* 获得程序路径 */
    WCHAR l_wcaAppPath[MAX_PATH];//保存应用程序路径 
    ::GetModuleFileName(NULL, l_wcaAppPath, MAX_PATH);   

    /* 获得版本信息大小 */
    UINT l_uiVersionInfoSize;//保存版本信息总体的大小
    TCHAR * l_ptcVersionInfo;   
    l_uiVersionInfoSize = ::GetFileVersionInfoSize(l_wcaAppPath, 0);//获得大小 
    l_ptcVersionInfo = new TCHAR[l_uiVersionInfoSize];//申请空间  

    /* 该结构用于获得版本信息的语言信息 */
    struct VersionLanguage
    {
        WORD m_wLanguage;
        WORD m_wCcodePage;
    };

    VersionLanguage * l_ptVersionLanguage;
    UINT l_uiSize;

    if (::GetFileVersionInfo(l_wcaAppPath, 0, l_uiVersionInfoSize, l_ptcVersionInfo) != 0)//获取版本信息 
    { 
        
        if (::VerQueryValue(l_ptcVersionInfo,_T("\\VarFileInfo\\Translation"),reinterpret_cast<LPVOID*>(&l_ptVersionLanguage),&l_uiSize))//查询语言信息并保存
        {       
            /* 生成查询信息格式符 */
            CString l_cstrSubBlock;
            l_cstrSubBlock.Format(_T("\\StringFileInfo\\%04x%04x\\ProductVersion"),l_ptVersionLanguage->m_wLanguage,l_ptVersionLanguage->m_wCcodePage);

            LPVOID * l_pvResult;

            /* 查询指定信息 */
            if(::VerQueryValue(static_cast<LPVOID>(l_ptcVersionInfo),l_cstrSubBlock.GetBuffer(),reinterpret_cast<LPVOID*>(&l_pvResult),&l_uiSize))
            {
                CString l_cstrProductVersion(reinterpret_cast<TCHAR *>(l_pvResult));//获得版本信息

                /* 将版本信息加入到标题栏 */
                CString l_cstrCaption;
                GetWindowText(l_cstrCaption);
                l_cstrCaption += _T(" ") + l_cstrProductVersion;
                SetWindowText(l_cstrCaption);
            }

        }   
    }

    delete [] l_ptcVersionInfo;    
    
    return TRUE;  // return TRUE unless you set the focus to a control
    // EXCEPTION: OCX Property Pages should return FALSE
}

  可以看到核心代码的过程就是首先获得版本信息的全部数据,保存在l_ptcVersionInfo这个量中,但是具体的信息怎们取就序号获得相应的偏移值才可以了,核心的还是是VerQueryValue这个函数,第一个参数是已获得版本信息,应该是计算其中的偏移使用,第二个参数很重要,具体来说有三种格式,具体可以加MSDN:http://msdn.microsoft.com/zh-cn/subscriptions/downloads/aa909243.aspx,分别对应了一个包含信息的结构体和获得语言及指定语言的若干信息等,第一种参数比较简单,所以功能好像也不是很完全,和MFC的资源好像并没有对应的关系,所以我使用的是第二种加第三种,这两种一般是要一起使用的。

  通过第一次调用VerQueryValue这个函数可以获得MFC中Version中标志为Blocker Header的项,然后根据此项构造参数,再次调用VerQueryValue就可以获得指定的信息,后面只需要将其在标题栏末端显示出来就好了。

总结

  这个问题感觉解决的还是可以,但是其实使用上还是有一定的问题,就是每次提交SVN的时候都需要对资源进行更改,这就比较麻烦了,如果忘记的话,为了保持同步还需要额外提交一个只变更资源的更新,太过于山寨,感觉SVN应该有自身的更新机制可以定制脚本完成这方面的工作,但是自己还仅仅是会用而已,暂时没有接触到这种功能,学习还是无止境啊。

posted @ 2012-10-24 15:46  Geminiv  阅读(2827)  评论(1编辑  收藏  举报