From: RB on
I have reached a point where I need input on the following:
For some time I have used MFC created apps with Doc/View
and made my base view class as CFormView. It was
convenient and quick, but I was putting all of my data variables in
the ViewClass since that was where the class wizard put all my
control variables and it seemed convenient in my ignorance. If I
had to access files I used ofstream from within my view class.
So now it has become apparent that I have things backwards
(so it appears from what I read ) in that I should have been creating
data variables in the CDocument class.
My problem in understanding some of the logistics is that I see
plenty of example code "getting" data into the view from the document,
but I don't see much on getting the user input from the view to the
document. At first I thought I could just make the view class a friend
of the document, but I think maybe that is not the way it is done. So
I am assuming you get a CDocument ptr as I have at the bottom of
shown code below, (appreciate all comments on my understanding
of theory (or not understanding ) and code criticism of how I am
attempting to feed input data to variables in Document class.

CMyView::CMyView() // start of predicated view code
: CFormView(CMyView::IDD)
{ // Edit Control Variables
//{{AFX_DATA_INIT(CMyView)
m_Invert_In_1 = 0.0;
m_Invert_Out_1 = 0.0;
m_InletNum = 0;
//}}AFX_DATA_INIT
}

CMyView::~CMyView()
{
}

void CMyView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyView)
DDX_Text(pDX, IDC_Invert_In_1, m_Invert_In_1);
DDX_Text(pDX, IDC_Invert_Out_1, m_Invert_Out_1);
DDX_Text(pDX, IDC_ItemLabel, m_InletNum);
//}}AFX_DATA_MAP
} // end of predicated view code

