Embedding multiple, identically named resource (RC) files in a native DLL - c++

For my application (an MMC snap-in) I need to create a single native DLL containing strings that are localized into different languages. In other words, if you were to inspect this DLL with Visual Studio, you would see multiple string tables, each associated with a different locale but containing the same string IDs.
The approach I would like to take is to have various subdirectories under my project directory such as "de", "en", "es", etc (i.e. one for each language). Inside each subdirectory would be a file called "Resources.rc" which would be the RC file containing the strings for that language. Having my resources in this structure would be ideal for the localisation team.
I have managed to create my various RC files and have added them to my Visual C++ project. They all appear correctly in Solution Explorer in Visual Studio (you basically see five instances of an entry called "Resource.rc", but each entry points to a different file).
The problem comes with building my project. It seems that only a single one of the RC files (the one that is specified first in the vcproj file) is compiled into a RES file and included into my DLL. Presumably this is because Visual Studio does not like the fact that the RC files all have the same name.
Is there any way to achieve what I want?
Thanks!

Yes. And No.
If you want multiple RC files you are going to have to leverage off the Operating systems support to have multiple resources in one file. In the resource editor, for each resource, you can set its locale AND the resource editor will allow you to have multiple resources with the same ID, as long as their locale is different.
So, your first step would be to edit each of the RC files to ensure that the resources in one are English/US, another contains French etc.
Next, get the main RC file to #include the others.
Lastly, and this is the problem, you need to rely on the Operating systems logic to load the correct resources. If you are happy to let the locale of the PC determine what UI language is used you have done enough.
If you want to provide a menu option allowing users to change languages: SetThreadLocale used to be an easy way to switch the Locale of loaded resources on the current thread. Since Windows 2000 some unfortunate overloaded usage of the API has caused MS to deprecate its usage in favor of requiring App Developers to always use FindResourceEx - which really doesn't help you if you want, for example, to load a string from a string table.
If you really want an easy way to have a user selectable UI language, then you need to place each of your .rc files into a seperate dll. and then LoadLibrary on the appropriate language resource dll.

Related

Pick appropriate .rc file on language selection

In my MFC application,there are three resource files(.rc) for three different languages(jap,eng,russian) and one main.rc file which includes other three resource file.All resource files contains same resource string in different languages and they all includes same resource header resource.h.
When user runs the application ,popup window will appear asking user to select one language.Based on the user selection application has to select appropriate rc from which it will load resources.
Is there any way by which when user select one language application will pick appropriate resource file.
In the MFC this is done via satellite DLLs.
Place each language RC in a separate DLL. Than upon load of the application load the specific language DLL and use AfxSetResourceHandle with this handle.
In this case resource are searched in this DLL.
An alternative is to consider adding additional stringtables to your project.
More details are provided here:
http://www.dev102.com/2008/10/20/how-to-localize-your-application-using-string-tables/
Basically, you add an additional table and set the culture information in the resource editor. Then, you can specify that culture before getting the value.
The example provided is for C# but the principles are just the same.
A possible way forward if needed.

VC++ 10 MFC: What is the correct way to do localization

