Re: document class
If the user opens the display submenue by clicking on the specific
button, the following method will be called
void CMIAppView::OnBnClickedBtnDisplaySub()
{
GetDocument()->StartSubMenu(this, CMIAppDoc::SMENUE_DISPLAY);
}
void CMIAppDoc::StartSubMenu(CWnd *wnd, UINT submenue)
{
CWizardStartDialog dlgStartWiz(wnd);
CDisplayPage DisplayPage;
CStringList sListGetParams;
switch(submenue)
{
case SMENUE_NETWORK:
break;
case SMENUE_DISPLAY:
dlgStartWiz.AddPage(&DisplayPage, CDisplayPage::IDD);
dlgStartWiz.DoModal();
/* the document class didn`t have
the latest information the user made in the
dialog - so far: */
//global variable DisplayInfo from
the CDisplay Class
DisplayInfo.GetParam(sListGetParams);
//add these new information to the xml list
XmlFile.UpdateXmlList(sListGetParams, submenue);
break;
}//end of switch (of course there are more
cases... within the switch )
//update all views
UpdateAllViews(NULL, submenue, sListGetParams);
}
XML file represents document state;
CNetwork and CDisplay will have one global varialbe and the CXmlList
class will have a protected member installed in the document class,
which is called XmlFile (see the above method). Because I want to use
the doc/view modell - which means that the document will have all
information for the view and these information are stored in the xml
file.
I agree. THere are a couple solutions. One is, why is the docume=
nt managing the display?
If the display is managed by a display state class, then you can inclu=
de a pointer to the
display-state class and initialize it before you do the DoModal, possi=
bly even by
extending the constructor to the CDisplayDlg class. Another is to s=
imply have a public
member that is initialized. Or, you can have this dialog directly a=
ccess the one-and-only
global display state object (because it is really the interface; in fa=
ct, I'd probably
include the dialog interaction as part of the display state object, su=
ch as
CDisplay::AskUserForParameters();
which launched a dialog to get the values, and therefore the whole mec=
hanism is completely
hiddent from the non-display-state components.
The CDisplayPage (dialog showing the display submenue) will have
access directly to the global CDisplay class variable to get the
parameters for all controls (checkboxen and so on) in the
OnInitDialog() class and before the dialog will be closed due to the
user clicked the OK button, the CDisplay class method SetParams() will
be called to verify the new settings and store them in the display
class.
I can`t see any advantage in extending the constructor to the
CDisplayPage (dialog) class to add the global variable of the CDisplay
class there instead of using the global CDisplay varialbe.
****
One of the interesting questions is how you pass information to and from =
the dialog. There
is no agreement on the best way to do this; I use a variety of techniques=
..
****
Here`s the method I`m using to get the information from the CDisplay
class.
BOOL CDisplayPage::OnInitDialog()
{
CWizardPage::OnInitDialog();
CFont *font;
font = DisplayInfo.GetStatFont();
//set font to the controls
m_EdtBright.SetFont(font);
m_CheckDispOnOff.SetFont(font);
m_StatBright.SetFont(font);
//get params from CDisplay class
CStringList slist;
DisplayInfo.GetParam(slist);
POSITION pos = slist.FindIndex(CDisplay::Brightness);
//cedit control
m_EdtBright.SetWindowText(slist.GetAt(pos));
//checkbox control
pos = slist.FindIndex(CDisplay::State);
m_CheckDispOnOff.SetCheck(_wtoi(slist.GetAt(pos)));
return TRUE;
}
After getting back from the dialog, you said it`s a good time to call
UpdateAllViews(). So at first I will call the =B4CXMLFile class to get
the latest version of the CStringList which includes the updated
information from the CDisplay-class and after that I call
UpdateAllViews()?
****
The question is what value this operation has. I'd skip any concept of=
string lists and
go directly for the abstractions.
joe
****
ok but if I need to update several values (for exmaple in the network
dialog - ipaddr, subnetmask, gateway-addr, dhcp(enabled or not)), a
string lists make sense or not?
class HttpSoc :
public CConnSoc
protected:
CStringList sListGetXmlParam;
};
void HttpSoc::ProcessPktRecv(CByteArray &data)
{
//among other things
viswnd->PostMessage(UWM_GET_DATA_FROM_XML_LIST,
(WPARAM)sListGetXmlParam, ::GetCurrentThreadId());
}
In the visible window class;
***
The repeated use of "Xml" here shows that you are creating an unfortunate=
coupling between
the abstraction and an implementation. Nobody should care that the dat=
a is in XML. Nobody
should care anything more than the fact that there is a representation; i=
f nobody looks at
this, even calling it a CStringArray is saying too much about what is goi=
ng on. If I
wanted to make a really clean interface, I'd have a CParameters structure=
which handled
this, and if it was implemented by CStringArray, well, that's nobody's bu=
siness I might
have functions "CString CParameters::GetNamedParameter(cont CString & nam=
e)" which looked
up a parameter by name and returned its value, and if that has to iterate=
over a
CStringArray, or query a CMap, who cares? (Actually, I did exactly tha=
t in my XML file
parser) ...
That means you will use Xpath to search for each specific item in the
xml file direct - or in a CMap, CstringArray where you have stored all
items from the xml file?
I mean I understand your approach, but for example the http soc class
will get some parameters from the document, I have to use a
PostMessage to the mainthread (because the http soc class uses not the
mainthread) and within such a message I`ve only one parameter wPARAM
to add informtion from the document because the other one is the
threadID of the http soc class.
//in the http soc class:
viswnd->PostMessage(UWM_GET_DATA_FROM_DOC,
(WPARAM)wPARAM, ::GetCurrentThreadId());
If I will ask for each value I`ll have to use 10x or 12x such
postmessages; I`m not sure but it sounds not really good to me that
this would be a good programming style.
viswnd->PostMessage(UWM_GET_IP_ADDR_FROM_DOC,
(WPARAM)wPARAM, ::GetCurrentThreadId());
viswnd->PostMessage(UWM_GET_SUBNET_MASK_ADDR_FROM_DOC,
(WPARAM)wPARAM, ::GetCurrentThreadId());
viswnd->PostMessage(UWM_GET_GATEWAY_ADDR_FROM_DOC,
(WPARAM)wPARAM, ::GetCurrentThreadId());
The advantage of using a CStringlist or CStringArray is that I will
pass these information by FormatMessage to the CString (in the http
socket class) which includes the html page (with %1%, %2% and so on).
So the list (getting back from the doc to the http soc class) includes
the information already in the right order for the specific http
page.
According to the CXML file class: at the beginning (in the
OnNewDocument method) I will call the xml class method to load the
specific xml file and load all the values / node values from the xml
file into a CStringList; after that I release the xml file.
The xml file looks like:
<myxmlfile>
<display>
<state checked=checked>1</state>
<brightness disabled="">50</brightness>
<contrast disabled="">50</contrast>
</display>
</myxmlfile>
The display has three information in the xml file (brightness,
contrast and state which indicates if the display is on or off by a
checkbox); If the state is checked, the brightness and contrast is not
disabled (therefore I installed the attribute disabled=""). IF the
checkbox (state) would not be checked, brightness and contrast will
have the attribute in the xml file disabled="disabled".
So the xml file includes all information I need to know to get the
correct state and behaviour of each item regarding to the display... I
know if a ceditbox has the possibility to be disabled or not and so
on...
But I`m not really happy about using a CStringList for the xml file,
because it is a little bit complicated. I think there must be a quite
simpler solution to acchieve the same thing.
My CStringlist has the structure:
<menue display>
<!-- the next information are from the xml file -->
<first nodename> - <path to first nodename> - <value> - <attributes if
available> - <" " string which indicates the end of this node>
<second nodename> - <path to second nodename> - <value> - <attributes
if available> - <" " string which indicates the end of this node>
<empty string "">
<menue network>
....and so on
Is is possible to add more than one parameter to a CMap??? For
example: the node name is the key because its the only value which is
unique, the second parameter holds the path to the value in the xml
file (for storing this value later using xpath), the third parameter
holds the value and the forth parameter will hold any additional
attributes (not every item will have such attributes).
Then if the http socket class say: I need the ip addr (Postmessage
which includes the node name) -> I will take a look into the CMap
searching for the key (name of the node which holds the value and the
attributes) -> add all these information in the correct order into a
CStringlist or CStringArray and return this list to the http socket
class....
I know what you are thinking about that!? it`s really difficult and
not simple.... The key is that the http socket class as well as the
CNetworkDlg needs the value of e.g. the ip addr as well as the
behaviour of the ip addr (is it disabled or not) . The ip (which
represents a cedit field in the CNetworkDlg class) could be disabled
(if the user will use dhcp to get a ip addr) or the ip could be not
disabled (if the user will use a static ip configuration).
Which approach will you prefer to send the right information from the
xml file to the http socket class? I think the xml file class only
needs to know if a item could be disabled / checked / selected or not
- and the http socket class only wants to get some information to
display the page in the right way with all required information.
best regards
Hans