Confused about CWnd::OnLButtonDown() and CTreeCtrl::OnLButtonDown() - c++

MFC Library Reference
CWnd::OnLButtonDown
void CMyCla::OnLButtonDown(UINT nFlags, CPoint point)
{
CWnd::OnLButtonDown(nFlags, point);
}
void CMyTreeCla::OnLButtonDown(UINT nFlags, CPoint point)
{
CTreeCtrl::OnLButtonDown(nFlags, point);
}
I know the inheritance.
class CTreeCtrl : public CWnd
{
......
}
Is there any clear rule to follow when i want to call OnLButtonDown()?
Thank you.

I think this is what you want.
In your class header, you will need to declare the message map, and also write the function header.
Class myCWnd : public CWnd
{
DECLARE_MESSAGE_MAP() //note, no semi colon
afx_msg void OnLButtonDown( UINT nFlags, CPoint pt );
};
in the cpp file:
BEGIN_MESSAGE_MAP(myCWnd, CWnd)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
void myCWnd::OnLButtonDown( UINT nFlags, CPoint pt )
{
//do what you want here
CWnd::OnLButtonDown(nFlags, pt); //call base class method
}

If you want the parent class implementation to be called first then you call the parent class's OnLButtonDown() and then add your implementation.

Usually, you do what you want to do with the event in your implementation and then you call the implementation of the parent class. This codeguru post shows a nice example in step 2 of the tutorial. But this depends on what exactly you want to do with the OnLButtonDown event, so it might be the other way around in your case.
I assume the inheritance in your example is as follows:
class CMyCla : public CWnd
{
}
class CMyTreeCla : public CTreeCtrl
{
......
}
So indeed, as you do, you do your thing in either OnLButtonDown and then call the parent implementation:
void CMyCla::OnLButtonDown(UINT nFlags, CPoint point)
{
// Your stuff here
// blah
// end your stuff
CWnd::OnLButtonDown(nFlags, point);
}
void CMyTreeCla::OnLButtonDown(UINT nFlags, CPoint point)
{
// Your stuff here
// blah
// end your stuff
CTreeCtrl::OnLButtonDown(nFlags, point);
}

Related

how to define function pointer compatible with using lambda with capture as call back