I am a .NET guy who is having to do some work on an MFC app. The app is a VS2008 MFC executable which I have converted to VS2010. The original developers did localisation by specifying the name of a .txt file with key value pairs in it on the applications command line. Installed shortcuts to the executable specify a different .txt file depending on which country the app is being installed in. This of course does not work if you just run the .exe directly. This seems like a weird way to do things to me.
I want to do this the propper MFC way, but I am having difficulty finding definitive answers on Google. My understanding is that the String Table in the .rc file should be used for this localisation? Is this the current best practice for MFC?
With respect to the String Table I have read that the practice is to create multiple string tables each for a different language. How do MFC applications choose which language to use? Is it based on the machines current language settings or can I control this (it may be that we want the language to be specified by the Wix .msi installer we are also building)?
I have also read that embedding all resource inside an MFC application has fallen out of favor and that now you should compile seperate resource .dlls? Is this is true ill investigate how to do it...
Finally, do I have to do something special to get MFC to support Unicode or is MFC Unicode by default?
Thanks
The idea is that all localizable items should be stored in resources. Standard UI objects such as menus and dialogs are automatically stored in there (resources) for you but items such as string literals (eg: error messages, messagebox prompts,...) should be pulled from source code to the string table. This short codeproject article of mine demonstrates how to easily pull strings from the string table in your code.
Note: You should have only one string table in your resource script (.rc).
From there on, you can translate your resources and create resource DLLs (aka satellite DLLs). The idea is that you keep a different copy of the .rc file(s) for each language. Each translation is compiled into a codeless DLL that acts as a container for the resources.
This other codeproject article of mine lets you easily load resource DLLs according to system settings or user preferences: The code looks among your resource DLLs which available language best matches user settings (based on user's UI language and regional settings). The code also lets you easily build a menu with all available languages. That way, your user can override the default choice.
DISCLAIMER: My ad follows. Feel free to skip :-)
Regarding the translation of resources, the management of translations and the creation of resource DLLs, you may want to check out appTranslator.
END OF AD :-)
Regarding Unicode, MFC ships with ANSI and Unicode versions of the code. It's up to you to choose if you want to build an ANSI or a Unicode app: Just make your pick in the first page of project settings. Of course, if you are startgin from scratch, you should definitely go Unicode. But if legacy reasons force you to stay ANSI/MBCS, don't worry to much: It won't prevent you from localizing your app.
Years ago when I had to work with multiple languages in MFC, we used separate resource DLLs. All you need do is make one call to switch which handle the resource functions would use and all was automatic from that point forward.
You need to do more than just change the strings. Dialogs in particular will have strings inside of them, and you may need to change the layout if those strings become too long after translation.

How to write a shell extension in C++?

This seemed like a common question but after doing some searching, I wasn't really able to find my answers. There is an article on this here:
http://www.codeproject.com/KB/shell/shellextguide1.aspx
But it's for a very old version of Visual Studio. I'm using VS 2008, so the instructions and interfaces don't seem to match what I'm seeing.
I want to create a simple shell extension using C++ that creates a context menu for files with extension .GZ. When right clicking on these files, I should be able to click my context menu item and have a callback in code to do some sort of operation on that file.
Other context menu items would do things like spawn modless dialogs to accept user input before executing some action.
From what I've seen, ATL is used for this but I have never used ATL, so all of the object types and interfaces are very confusing to me. It wouldn't be so bad if I had a proper tutorial or documentation to read.
Can anyone help me out? Isn't there some sort of tutorial out there that isn't 10 years old?
I can't tell you exactly how to write a shell extension, but I will provide a number of tips. Writing a Shell Extension offers some significant advantages over the much simpler “registry-only” method:
With a Shell Extension, you can dynamically create a context menu item (or submenu) that is more relevant to the selected file(s). For example, if you are writing a Shell Extension for zip files, it is possible to create a submenu within the context menu that shows the entire contents of the zip.
You can handle multiple files simultaneously, which may be more beneficial not just for performance purposes but also so that you can work out what to do based on the selection as a whole rather than just for each file.
Some of the downfalls to Shell Extensions are:
Substantially increased complexity. Be prepared to spend a lot of effort on this to get it working. Have a home-espresso machine installed next to your computer and/or hire someone to make you coffee.
Substantially increased difficulty in debugging. Ditto about coffee.
It's difficult to write a Shell Extension because they can be very hard to debug.
Shell Extensions are loaded by the explorer.exe process, and without specific configuration of Explorer, you need to force-quit the explorer.exe process so that you can install a newer version of your Shell Extension. There is a way to get Explorer to unload DLLs that it is no longer using, but you should only do this on a development machine and not on a deployment target:
In RegEdit, browse to the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer
Add a new DWORD key called “AlwaysUnloadDLL” and set its value to 1.
Restart explorer.
This works most of the time, but there may still be times where you need to close Explorer because the Shell Extension was not unloaded.
Keep in mind that your Shell Extension may be loaded by other applications, for example, if you right-click on a file with an applications “open file” dialog, then your Shell Extension will be loaded into that application, and not Explorer.
If your Shell Extension causes a runtime error, quite often the result will simply be that your context menu item does not show, very rarely will you be told that your Shell Extension failed to load or that it caused a runtime error.
Configuration can be hard, even with an installation, registry data needs to be created in several places, and depending where you want your context menu to show, the places in the registry may differ between different versions of Windows.
What you'll need to do:
Visual Studio offers some shortcuts to creating Shell Extensions, but basically you'll need to create a COM DLL. A Shell Extension for context menu items must implement both the IContextMenu interface and the IShellExtInit interface.
In the IShellExtInit::Initialize() method, you can obtain the selected files from the IDataObject parameter. From memory, the data is in “Drag-n-Drop” format, so you need to get an HDROP handle from the IDataObject and query the files from there (this is from memory, it may actually be different than as I described here, so proceed with caution).
Once your DLL is ready to be “installed”, you must copy it somewhere, and then run regsvr32 to make sure it is registered.
Follow this guide to know where to put registry keys.
There may be issues with 64-bit Windows, if you build a 32-bit DLL it may not load in 64-bit Explorer… so keep this in mind if you are having trouble with 64-bit Windows.
Your DLL will actually have two GUIDs associated with it. I can't remember exactly how it works, but one GUID refers to the DLL itself and the other refers to the actual Shell Extension. Make sure you use the GUID of the actual Shell Extension when creating keys in the registry where a GUID is required.
All things considered… (tl;dr)
Weigh up the costs of whether a Shell Extension is worth it. If you want to create menu items dynamically based on the selected files, then a Shell Extension may be the only way. If you want to handle all files simultaneously then you'll probably need a Shell Extension as well.
An alternative to the context menu method, could be to have a drag-n-drop target on the user's desktop or something. Explore other ways that you could have the user submit your files to your application, because a Shell Extension is often far more effort than it is worth. I found this out the hard way and I think everyone else has too.

