CRichEditCtrl not working properly in shared dll written using MFC? - c++

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!

Related

Why is IExplorerCommand::Invoke() no longer being called?

I have created a File Explorer context menu extension that uses the IExplorerCommand interface to add menu commands to the Windows 11 context menu.
This has been working fine, but after the last Windows update, it no longer works properly.
Although the menu commands still appear, nothing happens when I click on any of them. I've added logging and I can see that IExplorerCommand::Invoke() is no longer being called.
Strangely, if I select the "Show more options" menu to get the legacy Windows 10 context menu, the commands work fine from that menu, it is only in the new Windows 11 context menu that they don't work.
I have tried running File Explorer in a debugger while selecting my menu commands, and I get lines like this in the output window when I click on the command:
onecore\com\combase\dcomrem\stdid.cxx(726)\combase.dll!00007FF9EB9947F5: (caller: 00007FF9C22E1E38) ReturnHr(2627) tid(67bc) 8001010E The application called an interface that was marshalled for a different thread.
I'm guessing this is the reason why my commands are not being called. Does anyone have any suggestions for what is causing this? Could it be a bug in File Explorer?
I've tried both STA and MTA threading models, and changing this made no difference.
Well, after wasting hours on this I finally have a solution!
My code was based on the PhotoStoreContextMenu sample code here:
https://github.com/microsoft/AppModelSamples/tree/master/Samples/SparsePackages/PhotoStoreContextMenu
This uses the Windows Runtime C++ Template Library (WRL), and defines the base classes used by the class like this:
class TestExplorerCommandBase : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IExplorerCommand, IObjectWithSite>
The change that fixed it for my code was to use WinRtClassicComMix instead of ClassicCom, i.e.
class TestExplorerCommandBase : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IExplorerCommand, IObjectWithSite>
I'm pretty sure this problem started when I installed KB5019509, which is the Windows update that changes File Explorer so that it now has tabs.
Note: this problem only happens for IExplorerCommands created in the plug-in for submenus, the top level commands that are defined in the APPX file work fine.
Also note that although this change does fix the problem with Invoke() not being called, it does introduce a new problem which is that IOleWindow::GetWindow() no longer works so it is not possible to get the parent HWND. (See Calling IOleWindow::GetWindow() from IExplorerCommand::Invoke() is giving error 8001010d (RPC_E_CANTCALLOUT_ININPUTSYNCCALL)).

CRichEditCtrl from resource loads 1.0 instead of 2.0

I'm trying to update my application to use RichEdit 2.0; it's been using 1.0 since forever. Per the Microsoft documentation, I've changed AfxInitRichEdit() to AfxInitRichEdit2(), and I changed the class in the resource file from RICHEDIT to RichEdit20A (which is correct for this application). There is only one richedit in the resource file.
The application fails when I try to do anything with the window that includes this richedit. The dialog creation fails somewhere inside of ::CreateDialogIndirect(), and although I put breakpoints in CRichEditCtrl::Create and also on the class I derive from it, those breakpoints do not trip.
Out of frustration I tried calling AfxInitRichEdit() again and also calling AfxInitRichEdit2(). The application works! The breakpoints I put in do trip--but only on controls I create dynamically, not the one from the resource file. And when I run Active Window Spy, I see that the richedit created from the resource file somehow has a class of RICHEDIT even though I explicitly said RichEdit20A, and yet the dynamic ones are RichEdit20A as intended.
_RICHEDIT_VER is 0x210, and I'm using Visual Studio 2013.
I just can't figure out why CreateDialogIndirect() is making a RICHEDIT control--or trying to make one and failing, if I don't call AfxInitRichEdit()--instead of a RichEdit20A in spite of explicit instructions to the contrary. Any ideas?
Well, I feel stupid. There's a script that runs as part of the build process to update some resources, and for some reason that script has sometimes gotten confused between the debug and release versions, and copied resources from the release build into the debug build. I don't know why that happens and it's an issue for another day, but the upshot is the .rc file I had changed was getting replaced with another one.
Building the release version with the changes, and then building the debug version again, solved the problem.

Asserts when using an extension dll in MFC

I am trying to create a new frame window with toolbars inside a dll.
I was able to create the frame and the toolbars but however the messages do not work properly in the CToolbar. Particularly the ON_UPDATE_COMMAND_UI messages are never called in the DLL.
After some research I came to know that this is because
PreTranslateMessage(MSG* pMsg)
and
OnIdle(LONG lCount)
need to be called.
But my calling application is Delphi based and this cannot be done.
After research I came to know that this is best possible from an Extension dll.
Since MFC extension dlls can only be called from an MFC application. I thought of the following solution.
Delphi calls an regular MFC dll
The MFC dll calls the Extension dll.
But I have run into problems because of asserts in in MFC AfxGetResourceHandle() and AfxGetInstanceHandle().
But I am also aware that AFX_MANAGE_STATE(AfxGetStaticModuleState()); cannot be called from an extension dll.
Does anybody have a solution for this problem?
The ON_UPDATE_COMMAND_UI messages are created by the MFC message loop. You don't have one. You will have to build your own ON_UPDATE_COMMAND_UI translator or something equivalent. It all starts with this in your frame window message map:
ON_WM_INITMENUPOPUP()
Your OnInitMenuPopup handler will be called when the user selects a menu, before the menu is displayed.

Switch between resources DLL

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

need help using 2 mfc projects in one solution

ive created the first project as mfc application and i have tried to enter the solution another project which created as mfc dll. when i running program the gui from the first solution(demodlg) is shows up. and i want that in a prss of a button in the gui the second gui(CAnalyzerDialog) will show up. i've tried a lot of options and i cant get it done right.
the last option ive tried is this code :
CAnalyzerDialog dlg;
dlg.Create(CAnalyzerDialog::IDD);
please help. thank you for your time
I think the problem is that the program and DLL both have their own resource files, but MFC is only accessing the program resources and ignoring the DLL ones. Look into AFX_MANAGE_STATE and see if that helps.
Have you tried to set CAnalyzerDialog as primary project?
On solution explorer, right click on the CAnalyzerDialog, tick "Set as startup project".
Probably you are trying to elaborate that:
demodlg - EXE
CAnalyzerDialog - DLL
Check the way you link both project(static or dynamic-runtime/compile time).