Question

I use SHBrowseForFolder API to display folder selection dialog in Windows. My app supports UI language localization based on an end-user's selection. This is achieved by loading all resources using FindResourceEx API for a specific LCID.

So I was curious, is there any way to make SHBrowseForFolder honor thread's LCID selection? Or, in any other way make it display text for my preferred language based on LCID?

Was it helpful?

Solution 2

Just curious, who's downvoting it? You guys don't care about localization?

Nonetheless, I think I found a solution. It was suggested to me on a separate thread and it is a C# project designed for MessageBox API, but the concept is the same. Install the thread-wide hook before calling SHBrowseForFolder using SetWindowsHookEx(WH_CALLWNDPROCRET) and then trap the WM_INITDIALOG notification from the hook procedure. From there simply load your localized text depending on the UI language and set it to controls using SetDlgItemText, where hDlg=window handle you get in the hook procedure and nIDDlgItem=ID of buttons and text fields that need localization. Here are the ones currently used: IDOK=OK button, IDCANCEL=Cancel button, 0x3746="Make new folder" button. You can also change the title of the browse window itself by calling SetWindowText on the window handle. Then when the SHBrowseForFolder returns call UnhookWindowsHookEx to unhook from it.

This approach has some drawbacks. One is that it relies on MS to keep the layout of the browse window. So far it's been relatively the same. So you may want to track Windows version with GetVersionEx and adapt accordingly.

Secondly, you may need to adjust the sizes of buttons and labels after adding new text. But luckily that is not a problem. Use DrawText with the DT_CALCRECT flag to see the outlines of a new label and then change each control's size with MoveWindow. Note that a more sophisticated approach would involve a full resizing of the browse window itself. But I'll leave it up to you.

In closing, I want to say that it's a shame that Microsoft is so lame in proving decent means of localization of their UI. There are some APIs that were supposedly designed to do that, to name a few:

  • SetThreadLocale - I honestly don't know what exactly it does and what is it's purpose. The documentation is close to being moronic.

  • SetThreadUILanguage - in despite of having been introduced in Windows XP, this API only does something starting with Windows Vista. But still, it sets only about 80% of the UI to a provided LCID. For instance, SHBrowseForFolder is not affected by it, but there may be more. I didn't check other common controls.

  • InitMUILanguage - I don't know what this thing does. It had no effect on my app...

  • setlocale - affects only the legacy C stuff like printf and such. None of it is used for the UI though.

So here you go. None of it technically works. So a developer forced to write for Windows (and trust me I'd avoid it as soon as I can) who wants to give end-user the capability to change the UI language from their program without resorting to a cumbersome Windows user-wide change of the language, is left to devise his/her own way of doing it. Good going Microsoft!

And lastly, to what @HansPassant suggested above. I cannot make my users pay $100+ just to be able to use their language for my app's UI. I'm sorry, but I can't fall that low...

OTHER TIPS

AFAIK, SHBrowseForFolder() is not natively user-localizable. What text within the dialog are you trying to localize exactly? You have to provide it with a title, so you can provide whatever pre-localized text you want for that.

Are you trying to localize the button captions or other controls, maybe? You would have to use the callback functionality to access and manipulate the dialog controls manually for that.

Have a look at switching to the IFileOpenDialog interface. It has SetFileNameLabel() and SetOkButtonLabel() methods, at least.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top