The Origin Forum
File Exchange
Try Origin for Free
The Origin Forum
Home | Profile | Register | Active Topics | Members | Search | FAQ | Send File to Tech support
 All Forums
 Origin Forum for Programming
 Forum for Origin C
 Origin C Dialog Examples

Note: You must be registered in order to post a reply.
To register, click here. Registration is FREE!

Screensize:
UserName:
Password:
Anti-Spam Code:
Format Mode:
Format: BoldItalicizedUnderlineStrikethrough Align LeftCenteredAlign Right Horizontal Rule Insert HyperlinkUpload FileInsert Image Insert CodeInsert QuoteInsert List
   
Message:

* HTML is OFF
* Forum Code is ON
Smilies
Smile [:)] Big Smile [:D] Cool [8D] Blush [:I]
Tongue [:P] Evil [):] Wink [;)] Clown [:o)]
Black Eye [B)] Eight Ball [8] Frown [:(] Shy [8)]
Shocked [:0] Angry [:(!] Dead [xx(] Sleepy [|)]
Kisses [:X] Approve [^] Disapprove [V] Question [?]

 
Check here to subscribe to this topic.
   

T O P I C    R E V I E W
peter.cook Posted - 04/12/2005 : 10:18:24 AM
Origin Version (Select Help-->About Origin): 7.5 SR5
Operating System: Win 2000

Hi,

I've struggled with Origin C dialogs for a while with varying degrees of success based on two examples provided by CP and Eric (see http://www.originlab.com/forum/topic.asp?TOPIC_ID=3771 & http://www.originlab.com/forum/topic.asp?TOPIC_ID=3860 ).

For the simple dialog example provided by CP I found it necessary to initialise the controls, account for a missing xml settings file and allow for incorrect or missing settings.
(the sort of errors I got were 'invalid property info' or unattached wrapper class)

The code below does the job for me for the simple dialog.


class LINEARPLOT : public Dialog
{
public:
LINEARPLOT() : Dialog(IDD_LINEARPLOT, "LinearPlot")
{
}
int DoModal(HWND hParent = NULL)
{
InitMsgMap();// will be called from internal later
int nRet = Dialog::DoModal(hParent);
return nRet;
}
public:
///----------------- Message Map ----------------
EVENTS_BEGIN
ON_INIT(OnInitDialog)
ON_OK(OnOK)
ON_CANCEL(OnCancel)
EVENTS_END
///----------------------------------------------

BOOL OnInitDialog()
{
m_ebxXLABEL = GetItem(IDC_XLABEL);

// Pete Cook - need to initialise controls
m_ebxXLABEL.Text = "a";

// Pete Cook - needed to account for missing xml settings file (eg first time of use)
//SetData();
if(!SetData()) {
Tree STree;
STree.MainSheet.XLabel.strVal="Conc";
STree.Save("c:\\pete\\Pete.xml");
};
}

BOOL SetData()
{
if(m_trData.Load("c:\\pete\\pete.XML"))
{
if(m_trData.MainSheet) // to ensure that we have the right tree
{
// Pete Cook - if missing (eg modified application) or incorrect settings
if(m_trData.MainSheet.XLABEL) {
m_ebxXLABEL.Text = m_trData.MainSheet.XLABEL.strVal;
} else {
str = "Conc";
m_ebxXLABEL.Text=str;
}
// other controls

return true;
}
}
return false;
}


BOOL OnOK()
{
// tree nodes are automatically created when making assignment
m_trData.MainSheet.XLABEL.strVal = m_ebxXLABEL.Text;
m_trData.MainSheet.YLABEL1.strVal = m_ebxYLABEL1.Text;
// other controls

// Save settings
m_trData.Save("c:\\pete\\pete.XML");

// Pete Cook - Set LabTaolk variables
LT_set_str("XLABEL$", m_trData.MainSheet.XLABEL.strVal);

return TRUE;
}

public:
Edit m_ebxXLABEL;
Edit m_ebxYLABEL1;

Tree m_trData;
};
bool DoLINEARPLOT()
{
// tree should be read in OnInitDialog
myDlg.DoModal( GetWindow() );
return TRUE;
}



The Tabs example provided worked as it was BUT I found it impossible to add the equivalent connection to saving and reading the xml file settings (again allowing
for missing xml file and / or missing & incorrect settings as per simple dialog example). Okay, my C is ropey but I found the example difficult (impossible in parts) to follow.
Looking at the local variables window just threw me completely as the various 'nodes within nodes' made no sense and were surely unnecessarily complicated (or not).
This example also would need to account for the fact that not all windows would be activated by the user and yet settings are required to be read and saved from all forms.

Can I please ask for an explanation as to why or confirmation that the changes I made to the simple dialog example were necessary and an updated Tabs example
(with more explanation - is a simpler structure feasible?) as described. I'd like to think that this would be generally useful or am I the only one struggling with this topic!?

Thanks,

Cheers,

pete

4   L A T E S T    R E P L I E S    (Newest First)
Gary Lane Posted - 04/13/2005 : 3:48:08 PM
Hi Peter,

I think I may have misunderstood the exact intention of your last question. You do not need to use all the "AddNode" verbiage even in v75 - you can just use the a.b.c tree notation that CP used. Replace the Tabs() function as below and all is still fine.

In v8 it will even be easier as you will be able to also say:


trData.Tab1.CheckBox.nVal = 0;
trData.Tab1.CheckBox.DataID = ID_TAB1_CHECKBOX;
// etc.



Hope this helps...sorry if I misled.

Gary
OriginLab



// Function to launch main Tabs dialog
void Tabs()
{
/// EJP 2005-03-03 ADD_DATA_TREE
Tree trData;
trData.Tab1.CheckBox.nVal = 0;
trData.Tab1.CheckBox.SetAttribute("DataID", ID_TAB1_CHECKBOX);

trData.Tab2.EditBox.strVal = "Enter Text to Upper Case";
trData.Tab2.EditBox.SetAttribute("DataID", ID_TAB2_EDITBOX);

trData.Tab3.ComboBoxSel.nVal = 0;
trData.Tab3.ComboBoxSel.SetAttribute("DataID", ID_TAB3_COMBOBOXSEL);

// Save and load the dialog settings from a file in the user's path.
string strDlgSettingsFileName;
strDlgSettingsFileName = GetAppPath() + "SampleTabDlgSettings.xml";

// When you save and load tree settings by ID you can make changes to node names
// in the future and still be able to load older setting files.
vector<int> vnIDs;
vector<string> vsValues;
if( tree_read_values_with_ids(strDlgSettingsFileName, vnIDs, vsValues) )
tree_set_values_by_ids(trData, vnIDs, vsValues);

// Show tree contents before dialog
out_tree(trData);
/// end ADD_DATA_TREE

TabbedDialog tdlg(IDD_TABS);
tdlg.SetData(trData);
tdlg.TabsDoModal(GetWindow());

/// EJP 2005-03-03 ADD_DATA_TREE
// Show tree contents after dialog
out_tree(trData);

tree_get_values_with_ids(trData, vnIDs, vsValues);
tree_save_values_with_ids(strDlgSettingsFileName, vnIDs, vsValues);
/// end ADD_DATA_TREE
}




Edited by - Gary Lane on 04/13/2005 3:49:08 PM
Gary Lane Posted - 04/13/2005 : 1:01:03 PM
Hi Peter,

I think CP's earlier example was for simpler cases - so he just saved and loaded settings directly from XML files - which is what we were doing at the time. In the past we created the tree structure just by directly loading it from an XML file which is easy and great for simple cases but we found it caused the two issues I mentioned above. It is not that you "have to" use AddNode and DataID it is that with experience we have found that this solves the above 2 issues. We now prefer this method for ourselves and are recommending it to users. This will all be in v8 documentation.

I think the general concept is that the primary location for saving all dialog settings should not be the dialog itself rather it should be some other more easily accessible structure like a tree that is not dependent on the GUI. This solves the "unattached wrapper class" issue which occurs when you access by code a setting on a tab that has not yet been activated in Origin (and as I understand it separating data and process from GUI is also good program design). CP's main point was to always access the settings from the tree and not from the dialog and initialize the dialog from the tree and update the tree only when you leave a tab.

Creating the nodes "manually" (using AddNode) and assigning settings by ID rather than just by loading from an XML file is an extension of this technique that again solves the 2 issues I mentioned above.

Hope this helps.

Gary
OriginLab

peter.cook Posted - 04/13/2005 : 09:56:16 AM
Hi Gary,

Thanks for the reply. I've wasted quite a lot of time simply not knowing that I had to do this. I'll try and get to grips with it tonight but can you please explain why this wasn't required with CPs example for the linear dialog ie what the difference is such that I have to use 'addnode'.

Thanks,

Cheers,

Pete

Gary Lane Posted - 04/13/2005 : 08:54:20 AM
Hi Peter,

The code below shows how we are populating controls on a dialog builder dialog by loading and saving settings to and from an XML file. It should work with the resource files in the v75SR5 OriginPro\Samples\Programming\User Interface Development\Dialog Builder\Tabs subfolder. As you will see we rely on node IDs for two reasons:

1. Tree structure may change over time but IDs can remain same.
2. At least for GetN dialogs, a direct load/save from an xml file by node name causes complications when dialog event handler's exist. See last post in http://beta.originlab.com/forum/topic.asp?TOPIC_ID=1402 for GetN example.

In v75 you must set the node ID using the TreeNode class SetAttribute member function but in v8 this has been simplified.

This is fairly new stuff and will be in v8 documentation.

Gary
OriginLab


/*------------------------------------------------------------------------------*
* File Name: Tabs.cpp *
* Creation: GJL 11/11/03 *
* Purpose: OriginC Source CPP file containing sample code for the Tabs Dialog *
* Builder example. *
* Copyright (c) OriginLab Corp. 2003, 2004, 2005, 2006, 2007 *
* *
* Modification Log: *
* EJP 2005-03-03 ADD_DATA_TREE *
*------------------------------------------------------------------------------*/

#include <Origin.h>
#include <Dialog.h>
#include "TabsRes.h"

class TabSheet;

// Base Tab class
class Tab : public PropertyPage
{
public:

// Constructor for base Tab class
Tab(int nID) : PropertyPage(nID) {}

// Event handler when Tab becomes active (inherited by all Tab derived classes)
BOOL OnActiveTab()
{
int iTabNum = GetID() - IDD_FIRSTTAB + 1;
printf("Tab%d Active\n", iTabNum);
return TRUE;
}

/// EJP 2005-03-03 ADD_DATA_TREE
BOOL InitTab(int nID, TabSheet *pSheet)
{
SetID(nID);
m_pSheet = pSheet;
return TRUE;
}

TabSheet *m_pSheet;
/// end ADD_DATA_TREE
};

// Derived Tab class for Tab1
class Tab1 : public Tab
{
public:

// Constructor for Tab1 class
Tab1(int nID) : Tab(nID) { }

// InitMsgMap function setting up event handler map for Tab1
EVENTS_BEGIN
PAGE_ON_INIT(OnInitTab)
PAGE_ON_ACTIVE(OnActiveTab)
ON_BN_CLICKED(IDC_BUTTON1, OnClickToggleButton)
EVENTS_END

// Event handlers for Tab1
BOOL OnInitTab()
{
out_str("Tab1 Init");
m_btnCheckBox = GetItem(IDC_CHECK1);
m_btnCheckBox.Check = 1;

/// EJP 2005-03-03 ADD_DATA_TREE
UpdateData(FALSE); // FALSE = data to dialog
/// end ADD_DATA_TREE

return TRUE;
}

BOOL OnClickToggleButton(Control ctrl)
{
out_str("Click Toggle Button");
m_btnCheckBox.Check = mod(m_btnCheckBox.Check + 1, 2);
return TRUE;
}

/// EJP 2005-03-03 ADD_DATA_TREE
BOOL UpdateData(BOOL bDialogToData=TRUE)
{
if( bDialogToData )
{
if( m_btnCheckBox )
m_pSheet->m_tnData.Tab1.CheckBox.nVal = m_btnCheckBox.Check;
}
else // data to dialog
{
int n;

if( m_btnCheckBox )
{
if( m_pSheet->m_tnData.Tab1.CheckBox )
n = m_pSheet->m_tnData.Tab1.CheckBox.nVal;
else
n = 0; // lets have our internal default be off
m_btnCheckBox.Check = n;
}
}
return TRUE;
}
/// end ADD_DATA_TREE

// Data member controls on Tab1
Button m_btnCheckBox;
};

// Derived Tab class for Tab2
class Tab2 : public Tab
{
public:

// Constructor for Tab2 class
Tab2(int nID) : Tab(nID) {}

// InitMsgMap function setting up event handler map for Tab2
EVENTS_BEGIN
PAGE_ON_INIT(OnInitTab)
PAGE_ON_ACTIVE(OnActiveTab)
ON_BN_CLICKED(IDC_BUTTON2, OnClickUpperCaseButton)
EVENTS_END

// Event handlers for Tab2
BOOL OnInitTab()
{
out_str("Tab2 Init");
m_ebxText = GetItem(IDC_EDIT1);

/// EJP 2005-03-03 ADD_DATA_TREE
UpdateData(FALSE); // FALSE = data to dialog
/// end ADD_DATA_TREE

return TRUE;
}

BOOL OnClickUpperCaseButton(Control ctrl)
{
out_str("Click Upper Case Button");
m_ebxText.Text.MakeUpper();
return TRUE;
}

/// EJP 2005-03-03 ADD_DATA_TREE
BOOL UpdateData(BOOL bDialogToData=TRUE)
{
if( bDialogToData )
{
if( m_ebxText )
m_pSheet->m_tnData.Tab2.EditBox.strVal = m_ebxText.Text;
}
else // data to dialog
{
string str;

if( m_ebxText )
{
if( m_pSheet->m_tnData.Tab2.EditBox )
str = m_pSheet->m_tnData.Tab2.EditBox.strVal;
m_ebxText.Text = str;
}
}
return TRUE;
}
/// end ADD_DATA_TREE

// Data member controls on Tab2
Edit m_ebxText;
};

// Derived Tab class for Tab3
class Tab3 : public Tab
{
public:

// Constructor for Tab3 class
Tab3(int nID) : Tab(nID) { }

// InitMsgMap function setting up event handler map for Tab3
EVENTS_BEGIN
PAGE_ON_INIT(OnInitTab)
PAGE_ON_ACTIVE(OnActiveTab)
ON_BN_CLICKED(IDC_BUTTON3, OnClickOutputButton)
EVENTS_END

// Event handlers for Tab3
BOOL OnInitTab()
{
out_str("Tab3 Init");
m_cmbxStooges = GetItem(IDC_COMBO1);
m_cmbxStooges.SetCurSel(0);

/// EJP 2005-03-03 ADD_DATA_TREE
UpdateData(FALSE); // FALSE = data to dialog
/// end ADD_DATA_TREE

return TRUE;
}

BOOL OnClickOutputButton(Control ctrl)
{
out_str("Click Output Button");
string str;
m_cmbxStooges.GetLBText(m_cmbxStooges.GetCurSel() ,str);
str.Format("You selected %s.",str);
str.Write(WRITE_MESSAGE_BOX);
return TRUE;
}

/// EJP 2005-03-03 ADD_DATA_TREE
BOOL UpdateData(BOOL bDialogToData=TRUE)
{
if( bDialogToData )
{
if( m_cmbxStooges )
m_pSheet->m_tnData.Tab3.ComboBoxSel.nVal = m_cmbxStooges.GetCurSel();
}
else // data to dialog
{
int n;

if( m_cmbxStooges )
{
if( m_pSheet->m_tnData.Tab3.ComboBoxSel )
n = m_pSheet->m_tnData.Tab3.ComboBoxSel.nVal;
m_cmbxStooges.SetCurSel(n);
}
}
return TRUE;
}
/// end ADD_DATA_TREE

// Data member controls on Tab3
ComboBox m_cmbxStooges;
};


// Tab place holder class
class TabSheet : public PropertySheet
{
public:

// Constructor for PropertySheet class
TabSheet()
{
/// EJP 2005-03-03 ADD_DATA_TREE
///m_Tab1.SetID(IDD_FIRSTTAB);
///m_Tab2.SetID(IDD_SECONDTAB);
///m_Tab3.SetID(IDD_THIRDTAB);
m_Tab1.InitTab(IDD_FIRSTTAB, this);
m_Tab2.InitTab(IDD_SECONDTAB, this);
m_Tab3.InitTab(IDD_THIRDTAB, this);
/// end ADD_DATA_TREE

AddPage(m_Tab1);
AddPage(m_Tab2);
AddPage(m_Tab3);
}

// Initialize message maps for each Tab
void InitMaps()
{
m_Tab1.InitMsgMap();
m_Tab2.InitMsgMap();
m_Tab3.InitMsgMap();
}

/// EJP 2005-03-03 ADD_DATA_TREE
BOOL UpdateData()
{
m_Tab1.UpdateData();
m_Tab2.UpdateData();
m_Tab3.UpdateData();
return TRUE;
}

// The data used to init and get the settings from each tab
// will be kept in a tree node.
TreeNode m_tnData;
/// end ADD_DATA_TREE

// Data members of PropertySheet are Tab objects
Tab1 m_Tab1;
Tab2 m_Tab2;
Tab3 m_Tab3;
};



// Main dialog class
class TabbedDialog : public Dialog
{
public:

// Constructor for main Dialog
TabbedDialog(int ID) : Dialog(ID, "Tabs.DLL")
{
SetResizingStyle(RESIZE_DEPENDENCY_DOMINANT_DIALOG);
}

// Function to launch main Dialog
int TabsDoModal(HWND hWnd)
{
InitMsgMap();
return DoModal(hWnd, DLG_MODAL_WITH_KEY);
}

// InitMsgMap function setting up event handlers for main Dialog
EVENTS_BEGIN
PAGE_ON_INIT(Init)
PAGE_ON_OK(OnClickOk)
PAGE_ON_CANCEL(OnClickCancel)
EVENTS_END

// Event handlers for main Dialog
BOOL Init()
{
out_str("Tabbed Dialog Init");
m_Sheet.Create(IDC_TAB_PLACEHOLDER, *this);
m_Sheet.InitMaps();
return TRUE;
}

BOOL OnClickOk()
{
out_str("Click OK Button");
m_Sheet.UpdateData();
return TRUE;
}

BOOL OnClickCancel()
{
out_str("Click Cancel Button");
return TRUE;
}

/// EJP 2005-03-03 ADD_DATA_TREE
BOOL SetData(TreeNode &tnData)
{
m_Sheet.m_tnData = tnData;
return TRUE;
}
/// end ADD_DATA_TREE

// Data member of main Dialog is PropertySheet (place holder)
TabSheet m_Sheet;
};

// The following IDs are used for the tree nodes that will hold
// our dialog settings.
#define ID_TAB1_CHECKBOX 100
#define ID_TAB2_EDITBOX 200
#define ID_TAB3_COMBOBOXSEL 300

// Function to launch main Tabs dialog
void Tabs()
{
/// EJP 2005-03-03 ADD_DATA_TREE
Tree trData;
TreeNode tnTab;

tnTab = trData.AddNode("Tab1");
tnTab.AddNumericNode(0, "CheckBox");
tnTab.CheckBox.SetAttribute("DataID", ID_TAB1_CHECKBOX);

tnTab = trData.AddNode("Tab2");
tnTab.AddTextNode("Enter Text to Upper Case", "EditBox");
tnTab.EditBox.SetAttribute("DataID", ID_TAB2_EDITBOX);

tnTab = trData.AddNode("Tab3");
tnTab.AddNumericNode(0, "ComboBoxSel");
tnTab.ComboBoxSel.SetAttribute("DataID", ID_TAB3_COMBOBOXSEL);

// Save and load the dialog settings from a file in the user's path.
string strDlgSettingsFileName;
strDlgSettingsFileName = GetAppPath() + "SampleTabDlgSettings.xml";

// When you save and load tree settings by ID you can make changes to node names
// in the future and still be able to load older setting files.
vector<int> vnIDs;
vector<string> vsValues;
if( tree_read_values_with_ids(strDlgSettingsFileName, vnIDs, vsValues) )
tree_set_values_by_ids(trData, vnIDs, vsValues);

// Show tree contents before dialog
out_tree(trData);
/// end ADD_DATA_TREE

TabbedDialog tdlg(IDD_TABS);
tdlg.SetData(trData);
tdlg.TabsDoModal(GetWindow());

/// EJP 2005-03-03 ADD_DATA_TREE
// Show tree contents after dialog
out_tree(trData);

tree_get_values_with_ids(trData, vnIDs, vsValues);
tree_save_values_with_ids(strDlgSettingsFileName, vnIDs, vsValues);
/// end ADD_DATA_TREE
}




Edited by - Gary Lane on 04/13/2005 08:58:56 AM

The Origin Forum © 2020 Originlab Corporation Go To Top Of Page
Snitz Forums 2000