Customizing MFC ribbon controls with dynamic linking - c++

I have a VS2017 MFC C++ application which uses a ribbon based UI. Up until now I have been using the statically linked MFC libraries but now have to move to MFC in a DLL as I need Multithreaded DLL linkage /MD in order to support another third party SDK (Vulkan). One of the reasons for using statically linked MFC is that it allowed me overcome some problems in the implementation simply by including the source for the item I needed to change in my application. e.g. to use data the edit part of a combo box to select the nearest item in the drop down. This doesn't work when I use the DLL version of MFC for obvious reasons, is there any way around this? I can't simply inherit from MFC base classes as my application is building the ribbon interface from a ribbon resource file and there don't seem to be any hooks to customise this behaviour.
My current thoughts for possibilities include building my own version of the MFC DLLs or simply adding the full MFC source as a sub-project and change my main project Use of MFC to Use Standard Windows Libraries. Both of these seem like nasty hacks.
Edit: In response to the comment below from IInspectable, I'm not entirely sure why the current behaviour doesn't work but have some ideas. Linking the static lib version of the code, if I include my own copy of a function that occurs in the lib, the lib version never gets called (possibly never even gets linked). When linking the DLL version of MFC, my modified function never gets called. This could be because it is called by another function in the same DLL which never sees my code or it has a slightly different decorated name. My thinking is that including all the MFC source in my app and not linking any MFC in the compiler options is one brute force solution, though a pretty horrible one.

I ended up recompiling a custom version of the MFC DLL based on this project, https://www.codeproject.com/Tips/5263509/Compile-MFC-Sources-with-Visual-Studio-2019 This lets me keep my MFC modifications while also using MFC in a DLL with minimal changes to my existing project

Related

What is Different Between "MFC DLL" and "Console Application DLL"?

