1.18.1.4.4 Splitter DialogSplitter DialogDialog with Tree View Control
This example shows how to create a splitter dialog, which provides a better display of tree view or grid view.
Prepare Dialog Resource
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.
Prepare Source File
Source File, NewIn Code Builder, click New button , type file name, and set Location as the same path of the above dialog resource dll oDlg8.dll - Origin install path OriginC\Originlab subfolder.
Including Header Files
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>
Adding User Defined Splitter Class
Classes, User DefinedWe 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.
Message Map
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;
}
Adding User Defined Splitter Dialog Class
Dialog, Event FunctionsThe 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;
}
Open Dialog
Dialog, OpenAfter 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());
}
|