How to display a MFC dialog from a console application in C++? - c++

I have a simple MFC dialog.
class CMessageBoxWithCustomTextDlg : public CDialogEx
{
// Construction
public:
CMessageBoxWithCustomTextDlg(CWnd* pParent = NULL); // standard constructor
__declspec(dllexport) void SetData(std::string& data);
// Dialog Data
enum { IDD = IDD_MESSAGEBOXWITHCUSTOMTEXT_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedShowMessagebox();
};
I would like to export it as dll and call it from a simple console application. Is it possible?

It is possible; here is how I did it:
For your console application have it be simply this:
#include <Windows.h>
typedef void (*EntryFunc)();
int main()
{
HMODULE hMod = LoadLibrary(L"MFCDll.dll");
EntryFunc func = (EntryFunc)GetProcAddress(hMod, "entrypoint");
func();
}
The name of the DLL is MFCDll.dll and there is an exported function called entrypoint in that DLL.
For the DLL I created a New MFC DLL project. And other than the dialog code and the dialog in the resources add this code:
extern "C" __declspec(dllexport) void entrypoint()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CMessageBoxWithCustomTextDlg dlg;
dlg.DoModal();
}
And the console program will load the DLL, call into the DLL and the dialog shows.

Related

Visual Studio Class Wizard - failed to retrieve controls of dialog

If I try in Visual Studio 2019 run class wizard for some dialog, the error "Failed retrieve controls of dialog 'IDD.....' is shown. But after it is class wizard opened and work properly.
But I am interesting, why it throw this error.
Dialog is inherited from my own class, not from CDialogEx. But My own class is inherited from CDialogEx.
My dialog class code:
#pragma once
#include "resource.h"
#include "CMjAcDialog.h"
// CMjcDlgVyberTrasu dialog
class CMjcDlgVyberTrasu : public CMjAcDialog
{
DECLARE_DYNAMIC(CMjcDlgVyberTrasu)
public:
CMjcDlgVyberTrasu(CWnd* pParent = nullptr); // standard constructor
virtual ~CMjcDlgVyberTrasu();
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_VYBER_TRASU };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
vector<CMajTrasa *> *m_pVecOfTrasy;
CListCtrl m_cList;
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedBtUkaz();
virtual BOOL OnInitDialog();
};
And part of my my Dialog Class CMjAcDialog code:
class CMjAcDialog : public CDialogEx
{
DECLARE_DYNAMIC(CMjAcDialog)
protected:
UINT m_IDD;
CMajCtrlMap m_majCtrlMap;
CFont m_Font_mid, m_Font_big;
CString m_csDlgTitle;
HICON m_hIcon;
private:
int m_idMainIcon;
float m_dCurDpiScale;
// konstruktor
public:
CMjAcDialog(UINT idd, CWnd* pParent = NULL, CString acsWinCaption = L"", int idMainIcon = 0);
~CMjAcDialog();
protected:
virtual BOOL OnInitDialog();
.....
....

How to make a MFC application to DLL?

I am new to MFC programming. I have a very simple MFC application that shows a plain dialog. I want to make a DLL that do the same as this piece of code.
The working dialog code looks like this:
class MyForm : public CDialog
{
public:
MyForm(CWnd* pParent = NULL) : CDialog(MyForm::IDD, pParent) {};
enum { IDD = DIALOG1 };
protected:
virtual void DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); };
virtual BOOL OnInitDialog()
{
CDialog::OnInitDialog();
return true;
}
public:
DECLARE_MESSAGE_MAP()
};
//Actural App
class MyApp: public CWinApp
{
public:
MyApp() {};
virtual BOOL InitInstance()
{
CWinApp::InitInstance();
MyForm dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
return false;
}
};
BEGIN_MESSAGE_MAP(MyForm, CDialog)
END_MESSAGE_MAP()
//start the app
MyApp theApp;
I use visual studio MFC DLL project to make a new DLL project. I make a separate *.h file to declare the dll class, and a *.cpp file to define the class.
This is the *.h file looks like:
//header file for dll project
#include "stdafx.h"
#include <afxwin.h>
#include "resource.h"
class CMyDllApp : public CDialog
{
public:
__declspec(dllexport) CMyDllApp();
enum { IDD = DLL_Dialog };
protected:
__declspec(dllexport) virtual void DoDataExchange(CDataExchange* pDX);
__declspec(dllexport) virtual BOOL OnInitDialog();
public:
__declspec(dllexport) afx_msg void myFunction();
DECLARE_MESSAGE_MAP()
};
//Actural App
class MyDllMain : public CWinApp
{
public:
__declspec(dllexport) MyDllMain() {};
__declspec(dllexport) virtual BOOL InitInstance();
};
Now I include the *.h file in my client application, but I don't know how to call the dll class correctly.
Even if I only include the *.h file and do not add any other code, the dialog of dll class just replace my client dialog, if have MyDllMain theApp; in the cpp file of dll project.
//in *.cpp of the dll project
...
MyDllMain theApp;
If I put this line in my client application, I just get a "Assertion Failed" error when running.
But if I don't put the line MyDllMain theApp; in dll project, how can I call my dll class when I want?

