I tried to make a simple MFC GUI application with C++, but it seems to have problem at generating the main window(dialog?). When I'm trying to compile the code, following message shows :
Unhandled exception at 0x00E7A9DC in GUI_Employee_0501.exe:
0xC0000005: Access violation reading location 0xFEFEFF66.
and the break point stops inside winmain.cpp, at pThread->m_pMainWnd->DestroyWindow();. The value of pThread->m_pMainWnd is NULL, which I suspect as the cause of the problem.
Can you specify what is the problem here? I have a sample code and that is very similar to mine but that works, so I truly have no idea what is happening!
#include <afxwin.h>
#include "resource.h"
#include <iostream>
using namespace std;
#pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console")
CEdit *pFNAME;
CEdit *pLNAME;
CEdit *pSALARY;
CEdit *pDDAY;
CEdit *pMMONTH;
CEdit *pYYEAR;
CComboBox *pGENDER;
CButton *pADD;
CButton *pDELETE;
CButton *pSAVE;
CButton *pLOAD;
class ENTRY_FORM : public CDialog
{
public:
ENTRY_FORM(CWnd* pParent = NULL) : CDialog(ENTRY_FORM::IDD, pParent) { }
enum { IDD = dialog_main };
protected:
virtual void DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); }
virtual BOOL OnInitDialog()
{
CDialog::OnInitDialog();
SetUpInterfacePointers();
return true;
}
void SetUpInterfacePointers(){ ... does its own thing ... }
public:
afx_msg void add() { PRESS_ADD(); }
void PRESS_ADD() { ... does its own thing ... }
DECLARE_MESSAGE_MAP()
};
class Program : public CWinApp
{
public:
Program(){ }
public:
virtual BOOL InitInstance()
{
CWinApp::InitInstance();
cout << "CWinAPP:initInstance" << endl;
ENTRY_FORM dlg;
m_pMainWnd = &dlg;
cout << "mpMainWnd" << endl;
INT_PTR nResponse = dlg.DoModal();
return FALSE;
}
};
//
BEGIN_MESSAGE_MAP(ENTRY_FORM, CDialog)
ON_COMMAND(button_add, add)
END_MESSAGE_MAP()
//
Program theApp;
Change in InitInstance():
return FALSE;
to
return TRUE;
This is because CWinApp::InitInstance should return FALSE only in case of failure, and TRUE if all initialization went OK. In case of failure, AfxWinMain will try to destroy window pointed by m_pMainWnd, which is not possible (it causes Undefined Behaviour) because you assign to m_pMainWnd a local object (which is destroyed once InitInstance ends).
[edit]
S.B Bae - to investigate it further and find a root cause, you will need to debug place where m_pMainWnd should be set to NULL once your dialog ends. This should be in CWnd::OnNcDestroy() in wincore.cpp. There is a line pThread->m_pMainWnd = NULL; which apparently is not being executed in your application.
Late to the party, but I saw the exact problem when creating an MFC Dialog application. I found I had accidentally changed the application dialog Style (in Properties) from 'Popup' to 'Child'. Toggling this can consistently toggle this error. 'Overlapped' seems to work just as well as 'Popup'.
https://learn.microsoft.com/en-us/cpp/mfc/reference/styles-used-by-mfc?view=vs-2019#window-styles
Related
I have a lot of CDialogEx derived classes that do something like this in OnInitDialog:
CMeetingScheduleAssistantApp::InitialiseResizeIcon(m_bmpResize, m_lblResize, this);
CMeetingScheduleAssistantApp::RestoreWindowPosition(_T("PublisherDB"), this, true);
Then, I have the following added to each derived dialog class:
int CPublishersDatabaseDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// Save Initial window size to m_rcInit
GetWindowRect(&m_rcInit);
return 0;
}
void CPublishersDatabaseDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Set the minimum window size to initial size.
lpMMI->ptMinTrackSize.x = m_rcInit.Width();
lpMMI->ptMinTrackSize.y = m_rcInit.Height();
CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CPublishersDatabaseDlg::OnClose()
{
CMeetingScheduleAssistantApp::SaveWindowPosition(_T("PublisherDB"), this);
CDialogEx::OnClose();
}
The only thing that is different for each dialog is the phrase that is used for saving the window position.
I want to have a based CDialogEx class that I can inherit from that will perform the above actions. I have looked on SO and seem some questions and creating a CDialog class and inheriting from another CDialog class. But this class I want to create is more generic. Effectively to be used as a base instead of CDialogEx.
Can this be done? Am I over-complicating this?
Problems
Why I try to create a new class, derived from CDialogEx:
I don't know if it is because it requires a dialog ID as stated here.
Classes such as CDialog, CFormView, or CPropertyPage, which require a dialog ID.
So I can't work out the correct way to create a base CDialogEx class for use in all my other dialog classes.
Update
I created this code and it tells me that CResizingDialog is not a class or a namespace:
#include "ResizingDialog.h"
#include "resource.h"
#include "stdafx.h"
IMPLEMENT_DYNAMIC(CResizingDialog, CDialogEx)
CResizingDialog::CResizingDialog(const CString& strWindowID, UINT nIDTemplate, CWnd* pParent = nullptr)
: m_strWindowID(strWindowID), CDialogEx(nIDTemplate, pParent)
{
}
CResizingDialog::~CResizingDialog()
{
}
void CResizingDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CResizingDialog, CDialogEx)
ON_WM_CREATE()
ON_WM_GETMINMAXINFO()
ON_WM_CLOSE()
END_MESSAGE_MAP()
int CResizingDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// Save Initial window size to m_rcInit
GetWindowRect(&m_rcInit);
return 0;
}
void CResizingDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Set the minimum window size to initial size.
lpMMI->ptMinTrackSize.x = m_rcInit.Width();
lpMMI->ptMinTrackSize.y = m_rcInit.Height();
CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CResizingDialog::OnClose()
{
SaveWindowPosition(m_strWindowID, this);
CDialogEx::OnClose();
}
Based on the comments encouraging me to try to create the class manually, I have it working:
#include "stdafx.h"
#include "resource.h"
#include "ResizingDialog.h"
IMPLEMENT_DYNAMIC(CResizingDialog, CDialogEx)
CResizingDialog::CResizingDialog(const CString& strWindowID, UINT nIDTemplate, CWnd* pParent /* nullptr */, bool bOnlyStorePosition /* false */)
: m_strWindowID(strWindowID),
m_bOnlyStorePosition(bOnlyStorePosition), CDialogEx(nIDTemplate, pParent)
{
}
CResizingDialog::~CResizingDialog()
{
}
void CResizingDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CResizingDialog, CDialogEx)
ON_WM_CREATE()
ON_WM_GETMINMAXINFO()
ON_WM_CLOSE()
END_MESSAGE_MAP()
int CResizingDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// Save Initial window size to m_rcInit
GetWindowRect(&m_rcInit);
return 0;
}
void CResizingDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Set the minimum window size to initial size.
lpMMI->ptMinTrackSize.x = m_rcInit.Width();
lpMMI->ptMinTrackSize.y = m_rcInit.Height();
CDialogEx::OnGetMinMaxInfo(lpMMI);
}
void CResizingDialog::OnClose()
{
SaveWindowPosition(m_strWindowID, this);
CDialogEx::OnClose();
}
void CResizingDialog::OnOK()
{
SaveWindowPosition();
CDialogEx::OnOK();
}
BOOL CResizingDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
if(!m_bOnlyStorePosition)
InitialiseResizeIcon(m_bmpResize, m_lblResize, this);
RestoreWindowPosition(m_strWindowID, this, true);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
I decided to duplicate the methods that were in the app class into this new dialog class instead. Eventually they can be removed from the app class. The only thing I also had to do was #include my resource file because the image needs to know the value of the resource ID.
This is the ResizingDialog.h header:
#pragma once
#include <afxwin.h>
class CResizingDialog : public CDialogEx
{
DECLARE_DYNAMIC(CResizingDialog)
public:
CResizingDialog(const CString& phrase, UINT nIDTemplate, CWnd* pParent = nullptr, bool bOnlyStorePosition = false); // Constructor
virtual ~CResizingDialog(); // Destructor
protected:
void OnOK() override;
virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support
void SaveWindowPosition(void) { SaveWindowPosition(m_strWindowID, this); }
public:
BOOL OnInitDialog() override;
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
afx_msg void OnClose();
DECLARE_MESSAGE_MAP()
private:
CBitmap m_bmpResize;
CStatic m_lblResize;
CRect m_rcInit;
CString m_strWindowID;
bool m_bOnlyStorePosition;
void RestoreWindowPosition(CString strWindow, CWnd* pWindow, bool bOverrideState = false);
void SaveWindowPosition(CString strWindow, CWnd* pWindow);
void InitialiseResizeIcon(CBitmap& rBmpResize, CStatic& rLblResize, CWnd* pDialog);
};
The actual functions SaveWindowPosition, RestoreWindowPosition and InitialiseResizeIcon are not shown here as they don't directly relate to the issue.
I have a Dialog on MFC application.
MyDialog :
{
int variable1;
int variable2;
Class1 cls = new Class1();
}
And in class1()
Class1()
{
void Function1()
void Function2()
}
--
So How to Access and return to variable1 in Class1::Function1()
Class1::Function1()
{
MyDialog dlg = new MyDialog ();
Get x = dlg->variable1; //if like this, variable1 alway=0, because in above line, i'm define new myDialog()
}
I think to delegate on .NET but in MFC application, I can't get it done ?
You can
"extend" your constructor, by adding a pointer to the parent in your child dialog and access your variable or call public functions (requires header of parent)
use SendMessage and handle the messages in your parent dialog
use GetParent in-place and dynamic_cast it to your parent dialog (requires header of parent)
1.
Class1::Class1(MyParent *parent)
{
m_parentPointer = parent;
}
void Class1::Function1(void)
{
m_parentPointer->myPublicVariable;
}
2.
void Class1::Function1(void)
{
CWnd *parent = GetParent();
if (parent)
parent->SendMessage(WM_YOUR_MESSAGE, yourWPARAM, yourLPARAM);
}
//MessageMap of parent
ON_MESSAGE(WM_YOUR_MESSAGE, ParentClassHandler)
LRESULT Parent::ParentClassHandler(WPARAM wp, LPARAM lp)
{
//Process
}
3.
void Class1::Function1(void)
{
CWnd *parent = GetParent();
if (parent)
{
Parent *p = dynamic_cast<Parent*>(parent);
if (p)
{
//Process
}
}
}
If Class1::Function1() needs to access the dialog, then you need a pointer to the dialog in Function1.
void Class1::Function1(MyDialog *dlg) {
}
If you want to store the dialog pointer permanently, then adjust the constructor of Class1.
class Class1 {
public:
Class1(class MyDialog *dlg_) : dlg(dlg_) {}
class MyDialog *dlg;
}
Another, probably better, way to implement it, is to move the code that needs to access Class1 and MyDialog into global functions or into MyDialog member functions. But which way to go depends on what the classes do and which design you want.
You have to start with basic C++ classes before diving in to this. But here is how it's done:
MyDialog dlg = new MyDialog ();
dlg->variable1 = 1; //set the variable
if (IDOK == dlg->DoModal()) //wait for user to click OK
{
int x = dlg->variable1; //get the variable
}
However, dlg->variable1 is not changed unless you drive your own class and do something to change it.
For example, you can use Dialog Data Exchange to assign variable1 to a check box.
void MyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Check(pDX, IDC_CHECK1, variable1);
}
To try it, use Visual Studio's dialog wizard to create a check box and an edit box. It will probably create check box with resource id IDC_CHECK1, an edit box with resource id set to IDC_EDIT1.
Another option:
use OnInitDialog to assign variable to dialog controls
use OnOK() to get variables from dialog controls:
:
BOOL MyDialog::OnInitDialog()
{
//put `CString m_string1;` in class declaration
BOOL result = CDialog::OnInitDialog();
SetDlgItemText(IDC_EDIT1, m_string1);
return result;
}
void MyDialog::OnOK()
{
GetDlgItemText(IDC_EDIT1, m_string1);
CDialog::OnOK();
}
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.
I'm building my first c++ project using classes (trying to get more experience) and now I'm stuck. I need to determine which button was pressed from my calculator application. The way I have my project set up is:
Windows.cpp
// Windows.cpp
#include <Windows.h>
#include <wchar.h>
#include "Resource.h"
#include "Application.h"
int WINAPI wWinMain(...)
{
// after register class and create/show/update window ( winMain() )
Application App(hwnd);
App.Go();
// Main message loop, etc.
MSG msg;
ZeroMemory(&msg,sizeof(msg));
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
Application.h
#pragma once
#include "Calculator.h"
class Application
{
public:
Application(HWND hwnd);
~Application();
void Go();
private:
void Run();
private:
Calculator calc;
};
Application.cpp:
// Application.cpp
#include "Application.h"
Application::Application(HWND hwnd)
: calc(hwnd)
{}
Application::~Application()
{}
void Application::Go()
{
calc.Initiate(); // This function shows all my button controls for my calculator
Run();
}
void Application::Run()
{
// This is where i want to determine which button was pressed(if any)
if(buttonONEwasPRESSED) { /* do stuff */ } // etc
}
I thought about adding a function to Calculator class to determine if a button was pressed, but I'm not sure how to access wm_command, or if theres another way. Then I could just call calc.IsButtonPressed().
You are stuck because you want to know which button was pressed. That reminds me some console programs dealing with user input.
That's not how to go with GUI. What you should do is code what to do when a button is pressed. That's event drived programming.
With standard Win32 application, the "event" for pushbutton press is WM_COMMAND.
For mapping a HWND to a C++ class with easy mapping between a WM_MESSAGE_X and an OnMessageX member function, see for example https://stackoverflow.com/a/20356046/1374704
Hi I have created a dialog box and it woks.
My question is: how do you retreive the handle for it?
Also, if you get the handle, how would you change the static text control text inside it?
class CStatisticsDlg : public CDialogEx
{
public:
CStatisticsDlg();
// Dialog Data
enum { IDD = IDD_STATISTICS };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
public:
};
CStatisticsDlg::CStatisticsDlg() : CDialogEx(CStatisticsDlg::IDD)
{
}
void CStatisticsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CStatisticsDlg, CDialogEx)
END_MESSAGE_MAP()
Assuming you're using MFC (as indicated by the tag), then presumably you have a CDialog class instance. CDialog is a subclass of CWnd, so you can retrieve the window handle by one of 3 ways:
Directly accessing its m_hWnd member
Casting it to an HWND with operator HWND()
Calling GetSafeHwnd() on it
Here is how to do it.
First create a member function to the main application class.
Then use the following code (Assuming the class name is CGenericApp, and your Dialog class is CGenericDlg.
CWnd* CGenericApp::GetDlg()
{
return m_pMainWnd;
}
Then when you want to get a handler to the main Dialog box, use:
CGenericApp* app = (CGenericApp*)AfxGetApp();
CGenericDlg* pDlg = (CGenericDlg*)(app->GetDlg());
HWND win = pDlg->GetSafeHwnd();
'win' will hold the HWND you are looking for.