MFC on form create event - visual-c++

I have simple FMC dialog form. Can't find how to manage event that should be called on form create moment. Something like onFormCreate like it is in VB or Delphi.
How to create such functionality?
My simple form header:
#pragma once
// CMFCApplicationUPTDlg dialog
class CMFCApplicationUPTDlg : public CDialog
{
// Construction
public:
CMFCApplicationUPTDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_MFCAPPLICATIONUPT_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 OnBnClickedOk();
afx_msg void OnBnClickedButton1();
};

You want to handle it in the OnInitDialog() member function. At the point that OnInitDialog() is called, the dialog and all of its child windows will have been created. However, the dialog will still be invisible to the user. After exiting OnInitDialog(), the dialog will be shown to the user.
So, it is the place where you would want to do initialization of your dialog.

You need to implement OnInitDialog in your own derived class.
BOOL CMFCApplicationUPTDlg::OnInitDialog()
{
// this will create the controls you defined in the resources.
BOOL retValue = __super::OnInitDialog();
// initialize (or add new controls to ) your dialog content here.
// ...
return retValue;
}

Related

How to capture windows message from the up/down button of a CDateTimeCtrl control?

I am using a CDateTimeCtrl, along with a callback field, in my dialog application. All works well as intended but I want to capture the windows message when the up-down button ( looks a lot like the spin control) of the CDateTimeCtrl is clicked without success. Spy++ reported the class of the up-down button to be msctls_updown32. Spy++ message log offer no clue either. How do I capture the mouse click messages from this up-down control ( looks like an OLE control to me)?
Edited: : I've tried handling the UDN_DELTAPOS message like so but still unable to capture the message from CMyTimeCtrl.
class CMyTimeCtrl : public CDateTimeCtrl
{
DECLARE_DYNAMIC(CMyTimeCtrl)
public:
CMyTimeCtrl();
virtual ~CMyTimeCtrl();
protected:
int m_msec;
DECLARE_MESSAGE_MAP()
public:
virtual void DoDataExchange(CDataExchange* pDX);
afx_msg void OnDtnFormat(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnDtnFormatquery(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnDtnWmkeydown(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnDeltaposSpin(NMHDR* pNMHDR, LRESULT* pResult);
};
BEGIN_MESSAGE_MAP(CMyTimeCtrl, CDateTimeCtrl)
ON_NOTIFY(WM_NOTIFY, UDN_DELTAPOS, &CMyTimeCtrl::OnDeltaposSpin)
ON_NOTIFY_REFLECT(DTN_FORMAT, &CMyTimeCtrl::OnDtnFormat)
ON_NOTIFY_REFLECT(DTN_FORMATQUERY, &CMyTimeCtrl::OnDtnFormatquery)
ON_NOTIFY_REFLECT(DTN_WMKEYDOWN, &CMyTimeCtrl::OnDtnWmkeydown)
END_MESSAGE_MAP()
Thanks, with the guidance from the comment section I manage to resolve my issue. In the message map I made an error, corrected as shown below. Now it's working fine. In my resource section, the IDC_STATIC value is 1000:
BEGIN_MESSAGE_MAP(CMyTimeCtrl, CDateTimeCtrl)
ON_NOTIFY(UDN_DELTAPOS, IDC_STATIC, &CMyTimeCtrl::OnDeltaposSpin)
ON_NOTIFY_REFLECT(DTN_FORMAT, &CMyTimeCtrl::OnDtnFormat)
ON_NOTIFY_REFLECT(DTN_FORMATQUERY, &CMyTimeCtrl::OnDtnFormatquery)
ON_NOTIFY_REFLECT(DTN_WMKEYDOWN, &CMyTimeCtrl::OnDtnWmkeydown)
END_MESSAGE_MAP()

Set MFC dialog form caption

I need to set dialog form caption. I was trying to create CString variable that might be binded to caption with Class Wizard. But there is no main form control in selection menu. What is the way of doing that?
This is my dialog form:
#include "stdafx.h"
#include "MyDlg.h"
#include "afxdialogex.h"
// MyDlg dialog
IMPLEMENT_DYNAMIC(MyDlg, CDialog)
MyDlg::MyDlg(CWnd* pParent /*=NULL*/)
: CDialog(MyDlg::IDD, pParent)
, m_edit(_T(""))
{
}
MyDlg::~MyDlg()
{
}
void MyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_edit);
}
BEGIN_MESSAGE_MAP(MyDlg, CDialog)
ON_BN_CLICKED(IDOK, &MyDlg::OnBnClickedOk)
END_MESSAGE_MAP()
// MyDlg message handlers
void MyDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
CDialog::OnOK();
txt=m_edit;
}
This is code that creates dialog:
BOOL CPreparationApp::InitInstance()
{
MyDlg Dlg;
//how to tell Dlg to have form caption "BLABLABLA"?
Dlg.DoModal();
return TRUE;
}
Hoping I've understood your question in the right way:
// MyDlg.h
class MyDlg
{
public: // private is fine too if you're OOP nazi but you have to provide a SetDlgCaption method then.
CString m_strDlgCaption;
};
// MyDlg.cpp
BOOL MyDlg::OnInitDialog( )
{
SetWindowText( m_strDlgCaption );
}
BOOL CPreparationApp::InitInstance()
{
MyDlg Dlg;
Dlg.m_strDlgCaption = _T("A fancy caption for your dialog");
Dlg.DoModal();
}
If you have not already done it you first need to add an override in the dialog class for OnInitDialog. This is the first place you can execute code after the dialog and its control windows exist. You can put SetWindowText(_T("BLABLABLA")) in OnInitDialog to set the dialog caption.

