VC使用#定义方便控制版本号的宏
一个 VC Project 中,可能有很多地方需要用到版本号,比如 About 对话框、版本资源等。如果每次版本更改都一一去改变这些值,不但非常麻烦,而且有悖唯一原则。
巧妙地使用宏定义,可以很好地解决这个问题。
先来看看几个预处理操作符 (Preprocessor Operators):
| Operator | Action |
|---|---|
| Stringizing operator (#) | Causes the corresponding actual argument to be enclosed in double quotation marks |
| Charizing operator (#@) | Causes the corresponding argument to be enclosed in single quotation marks and to be treated as a character (Microsoft Specific) |
| Token-pasting operator (##) | Allows tokens used as actual arguments to be concatenated to form other tokens |
简单说,# 就是使参数用引号包住,形成字符串;#@ 使参数用单引号包住,形成一个字符;## 是粘结符。这几个操作符从语言上来说比较晦涩,仔细看看 MSDN 的例子,好好理解一下。
下面举例说一下怎么定义统一的版本宏。
假设工程中有资源脚本文件 Resource.rc,唯一的版本号码存放在 Define.h 里。其它需要用到版本号的 CPP 文件均包含此文件。
先看看 Define.h:
#define VER_Major 2
#define VER_Minor 2
#define VER_Release 137
#define VER_Build 1762
#define VER_Version MAKELONG(MAKEWORD(VER_Major, VER_Minor), VER_Release) #define _Stringizing(v) #v
#define _VerJoin(a,b,c,d) _Stringizing(a.b.c.d) #define STR_BuildDate TEXT(__DATE__)
#define STR_BuildTime TEXT(__TIME__)
#define STR_BuilDateTime TEXT(__DATE__) TEXT(" ") TEXT(__TIME__)
#define STR_Version TEXT(_VerJoin(VER_Major, VER_Minor, VER_Release, VER_Build))
假设有了上面的定义后,就可以方便地使用 VER_Major、VER_Minor、VER_Release、VER_Build 作为版本号数字;STR_Version 作为版本字符串 (上面的例子中 STR_Version 执行宏展开后是 TEXT("2.2.137.1763") 的 TCHAR 字符串)。任何 CPP 文件中可以直接使用这些宏定义。
资源脚本 Resource.rc 中,假设我们需要版本资源,可以首先在 Define.h 中再定义一些宏,比如:
#define STR_AppName TEXT("CuteFoto")
#define STR_Author TEXT("Yonsm")
#define STR_Corporation TEXT("Yonsm.NET")
#define STR_Web TEXT("Yonsm.reg365.com")
#define STR_Email TEXT("Yonsm@163.com")
#define STR_WebUrl TEXT("http://") STR_Web
#define STR_EmailUrl TEXT("mailto:") STR_Email TEXT("?Subject=") STR_AppName
#ifdef _CHS
#define STR_Description TEXT("灵巧的批量扫描照片切割工具。")
#define STR_Copyright TEXT("版权所有 (C) 2002-2004 ") STR_Corporation TEXT(",保留所有权利。")
#else // _CHS
#define STR_Description TEXT("Picture cutting tool for batch-scanned photo.")
#define STR_Copyright TEXT("Copyright (C) 2002-2004 ") STR_Corporation TEXT(". All rights reserved.")
#endif // _CHS
这时,我们在 Resouurc.rc 中添加版本资源——注意,不要直接添加,否则会被 VS 更改成实际的值,这样就不能达到我们的目的了。一个好的解决方法是:
- 在 VS IDE 中双击 Resource.rc 转到 资源视图 中,右击 Resource.rc,选择“资源包括”,在“只读符号指令”中包含 Define.h:
#define APSTUDIO_HIDDEN_SYMBOLS
//……
#include "Define.h"
#include "Windows.h"
//……
#undef APSTUDIO_HIDDEN_SYMBOLS - 在“编译时指令”中输入:
LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT
#pragma code_page(DEFAULT) VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_Major, VER_Minor, VER_Release, VER_Build
PRODUCTVERSION VER_Major, VER_Minor, VER_Release, VER_Build
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS 0
FILEOS VOS__WINDOWS32
FILETYPE 0
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040004e4"
BEGIN
VALUE "FileVersion", STR_Version
VALUE "FileDescription", STR_Description
VALUE "ProductName", STR_AppName
VALUE "ProductVersion", STR_Version
VALUE "CompanyName", STR_Corporation
VALUE "LegalCopyright", STR_Copyright
VALUE "Comments", "Powered by " STR_Author "."
VALUE "OriginalFilename", STR_AppName EXT_Exe
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0400, 0x04e4
END
END
OK,以后要更改版本号或程序信息,只要修改 Define.h 即可了。
继续……
Define.h 中假设 VER_Release/VER_Build 分别指 Release 号和 Build 号,如果让这两个值分别表示我们用 Release 方式编译的次数和总编译次数,多好:)为此我写了个小工具 BPP (Build++ 的意思):
首先把 BPP.exe 放在工程目录下,然后在 VC Project 属性中,Debug 方式:在“生成事件”->“预生成事件”->“命令行”中输入“BPP Define.h”,Release 方式:“BPP -Release Define.h”。这样,每次 VC 编译都会调用 BPP.exe 使 VER_Build 或 VER_Reelase 自增一。好酷酷吧……
VC使用#定义方便控制版本号的宏的更多相关文章
- 在makefile通过宏定义来控制源程序的编译
在Makefile中我们可以通过宏定义来控制源程序的编译.只要在Makefile中的CFLAGS中通过选项-D来指定你于定义的宏即可. 如:CFLAGS += -D _XXX在编译的时候加上此选项就可 ...
- [转载]学习VC MFC开发必须了解的常用宏和指令————复习一下
1.#include指令 包含指定的文件 2.#define指令 预定义,通常用它来定义常量(包括无参量与带参量),以及用来实现那些“表面似和善.背后一长串”的宏,它本身并不在编译过程中进行,而 ...
- 学习VC MFC开发必须了解的常用宏和指令
1.#include指令 包含指定的文件 2.#define指令 预定义,通常用它来定义常量(包括无参量与带参量),以及用来实现那些“表面似和善.背后一长串”的宏,它本身并不在编译过程中进行,而 ...
- 宏定义(无参宏定义和带参宏定义),C语言宏定义详解
1.宏定义说明 宏定义是比较常用的预处理指令,即使用"标识符"来表示"替换列表"中的内容.标识符称为宏名,在预处理过程中,预处理器会把源程序中所有宏名,替换成宏 ...
- ANSI 标准C 还定义了如下几个宏
ANSI 标准C 还定义了如下几个宏:_LINE_ 表示正在编译的文件的行号_FILE_ 表示正在编译的文件的名字预处理名称意义#define 宏定义#undef 撤销已定义过的宏名#include ...
- VC 预定义宏
列出预定义的 ANSI C和C++ Microsoft实现宏. 编译器识别预定义的ANSI C宏,并且Microsoft C++实现提供几个更多.这些宏不带参数,并且不能重定义.下面列出的某些预定义的 ...
- Kernel 中的 GPIO 定义和控制
最近要深一步用到GPIO口控制,写个博客记录下Kernel层的GPIO学习过程! 一.概念 General Purpose Input Output (通用输入/输出)简称为GPIO,或 总线扩展器. ...
- Spring核心——Bean的定义与控制
在Sring核心与设计模式的文章中,分别介绍了Ioc容器和Bean的依赖关系.如果阅读过前2文就会知道,Spring的整个运转机制就是围绕着IoC容器以及Bean展开的.IoC就是一个篮子,所有的Be ...
- C++ - 定义无双引号的字符串宏
在某些特殊场合下,我们可能需要定义一个字符串宏,但又不能用双引号 比如像这样 #define HELLO hello world 如果我们只是简单的展开HELLO,肯定会无法编译 std::cout ...
随机推荐
- UML--核心元素之参与者Actor
参与者(actor):在系统之外与系统交互的某人或某事物.例如,管理员,用户等等. 参与者位于边界之外,边界之内的都不叫参与者.用一个词来形容更准确,主角.也就是只有主动启动了这个业务的人,才是参与者 ...
- Thinkphp将中文年份转换为数字年份的问题
今天遇到一个问题:想将中文年份转换为数字年份,例如:"二零一六"-->'2016'. 在网上搜了一下,没找到可以直接处理的函数(也许是我搜索信息的能力有限吧>_< ...
- MySQL的备份和还原
MySQL的备份和还原 备份:副本 RAID1,RAID10:保证硬件损坏而不会业务中止: DROP TABLE mydb.tb1; 备份类型: 热备份.温备份和冷备 ...
- FFmpeg缩放swscale详解 <转>
利用ffmpeg进行图像数据格式的转换以及图片的缩放应用中,主要用到了swscale.h文件中的三个函数,分别是: struct SwsContext *sws_getContext(int srcW ...
- qt model/view 架构基础介绍之QListWidget
# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import * from Py ...
- android jni ——Field & Method --> Accessing Field
现在我们知道了怎样使用native code访问简单的数据类型和引用参考类型(string,array),下面我们来介绍怎样让jni代码去访问java中的成员变量和成员函数,然后可以再jni中回调ja ...
- Android 打造自己的个性化应用(三):应用程序的插件化
在android的项目开发中,都会遇到后期功能拓展增强与主程序代码变更的现实矛盾,也就是程序的灵活度. 由于linux平台的安全机制,再加上dalvik的特殊机制,各种权限壁垒,使得开发一个灵活多变的 ...
- MySql命令——命令行客户机的分隔符
delimiter // create procedure productpricint() begin select avg(price) as priceaverage from product; ...
- Sql语句不能识别Go的解决办法(动态创建表的触发器)
问题来源 用sqlserver直接打开sql文本,执行没问题,但是当用Sqlcommand类执行cmdtext命令文本时总是失败报错. 原因分析及解决 用数据库直接执行sql语句没问题,甚至还可以用G ...
- 求一无序数组中第n大的数字 - 快速选择算法
逛别人博客的时候,偶然看到这一算法题,顺便用C++实现了一下. 最朴素的解法就是先对数组进行排序,返回第n个数即可.. 下面代码中用的是快速选择算法(不晓得这名字对不对) #include <v ...