A note on using .wxr resources in Borland C++

[This has been tested with wxWidgets 1.67 and Borland C++ 5.02, Win32 target]

If you use Borland C++, there is a way of conveniently managing the .wxr files via your .rc file. With this route, all resources in the .wxr file are always automatically parsed and the .wxr data is encapsulated in the .exe.

The main problem with getting this to work is that when one includes a user-defined resource in the .rc file, the resource data derived from the .wxr file is not necessarily null-terminated. So we need to produce an intermediate file which is just the .wxr file with a null-character (0x0) appended. We will give this modified file the .wxrrc suffix.

How to set up the .rc file

Here is an example of 3 wxWin resource files included into the .rc file. Add some lines similar to these to your .rc file. Note you can have more than one .rc file in your project - add a new one for .wxWin resources if you want.
menuswxr WXRDATA intermediate\menus.wxrrc
dialogs1wxr WXRDATA intermediate\dialogs1.wxrrc
dialogs2wxr WXRDATA intermediate\dialogs2.wxrrc

The "intermediate" directory should be as set in the box /Options/Project/Intermediate Directory in the Borland IDE. If you do not use an intermediate directory then you can just write "menus.wxrrc" etc.

Creating the .wxrrc file

Borland C++ can be set up to automatically produce the .wxrrc file from the .wxr using a translator. The code for the translator is pretty trivial and here it is. To compile, create a Win32/GUI target with just this file. Call the target executable "wxrprepare.exe"

#include <stdio.h>
#include <windows.h>

/*
This utility is used to assist in including .wxr files within a .rc file
It expects two parameters - param1 is input .wxr filename, param2 is output .wxrrc filename.
*/
int PASCAL WinMain(HINSTANCE, HINSTANCE , LPSTR lpCmdLine, int) {
   FILE *fp1,*fp2;
   char infile[500],outfile[500];
   if (2>sscanf(lpCmdLine,"%s %s",infile,outfile)) exit(3);
   fp1=fopen(infile,"rb");
   if (fp1==NULL) exit(3);
   fp2=fopen(outfile,"wb");
   if (fp2==NULL)	exit(3);
   while(1) {
      int c=fgetc(fp1);
      if (feof(fp1)) break;
      fputc(c,fp2);
   }
   fputc(0,fp2); 
   fclose(fp1);
   fclose(fp2);
   return 0;
}

Once you have created the executable, put it somewhere in the OS path.

Install the translator

Unfortunately, you will have to install the translator for each project you wish to use this facility with.

1. From /Options/Tools click New. Enter:

Name: wxrPrepare

Path: wxrprepare.exe

Command Line: $EDNAME $OUTNAME

2. Click Advanced button to set further wxrprepare tool params as follows:

Tool Type: Translator

Translate From: .wxr

Translate To: .wxrrc

Default For: .wxr

Configure your project tree

By now the .rc file containing the reference to the .wxr files, should be included somewhere in your project as a dependent node of the target. Right click on the .rc file and using the Add Node menu, add each .wxr file listed in the .rc file, as a sub-node of the .rc node.

When you build your project, the .wxr files should now be automatically compiled into your executable and the ide should automatically re-build if you change any of the .wxr files. [If it is always now rebuilding the .rc file - check that you have the intermediate directory set up consistently. Using Preview Make in the Project Manager will also give you some clues]

Parsing the Resources

The last thing to do is to get the resources parsed by wxWidgets, ready for use. Here is a utility that will conveniently do the job:

void loadWXRDATA(const char *resname,const char *restype) {
   int ok;
   char *res = wxLoadUserResource(resname,restype);
   if (res==NULL) {
      char buff[80];
      sprintf(buff,"Failed to find resource chapter %s",resname);
      wxMessageBox(buff);
      exit(1);
   }
   ok=wxResourceParseString(res);
   if (!ok) {
      char buff[80];
      sprintf(buff,"Resource parse error in chapter %s",resname);
      wxMessageBox(buff);
      exit(1);
   }
}

Call this function for each .wxr file you have included in the .rc file. The first parameter is the resource name you gave in the .rc file and the second is the resource type you specified. So for the example given earlier you would have:

loadWXRDATA("menuswxr" ,"WXRDATA");
loadWXRDATA("dialogs1wxr","WXRDATA");
loadWXRDATA("dialogs2wxr","WXRDATA");

That’s all there is to it! OK, so it is a bit tedious, but easily worthwhile if you use .wxr resources extensively.

DFGG 10th May 1999

================