How to implement #pragma pointers_to_members() for just one class?

I want to use #pragma pointers_to_members() to just one class.
I have other class definitions in my header file but I want to apply the required pragma to only one class and other classes should not be affected. How can this be achieved? There are not many code examples for that.
I have resolved this issue. I used the # pragma directive just before the BEGIN_MESSAGE_MAP() in my .cpp file.
#pragma pointers_to_members(full_generality,virtual_inheritance)
BEGIN_MESSAGE_MAP(CMy4407Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CMy4407Dlg::OnBnClickedButton1)
END_MESSAGE_MAP()
This is my derived class CMy4407Dlg:
class CMy4407Dlg : public CDialogEx, public virtual ABCD
{
// Construction
public:
CMy4407Dlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_MY4407_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton1();
};

How to add images when creating Visual C++ MFC project from scratch?

I am try to create very simple c++ MFC project. Since it is very simple one I need to create it form scratch.
my code so far is shown below. But now I need to add picture control and thus my Intent use CImage class. But to use CImage class I need to add altimage.h header to my project. But When I do so it gives a error that cannot open source file altimage.h. So
How can I overcome this problem.
How to add the file I needed when I creating the MFC projects form the scratch.
please help me solvethis.
thanks
#include <afxwin.h> //MFC core and standard components
//#include <altimage>
#include "resource.h" //main symbols
//-----------------------------------------------------------------------------------------
//Globals
//CEdit * TEST;
CEdit * RECOG_CHARS;
CButton * BTN_CONVERT;
CButton * BTN_QUIT;
CStatic * IMG_IMAGE;
class HWCR_FORM : public CDialog
{
public:
HWCR_FORM(CWnd* pParent = NULL) : CDialog(HWCR_FORM::IDD, pParent)
{ }
// Dialog Data, name of dialog form
enum{ IDD = ID_MAIN_INTERFACE };
protected:
virtual void DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); }
//Called right after constructor. Initialize things here.
virtual BOOL OnInitDialog()
{
CDialog::OnInitDialog();
RECOG_CHARS = (CEdit *)GetDlgItem(CE_ID_TEXT);
BTN_CONVERT = (CButton *)GetDlgItem(CB_ID_START);
BTN_QUIT = (CButton *)GetDlgItem(CB_ID_QUIT);
IMG_IMAGE = (CStatic *)GetDlgItem(CS_ID_IMAGE);
HBITMAP image = (HBITMAP)LoadImage(NULL,L"C:\\Users\\Kasun\\Desktop\\image.bmp",IMAGE_BITMAP,150,120,LR_LOADFROMFILE);
IMG_IMAGE->SetBitmap(image);
RECOG_CHARS->SetWindowTextW(L"Hi there");
return true;
}
public:
DECLARE_MESSAGE_MAP()
};
//-----------------------------------------------------------------------------------------
class HWCR : public CWinApp
{
public:
HWCR() { }
public:
virtual BOOL InitInstance()
{
CWinApp::InitInstance();
SetRegistryKey(_T("Hills Of Darkness"));
HWCR_FORM dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
return FALSE;
} //close function
};
//-----------------------------------------------------------------------------------------
//Need a Message Map Macro for both CDialog and CWinApp
BEGIN_MESSAGE_MAP(HWCR_FORM, CDialog)
END_MESSAGE_MAP()
//-----------------------------------------------------------------------------------------
HWCR theApp;
First at all, in order to use CImage, you need to include header file
#include <atlimage.h>
instead of
#include <altimage>
Secondly, be sure that this file's directory is included into MSVC paths...
Normally it should be included as this header file is part of MFC / Win32 SDK....check the directories in VS properties.
Z.

