D Tutorial /
Windows Resources
Prerequisites
|
Creating Resource Files
You can use a resource editor such as ResEdit to create the .rc resource file, or write the resource file manually by following the syntax rules defined on these MSDN pages: Resource File Syntax and Resource Types.A separate C header file (usually resource.h) should be defined which lists the unique IDs of all the resources in the .rc file. This is either generated automatically by a resource editor, or you'll have to write the header file yourself.
Compiling Resource Files
Use rcc to compile the resource file, for example:
|
-D_WIN32 defines the _WIN32 macro, which might be needed in existing RC files generated by Visual Studio, otherwise RCC could attempt to include the win16 header files.
-I adds a directory search path for Windows header files. Double quotes are needed for paths with spaces. These include paths might be:
|
Set these include paths accordingly to where you've installed the Windows SDK. The Visual Studio directory might be needed if the resource file was generated by VS. You could try compiling without the VS headers and see if that works for you.
The resource file will typically #include a resource.h header file, and RCC must be able to find it when you invoke it. After compiling the resource file with RCC, use HTOD to convert the header file to a .d file:
|
Import the resulting header.d file into your project's source module. This will give your project access to the unique resource IDs.
Using RC Instead Of RCC
Sometimes RCC will fail to compile a resource file. In this case you might want to try using Microsoft's Resource Compiler, which should be distributed with the Windows SDK. RC is typically installed in the C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin directory. An example command to compile a resource file is:
|
You will have to experiment with the include paths, since some needed headers might be located in different directories. Don't forget to put double quotes for paths that have spaces.
Writing Code That Uses Resource Files
Make sure you specify the correct name of a resource when using it in your code. Names are case-insensitive.Download the example project here.
Walktrough:
We have a header file that lists the unique IDs for every resource:
|
Our menu resource is called AboutWindow. We use it in a windows class:
|
The resource.rc file has this definition:
|
Inside the window procedure we check if the menu is invoked, and if so we invoke a dialog box:
|
We need another resource for the dialog box, named AboutBox. In the resource.rc file, the dialog box is defined as:
|
We also need a dialog box procedure;
|
If you're using ResEdit, you can invoke a code-generating feature from the menu File->Code Preview->c/c++, which creates sample C code that uses your resources. You can easily translate this code to D. Note that resource files generated with ResEdit? might need to be compiled with Microsoft's resource compiler.
Important Notes
Unicode
For Windows unicode functions which expect string arguments, Windows expects pointers to zero-terminated UTF16 strings. To convert any D string into a zero-terminated UTF16 string you can use the std.utf.toUTF16z function, e.g.:
|
For non-Unicode WinAPI calls you should use the std.string.toStringz function. Note that you don't have to call this function for string literals, since they already have a null terminator appended to them:
|
Version Resources
An example version resource:
|
Compiling Code That Uses Resource Files
If you want to use the WindowsAPI bindings (highly recommended over the slightly outdated std.c.windows.windows module), you will have to define some version identifiers when both building the bindings for the first time, and every subsequent use of the bindings, e.g:
|
Using the -version=Unicode flag means that a function such as CreateWindow will be aliased to the Unicode function CreateWindowW. Otherwise the function would be aliased to the CreateWindowA function. You can still invoke Unicode and non-Unicode functions explicitly if you want to.
You can pass the -L-Subsystem:Windows switch when invoking DMD to remove the console window from your GUI apps. However using the console window and D's various writeln() functions can be useful for debugging purposes.
To compile your project you will have to invoke DMD with your project file, several version identifiers which the WindowsAPI bindings expect, the translated resource header file (translated by htod), and the compiled resource file. If you are using the WindowsAPI bindings, you need to add an include switch with the path of the bindings' win32 directory.
Here's an example of compiling a project that uses resources:
|