Switch between resources DLL - c++

I am working on MFC solution that consists of many projects. One of my projects "App.exe" depends on other project output dll "SC.dll".
I added reference to the other project via Add Reference option under the App project.
I want to "based on an option" switch between languages by using resources dll.
I've another resources project that produces Arabic resources "SC_AR.dll".
I tried to use LoadLibrary based on the option ,but it failed.
Is the "Add Reference" approach is wrong?
If not, how I could switch between the Dlls?
If yes, what is the right approach to follow?

There is no need to reference a resource satellite. MFC searches satellite DLLs using the user's Windows UI language and your application's file name. To switch to another satellite, call LoadLibrary() and then call AfxSetResourceHandle().
Of course, this is assuming you are loading all resources via MFC (e.g. use CString::LoadString instead of LoadResource ). You have to use your own satellite DLL handle explicitly if you call API directly.
PS the less said about SetThreadLocale the better.

If you're using MFC then the resource dll is loaded in the boilerplate that's generated in the main file. (can't rememebr it offhand) but search for LoadResource(). You'll have to call LoadLibrary to get the hmodule to pass into this.
Be aware that if you're displaying resources from several dlls, you will have to be careful about dialogs in a different resource dll. If youre simply swapping dlls, you won't have a problem.

As MFC doesn't support Arabic, I made an English dialog and Arabic one inside the dll. And according to the Language property I send the resource ID to the Constructor of Dialog.
And for any String I use LoadString

Related

MFC C++ Language Resource DLL - only override some dialogs

I have successfully made a resource only DLL, and placed some dialogs, that were in the main exe. So I have Test.exe, and TestENU.dll. It works fine, but I am trying to find a way to only override some dialogs, instead of being required to have all exactly the same dialogs, and instead pull some from the base exe, as my real project has around 40 dialogs, and I only want to have to translate some, slowly over time.
(I used this link to do satellite/resource dll)
http://msdn.microsoft.com/en-us/library/8fkteez0(v=vs.90).aspx
Default resources (including dialogs) are governed by the current setting of the resource handle. You can set the resource handle at any time using AfxSetResourceHandle to point to a resource only dll, or, your executable. You'll need to be prudent in making sure that the handle is pointing to the correct resource location before instantiating a dialog, so, you'll need to save the current handle before changing it to a new resource handle, and, changing it back when you are done.
Pass a template ID to the constructor of your dialogs.
Constructor:
CTestDlg::CTestDlg(int Template, CWnd* pParent = NULL) : CDialog(Template)
{
...
Call:
int idd;
if (bTestDialogTranslationExists)
idd = IDD_TESTDIALOG_FROM_DLL;
else
idd = IDD_TESTDIALOG;
CTestDialog dlg(idd);
dlg.DoModal();
This code is for demonstration only. You might want to derive a new class from CDialog that handles localized dialog templates automatically, depending on, for example, if the Template exists in a replacement map.
// have this as a global variable or in your CWinApp class
CMap <int, int, int, int> translatedDialogsMap;
// put this maybe in you CWinApp::InitInstance before any dialog could possibly be displayed
translatedDialogsMap[IDD_TESTDIALOG] = IDD_TESTDIALOG_FROM_DLL;
translatedDialogsMap[IDD_TESTDIALOG2] = IDD_TESTDIALOG2_FROM_DLL;
translatedDialogsMap[IDD_TESTDIALOG3] = IDD_TESTDIALOG3_FROM_DLL;
...
// check in your dialog subclass constructor code, if a mapped dll dialog exists
int idd_replaced;
if (translatedDialogsMap.Lookup(Template, &idd_replaced))
Template = idd_replaced;
In 2022 I am in the process of doing the same thing - trying to localize only some resources. Like the author, I am having a very hard time, and the solution has not been found yet. Here's what I can say after reading countless articles on the subject, some making careless statements that cost hours of work just to see that they don't work.
Given : you have an EXE with "default" resources and an extension DLL that replaces only some of then (I specifically tested it on strings so far).
The resource handle (AfxGetResourceHandle()) points to the EXE
If the DLL is properly loaded, it's placed in the search list for resources
The search process is as follows:
a. The resource handle module (EXE) is searched
b. If not found, the extension DLL resources are searched
Given this order, if the EXE has the needed resource, it wins. In our task it always does, so the DLL is as good as not loaded - useless.
Some people suggest setting the DLL module as the resource handle (AfxSetResourceHandle), claming it will reverse the order. DO NOT do it. It will not reverse the order, and here's why.
Doing so will replace the EXE's handle by the DLLs, that's all. It's a one liner in the MFC source. Now the search process will go as follows:
The resource handle (AfxGetResourceHandle()) now points to the DLL
The DLL is searched
If not found, the extention DLL resources are searched again!
This is because extension DLLs are added to a search linked list when loaded, but the EXE (I should say the resource handle that defaults to the EXE) is not! It is handled separately upfront. Replacing the resource handle does nothing to the linked list.
Setting the resource handle to the DLL makes EXE-based resources unavailable, so you end up with only localized resources, and now your program will most likely not start up.
I don't see a way (yet) to add the EXE to this list. The type required is (roughly) "extension DLL", you can't just do a new CDynLinkLibrary call.
What I am thinking is separating out even the default resources into a DLL. That way both DLLs become equal and get added to the search list. The precedence will, I suppose, be governed by the LoadLirary call order, so if you first load the localized DLL and then the "main", you should be OK.
P.S. Creating resources in two languages inside the EXE, while doable, has proven to be a nightmare - it has never worked the way you'd want: first the selected UI language (see SetThreadUILanguage) then, if not found, the main in any language available. Comments on StackOverflow say "make DLLs, it's the only way" without going into details why.

Can windows 7 and 8 common dialogs be hooked

I am trying to replace all Windows Common (Open/Save) filedialog calls with my own custom dialog. From what I read so far, I could do this with a hook on the calls either by writing my own or by using libraries like detours or easyhook. But someone told me recently that such an approach is only possible pre-Vista, because of the change in sessions architecture and it is impossible to do such a switch in Win 7/8. Now, I am not a guy who likes the word 'impossible' :) So if you have any advice on the matter, any at all, please do tell and I will appreciate your kindness.
For what I what to do, my application will be run by the user, it will reside in the tray, and when the user calls for Open/Save dialog from any application, it should replace the default common dialog with a custom dialog.
The newer style Common Item dialogs are implemented as standard COM objects, so you could just implement your own DLL that exposes the same COM interfaces (IFileOpenDialog, IFileSaveDialog, etc) and then override the default registrations in the Registry with your own. That way, every app that uses the dialogs will load your DLL instead of Microsoft's.

How can I change the language in AfxMessageBox?

I have an MFC app that uses AfxMessageBox to display message boxes. The app itself lets an end-user to change the user interface language. On the inside it does so by loading resources using LCIDs (or FindResourceEx API.) My issue is that I can't seem to make AfxMessageBox to take LCID to change the language for OK, Cancel buttons, etc. This also affects File and Folder Open dialog windows.
Any ideas how to do this?
PS. This approach must work under Windows XP and up.
According to this SO article, there are no standard functions for this, there's a link to a CodeProject article "Localizing System MessageBox" with source code for a DLL (it's in c# but seems simple enough to be rewritten in C++) which uses Windows Hook so that you can supply your own text for the MessageBox buttons; there's even a suggestion for sizing buttons to the text in the discussion part of the same article.

CRichEditCtrl not working properly in shared dll written using MFC?

I am writing a DLL written in MFC to be used by other application.
project settings:
1. Use MFC in static library
2. preprocessor : AFXDLL
3. MD Build
I have also used AFX_MANAGE_STATE (AfxGetStaticModuleState()) before calling
CWinApp which internally calls InitInstance and DLL main.
This Dialog has tab in it and I am able to see only the first tab all other tab are coming as blank. When I am running the same DLL as exe (with required changes) its working fine.
Also DLL is crashing when i am calling AfxGetApp() ?
I suppose major problem is due to DOMODAL(). Can anyone tell what might be the issue of tab control not working?
Update I found out that CRichEditCtrl was the problem. In dialog tab I had this as well when I removed this It worked fine. Can anyone know the reason of this..
I have used AfxInitRichEdit2() before in InitiInstance()
I am new to MFC so let me know if you need any more info
You have to call AfxInitRichEdit() before the rich edit control is used.
Do you call AfxInitRichEdit2 in InitInstance of the EXE?
Try putting it in the DLL's InitInstance too!

How to convert an ActiveX (webbrower hosted) project into static library project?

I have an ActiveX component which contains a control (webbrowser control embedded in composite control dialog pane) for accessing certain URL. The ActiveX component accessing URL can be used in other MFC or VB projects. The usage is to register the ActiveX component (use regsvr32 cmd) and then insert the control in a dialog window by using "Insert ActiveX control".
Now I am planning to convert the ActiveX component to static library with the same browser window and web access functions. I wonder how to do it? In addition, how the browser window (in static library) can be used in other MFC projects. Is it through functions call? Is there a sample project available?
I used Microsoft .Net 2003 as development tool.
Thank you very much in advance.
I'm a little unclear about the extent to which you think you can put all of that in a static library.
This is probably not going to be as straightfoward as you think. The wizard and code in VS/MFC/ATL which allows you to insert an ActiveX control in a dialog is doing a lot of work for you. That said, it makes certain assumptions about the nature of the site for the ActiveX control, such as how the message pump works, who is the owner window, the threading model, and so on. In a dialog, these are knowns. In another context, they are not.
The right way to go about doing what you're doing is to leave it as an ActiveX control. Maybe if you stated what problem you are trying to solve by putting it into a static library, we could give other options.
The WebBrowser ActiveX control is really a wrapper for the shdocvw.dll library, in the system32 folder. shdocvw.dll is the heart and soul of IE (and, by extension, much of the Windows Explorer interface). It's all very heavily based on COM, which has its own rules for loading libraries and so on. So the site (any application which wants to use your ActiveX control) really needs to be friendly to ActiveX/COM anyway.