Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have an issue with OnTimer() function of Modeless Dialog window (who is a child window of CDialogEx window) ,it refuse to trigger.
When i make the dialog Modal with CDialog::DoModal() function its working fine.
But i want Modeless Dialog.
Could you explain me what happen here .
I try to be accurate. The ClogoDlg Dialog is a SPLASH window of the application .It showing for 3 minutes, in the middle the program running Lengthy Operation. The SPLASH window displays a duration of time. Therefor i want the OnTimer() function.
Thanks .
my code is:
BOOL Clotto2Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
ClogoDlg* pdlg=new ClogoDlg();
pdlg->Create(GetDesktopWindow());
//pdlg->DoModal();
pdlg->ShowWindow(SW_SHOW);
}
My ClogoDlg.cpp
#include "stdafx.h"
#include "ClogoDlg.h"
IMPLEMENT_DYNAMIC(ClogoDlg, CDialog)
ClogoDlg::ClogoDlg(CWnd* pParent ) : CDialog(ClogoDlg::IDD, pParent)
{
}
ClogoDlg::~ClogoDlg()
{
KillTimer(m_nTimer);
}
BOOL ClogoDlg::Create(CWnd* pParentWnd)
{
// TODO: Add your specialized code here and/or call the base class
return CDialog::Create(ClogoDlg::IDD,pParentWnd);
}
BEGIN_MESSAGE_MAP(ClogoDlg, CDialog)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_PAINT()
ON_WM_TIMER()
END_MESSAGE_MAP()
void ClogoDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
Invalidate();
CDialog::OnLButtonDown(nFlags, point);
}
void ClogoDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDialog::OnLButtonDblClk(nFlags, point);
}
BOOL ClogoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
m_nTimer = SetTimer(2, 1000, NULL);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
BOOL ClogoDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
return CDialog::PreTranslateMessage(pMsg);
}
void ClogoDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CDialog::OnPaint() for painting messages
CTime timeNow;
timeNow = CTime::GetCurrentTime();
CString str;
str.Format(L"%3d:%2d:%2d", timeNow.GetHour(), timeNow.GetMinute(), timeNow.GetSecond());
dc.TextOut(10,10, str);
}
void ClogoDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
Invalidate();
CDialog::OnTimer(nIDEvent);
}
And my ClogoDlg.h
#pragma once
#include "resource.h"
class ClogoDlg:public CDialog
{
DECLARE_DYNAMIC(ClogoDlg)
public:
enum{IDD=IDD_LOGO};
ClogoDlg();
~ClogoDlg();
BOOL Create(CWnd * pParent = NULL);
CTime timer;
int m_nTimer;
DECLARE_MESSAGE_MAP()
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
virtual BOOL OnInitDialog();
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnPaint();
afx_msg void OnTimer(UINT_PTR nIDEvent);
};
Related
I am doing a program in MFC and I have come up with an issue. I have a text box created by using the toolbars in Visual Studio.
My text box ID is IDC_TEXT1 and I need to get the value from the text box (float value not string). How do I do it?
You can get the value of by calling GetDlgItemText and std::stod like in this example:
class CAboutDlg : public CDialogEx
{
CString m_txt;
double m_num;
public:
CAboutDlg() noexcept;
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedOk();
};
CAboutDlg::CAboutDlg() noexcept : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
ON_BN_CLICKED(IDOK, &CAboutDlg::OnBnClickedOk)
END_MESSAGE_MAP()
// App command to run the dialog
void CSO55114372App::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
// CSO55114372App customization load/save methods
void CSO55114372App::PreLoadState()
{
BOOL bNameValid;
CString strName;
bNameValid = strName.LoadString(IDS_EDIT_MENU);
ASSERT(bNameValid);
GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EDIT);
bNameValid = strName.LoadString(IDS_EXPLORER);
ASSERT(bNameValid);
GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EXPLORER);
}
void CSO55114372App::LoadCustomState()
{
}
void CSO55114372App::SaveCustomState()
{
}
// CSO55114372App message handlers
void CAboutDlg::OnBnClickedOk()
{
GetDlgItemText(IDC_EDIT2, m_txt);
std::wstring s((LPCTSTR)m_txt);
m_num = std::stod(s);
CDialogEx::OnOK();
}
I just wanted to show you a second way of mapping a edit control to a float value. This is by using the ClassWizard.
Right-click the control and choose Add Variable...:
Set the variable category as value, the access to private, specify the name and finally set the variable type to float.
Click Next (if required) and set the numeric range for input.
Click Finish
Look at the DoDataExchange method. It will look something like this:
void CMFCApplication2Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_fValue);
DDV_MinMaxFloat(pDX, m_fValue, 1, 100);
}
Whenever you need to work with the current value of the edit control, you type UpdataData(TRUE); This synchronises the variable with the contents of the edit control. An example with a break-point in debug mode:
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'm trying to display a tooltip on a CMfcButton.
When my code run the SetToolTip(), the application crash.
BOOL CGenerationDlg::OnInitDialog()
{
BOOL bret = CPropertyPage::OnInitDialog();
m_pButtonExport = (CMFCButton *)GetDlgItem(IDC_BTN_EXPORTE_BILAN);
m_pButtonExport->EnableFullTextTooltip();
m_pButtonExport->SetTooltip(L"my tooltip");
return bret;
}
void CKenoDlg::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
}
Here is my Header file :
// KenoDlg.h : fichier d'en-tête
//
#pragma once
#include "keno.h"
#include "AboutDlg.h"
// boîte de dialogue CKenoDlg
class CKenoDlg : public CPropertyPage
{
// Construction
public:
CKenoDlg(CWnd* pParent = NULL); // constructeur standard
CAboutDlg* myDialog;
// Données de boîte de dialogue
enum { IDD = IDD_KENO_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // Prise en charge de DDX/DDV
CMFCButton * m_pButtonExport;
// Implémentation
protected:
HICON m_hIcon;
// Fonctions générées de la table des messages
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedBtnGenerate();
afx_msg void OnBnClickedBtnExport();
afx_msg void OnStnClickedStaticAbout();
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
Here is my error :
Any idea please ?
Thanks a lot :)
Best regards,
Try this:
Change your header to define a CMFCButton instance rather than a pointer:
class CKenoDlg : public CPropertyPage
{
// ... existing code ...
protected:
virtual void DoDataExchange(CDataExchange* pDX); // Prise en charge de DDX/DDV
CMFCButton m_pButtonExport;
// ... existing code ...
};
Then change your DoDataExchange function as follows:
void CKenoDlg::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BTN_EXPORTE_BILAN, m_pButtonExport);
}
Finally, in OnInitDialog, do something like this:
BOOL CGenerationDlg::OnInitDialog()
{
BOOL bret = CPropertyPage::OnInitDialog();
m_pButtonExport.EnableFullTextTooltip();
m_pButtonExport.SetTooltip(L"my tooltip");
return bret;
}
The reason why you need to do it like this rather than with a pointer is because MFC has to subclass the control to a CMFCButton rather than the default CButton. When you use the DDX macro in DoDataExchange, this is done behind the scenes when the default implementation of OnInitDialog calls UpdateData, which in turn calls DoDataExchange and - if I recall correctly - on the first time through, the dialog controls are sub-classed to the correct types.
As you used a pointer, and had no link between the button control and the type you were using it as, there was a mismatch between the actual and expected types and that was the reason for the crash.
If you use the VS2012 wizard to add a variable from the dialog designer (right-click on a dialog control and choose Add Variable), it will create the member variable declaration in the header file and will add the DDX macro to the DoDataExchange function for you. You can then choose to change the type of the member variable, e.g. from CButton to one of your own CButton derived classes.
You use the term pointer to button and name the variable 'm_pButtonExport'. That is incorrect. The code creates an instance of a CMFCButton object, not a pointer to an instance of a button object. The variable should be named 'm_ButtonExport' and referred to as an instance of a CMFCButton object NOT a pointer to one.
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?
In Delphi, there is FormCloseQuery event. What is equivalent in MFC?
I want to stop CMainFrame from closing
1) Add a handler to the WM_CLOSE message in your CMainFrame Message Map:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
...
ON_WM_CLOSE()
...
END_MESSAGE_MAP()
2) Add afx_msg void OnClose(); to class definition in the header file
3) Add CMainFrame::OnClose() implementation
void CMainFrame::OnClose()
{
if (okToClose)
{
CFrameWnd::OnClose();
}
else
{
// Do nothing
}
}