2

My app requires me to change logos and icons every time it is compiled for each customer. Doing this by hand is, naturally, time consuming and error prone, so I have written the .Net form to load its images and icons from a .rc file, but I'm trying to work some preprocessor magic in the resources file.

My goal is to have it automatically load only one image and icon from a directory that has the customer's id. This will prevent the .rc file from linking unneeded images and files, and make setup for each customer as simple as a single prepcessor command.

I have a token called "CUSTOMER_ID" that is the folder name of their resources. So, their files would be in "../files/images/customer1/" where CUSTOMER_ID = customer1.

I want to get the preprocessor to concatenate the constant of "..files/images/" with CUSTOMER_ID, followed by "icon.ico" or "logo.bmp" so that I can define the resource. This is what I have currently:

//in resources.rc
#include "airline.h"
#define CONCAT(dir, cid, filetype) dir ## cid ## filetype

IDI_ICON1 ICON  CONCAT("../files/images/",CUSTOMER_ID,"icon.ico")

However, the results always end up off. Advice?

wjl
  • 7,519
  • 2
  • 32
  • 41

1 Answers1

1

For RC files preprocessor directives are very limited, see: http://msdn.microsoft.com/en-us/library/windows/desktop/aa381033(v=vs.85).aspx


Directive   Description
#define         Defines a specified name by assigning it a given value.
#elif           Marks an optional clause of a conditional-compilation block.
#else           Marks the last optional clause of a conditional-compilation block.
#endif          Marks the end of a conditional-compilation block.
#if         Conditionally compiles the script if a specified expression is true.
#ifdef          Conditionally compiles the script if a specified name is defined.
#ifndef         Conditionally compiles the script if a specified name is not defined.
#include    Copies the contents of a file into the resource-definition file.
#undef          Removes the definition of the specified name.

And #define is of simple form: (after http://msdn.microsoft.com/en-us/library/windows/desktop/aa381061(v=vs.85).aspx):

#define name value

There is solution - according to this answer prepare your ICON/BITMAPS paths as environment variables, you can build them from costumer name - but it must be done in your batchFile or makefile:

From the already mentioned answer:

In your project properties add ;$(CMDLINE_DEFINES) to the end of your resource preprocessor definitions. (Be sure to pick the right configuration.)

Then when you use MSBuild from the command line type (or add to a batch file)...

C:\Projects\SomeProject> set CMDLINE_DEFINES=SOMETEST=42
C:\Projects\SomeProject> MSBuild SomeProject.vcproj

This answer was for C++ files:

For your example:

CONCAT("../files/images/",CUSTOMER_ID,"icon.ico")

You should use such macro:

#define TOSTRING(T) #T
#define CONCAT(dir, cid, filetype) dir TOSTRING(cid) filetype

This is because this macro expansion is: "../files/images/" "customer1" "icon.ico". And the C++ compiler will concatenate adjacent string literals.

This example:

#include <iostream>

#define TOSTRING(T) #T
#define CONCAT(dir, cid, filetype) dir TOSTRING(cid) filetype

#define CUSTOMER_ID customer1

int main() {
    std::cout << ">>>>>" << CONCAT("../files/images/",CUSTOMER_ID,"icon.ico") << "<<<<\n";
}

will produce output:

>>>>>../files/images/customer1icon.ico<<<<

Possible you should add / before icon.ico...

Community
  • 1
  • 1
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • I did it exactly like that, and I'm getting two compiler errors: file not found: "/ICON.ICO" file not found: ../files/images/ The errors are written exactly as they are above. – Collin Biedenkapp Nov 16 '12 at 22:28
  • @CollinBiedenkapp oops, my answer was for C++ files. rc files preprocessor directives are very limited, see: http://msdn.microsoft.com/en-us/library/windows/desktop/aa381061(v=vs.85).aspx – PiotrNycz Nov 16 '12 at 22:47
  • The solution for me ended being storing the path to the file as an .RC capable #define, and commenting it out along with the rest of the customer-specific information. This being said, thank you greatly for your response, and it will benefit me in other scenarios! – Collin Biedenkapp Nov 17 '12 at 00:54