Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

DDX/DDV and DoDataExchange for PropertySheets

7 views
Skip to first unread message

Luigino

unread,
Nov 23, 2009, 3:40:39 AM11/23/09
to
Hello everyone!!!!

I have a nested propertysheets (on some propertypages I have another
propertysheet with pages itself). I have also a XML file of general
settings that I read in OnInitDialog()'s form event.
Some pages of this nested propertysheets have settings that depends
from other pages and of general settings from xml file. Like if I
activate a checkbox in a page I change in the xml file the related
value from 0 to 1 and in the same time I enable the controls in
another page.
I know there's a way to communicate between propertypages from the top
(the dialog form) so it can share also xml file object maybe using
DoDataExchange. But how I can do that?... I tried to read the help of
MSDN but it's like messing me a bit so I'm here asking you...

Thanks to all.
Ciao
Luigi

Goran

unread,
Nov 23, 2009, 5:44:07 AM11/23/09
to

Looks like you want to change an UI element in one page when state of
your UI changes in another (XML text behind or not, does not matter).
Simplest possible way is to just use a common parent, e.g.:

(I presume that Sheet has Page1 and Page2).

class Sheet: public CPropertySheet
{
public:
Page1 m_Page1;
Page2 m_Page2;
};

Page1::OnSomeButonClicked()
{
STATIC_DOWNCAST(Sheet, GetParent())->m_Page2.StateOfDataItemXChanged
(GetButtonState());
}

Page2::StateOfDataItemXChanged(bool bValue)
{
if (m_hWnd)
{ // m_Page2 was created, too!
someWindow.EnableWindow(bValue);
}
else
{ // m_Page2 wasn't created yet (e.g. user didn't click on it yet)
m_bEnableSomeWindowAtPropertyPageCreationTime = bValue;
}
}

If you have this situation for many data items, or if you don't have a
simple parent sheet-child pages situation, this gets complicated
rather quickly, so then you might want to resort to some elaborated
update mechanics. You would have do that if your underlying data can
change without the knowledge of UI elements you have listed here. But
that seems to be another question.

HTH,
Goran.

Joseph M. Newcomer

unread,
Nov 23, 2009, 12:40:07 PM11/23/09
to
As already suggested, the idea is to treat the property sheet as a "document" and the
property pages as the "view". What I would do (and have done) with the nested mechanism
is store the data in the base property sheet, and have setter/getter methods that retrieve
the values. The one I did had a UWM_SETVALUE that took the ID of the thing to set as the
WPARAM (in my case, a pointer to the string that was the name of the value) and the second
was the value (type-dependent; bool, int took an LPARAM directly; string took a string
pointer). I used SendMessage since it was all in the same thread, and all I had to do was
send it to the parent (I did not nest property sheets, which I think is silly; I just used
tabbed dialogs all the way down). A parent tab saw a setter or getter and set it to ITS
parent, e.g.,

LRESULT SomeInternalPage::OnSetValue(WPARAM wParam, LPARAM lParam)
{
return GetParent()->SendMessage(wParam, lParam);
}

and only the top-level window (the property sheet in this case) had handlers that fetched
or restored values, e.g.,

LRESULT CMyPropertySheet::OnSetValue(WPARAM wParam, LPARAM lParam)
{
CString * name = (CString *)wParam;
DataDescriptor * desc = FindData(*name);
if(desc == NULL)
{
ASSERT(FALSE);
return (LRESULT) FALSE;
}
switch(desc->type)
{
case DATA_BOOL:
case DATA_INT:
desc->value.scalar = (int)lParam;
return TRUE;
case DATA_STRING:
desc->value.string = *(CString *)lParam;
return TRUE;
default:
ASSERT(FALSE);
return FALSE;
}
}

In the OnSetActive handler, I would do GetValue calls for all the data the page needed,
and popupate the page's controls; then I'd call updateControls() (see my essay on dialog
control management) to deal with all enabling/disabling/showing/hiding/selecting issues.
On the OnKillActive handler, I would gather all the fields and do a series of SetValue
calls (these are the subroutines in the superclass of all the pages that generated the
SendMessage calls). I used string names for the values because the pages were in fact
created based on the names found in the XML-equivalent input description.

Note that this now handles all the cases, such as checking a check box in page 3 means
that certain controls on page 4 are now active, and changing a value on page 5 causes it
to appear as an editable string on page 6, and if it is edited on page 6, when I switch
back to page 5 the edited value appears. Clean and nicely abstracted.
joe

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

0 new messages