I have an MFC application using satellites DLLs in order to support the multilingualism. I am using Visual Studio 2010.
I am able to change the language of the core part of the application without any problems. Things go wrong when I try to load a modeless dialog containing a "special" MFC control (CMFCColorButton, CVSListBox, etc).
The problem occurs at the following statement :
m_dlg->Create(SOME_IID, this); // returns false
How should I proceed to load a "special" MFC control from a satellite DLL?
You must register their classes before you reach OnCreate(). For custom controls, this is typically done in the constructor:
CMyClass::CMyClass()
{
// Pseudo code
m_mfcColorButton.RegisterWindowClass(AfxGetResourceHandle());
}
For MFC controls, I bet there is an initialization function that needs to be called.
I had the same problem: my CDialog - derived class failed in DoModal if I use localized resource dll. It contains CMFCColorButton on resource template.
My solution was to call in a resource dll AfxRegisterMFCCtrlClasses();
class CMyApp: public CWinApp
{
BOOL InitInstance()
{
AfxRegisterMFCCtrlClasses();
return CWinApp::InitInstance();
}
};
Related
Starting out with GUI programming with C++. So, following some tutorials, I 'wrote' the following code to display a dialogue box. To be honest, the Visual Studio 2015 Wizard did most of the job, but here is the code file. It correctly displays the dialogue box pointed by the identifier, but I really cannot figure out how it works. To begin with, what is the entry point, of the code? There is not even a function, so what exactly executes when I build and run it?
#include<afxwin.h>
#include"resource.h"
class CExampleDlg :public CDialog
{
public:
CExampleDlg():CDialog(IDD_EXAMPLE_DLG){}
~CExampleDlg(){}
};
class CExample:public CWinApp
{public:
BOOL InitInstance()
{
CExampleDlg myDlg;
m_pMainWnd = &myDlg;
myDlg.DoModal();
return TRUE;
}
};
CExample MyApp;
Unlike normal c/c++ application where the entry point is main and you have full control over the flow of execution. MFC applications are event driven. The code you write is executed based on the events that occur due to user interaction with the application like, clicking on the button, entering text in the text box etc. When there is no interaction the application sits idle.
1) The best place to is OnInitDialog to place your initialization code. You can initialize all the member variables in OnInitDialog. (Remember winMain is the entry point for windows application. But in MFC this is embedded deep down in the boilerplate code.)
2) Add message handlers to handle the user actions to execute your core logic later. For e.g.: If you have a button on the dialog then you need to add the message handler function for the button which will get invoked when the user clicks on that button. This can be done easily using the class wizard (https://msdn.microsoft.com/en-us/library/ee748520.aspx).
I have two projects: one MFC .exe and an MFC .dll. I have an MFC dialog defined in a DLL. It has a resource associated to it and it also has a class CToolboxDiag derived from CDialog.
The dialog has a simple button that shows a message dialog when clicked.
void CToolboxDiag::OnBnClickedButton()
{
MessageBox(_T("Test"), _T("T"));
}
I can export the resource from the DLL to my code, and create a standard CDialog with the correct appearance using the following code:
CDialog *diag = new CDialog;
HINSTANCE hClientResources = AfxGetResourceHandle();
//Tell the client to use the .DLL's resources
AfxSetResourceHandle(dll);
// resource_id is the resource_id in the DLL
diag->Create(resource_id, NULL);
//Restore the client application resource handle
AfxSetResourceHandle(hClientResources);
But this only results in the dialog showing up but the controls (i.e. the button) performs no action when clicked, as it doesn't have the linkage to the CToolboxDiag definition in the .exe.
I wanted to export the dialog (with the button code) without having to export the class definition to the .exe. In other words, I want to export a fully functional dialog, including its buttons actions, without having the CToolboxDialog definition on my .exe, so that this can be fully modular. How could I do this?
This can't work in this way. The resource template has no direct connection to your code in the DLL. Your code just created an "empty" CDialog class that has no handlers hat all, expect the default handlers (OnOk, OnClose...)
So you need to create the object CToolboxDiag and this has to happen wehere the dialog code is located. This is inside the DLL.
The easiest way is to export a function that just creates the dialog inside the DLL and just returns a CDialog* to your application.
Be aware that this is only allowed and will work without problems when you are using the DLL shared version of the MFC.
Got a third party ActiveX dll which has control dialog for a fan. Would like to access the ACtiveX dll from a MFC dll with APIs, so that be able open the control dialog and access some other functions in the ActiveX. IS this practically easy?., and what resources should be called where?. any examples?. Need to record temperature continuously while no around around.
After reading so much at the microsoft site, came up with a MFC dll that its dialog uses an ActiveX control. Also, wrote a MFC and a console applications that by calling dll's opendialog(), I see the dialog launches. I hope I am not causing any memory leak. or causing any resource (de)allocation errors without knowing. so far , things seem to be working.
BOOL CDllApp::InitInstance()
{
CoInitialize(0);
AfxEnableControlContainer();
return CWinApp::InitInstance();
}
int CDllApp::ExitInstance()
{
CoUninitialize();
return CWinApp::ExitInstance();
}
In another class, in the same mfc dll, i do this.:
void CMyClass::opendialog()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CMyDialog dlg;
dlg.DoModal();
}
I have made an MFC application (VS2010) - exe.I then changed it to be dll (in project properties).
Some class CmyClass is inheriting CWinApp in my MFC dll.
From the other DLL (standard win32 DLL) I want to create the class and call it as it made by running the MFC as application (EXE).
I have tried to declare the CmyClass with DLLEXPORT, in my win32 DLL I Load the MFC dll dynamically and performing AfxWinInit with the hinstance of the MFC dll.
I have tried than to:
Create (CmyClass * a= new CmyClass()), wanted to call InitApplication(), InitInstance() and Run()
Call AfxGetApp() -> retrieving NULL pointer.
All without success. What Am I doing wrong?
10x,
Guy
EDIT:
I need the other way around though... I have created MFC App since it's wizard is wider and richer then the MFC Dll one. I want to consume this Dll the same manner I will consume the App (Exe). I found that from the consuming Dll it is sufficient just to LoadLibrary(MFCDll) to start the MFC Initialization (AfxWinInit is called and CMyClass->InitInstance is being called as well, but fails afterwards with exceptions.
We layout dialogs using the resource editor. So say I have a RichEditCtrl called IDC_RICH. And I want to link it to an instance of a custom class CMyRichEditCtrl : CRichEditCtrl, without losing the ability to set properties on it in resource editor.
What's the right way? You can certainly get some functionality by creating a DDX-linked variable, and changing the type to CMyRichEditCtrl. But in some cases I see people calling code like:
m_Rich.SubclassDlgItem(IDC_RICH, this));
What's the difference?
EDIT: One problem I'm seeing is that when I override Create(Ex) methods, they don't get called. It's kind of like the control is already created by the time my object gets linked to the resource identifier, pehaps?
DDX_Control() does SubclassWindow() under the hood. SubclassDlgItem is a shortcut for SubclassWindow(GetDlgITem()). Usually (broad generalisation here) the people using SubclassWindow are the ones who picked up that habit before DDX_Control existed (pre-1995 or so?) and never really got into MFC-mode, or people who copy and paste their programs together from blog snippets left and right.
So, use DDX_Control() for clarity, although it will technically not make a difference if you use SubclassDlgItem().
The windows you put on a dialog with the resource editor are created using CreateWindow(Ex) with the first argument set to the class name that is specified in the .rc file. The DDX_ mechanism then associates this instantiated window with the dialog class member in DoDataExchange().
MFC is a layer over Win32 but MFC development doesn't completely shield you from Win32. It's more like a bunch of classes and methods that take away some of the drudgery of MFC and provide some form of object-orientedness. The methods of MFC object aren't the ones that are doing the real work, and much of the framework does things under the hood and doesn't notify the 'upper layer' (i.e., MFC objects) unless that is explicitly hooked up. Create() is such a method that is only there if you want to manually create a control, it's not called by MFC when the object is created. (this is a generalization because sometimes it is, but that's outside of the scope of this discussion).
1> For controls that you put on a dialog with the resource editor, used DDX_Control:
class CMyDlg : public CDialogEx
{
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
public:
CRichEditCtrl m_Rich;
};
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_RICHEDIT1, m_Rich);
}
2> For controls that create manually:
CRichEditCtrl m_Rich;
m_Rich.Create(...);
m_Rich.SubclassDlgItem(IDC_RICH, this));