void CMyView::OnEnter() // Begin question code area
{
UpdateData(TRUE);
// Code here is asking for comment and design theory input //
// I am moving edit control variables input to my data variables
CMyDoc* DocPtr = GetDocument();
DocPtr->InletA->dInvert_In_1 = m_Invert_In_1;
DocPtr->InletA->dInvert_Out_1 = m_Invert_Out_1;
DocPtr->InletA->uiInletNum = m_InletNum;
}
--------------- predicated variables in document class
class CMyDoc : public CDocument
{
protected: // create from serialization only
CMyDoc();
DECLARE_DYNCREATE(CMyDoc)

// Attributes
public:

struct Inlet
{ double dInvert_In_1;
double dInvert_Out_1;
unsigned int uiInletNum;
};

Inlet InletA;
.................rest of document class......


From: David Ching on
"RB" <NoMail(a)NoSpam> wrote in message
news:uZPz7h$6KHA.2220(a)TK2MSFTNGP04.phx.gbl...
> // Code here is asking for comment and design theory input //
> // I am moving edit control variables input to my data variables
> CMyDoc* DocPtr = GetDocument();
> DocPtr->InletA->dInvert_In_1 = m_Invert_In_1;
> DocPtr->InletA->dInvert_Out_1 = m_Invert_Out_1;
> DocPtr->InletA->uiInletNum = m_InletNum;

Yup, this is pretty much how you do it. Although you may prefer to create
methods in your document which the view calls to get/set the data, instead
of accessing the member data directly. This encapsulates the document
implementation so you can just change it in the document without affecting
all the views (remember you can have multiple view classes showing different
aspects of the same document) interaction.

-- David

From: Joseph M. Newcomer on
See below...
On Tue, 4 May 2010 22:12:46 -0400, "RB" <NoMail(a)NoSpam> wrote:

> I have reached a point where I need input on the following:
>For some time I have used MFC created apps with Doc/View
>and made my base view class as CFormView. It was
>convenient and quick, but I was putting all of my data variables in
>the ViewClass since that was where the class wizard put all my
>control variables and it seemed convenient in my ignorance.
****
I consider using data variables to be a serious design error. I avoid them entirely. You
should think about whether or not their existence makes sense. I consider the whole
UpdateData mechanism to be a seriously deep design failure. I have yet to find a reason
that it could ever make sense within the context of a dialog or CFormView-derived class.
Their only value, which is marginal at best, is for a very limited subset of control types
(edit controls, static controls, and check boxes; they are completely useless for any
other kind of control)
****
>If I
>had to access files I used ofstream from within my view class.
****
Probably the wrong decision. What I do is keep the values in variables in the
CDocument-derived class. In the serialize routine I simply call UpdateAllViews() using a
specific lHint and pHint value which are not (0,NULL), and when this particular
combination is detected in my OnUpdate handler, I simply use operations like
GetWindowText, GetCurSel, and similar operations to copy the values out of the controls
and place them in variables in the CDocument-derived classs. In this way, onlly the
document understands how to read and write the data, and there is never any use of streams
in the view. Data transfer to and from the document are managed by the document class,
which is where it should be handled.

When the CFormView starts up, the OnInitialUpdate loads the controls from the variables in
the CDocument-derived class.

I do not believe in the DDX and DDV mechanisms at all, except for the DDX_Control calls to
bind the controls to control variables.
****
> So now it has become apparent that I have things backwards
>(so it appears from what I read ) in that I should have been creating
>data variables in the CDocument class.
> My problem in understanding some of the logistics is that I see
>plenty of example code "getting" data into the view from the document,
>but I don't see much on getting the user input from the view to the
>document. At first I thought I could just make the view class a friend
>of the document,
****
NO!!!! This would require the CDocument-derived class know about the views, and this is
COMPLETELY WRONG!. Use UpdateAllViews to handle the transfer, as described. NEVER include
a view header file in the document class; if you think you have to, your design is wrong!
*****
>but I think maybe that is not the way it is done. So
>I am assuming you get a CDocument ptr as I have at the bottom of
>shown code below, (appreciate all comments on my understanding
>of theory (or not understanding ) and code criticism of how I am
>attempting to feed input data to variables in Document class.
>
>CMyView::CMyView() // start of predicated view code
> : CFormView(CMyView::IDD)
>{ // Edit Control Variables
> //{{AFX_DATA_INIT(CMyView)
> m_Invert_In_1 = 0.0;
> m_Invert_Out_1 = 0.0;
****
I presume these values have types associated with them...
****
> m_InletNum = 0;
> //}}AFX_DATA_INIT
>}
>
>CMyView::~CMyView()
>{
>}
>
>void CMyView::DoDataExchange(CDataExchange* pDX)
>{
> CFormView::DoDataExchange(pDX);
> //{{AFX_DATA_MAP(CMyView)
> DDX_Text(pDX, IDC_Invert_In_1, m_Invert_In_1);
> DDX_Text(pDX, IDC_Invert_Out_1, m_Invert_Out_1);
> DDX_Text(pDX, IDC_ItemLabel, m_InletNum);
> //}}AFX_DATA_MAP
>} // end of predicated view code
>
>void CMyView::OnEnter() // Begin question code area
>{
> UpdateData(TRUE);
***
I consider writing UpdateData to be a fundamental design error. It is based on a set of
myths that I simply do not believe; that it makes sense to EVER transfer *every* data
value either to the controls, or from the controls. This has nasty implications when the
values interact. Read my essay on Dialog Control Management on my MVP Tips site.
****
> // Code here is asking for comment and design theory input //
> // I am moving edit control variables input to my data variables
> CMyDoc* DocPtr = GetDocument();
> DocPtr->InletA->dInvert_In_1 = m_Invert_In_1;
> DocPtr->InletA->dInvert_Out_1 = m_Invert_Out_1;
> DocPtr->InletA->uiInletNum = m_InletNum;
***
THis is incosnsitent with your declaration; it should be
DocPtr->InLetA.dInvert_In_1 = m_Invert_In_1;

because InLetA is not a pointer varaible. It is not clear why you need to know the
internals of the data structure that holds these values.
>}

****
I would do it using approximately the same idea, but do it in the OnUpdate handler:

void CMyView::OnUpdate(CView * view, LPARAM lHint, CObject * pHint)
{
if(lHint == 0 && pHint == NULL)
{
CView::OnUpdate(view, lHint, pHint);
return;
}
switch(lHint)
{ /* lHint */
case VALUES_TO_DOCUMENT:
{
CMyDoc * DocPtr = ...etc.
DocPtr->SetInvertIn(...);
DocPtr->SetInvertOut(...);
DocPtr->SetInletNum(...);
// I prefer to use set/get methods rather than directly access variables
// I might also do this as
// DocPtr->SetInLetValues(..., ..., ....);
// and not worry about the specification of the structure at all!
}
break;
case ...
break;
default:
...maybe ASSERT(FALSE) here....your choice
break;
} /* lHint */
} // CMyView::OnUpdate
>--------------- predicated variables in document class
>class CMyDoc : public CDocument
>{
> protected: // create from serialization only
> CMyDoc();
> DECLARE_DYNCREATE(CMyDoc)
>
>// Attributes
> public:
>
> struct Inlet
> { double dInvert_In_1;
> double dInvert_Out_1;
> unsigned int uiInletNum;
> };
>
> Inlet InletA;
>................rest of document class......
>
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Goran on
On May 5, 4:12 am, "RB" <NoMail(a)NoSpam> wrote:
>    I have reached a point where I need input on the following:
> For some time I have used MFC created apps with Doc/View
> and made my base view class as CFormView.  It was
> convenient and quick, but I was putting all of my data variables in
> the ViewClass since that was where the class wizard put all my
> control variables and it seemed convenient in my ignorance. If I
> had to access files I used ofstream from within my view class.
>   So now it has become apparent that I have things backwards
> (so it appears from what I read ) in that I should have been creating
> data variables in the CDocument class.
>     My problem in understanding some of the logistics is that I see
> plenty of example code "getting" data into the view from the document,
> but I don't see much on getting the user input from the view to the
> document. At first I thought I could just make the view class a friend
> of the document, but I think maybe that is not the way it is done. So
> I am assuming you get a CDocument ptr as I have at the bottom of
> shown code below,  (appreciate all comments on my understanding
> of theory (or not understanding ) and code criticism of how I am
> attempting to feed input data to variables in Document class.
>
> CMyView::CMyView()                     // start of predicated view code
>  : CFormView(CMyView::IDD)
> {        // Edit Control Variables
>   //{{AFX_DATA_INIT(CMyView)
>   m_Invert_In_1 = 0.0;
>   m_Invert_Out_1 = 0.0;
>   m_InletNum = 0;
>   //}}AFX_DATA_INIT
>
> }
>
> CMyView::~CMyView()
> {
>
> }
>
> void CMyView::DoDataExchange(CDataExchange* pDX)
> {
>   CFormView::DoDataExchange(pDX);
>   //{{AFX_DATA_MAP(CMyView)
>   DDX_Text(pDX, IDC_Invert_In_1, m_Invert_In_1);
>   DDX_Text(pDX, IDC_Invert_Out_1, m_Invert_Out_1);
>   DDX_Text(pDX, IDC_ItemLabel, m_InletNum);
>   //}}AFX_DATA_MAP
>
> }                                          // end of predicated view code
>
> void CMyView::OnEnter()     // Begin question code area
> {
>   UpdateData(TRUE);
>   // Code here is asking for comment and design theory input //
>   // I am moving edit control variables input to my data variables
>   CMyDoc* DocPtr = GetDocument();
>   DocPtr->InletA->dInvert_In_1  =  m_Invert_In_1;
>   DocPtr->InletA->dInvert_Out_1 =  m_Invert_Out_1;
>   DocPtr->InletA->uiInletNum  =  m_InletNum;}
>
> --------------- predicated variables in document class
> class CMyDoc : public CDocument
> {
>   protected: // create from serialization only
>   CMyDoc();
>   DECLARE_DYNCREATE(CMyDoc)
>
> // Attributes
>   public:
>
>   struct Inlet
>    { double dInvert_In_1;
>      double dInvert_Out_1;
>      unsigned int uiInletNum;
>    };
>
>   Inlet InletA;
> ................rest of document class......

That should cover it. Don't forget "if (UpdateData(TRUE)) { transfer
from view to doc } ("if" is important, that's how UpdateData is
supposed to work). Also, don't forget to call UpdateAllViews upon the
change to the document (that's how doc/view is supposed to work).

Goran.
From: RB on
>you may prefer to create methods in your document which the view calls to get/set the data, instead of accessing the member data
>directly. This encapsulates the document implementation so you can just change it in the document without affecting all the views
>(remember you can have multiple view classes showing different aspects of the same document) interaction.
> David

Thanks David, I have read what you are referring to and as I move along I
want to embrace that facet also. I have an experimental app going that I am
using to feel my way out of the reverse logic that I had been using which was
pretty much "View" everything and "Document" nothing.