What is the difference between creating a MFC DLL from Visual Studio wizard and creating C++ Console Application and changing the configuration type to DLL instead of .exe?
You can surely figure out how to change a console application to dll type, but it's recommended to use the non-MFC DLL project template.
One major difference between a non-MFC and a MFC Extension DLL is that it would allow sharing resources like dialog templates or bitmaps to MFC appliactions by calling
// MFC extension DLL one-time initialization
AfxInitExtensionModule(PROJNAMEDLL, hInstance);
// Insert this DLL into the resource chain
new CDynLinkLibrary(Dll3DLL);
in DllMain(). Other benefits are that you can use MFC (CObject-derived) classes that sit in the dll and that the MFC Extension DLL can share the memory address space with the calling instance, meaning that two apps loading the same extension DLL will only share the code but won't interfere with allocated data.
Note that you need the "shared MFC DLL" project setting to use extension DLLs. Linking MFC statically into your project won't work. So extension DLLs aim at sharing code among different apps that run simultaneously, for example, but only use the code memory once. This way of code reuse was one intention at least when extension DLLs were introduced, but in the real world different apps tend to use different versions (dll hell, side-by-side). Speaking of:
One good use of an extension DLL is to customize an app (branding, localisation) just by installing differend versions of a dll.
Further reading: https://learn.microsoft.com/en-us/cpp/build/extension-dlls
According to Creating an MFC DLL Project it states:
An MFC DLL is a binary file that acts as a shared library of functions that can be used simultaneously by multiple applications. The easiest way to create an MFC DLL project is to use the MFC DLL Wizard.
This article Kinds of DLLs also states:
Using Visual Studio, you can build Win32 DLLs in C or C++ that do not
use the Microsoft Foundation Class (MFC) library. You can create a
non-MFC DLL project with the Win32 Application Wizard.
The MFC library itself is available, in either static link libraries
or in a number of DLLs, with the MFC DLL Wizard. If your DLL is using
MFC, Visual Studio supports three different DLL development scenarios ...
I believe the above explains the difference:
One version of the DLL exposes the MFC library.
One version does not.
That is my understanding.
Other related article: Create C/C++ DLLs in Visual Studio
An MFC DLL is a dynamic library that uses MFC components and the MFC runtime. This means that an MFC dynamic library usually requires the MFC support libraries along with the MFC runtime. To compile an MFC DLL requires the MFC include files and the MFC directives.
When you use the Visual Studio Wizard to create an MFC DLL all the compiler, linker, and other settings and options needed to create an MFC DLL are all generated for you along with an MFC DLL stub.
A Console Application is an application that uses the C++ Runtime from a console window.
When you use the Visual Studio Wizard to create a Console Application all the compiler, linker, and other settings and options to create a Console Application are all generated for you with a Console Application stub which is typically a Hello World type of application with a main() that contains a printf().
The source code for a DLL has required structure for a DLL main entry point that is different from the required structure for a Console Application main entry point. See the Microsoft article DllMain entry point which has this example source code:
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
So the differences between an MFC DLL and a Console Application involves a number of areas:
the structure of the source code
the include files used in the compile
the libraries used in the link
the options used in the compile
the options used in the link
Changing the configuration type does not modify the source code or include files specified in the source code. Nor does changing the configuration type change all of the necessary compiler and linker options and property settings that need to be changed.
See this Microsoft article, DLLs and Visual C++ run-time library behavior, that discusses the structure of DLLs and their run time behavior which provides an idea as to the differences between an EXE and a DLL.
An Application (executable) is a module that can be run. It contains one entrypoint, the main() (console) or WinMain() (windows GUI) function. A running instance of an executable is called a "process" in Win32.
A DLL is a library, intended for use by other applications. It is loaded at runtime - "dynamically", hence the name. DLLs contain no main entrypoint, instead they "export" functions or even classes and data. Lacking a main entrypoint, DLLs cannot be run stand-alone, instead they are "loaded into a process's (application's) address-space". The process can use their exported items. It is a good way to implement commonly used operations, for example a company's "development environment" or "foundation" - SDKs are typically implemented as DLLs.
MFC is a C++ library containing GUI (and other) classes and functions, largely (but not exclusively) wrapping Win32 objects. An application or DLL can be using the MFC library, or not.
As for your question, creating a console application and then changing it to DLL makes no sense. The Wizard will create a main() function, which you will have to manually remove. And finally you will have what, a normal DLL... You can simply create a DLL from the start, whether it will be using MFC or not.
EDIT:
According to the documentation from Microsoft:
Each process provides the resources needed to execute a program. A process has a virtual address space, executable code, open handles to system objects, a security context, a unique process identifier, environment variables, a priority class, minimum and maximum working set sizes, and at least one thread of execution. Each process is started with a single thread, often called the primary thread, but can create additional threads from any of its threads.
So yes, processes need to contain at least one thread - terminating the primary thread also terminates the process. Furthermore, an executable must contain an entry point, it's what the primary thread will execute and return a value to the system. It's actually impossible to build an executable without a main()/WinMain() function, it will generate Linker Error LNK1561:
entry point must be defined
The linker did not find an entry point, the initial function to call in your executable. By default, the linker looks for a main or wmain function for a console app, a WinMain or wWinMain function for a Windows app, or DllMain for a DLL that requires initialization. You can specify another function by using the /ENTRY linker option.
As for DLLs, the term dynamic "linking" is indeed used by MS, however only to highlight the differences to static linking (what most developers consider linking). It's not linking in the usual way, ie resolving externals, changing symbol names to addresses, performing fixups and the like. A DLL has no unresolved externals and the so called "linking" means just locating exported items from the loaded DLLs (in the case of using an import library they are also assigned to local functions) - the linker is not involved in the procedure. Further information here.
Therefore I don't think that there was something "slightly wrong" in what I had posted above, and certainly not "literally everything".
As for whether my answer should be considered useful or not, I think I was right to suggest not creating an executable and changing it to a dll. An MFC DLL is a DLL "based on" (using) the MFC library - this was clear in my first post. The OP didn't ask about MFC extension DLLs particularly.