OnSelectionChanged not getting called

Header:
#pragma once
class AlarmsList : public CVSListBox
{
DECLARE_DYNAMIC(AlarmsList)
public:
AlarmsList();
virtual ~AlarmsList();
void OnAfterAddItem(int index);
void OnSelectionChanged(NMHDR *pNMHDR, LRESULT *pResult);
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnDtnDatetimechangeDatetimepicker1(NMHDR *pNMHDR, LRESULT *pResult);
};
void AlarmsList::OnAfterAddItem(int index)
{
GetParent()->GetDlgItem(IDC_TIMEPICK)->EnableWindow(true);
LOGIC->addAlarm();
LOGIC->changeSelection(index);
}
void AlarmsList::OnSelectionChanged(NMHDR *pNMHDR, LRESULT *pResult)
{
}
OnAfterAddItem gets called when i add a new item but OnSelectionChanged NEVER gets called how much i even try.
Linking it trough a message map neither dosnt work:
IMPLEMENT_DYNAMIC(AlarmsList, CVSListBox)
BEGIN_MESSAGE_MAP(AlarmsList, CVSListBox)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST, OnSelectionChanged)
END_MESSAGE_MAP()
I create the AlarmsList object using the create function.
Source code and project: http://www.filedropper.com/clockmaster
Generally, I think the LVN_ITEMCHANGED notification is sent to the parent window. Put the handler and the message map entry int your dialog/window that is the parent of the list box.
Didnt help :/.
Tried both parent property page and that property pages dialog.
Overloading dosnt work either :/, it does for OnAfterAddItem tough.
And yes I'm then using the same parameters as the virtual function.
You can try overriding the functions in the CVSListBoxBase class.In this class, the signature of OnSelectionChanged function requires no arguments.
You can find the declaration of the CVSListBoxBase class in afxvslistbox.h.
Just had a look at some of my own MFC code that uses list boxes, and the following works;
CMyListBox : public CListBox
{
}
class CMyDialog : public CDialog
{
// Construction
public:
CMyDialog(CFeatureDoc* pFeatureDoc,BOOL SheetLayout = FALSE,CWnd* pParent = NULL); // standard constructor
//{{AFX_DATA(CMyDialog)
enum { IDD = IDD_MY_DIALOG };
CMyListBox m_MyListBox;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMyDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CMyDialog)
afx_msg void OnSelChangeListBox();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyDialog)
DDX_Control(pDX, IDC_MY_LIST_BOX, m_MyListBox);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
//{{AFX_MSG_MAP(CMyDialog)
ON_LBN_SELCHANGE(IDC_MY_LIST_BOX, OnSelChangeListBox)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyDialog message handlers
void CMyDialog::OnSelChangeListBox()
{
}
If you want to have your own control process messages from a dialog, you may want to subclass it. See this related question What's the correct way to create a subclass of a MFC control?