Needing several variations of a simple modal dialog with an MFC project, I wrote a simple class, CDialogDlg, which extends the standard MFC CDialog class and contains hooks for implementation specific callbacks that are normally implemented as methods in the class extending CDialog. These callbacks, if provided, are used when processing some events such as dialog initialization, OK button processing, and the DoDataExchange() function which provides the method for interfacing the dialog class variables and the actual dialog controls.
My first version of this class used standard functions for the callbacks. So the callback setting methods of the extended class set a function pointer with the address of the standard function.
void SetDataExchangeCallBack(void(*f)(CDataExchange* pDX)) { funcDX = f; };
void SetInitCallBack(void(*f)(CWnd *dlgWnd)) { funcInit = f; }
void SetOnOkCallBack(void(*f)(CWnd *dlgWnd, CDocument *pDoc)) { funcOK = f; }
Then I realized I should be able to use a lambda instead of a standard function. The first version of the lambdas, which used the same parameters as the standard functions, that did not capture any variables compiled fine and worked fine with the existing methods and function pointers in the extended class.
However when I tried to capture a variable in the lambda specified in the callback setter method, I had compile errors.
Reviewing Passing capturing lambda as function pointer and C++ lambda with captures as a function pointer I get that trying to do a lambda with capture will not compile with the definitions of function pointer and callback setting function that I am using.
So I decided that I should add an additional lambda specific function pointer within the class along with an override of the existing methods with an additional method setting the callbacks with the lambda specific function pointer within the class.
Question: What should the function pointer definition and the parameter definition in the function that sets the callback for accepting a lambda with captured variables look like? I would like to capture the local variable CPCSampleDoc *pDoc in the method CPCSampleView::OnDisplayReportList (). This variable contains a pointer to the CDocument derived object for the view that I would like to capture rather than using the method of storing it and doing the static_cast to get it back in the current version of the lambdas that do not capture.
Source Code
The CDialogDlg class which extends CDialog looks like the following:
class CDialogDlg : public CDialog
{
// Construction
void(*funcDX)(CDataExchange* pDX);
void(*funcDXpDoc)(CDataExchange* pDX, CDocument *pDoc);
void(*funcInit)(CWnd *dlgWnd);
void(*funcOK)(CWnd *dlgWnd, CDocument *pDoc);
CDocument *m_pDoc;
public:
CDialogDlg(UINT nIDTemplate, CWnd* pParentWnd = NULL, void(*f)(CDataExchange* pDX) = NULL) : CDialog(nIDTemplate, pParentWnd) { funcDX = f; funcInit = NULL; }
CDialogDlg(UINT nIDTemplate, CDocument *pDoc, CWnd* pParentWnd = NULL, void(*f)(CDataExchange* pDX, CDocument *pDoc) = NULL) : CDialog(nIDTemplate, pParentWnd) {
funcDX = NULL; funcDXpDoc = f; funcInit = NULL; m_pDoc = pDoc;
}
void SetDataExchangeCallBack(void(*f)(CDataExchange* pDX)) { funcDX = f; };
void SetInitCallBack(void(*f)(CWnd *dlgWnd)) { funcInit = f; }
void SetOnOkCallBack(void(*f)(CWnd *dlgWnd, CDocument *pDoc)) { funcOK = f; }
// Dialog Data
//{{AFX_DATA(CCashierNoDlg)
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CCashierNoDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
protected:
// Generated message map functions
//{{AFX_MSG(CCashierNoDlg)
virtual BOOL OnInitDialog();
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CDialogDlg, CDialog)
//{{AFX_MSG_MAP(CCashierNoDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CDialogDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
if (funcDX) funcDX(pDX);
if (funcDXpDoc) funcDXpDoc(pDX, m_pDoc);
//{{AFX_DATA_MAP(CCashierNoDlg)
//}}AFX_DATA_MAP
}
BOOL CDialogDlg::OnInitDialog()
{
CDialog::OnInitDialog();
if (funcInit) funcInit(this);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CDialogDlg::OnOK()
{
if (funcOK) funcOK(this, m_pDoc);
CDialog::OnOK();
}
The CView method which is triggered by a menu selection displays a dialog with a list of items to choose from. The dialog presented is a CDialogDlg object with a specific dialog template ID. For special processing, I am using two different callbacks which are currently using a lambda that does not capture. The result is the following:
void CPCSampleView::OnDisplayReportList ()
{
CPCSampleDoc *pDoc = GetDocument();
CDialogDlg myDialog(IDD_DIALOG_REPORTLIST, pDoc, this, [](CDataExchange* pDX, CDocument *pDoc) {
if (pDX->m_bSaveAndValidate) {
}
else {
CPCSampleDoc *pDocDoc = static_cast<CPCSampleDoc *>(pDoc);
POSITION pos = NULL;
do {
CPCSampleDoc::ListReportList sectionHeader;
CListBox *x = static_cast<CListBox *>(pDX->m_pDlgWnd->GetDlgItem(IDC_LIST1));
pos = pDocDoc->GetReportSectionHeader(pos, sectionHeader);
x->AddString(sectionHeader.m_SectionTitle);
} while (pos);
}
});
myDialog.SetOnOkCallBack([](CWnd *dlgWnd, CDocument *pDoc) {
CPCSampleDoc *pDocDoc = static_cast<CPCSampleDoc *>(pDoc);
CListBox *x = static_cast<CListBox *>(dlgWnd->GetDlgItem(IDC_LIST1));
int iPtr = x->GetCurSel();
POSITION pos = NULL;
do {
CPCSampleDoc::ListReportList sectionHeader;
pos = pDocDoc->GetReportSectionHeader(pos, sectionHeader);
if (iPtr < 1) {
pDocDoc->MoveToReportSectionHeader(sectionHeader.m_ListOffset);
break;
}
iPtr--;
} while (pos);
});
myDialog.DoModal();
}
You might use std::function to allow capturing lambdas and other functors and regular function pointers:
void(*funcDX)(CDataExchange* pDX);
void(*funcDXpDoc)(CDataExchange* pDX, CDocument *pDoc);
void(*funcInit)(CWnd *dlgWnd);
void(*funcOK)(CWnd *dlgWnd, CDocument *pDoc);
becomes
std::function<void(CDataExchange*)> funcDX;
std::function<void(CDataExchange*, CDocument*)> funcDXpDoc;
std::function<void(CWnd*)> funcInit;
std::function<void(CWnd*, CDocument*)> funcOK;
You setter/constructor should change pointer function to std::function too:
void SetInitCallBack(std::function<void(CWnd*)> f) { funcInit = f; }
Else your usage is identical:
if (funcDX) funcDX(pDX);
or
funcInit = nullptr;

MFC EditControl's value is not coming in private member

I have a dialog box with static text and edit control. In dialog control class, I have a control variable which to set initial value in edit box and a int which will have value of edit box when user changes it. Both are private variable but I am not getting values in integer variable. Is there any way to detect this below is sample code base
class CYrdAuthorityPage : public CPropertyPage
{
DECLARE_DYNAMIC(CYrdAuthorityPage)
public:
CYrdAuthorityPage();
virtual ~CYrdAuthorityPage();
// Dialog Data
enum { IDD = IDD_YRD_AUTHORITY_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
private:
CEdit m_authctrl;
int m_authval;
public:
afx_msg void OnEnChangeAuthEdit();
};
IMPLEMENT_DYNAMIC(CYrdAuthorityPage, CPropertyPage)
CYrdAuthorityPage::CYrdAuthorityPage()
: CPropertyPage(CYrdAuthorityPage::IDD)
{
}
CYrdAuthorityPage::~CYrdAuthorityPage()
{
}
void CYrdAuthorityPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
DDX_Control(pDX, IDC_AUTH_EDIT, m_authctrl);
DDX_Text(pDX,IDC_AUTH_EDIT,m_authval);
}
/*BEGIN_MESSAGE_MAP(CYrdAuthorityPage, CPropertyPage)
ON_EN_CHANGE(IDC_AUTH_EDIT, &CYrdAuthorityPage::OnEnChangeAuthEdit)
END_MESSAGE_MAP()*/
Here m_authval is not having value. I think it could be because it's private but making it public also gives the same result. I have set edit box to align text centrally.
Thanks
Data exchange between the control and the int variable does not occur magically. It occurs when you call the UpdateData member function. Do you have calls to that function?

Can I use CSplitterWnd in CWnd Derived class?

I have a MFC class derived from CWnd directly, not from CFrameWnd, And I use a CSplitterWnd as a member variable to create a Splitter and two views in OnCreate message handler.
But it shows nothing in the client area.
What's wrong with my approach? Do I have to use a CFrameWnd derived class?
Thanks
Code Snippet:
// CMyWnd.h
class CMyWnd : public: CWnd
{
DECLARE_DYNCREATE(CMyWnd)
public:
CMyWnd();
virtual ~CMyWnd();
// blahblah
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
private:
CXTPSplitterWnd m_WndSplitter;
}
// CMyWnd.cpp
int CMyWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
{
return -1;
}
if (!m_WndSplitter.CreateStatic(this, 2, 1))
return -1;
if (
!m_WndSplitter.CreateView(0, 0, RUNTIME_CLASS(CEditView),
CSize(100, 100), NULL) ||
!m_WndSplitter.CreateView(1, 0, RUNTIME_CLASS(CEditView),
CSize(100, 200), NULL)
)
{
m_WndSplitter.DestroyWindow();
return -1;
}
return 0;
}
The problem is that you create views. A element derived from a CView class must reside in a CFrameWnd derived class.
You can create a splitter in a CWnd derived class, but than the splitter window must host CWnd derived windows too.

