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());
}
|