Failed to run the mfc application when calling a mfc dll with the Common Language Runtime Support (/clr)

I need to add Common Language Runtime Support (/clr) to my mfc dll project in order to use managed code in it.
I have do some setting for the all projects according to how to compile MFC and ATL Code By Using /clr from msdn.
I have done a lot of testing. But still failed to run my application although I only add the /clr support to the project without adding any managed code.
See below for details:
The exception, call stack, output information, the difference of output information and dependency dll between using and without using /clr please see Exception Detail
I can't get any useful information from call stack. I don't know even where to add the break point for debugging. Anyway, it's too later to add the break point at the InitInstance() of the application.
It seems the exception caused by loading dlls according the output information. But I don't know the really reason.
Otherwise I have downloaded a sample solution from msdn see Sample about Using /clr in MFC. The sample contains a mfc application calling a mfc dll with /clr support. And it works well. When I add my mfc dll(with /clr support) into this sample, it can work well too. I really don't down why it can't work in my solution. I have checked the property setting of my project compare with the sample solution. There seems nothing special.
I do need help, any suggestion?
Thank you all.
I have solved the issue by delaying loaded the dll that cotaines /clr support in the project calling it. See Set Delay Loaded DLL for how to delay dlls. It seems the exception caused by the chaotic unmanaged and managed initialization.
"Unmanaged and managed initialization is performed in two separate and distinct stages. Unmanaged initialization takes place first (via DllMain), and managed initialization takes place afterwards, through a .NET-supported construct called a .cctor. " See Initialization of Mixed Assemblies for details

DLL should not require mfc dependency

Currently my DLL requires that mfc80u.dll and msvcr80.dll reside in the same directory when I want to use it from a different application.
I think there is a switch in VS2013 that somehow compiles the DLL in such a way that these files are no longer required.
I am pretty sure I have once read about it.
This makes the DLL much bigger, that to me that's worth it.
Does anybody know which switch that is?
Thank you!
To remove VC runtime DLLs (not specific to MFC), use the /MT compiler switch.
If you are using MFC, you must also use Use MFC in Static Library in General page of project settings.

convert "MFC Extension DLL" into "Regular DLL with MFC statically linked" in a hurry

I got the VC++ source code of a dll for a USB device project, which the deadline is close. Right now I have to call this usb dll from another VB program. But the source code is based on the template "MFC Extension DLL", which can´t be called by VB. On the other hand, "Regular DLL with MFC statically linked" can be called by programs written in Visual Basic.
Is there a way, with the least effort of modification of the source code, to be able to call this dll directly from VB?
I tried to modify the project´s configuration properties/Use of MFC to Use MFC in a Static Library. But there is build error.
Now I am modifying the source code based on the new template "Regular DLL with MFC", but there is a lot of problems. For example, I don´t know whether I can use AFX_EXTENSION_MODULE in my new dll code.
Your problem is likely due to not implementing a CWinApp derived object which provides services that the MFC classes in the DLL rely upon. Probably you can just bung one in and it will work.
See here for more information:
http://msdn.microsoft.com/en-US/library/h5f7ck28(v=VS.80).aspx

How can I statically link my MFC extension DLL?

I have an MFC extension DLL that I've written. It contains derived classes of MFC controls (e.g. replacements for CButton etc) and also contains bitmap resources.
I wanted to create a static library - mainly because I do not want the code seperated into a DLL. However, I found that even though it is possible to add resources to a static library, I couldn't get the Class Wizard to work. As a result I created a DLL instead and now I want to find a way of statically linking my DLL into my application.
Can anybody help please? I am still using MSVC++ 6.0.
To clarify - what I would really like to know is how to create static .LIB file that contains resources, and classes via the Class Wizard.
Update: I got around this by creating a seperate (common) .rc file that I include in my main applications. Works a treat.