Is "afx_msg" necessary for message handler function?

I used to add "afx_msg" prefix at declaration of message handler function.
But I found the function still called whithout the prefix.
Is "afx_msg" nessary?
Added:
class CVLManageDlg : public CDialog
{ ...
protected:
void OnAdd();
void OnModify();
void OnDel();
}
BEGIN_MESSAGE_MAP(CVLManageDlg, CDialog)
ON_BN_CLICKED(IDC_ADD_VL_MANAGE, OnAdd)
ON_BN_CLICKED(IDC_MD_VL_MANAGE, OnModify)
ON_BN_CLICKED(IDC_DEL_VL_MANAGE, OnDel)
ON_NOTIFY(NM_CLICK, IDC_LIST_VL_MANAGE, OnClickList)
ON_WM_SIZE()
END_MESSAGE_MAP()
void CVLManageDlg::OnAdd()
{...}
void CVLManageDlg::OnModify()
{...}
void CVLManageDlg::OnDel()
{...}
ClassWizard requires that you use the afx_msg keyword in your message map handler declarations.
And this

Trying to override CView::OnUpdate in CFormView

I am working on an SDI project where the View inherits CFormView. I am trying to override CView::OnUpdate, but the compiler complains like so:
'CMyFormView::OnUpdate' : 'virtual' storage-class specifier illegal on function
definition
Here's my class definition:
class CMyFormView : public CFormView
{
…
// Overrides
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual void OnInitialUpdate(); // called first time after construct
virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
};
The function I'm trying to override looks like this:
virtual void CMyFormView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
CFormView::OnUpdate(pSender, lHint, pHint);
//Get the current data from our document
CMyAppDoc* pDoc = GetDocument();
}
Could someone please tell me how to fix this?
Don't put "virtual" in the function definition (the .cpp file). You can put it only in the declaration (.h file). If it is already declared virtual in the base class hierarchy (CView?), then you don't need the "virtual" keyword at all since it will automatically be virtual if you have the same function declaration.