Can't get text info to member variable in form CDialog MFC dialog form

I have small dialog form with Edit Text control:
#include "stdafx.h"
#include "MyDlg3.h"
#include "afxdialogex.h"
// MyDlg3 dialog
IMPLEMENT_DYNAMIC(MyDlg3, CDialog)
MyDlg3::MyDlg3(CWnd* pParent /*=NULL*/)
: CDialog(MyDlg3::IDD, pParent)
, m_edit(_T(""))
{
}
MyDlg3::~MyDlg3()
{
}
void MyDlg3::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_edit);
}
BEGIN_MESSAGE_MAP(MyDlg3, CDialog)
ON_BN_CLICKED(IDOK, &MyDlg3::OnBnClickedOk)
END_MESSAGE_MAP()
// MyDlg3 message handlers
void MyDlg3::OnBnClickedOk()
{
txt=m_edit;
// TODO: Add your control notification handler code here
CDialog::OnOK();
}
And I have simple application that calls this dialog:
BOOL CPreparationApp::InitInstance()
{
MyDlg3 Dlg3;
Dlg3.DoModal();
CString strLine0=Dlg3.txt;
return true;
}
I cant't find why I can't get text that was entered in dialogs Text Control to txt and strLine0 variables.
I found that if I make MyDlg3 from CDialogEx (not from CDialog like it is now) - everything goes fine. Where is problem?
The text is transferred between the control and the member variable in DoDataExchange. DoDataExchange is called when you do CDialog::OnOK as you can see in the documentation for UpdateData. By copying the value before then you're not getting any results. You could fix this by moving the copy after the call to OnOK, or you could skip the copy altogether as suggested by another answer and use the member variable directly.
It's the call to CDialog::OnOK() in MyDlg3::OnBnClickedOk() that sets up the member variable m_edit, so you can write logic like
MyDlg3 Dlg3;
Dlg3.DoModal();
CString strLine0 = Dlg3.m_edit;
while making sure that m_edit is declared as public.
Try this:
BOOL CPreparationApp::InitInstance()
{
MyDlg3 Dlg3;
if(Dlg3.DoModal()==IDOK);
{
CString strLine0=Dlg3.txt;
return true;
}
return false;
}

Setting Cedit Text

