MFC EditControl's value is not coming in private member - c++

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?

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;

C++ Diamond Inheritance - Share variables with another non base class

This is my first post on stackoverflow so be gentle :)
I have standard diamond problem but I'd managed to sort it out.
class Control
{
public:
bool Focused;
};
class Caption : public virtual Control
{
public:
string Text;
};
class Frame : public virtual Control { };
class Textbox : public Caption, public Frame, public TextEditor { };
Sadly another problem with inheritance appeared. Class TextEditor has common variable names:
class TextEditor
{
public:
bool Focused;
string Text;
};
Compiler gives me errors:
ambiguous access of 'Text'
ambiguous access of 'Focused'
But all I want is those variables from all classes to be merged in derived class 'Textbox'.
Here's link to the UML picture with the problem
Thanks for any kind of help
Sorry for any languages mistakes and/or question I'm asking.
Update
A little explanation cause I might have use wrong words. Sorry for that.
By 'merge' I meant that:
If I use variables or methods of Control, Caption or Frame it will influence the values of TextEditor and vice versa. In other words variables are shared in derived class.
So my final class will look like this:
class Textbox : public Caption, public Frame, public TextEditor
{
public:
string Text;
bool Focused;
};
And not like this:
class Textbox : public Caption, public Frame, public TextEditor
{
public:
string Caption::Text;
bool Caption::Focused;
string TextEditor::Text;
bool TextEditor::Focused;
};
Which happening right now. Cause I can't do this:
Textbox A;
A.Text = "Text";
Because I have two variables with the name Text. So I would have to do this:
Textbox A;
A.Caption::Text = "Text";
A.TextEditor::Text = "Text";
Best regards
Lavi
Notes:
Consider using mutator methods
Please http://sscce.org/ - your example seems a bit over the show - would be easier to give you a clear example of how to solve your problem if your example in the problem was infact sscce. Either way, its still sufficient and your problem is clear enough I guess.
Answers:
Why does class TextEditor not also inherit from class Control and class Caption ? This would seem like the obvious solution - you would have to use virtual inheritance for class TextBox still though.
If 1 is not an option - then there is this - but in this limited sample HasText and Focusable seems to be pointless when compared to Caption and Control respectively.
class HasText
{
public:
virtual string& text() { return text; }
virtual const string& text() const { return text; }
private:
text
};
class Focusable
{
public:
virtual bool& focused() { return focused; }
virtual const bool& focussed() const { return focussed; }
};
class Control : public virtual Focusable { };
class Caption : public virtual Control, public virtual HasText { };
class Frame : public virtual Control { };
class TextEditor : public virtual HasText, public virtual Focusable { };
class Textbox : public virtual Caption, public virtual Frame, public virtual TextEditor { };

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.

How can I access a dialog item in MFC from another class?

I'm trying to access a dialog item from a function that is not in the same class as the dialog class. How can I do that?
Example:
class AnotherClass : CClas
{
AnotherClass();
public:
void MyFunction();
};
void AnotherClass::MyFunction() //Message overwriting, can't change parameters
{
CClass* temp = (CClass*)GetDlgItem(IDC_ID); //Reference to dialog item IDC_ID
temp->DoSomething(); //This gives me an assertion error
}
I know I can use "this" if it is the same dialog item than the message, but I want to access another dialog item.
Thanks for your attention.
Solution:
As suggested by Moo-Juice, you can simply pass the dialog when you instantiate the class. In my case, I couldn't do that. For some reason subclassing didn't work that way. If you face the same issue when doing an application in MFC , you can create a pointer to a CDialog and pass it your main dialog at OnInitDialog():
Example (Class):
class AnotherClass : CClass
{
AnotherClass();
public:
void MyFunction();
CDialog * mainDialog;
};
void AnotherClass::MyFunction() //Message overwriting, can't change parameters
{
CClass* temp = (CClass*)mainDialog->GetDlgItem(IDC_ID); //Reference to dialog item IDC_ID
temp->DoSomething(); //This gives me an assertion error
}
Example (OnInitDialog()):
MyMainDialog::OnInitDialog()
{
...
AnotherClass obj; //Instantiate class
obj->mainDialog = this;
return true;
}
In this example simply passing it as a parameter when creating the object makes more sense. It just didn't work with me for what I was doing.
Hope it helps anyone with a similar question.
When you instantiate AnotherClass, pass it the dialog class:
class AnotherClass
{
private:
CDialog& dialog_;
public:
AnotherClass(CDialog& dialog) : dialog_(dialog) { }
void MyFunction();
};
void AnotherClass::MyFunction()
{
CClass* temp = (CClass*)dialog_.GetDigItem(IDC_ID);
temp->doSOmething();
}

Initializing the base class to a derived base class?

I don't think this is possible, but if it is, I'd find it very usseful.
I'm making a Gui API where the user does the paint event. Lets say I want to make a Numeric TextBox. Well it would only seem good practice for it to inherit from TextBox. The problem with this, is that the user is then stuck to reimplement the paint event for the textbox since
TextBox::paint();
Would just call my default way of drawing it.
It would be annoying if they had to maintain all their TextBox derivatives.
Is there a way to get around this problem?
Lets say my TextBox paints a square, then the numeric part adds a circle, but the user's textbox, which derives from my TextBox draws a triangle, and my Numeric one derives from my TextBox I want the result to be triangle, circle.
Thanks
As I say in my comment, I think the bridge pattern is actually what you want, but since you're trying to insert a user's class as a base class for your NumericField thing the way you'd do THAT is to:
template < typename Base = TextField >
struct NumericField : Base
{
...
void paint() { Base::paint(); draw_circle(); }
};
Now the user could use NumericField<> or they could insert their class:
struct UserField : TextField
{
...
void paint() { draw_triangle(); }
};
NumericField<UserField> my_field;
The bridge answer would look more like so:
struct TextField
{
TextField() : extender_(new null_extender) {}
...
void set_extender(extender*);
virtual void paint() { draw_square(); extender_->paint(); }
...
};
struct extender { virtual void paint() = 0; };
struct null_extender { void paint() {}};
struct numeric_extender { void paint() { draw_circle(); }};
struct UserField
{
void paint() { draw_triangle(); extender()->paint(); }
};
Lots of details missing from that, but that would sort of be the story.
Isn't the only difference between NumericTextBox and TextBox that the former only allows the input of certain characters? Do you want it to paint differently?
I'm not sure quite what you mean. Your question is not that clear.
The title seems to be asking how to call the base class initializer or constructor,
is that what you want?
If this is what you want then just like this.
class TextBox
{
public:
TextBox() { }
virtual ~TextBox() { }
virtual Paint() { }
};
class NumericTextBox : public TextBox
{
public:
NumericTextBox() : TextBox() { }
~NumericTextBox() { }
};
Make sure the base class for TextBox::Paint and any other methods are declared virtual as well as the destructor.