Introduction
I find that OEM 'branding' is still a lot of trouble. I needed a simple way to produce OEM versions of multi-module products. Resources like graphics and icons are easy enough to deal with but the VERSIONINFO
structures and embedded string
s like the 'product name' are a hassle. Following is a simple method I have used for years to help ease things.
This method uses three header files (build.h, company.h, and product.h) and an object called CBrandingUtils
that is defined in brandingutils.h and brandingutils.cpp.
(build.h)
#define BUILD_NUMBER "1"
(company.h)
#define LEGAL_COPYRIGHT "Copyright © 2006"
#define LEGAL_COMPANY_NAME "PlanetHarrington, Inc."
#define LEGAL_RIGHTS "All rights reserved."
#define LEGAL_FULL_COPYRIGHT "Copyright © 2006 PlanetHarrington, Inc.
All rights reserved."
#define SIMPLE_COMPANY_NAME "PlanetHarrington"
#define COMPANY_CONTACT_URL "http:
(product.h)
#define PRODUCT_NAME "BrandingDemo"
#define PRODUCT_VERSION "1.0"
#define PRODUCT_TRADEMARKS "BrandingDemo is a trademark of PlanetHarrington."
#define PRODUCT_VSTRUCT_VERSION "1,0,0,0"
#define PRODUCT_VSTRUCT_VERSION_PART1 1
#define PRODUCT_VSTRUCT_VERSION_PART2 0
#define PRODUCT_VSTRUCT_VERSION_PART3 0
#define PRODUCT_VSTRUCT_VERSION_PART4 0
(brandingutils.h)
#pragma once
#include <string>
using namespace std;
#include "build.h"
#include "company.h"
#include "product.h"
class CBrandingUtils
{
public:
CBrandingUtils(){};
virtual ~CBrandingUtils(){};
HRESULT Put_COMPANY_NAME_InControl(HWND, UINT);
HRESULT Put_PRODUCT_NAME_InControl(HWND, UINT);
HRESULT Put_PRODUCT_VERSION_InControl(HWND, UINT);
HRESULT Put_BUILD_NUMBER_InControl(HWND, UINT);
HRESULT Put_COPYRIGHT_InControl(HWND, UINT);
HRESULT Put_COMPANY_CONTACT_URL_InControl(HWND, UINT);
HRESULT Put_RIGHTS_InControl(HWND, UINT);
HRESULT Put_FULL_COPYRIGHT_InControl(HWND, UINT);
HRESULT Put_FULL_COMPANY_NAME_InControl(HWND, UINT);
HRESULT Put_PRODUCT_NAME_InTitle(HWND, bool bPropPage = false);
HRESULT ReplaceStringWithString(wstring&, LPCTSTR, LPCTSTR);
HRESULT ReplaceStringWithStringInCtrl(LPCTSTR, LPCTSTR, HWND, UINT);
};
Most developers will want to modify the CBrandingUtils
methods and constants to suit their particular needs.
Using
1. Using with a VERSIONINFO Resource
Add the three include
files to your project.
Add the include
files to the *.rc file:
#define APSTUDIO_READONLY_SYMBOLS
#include "afxres.h"
#include "..\include\company.h"
#include "..\include\product.h"
#include "..\include\build.h"
#ifdef APSTUDIO_INVOKED
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"#include ""..\\include\\company.h""\r\n"
"#include ""..\\include\\product.h""\r\n"
"#include ""..\\include\\build.h""\r\n"
"\0"
END
Move the entire VERSIONINFO
section to the *.rc2 file.
Use the desired macros:
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION PRODUCT_VSTRUCT_VERSION_PART1,PRODUCT_VSTRUCT_VERSION_PART2,
PRODUCT_VSTRUCT_VERSION_PART3,PRODUCT_VSTRUCT_VERSION_PART4
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", LEGAL_COMPANY_NAME
VALUE "FileDescription", "Branding Demonstration"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "brandingdemo.exe"
VALUE "LegalCopyright", LEGAL_FULL_COPYRIGHT
VALUE "OriginalFilename", "brandingdemo.exe"
VALUE "ProductName", PRODUCT_NAME
VALUE "ProductVersion", PRODUCT_VSTRUCT_VERSION
VALUE "SpecialBuild", BUILD_NUMBER
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
Check the results after building by opening the 'Properties' dialog for the deliverable using Explorer, selecting the "Version" tab, and confirming that the information displayed is correct.
2. Using with Code in a Dialog Object
Add the brandingutils.h and brandingutils.cpp files to your project. Turn off precompiled headers for the CPP file.
Include the CBrandingUtils.h file in your source file and declare an instance of a CBrandingUtils
object. Use the definitions in the three header files along with the methods in the CBrandingUtils
to replace the embedded keywords with the desired text.
BOOL CBrandingDemoDlg::OnInitDialog() {
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL) {
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
wstring strReplace = strAboutMenu;
if(SUCCEEDED(m_brandingUtils.ReplaceStringWithString
(strReplace, TEXT("_PRODUCT_NAME_"), TEXT(PRODUCT_NAME)))) {
strAboutMenu = strReplace.c_str();
}
if (!strAboutMenu.IsEmpty()) {
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE); SetIcon(m_hIcon, FALSE); m_brandingUtils.Put_PRODUCT_NAME_InTitle(GetSafeHwnd());
return TRUE; }
Check out brandingdemDlg.h and BrandingdemDlg.cpp for a complete example.
Demo Project
The demo project download includes all the required files and a Visual Studio 7 project. The project output is both a branded application and a test harness for the CBrandingUtils
object. Run the application and note the application title and About Box information. Change the definitions in the three header files, recompile, and run again and check for your changes. Add another module to the solution and implement the branding in it to see how easy it is to change version information for both of the modules.
Summary
If I left out any details you think should be mentioned in the article, please let me know.
If you could take one last second to rate this article or even leave a comment, it would be much appreciated.
Thanks for reading!
16yrs of GUI programming experience gained at: (most recent first) BlackBall, Veritas, Seagate Software, Arcada, Stac, Mountain, and Emerald Systems.
Languages/Scripting: C, C++, JAVA, BASIC, JAVASCRIPT, HTML, XML, PHP, and SQL
Tools: MS Visual Studio, MS Visual SourceSafe, CVS, PVCS, Bounds Checker, VMWare, ToDoList, InstallShield, and Office Applications
Libraries and API: RTL, STL, WIN32, MFC, ATL, .NET, ActiveX, DirectX, COM, DCOM, Shell Extensions, and Shell Namespaces
Strengths: Honest, communicative, keen eye for usability, good at estimating workload and completion dates, ready to take on grunt work, team player, experienced working with QA, localization, Tech Pubs, Sales, and Marketing teams.