"Conditional" macros in visual studio 2010 property manager

The property manager allows having different property sets for different configurations - for example, release and debug.
However, it still means you have to manually assign each property file to each configuration.
Is there some method to automatically assign a property set to a project based on some parameters (like configuration or platform)
a specific example:
I have a solution with many sub-projects.
this projects depend on various external libraries.
for each external library I have a .props file with the relevant directories and other parameters (include , lib, dll's...)
In some cases the directory names can be easily constructed using the default macros such as $(Configuration), $(Platform), etc.
However some libraries come with a less standard \ consistent naming convention.
for these cases I create .props file which are specific to a configuration (Debug\Release) - but it requires assigning the manfully to each project, which is tedious and error prone.
This is possible, at least in principle, see this post, for example. However, I did not find a practical way to use the whole power of MSBuild in combination with c++ projects from within the IDE. Whatever smart MSBuild expressions you write down in your property sheet, once you fire up the property manager dialog in the IDE everything gets overwritten with either defaults or the values inferred from there. This is an odd behaviour and completely different from other project types. Looks like they just wanted to keep the old pre-MSBuild style of editing VCProjects...
You can record a macro and use VBA to create/generate these with a button click.

C++ DLLs newer version

All,
I have a C++ COM DLL written using Visual Studio. All the interfaces have GUIDs in idl and rgs files. We want to create a new DLL with brand new GUIDs as we want it to co-exist on the same machine with the old one but with different logic. The number of GUIDs is more than 200. Is there a tool that finds the GUIDs and replaces them ? I noticed for every GUID in idl file there are 3 same ones in the rgs files.
I am not really into C++ COM but I have to get this done :
Rgds,
MK
We use the following dumb but working approach: we store all the GUIDs relevant to COM classes and interfaces as #defines in one header that is included into the .idl file. When we need to break compatibility we just open that file and manually replace all the GUIDs. Not very elegant, but reliable and works.
So my suggestion is that you just search for all the GUIDs in your project and replace them. I guess you'll be better off moving them all in one place at the same time.