This example shows how to create a splitter dialog, which provides a better display of tree view or grid view.
To create this dialog, you first must prepare a dialog resource with a Static control and two Button controls. Here we just use the existing resource IDD_SAMPLE_SPLITTER_DLG in the built-in OriginC\Originlab\ODlg8.dll file to simplify this example.
, type file name, and set Location as the same path of the above dialog resource dll oDlg8.dll - Origin install path OriginC\Originlab subfolder.
The following header files will be used in the example. Copy the following to the above created source file.
#include <..\Originlab\DialogEx.h> #include <..\Originlab\SplitterControl.h> #include <..\Originlab\DynaSplitter.h>
We can derive a class from TreeDynaSplitter. Most dialog initialization and other event functions' code are done in a base class and make our splitter class a light class.
class MySplitter : public TreeDynaSplitter { public: MySplitter(){} ~MySplitter(){} //init the splitter control int Init(int nCtrlID, WndContainer& wndParent, LPCSTR lpcszDlgName = NULL) { TreeDynaSplitter::Init(nCtrlID, wndParent, 0, lpcszDlgName); return 0; } //output current settings void Output() { out_tree(m_trSettings); } protected: // Declare message map table and message handler DECLARE_MESSAGE_MAP BOOL OnInitSplitter(); BOOL InitSettings(); void OnRowChange(Control ctrl); private: BOOL constructSettings(); BOOL initSystemInfo(TreeNode& trSys);//show system information BOOL initUserInfo(TreeNode& trUser);//to collect user settings. private: GridTreeControl m_List; //grid control on left panel Tree m_trSettings;//splitter tree on right panel bool m_bIsInit;//indicate whether it is from init event }; //map the control messages and events. BEGIN_MESSAGE_MAP_DERIV(MySplitter, TreeDynaSplitter) ON_INIT(OnInitSplitter) //init splitter settings //save splitter size & position when destroy //this is done in base class. ON_DESTROY(OnDestroy) ON_SIZE(OnCtrlResize) //when control is ready, need to resize the splitter and its position ON_USER_MSG(WM_USER_RESIZE_CONTROLS, OnInitPaneSizs) //when user select different row on left panel ON_GRID_ROW_COL_CHANGE(GetMainPaneID(), OnRowChange) END_MESSAGE_MAP_DERIV BOOL MySplitter::OnInitSplitter() { TreeDynaSplitter::OnInitSplitter(&m_List); constructSettings(); //construct tree settings InitSettings(); //tree settings to splitter GUI SetReady(); return TRUE; } //when user selects a different row, update right panel void MySplitter::OnRowChange(Control ctrl) { if ( !m_bReady ) return; //show sub nodes under current branch TreeNode trCurrent = ShowListContent(-1, true, m_bIsInit); if ( trCurrent ) { //load settings from registry string strTag = trCurrent.tagName; LoadBranchSetting(GetDlgName(), strTag); } m_bIsInit = false; return; } //init splitter settings BOOL MySplitter::InitSettings() { m_bIsInit = true; ///set not ready, avoid flash and painting problem on GUI m_bReady = false; //set the splitter tree for display ShowList(m_trSettings, ATRN_STOP_LEVEL); m_bReady = true; //reset ready state. SelectRow(0); //select first row. return TRUE; } BOOL MySplitter::constructSettings() { TreeNode trSys = m_trSettings.AddNode("System"); trSys.SetAttribute(STR_LABEL_ATTRIB, "System Information"); initSystemInfo(trSys); TreeNode trUser = m_trSettings.AddNode("User"); trUser.SetAttribute(STR_LABEL_ATTRIB, "User Settings"); initUserInfo(trUser); return TRUE; } //display your Origin's basic information. //you can also display OS related information here. BOOL MySplitter::initSystemInfo(TreeNode& trSys) { if ( !trSys ) return FALSE; char szUser[LIC_USERINFO_NAME_COMPANY_MAXLEN]; char szCompany[LIC_USERINFO_NAME_COMPANY_MAXLEN]; char szSerial[LIC_OTHER_INFO_MAXLEN]; char szRegCode[LIC_OTHER_INFO_MAXLEN]; DWORD dwProd = GetLicenseInfo(szUser, szCompany, szSerial, szRegCode); string strProduct; switch( dwProd & 0x000000FF ) { case ORGPRODUCTTYPE_EVALUATION: strProduct = "Evaluation"; break; case ORGPRODUCTTYPE_STUDENT: strProduct = "Student"; break; case ORGPRODUCTTYPE_REGULAR: strProduct = "Regular"; break; case ORGPRODUCTTYPE_PRO: strProduct = "Professional"; break; default: strProduct = "Unknown"; break; } GETN_USE(trSys) GETN_STR(UserName, "User Name", szUser) GETN_READ_ONLY_EX(2) GETN_STR(Company, "Company Name", szCompany) GETN_READ_ONLY_EX(2) GETN_STR(SeriNum, "Serial Number", szSerial) GETN_READ_ONLY_EX(2) GETN_STR(RegCode, "Register Code", szRegCode) GETN_READ_ONLY_EX(2) GETN_STR(Product, "Product Version", strProduct) GETN_READ_ONLY_EX(2) return TRUE; } //controls to collect user information and settings. BOOL MySplitter::initUserInfo(TreeNode& trUser) { if ( !trUser ) return FALSE; GETN_USE(trUser) GETN_STRLIST(Language, "Language", "English", "|English|German") GETN_STR(UserID, "User ID", "") GETN_PASSWORD(Password, "Password", "") GETN_STR(Email, "Email", "user@originlab.com") return TRUE; }
The splitter dialog contains a splitter control object, so the dialog can initialize the splitter control and post messages to it on the proper events.
//dialog name, which will also be used to save settings in registry #define STR_DLG_NAME "My Splitter Dialog" class MySplitterDlg : public MultiPaneDlg { public: //resource ID and which DLL contains this dialog resource MySplitterDlg() : MultiPaneDlg(IDD_SAMPLE_SPLITTER_DLG, "ODlg8") { } ~MySplitterDlg() { } //open dialog until user close it. int DoModalEx(HWND hParent = NULL) { //set up message map InitMsgMap(); return DoModal(hParent, DLG_NO_DEFAULT_REPOSITION); } //init controls and other settings before dialog open BOOL OnInitDialog(); //when dialog initialization finish BOOL OnReady(); //when user click 'Output' button BOOL OnOutput(Control ctrl); protected: DECLARE_MESSAGE_MAP private: MySplitter m_Splitter; }; //map dialog message BEGIN_MESSAGE_MAP(MySplitterDlg) ON_INIT(OnInitDialog) ON_READY(OnReady) ON_BN_CLICKED(IDC_LOAD, OnOutput) END_MESSAGE_MAP BOOL MySplitterDlg::OnInitDialog() { //rename buttons title to meaningful text GetDlgItem(IDC_LOAD).Text = "Output"; GetDlgItem(IDCANCEL).Text = "Close"; m_Splitter.Init(IDC_FB_BOX, *this, STR_DLG_NAME); return TRUE; } BOOL MySplitterDlg::OnReady() { //update dialog UpdateDlgShow(); SetInitReady(); //set splittercontrol ready as to init the position and size m_Splitter.OnReady(); return TRUE; } BOOL MySplitterDlg::OnOutput(Control ctrl) { //dump current user settings. m_Splitter.Output(); return TRUE; }
After the steps above, save all the code and build it, then execute the following function to open the splitter dialog.
void test_MySplitterDlg() { MySplitterDlg dlg; dlg.DoModalEx(GetWindow()); }