I have the following code in trying to set the text in a Cedit text box:
class CMetaDlg : public CDialogEx
{
public:
CMetaDlg();
// Dialog Data
enum { IDD = IDD_META };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
public:
CEdit m_author;
CEdit m_sources;
afx_msg void OnBnClickedOk();
};
CMetaDlg::CMetaDlg() : CDialogEx(CMetaDlg::IDD)
{
}
void CMetaDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_AUTHOR, m_author);
DDX_Control(pDX, IDC_SOURCES, m_sources);
}
BEGIN_MESSAGE_MAP(CMetaDlg, CDialogEx)
ON_BN_CLICKED(IDOK, &CMetaDlg::OnBnClickedOk)
END_MESSAGE_MAP()
void CEmergenceApp::OnFileMeta()
{
CMetaDlg md;
md.DoModal();
md.m_author.SetWindowTextW(CEmergenceView::GetDoc()->author);
md.m_sources.SetWindowTextW(CEmergenceView::GetDoc()->sources);
}
This gives me a debug assertion error. I am assuming the problem lies in the lines:
md.m_author.SetWindowTextW(CEmergenceView::GetDoc()->author);
md.m_sources.SetWindowTextW(CEmergenceView::GetDoc()->sources);
As commenting them out, everything works fine.
When you call DoModal the dialog is created, the edit controls are created and then when the user clicks OK or Cancel the edit controls and dialog window are destroyed. Then DoModal returns. I do not understand what you are trying to do by trying to set the edit control's text after the dialog box closes.

Crashing while executing GetParent(). Closing of a modeless dialog box

I am creating a modeless dialog box. The dialog box is called from the menu item of main frame window.
MainFrm.h
CModeless* modeless;
bool modelessDlgOpen;
MainFrm.cpp
void CMainFrame::OnDatabaseMLdlg()
{
// TODO: Add your command handler code here
if (modelessDlgOpen == TRUE)
return;
modelessDlgOpen = TRUE;
modeless = new CModeless(this);
//modeless->Create(IDD_MLDLG, GetDesktopWindow());
modeless->Create(IDD_MLDLG, this);
mbPoll->ShowWindow(SW_SHOW);
}
When menu item is clicked, OnDatabaseMLdlg() function is called and a modeless dialog box with resource ID IDD_MLDLG appears.
The issue is while closing the modeless dialog box.
I am not able to find out the correct method to have a clean closure / destroy of this modeless dialog box. Upon clicking the cross button in right-top corner, which message gets
generated?
My current code which I have tried is as follows. (producing code related only to the closure of the dialog box)
MLDLG.h
#pragma once
#define WM_MLDLG_CLOSED (WM_USER + 555)
// CModeless dialog
class CModeless : public CDialog
{
DECLARE_DYNAMIC(CModeless)
public:
CModeless(CWnd* pParent = NULL); // standard constructor
virtual ~CModeless();
// Dialog Data
enum { IDD = IDD_MLDLG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
virtual BOOL Create(UINT nIDTemplate, CWnd* pParentWnd = NULL);
afx_msg void OnNcDestroy();
virtual void PostNcDestroy();
CWnd* mParent;
afx_msg void OnBnClickedCancel();
};
MLDLG.cpp
void CModeless::OnNcDestroy()
{
CDialog::OnNcDestroy();
// TODO: Add your message handler code here
}
void CModeless::PostNcDestroy()
{
CDialog::PostNcDestroy();
GetParent()->PostMessage(WM_MLDLG_CLOSED,0,0); // **CRASHES HERE**
delete this;
}
void CModeless::OnBnClickedCancel()
{
// TODO: Add your control notification handler code here
//CDialog::OnCancel();
DestroyWindow();
}
Not able to understand what am I doing wrong or what am I missing?
I can provide additional details in case required.
Thanks in advance.
EDIT-20130612: Additional information:
My constructor is as follows:
CModeless::CModeless(CWnd* pParent /*=NULL*/)
: CDialog(CModeless::IDD, pParent)
{
mParent = pParent;
if (mParent == NULL)
{
MessageBox(L"mParent is NULL");
}
else
{
MessageBox(L"mParent is not NULL");
}
}
Here, I have verified that mParent is not NULL.
PostNCDestroy() is called VERY late and most of the useful state of the MFC window is not valid at that point. GetParent() is probably returning NULL, which will cause a crash the way you are using it.
Try moving the PostMessage call to OnDestroy() before calling the base class implementation there.
Another option is to cache the parent's hWnd and call ::PostMessage() on that hWnd;

Resources