自发布《多文档界面(MDI)系统框架-C#完整版》后又有了新想法,就是再写个C#版C/S结构系统框架。
因时间关系断断续续写了很久。借周日机会,我将源代码整理好再写些说明文档发布出来,希望给大家
带来学习机会。
特别声明的是: C/S结构系统框架是优化和改编自几个大型系统,是经历过考验和实际应用的。希望大家好好珍惜。这个框架有很多学习要点,提醒大家不仅仅是下载代码而应该去好好研究,甚至阅读每一行代码每一个模块每一个细节! 你学会了它也许将来作为一个优秀架构师需要设计同样一个系统时,这时你用上它,不是事半功倍么?
另外,请尊重作者版权,写一个框架的确需要大量时间和精力。程序员有个共性是写作永无止境,虽是深夜2点,但我们仍在思考,仍在写作! 眼睛睡觉了但思维和创作动力仍在冗奋中,作为一个程序员的你,我说的对吗?有同样的感受吗? 所以:转载时请注明本文来自易学网www.vjsdn.net!
言归正传,接下来讲解系统框架实现过程。
首先看几个图对框架有个初步认识。
1.登陆窗体
准备登录窗体
如通过验证用户,则加载MDI主窗体,留意图片内的动态消息:
正在初始化用户界面,请稍候.
登录窗体是多数应用程序的入口,在进入系统前需要用户验证。请看实现过程:
2.MDI主窗体
登录成功后显示MDI主窗体.
图片为测试模块II的主界面.
登录成功后显示MDI主窗体.
图片为系统管理模块的主界面.
3.关于程序/作者
4.解决方案
用代码实现登录到加载MDI主窗体.
1.程序入口代码:
代码
static
class
Program
{
[STAThread]
static
void
Main()
{
//
捕获系统所产生的异常。
Application.ThreadException
+=
new
ThreadExceptionEventHandler(Application_ThreadException);
SystemConfig.ReadSettings();
//
读取系统设置
bllService.SetDataBasePath();
//
因用到Access,指定一个MDB文件
Process instance
=
SingletonProgram.GetRunningInstance();
if
(instance
!=
null
) Msg.Warning(
"
程序已经运行.
"
);
if
((instance
!=
null
)
&&
(
!
SystemConfig.CurrentConfig.AllowRunMultiInstance))
{
SingletonProgram.HandleRunningInstance(instance);
//
Active instance
return
;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(
false
);
//
注意:先打开登陆窗体,如登陆成功后再正式运行程序(MDI 主窗体)
//
学会这种写法。
if
(AppEntry.Login())
Application.Run(AppEntry.MainForm);
else
Application.Exit();
}
private
static
void
Application_ThreadException(
object
sender, ThreadExceptionEventArgs e)
{
Msg.ShowException(e.Exception);
}
}
转载请注明来自易学网 www.vjsdn.net 易学原创作品
留意这段代码:
if
(AppEntry.Login())
Application.Run(AppEntry.MainForm);
else
Application.Exit();
调用AppEntry类表态方法Login(),如登录成功,此时已经创建MainForm实例,则运行主窗体.
AppEntry类是个公共类,仅定义登录方法及MDI主窗体变量.
在登录窗体内用到该类.用户登录成功则创建frmMain实例.然后调用Application.Run(AppEntry.MainForm)方法.
2.AppEntry类,应用程序入口类.
代码
public
class
AppEntry
{
public
static
bool
Login()
{
return
frmLogin.TryLogin();
}
private
static
frmMain _mainForm
=
null
;
public
static
frmMain MainForm {
get
{
return
_mainForm; }
set
{ _mainForm
=
value; } }
}
3.登录窗体源代码:
代码
public
partial
class
frmLogin : Form
{
//
将构造器设为静态,防止外部创建实例
private
frmLogin()
{
InitializeComponent();
}
///
///
打开登陆窗体,公开一个主静态方法
///
///
public
static
bool
TryLogin()
{
frmLogin form
=
new
frmLogin();
bool
ret
=
form.ShowDialog()
==
DialogResult.OK;
return
ret;
}
private
void
btnLogin_Click(
object
sender, EventArgs e)
{
//
调用业务层登录方法
bool
ret
=
new
bllUser().Login(txtUser.Text, txtPwd.Text);
if
(ret)
{
//
登录成功创建主窗体
AppEntry.MainForm
=
new
frmMain();
//
初始化主窗体(如加载模块,初始化用户界,加载系统参数)
//
在初始化同时login窗体会动态显示信息。
AppEntry.MainForm.InitUserInterface(
new
StatusLable(
this
.lblLoadingInfo));
this
.DialogResult
=
DialogResult.OK;
this
.Close();
//
关闭登陆窗体
}
else
{
Msg.Warning(
"
登录失败,请检查用户名和密码!
"
);
}
}
private
void
btnCancel_Click(
object
sender, EventArgs e)
{
this
.Close();
}
}
转载请注明来自易学网 http:
//
www.vjsdn.net/ 易学原创作品
这里需要调用业务层执行用户登录. 要学会将业务代码与界面代码分离.
//
调用业务层登录方法
bool
ret
=
new
bllUser().Login(txtUser.Text, txtPwd.Text);
if
(ret)
{
.........
当登录成功,创建MDI主窗体实例,然后调用实例方法InitUserInterface.这时初始化主窗体.
//
初始化主窗体(如加载模块,初始化用户界,加载系统参数)
//
在初始化同时login窗体会动态显示信息。
AppEntry.MainForm.InitUserInterface(
new
StatusLable(
this
.lblLoadingInfo));
4.下面是MDI主窗体的代码:
代码
public
partial
class
frmMain : Form
{
//
模块管理器实例
private
ModuleManager _ModuleManager;
public
frmMain()
{
InitializeComponent();
}
//
初始化用户接口
public
void
InitUserInterface(StatusLable splash)
{
this
.SuspendLayout();
splash.UpdateMessage(
"
正在初始化用户界面,请稍候...
"
);
_ModuleManager
=
new
ModuleManager(
this
, xtraTabControl1);
//
创建模块管理器
_ModuleManager.LoadModules(splash);
//
加载可用模块
splash.UpdateMessage(
"
正在加载工具栏...
"
);
_ModuleManager.CreateNavBarButtons(
this
.navBarControl1,
this
.menuStrip1);
//
创建导航工具栏按钮
splash.UpdateMessage(
"
正在加载用户模块...
"
);
splash.UpdateMessage(
"
正在初始化数据...
"
);
splash.UpdateMessage(
"
加载完毕.
"
);
this
.ResumeLayout();
}
///
///
显示由参数指定的模块
///
public
void
ActiveModule(
string
moduleDisplayName)
{
foreach
(XtraTabPage page
in
this
.xtraTabControl1.TabPages)
{
if
(page.Text.Equals(moduleDisplayName))
{
xtraTabControl1.SelectedTabPage
=
page;
return
;
}
}
}
private
void
btnHelp_Click(
object
sender, EventArgs e)
{
new
frmAboutVjsdn().ShowDialog();
}
private
void
btnClose_Click(
object
sender, EventArgs e)
{
this
.Close();
}
private
void
btnAbout_Click(
object
sender, EventArgs e)
{
new
frmAboutVjsdn().ShowDialog();
}
}
转载请注明来自易学网 http:
//
www.vjsdn.net/ 易学原创作品
窗体类定义一个_ModuleManager变量,用于加载模块.请看ModuleManager详解.
InitUserInterface()方法是初始化主窗体方法.由frmLogin调用.
转载请注明来自易学网 http://www.vjsdn.net/ 易学原创作品
C# C/S结构数据库系统框架详解(二) ModuleManager详解[vjsdn]
一个大的应用程序由大量模块构成, 因人而异模块的理解和分类各有不同. 在C/S框架内我将模块(Module)定义为一个DLL程序(Class Library). 而每个DLL程序按业务分类. 如进销存系统我们可定义3个模块:采购模块(Purchase Module),销售模块(Sales Module)和库存模块(Inventory Module).而每个模块的业务代码封装在
DLL Class Library内. 则构成3个独立的DLL和一个可执行EXE文件. 如要细分还有公共模块(Common Module), 数据访问层(Data Access Layer Module),系统安全(System Security Module)和系统设置模块(System Setups Module)等模块. 这样就构成一个简单的多模块系统框架了.
C/S框架内定义了8个模块(DLL)和一个主程序(EXE).
从设计角度上讲模块也要分类,可分为系统模块和业务模块.
系统模块是框架组成部分,如Business.dll,Common.dll,DataAccess.dll,Library.dll,Models.dll.
业务模块封装核心业务,包括业务窗体,图片资源等信息. 如上所述的进销存系统:进,销,存3个模块为业务模块.
我们对模块有了初步认识. 由此可见一个系统是由很多模块构成的,而系统越大分的模块越多,模块越多程序越复杂和难以控制.当然安全问题也应运而生了.
假设A用户仅能使用采购模块(Purchase Module),另两个模块不可见, 在设计上我们可以这么做:
1.设计权限,隐藏其它两个模块.
2.在客户机仅发布exe和purchase.dll
3.其它设计.
假设不按业务独立模块,我想设计权限来隐藏其它两个模块是件复杂而危险的事. 可想而知你需要在每个窗体每个业务类都要判断A用户是否有Sales和Inventory的权限,成百上千种判断会使你疯狂!
但是只给客户机安装一个purchase.dll,即使在设计上不判断权限也用不着Sales和Inventory任何功能!
假设我们选择第2种方法, 因客户不同发布的dll也不同,这里牵涉到动态加载dll的问题!本文的重点就是介绍如何动态加载模块.下面且看相关源代码:
ModuleID类:模块编号,给每个模块一个唯一编号.
///
///
模块编号,给每个模块一个唯一编号.
///
public
enum
ModuleID
{
None
=
0
,
TestModule1
=
1
,
//
测试模块1
TestModule2
=
2
,
//
测试模块2
SystemManage
=
3
,
//
系统管理模块
}
模块信息类:实体类,封装与模块相关信息.
代码
///
///
模块信息类
///
public
class
ModuleInfo
{
private
Assembly _ModuleAssembly
=
null
;
private
ModuleID _ModuleID
=
ModuleID.None;
private
string
_ModuleName
=
string
.Empty;
private
string
_ModuleFile
=
string
.Empty;
///
///
构造器
///
public
ModuleInfo(Assembly asm, ModuleID id,
string
name,
string
file)
{
_ModuleAssembly
=
asm;
_ModuleFile
=
file;
_ModuleID
=
id;
_ModuleName
=
name;
}
///
///
加载DLL文件后程序集指针
///
public
Assembly ModuleAssembly
{
get
{
return
_ModuleAssembly; }
set
{ _ModuleAssembly
=
value; }
}
///
///
模块文件(*.dll)
///
public
string
ModuleFile
{
get
{
return
_ModuleFile; }
set
{ _ModuleFile
=
value; }
}
///
///
模块名称
///
public
string
ModuleName
{
get
{
return
_ModuleName; }
set
{ _ModuleName
=
value; }
}
///
///
模块编号
///
public
ModuleID ModuleID
{
get
{
return
_ModuleID; }
set
{ _ModuleID
=
value; }
}
}
转载请注明来自易学网 www.vjsdn.net 易学原创作品
ModuleLoader:模块加载器. 通过ModuleLoader类动态加载模块dll, 将程序集Assembly保存在
_ModuleAssembly变量.
代码
///
///
模块加载器
///
public
class
ModuleLoader
{
private
string
_ModuleFileName;
//
DLL 文件名
private
frmModuleBase _ModuleMainForm;
//
如果加載了模塊. 返回該模塊的主窗體對象.
private
Assembly _ModuleAssembly;
public
static
readonly
string
MODULE_FILTER
=
"
易学网C/S系统框架模块|VJSDN C/S Modules|*.dll
"
;
public
static
readonly
string
MODULE_PATH
=
Application.StartupPath;
public
ModuleLoader()
{
//
}
///
///
模块所在的程序集
///
public
Assembly ModuleAssembly
{
get
{
return
_ModuleAssembly; }
}
///
///
返回AssemblyModuleEntry,自定义模块特性
///
public
string
GetCurrentModuleName()
{
return
ModuleLoader.GetModuleEntry(_ModuleAssembly).ModuleName;
}
///
///
模块主窗体
///
public
frmModuleBase ModuleMainForm
{
get
{
return
_ModuleMainForm; }
}
///
///
加载模块的菜单
///
///
程序主窗体的菜单
public
void
LoadMenu(MenuStrip menuStrip)
{
if
(_ModuleMainForm
!=
null
&&
_ModuleMainForm.GetModuleMenu()
!=
null
)
{
menuStrip.Items.Insert(menuStrip.Items.Count
-
1
, _ModuleMainForm.GetModuleMenu().Items[
0
]);
}
}
///
///
加载模块主方法
///
///
模块信息
///
public
bool
LoadModule(ModuleInfo moduleinfo)
{
_ModuleFileName
=
moduleinfo.ModuleFile;
_ModuleAssembly
=
moduleinfo.ModuleAssembly;
string
entry
=
GetModuleEntryNameSpace(_ModuleAssembly);
if
(
string
.Empty
==
entry)
return
false
;
Form form
=
(Form)_ModuleAssembly.CreateInstance(entry);
_ModuleMainForm
=
null
;
if
(form
is
IModuleBase)
_ModuleMainForm
=
(frmModuleBase)form;
return
_ModuleMainForm
!=
null
;
}
///
///
获取模块列表,转换为ModuleInfo集合.
///
public
IList
<
ModuleInfo
>
GetModuleList()
{
try
{
string
[] files
=
null
;
//
模塊文件(*.dll)
IList
<
ModuleInfo
>
list
=
new
List
<
ModuleInfo
>
();
if
(Directory.Exists(MODULE_PATH))
files
=
Directory.GetFiles(MODULE_PATH,
"
*.dll
"
);
foreach
(
string
mod
in
files)
{
Assembly asm
=
null
;
try
{
//
.net framework dll
asm
=
Assembly.LoadFile(mod);
}
catch
{
continue
; }
ModuleID id
=
GetModuleID(asm);
string
name
=
GetCurrentModuleName();
if
(id
!=
ModuleID.None)
{
ModuleInfo m
=
new
ModuleInfo(asm, id, name, mod);
list.Add(m);
}
}
SortModule(list);
//
模塊排序.
return
list;
}
catch
(Exception ex)
{
Msg.ShowException(ex);
return
null
;
}
}
///
///
获取程序集自定义特性。是否用户自定义模块由AssemblyModuleEntry特性确定。
///
///
public
AssemblyModuleEntry GetModuleEntry()
{
return
ModuleLoader.GetModuleEntry(_ModuleAssembly);
}
///
///
判断加载的文件是否模块文件,因目录下可能有不同类别的DLL文件。
///
判断DLL为模块的条件是检查Assembly特性。
///
public
bool
IsModuleFile(
string
moduleFile)
{
try
{
Assembly asm
=
Assembly.LoadFile(moduleFile);
return
(ModuleLoader.GetModuleID(asm)
!=
ModuleID.None);
}
catch
{
return
false
; }
}
///
///
每一个模块对应一个XtraTabPage,然后將模块主窗体的Panel容器放置在XtraTabPage内。
///
因此,所有加载的模块主窗体的Panel容器都嵌套在主窗体的XtraTabControl内。
///
public
void
LoadGUI(XtraTabControl mainTabControl)
{
try
{
IModuleBase moduleBase
=
_ModuleMainForm
as
IModuleBase;
Panel container
=
moduleBase.GetContainer();
//
模块主窗体的Panel容器
if
(
null
!=
container)
{
container.Dock
=
DockStyle.Fill;
XtraTabPage page
=
new
XtraTabPage();
page.Text
=
this
.GetCurrentModuleName();
page.Controls.Add(container);
mainTabControl.TabPages.Add(page);
}
}
catch
(Exception ex) { Msg.ShowException(ex); }
}
///
///
模块排序
///
///
public
void
SortModule(IList
<
ModuleInfo
>
list)
{
int
i, j;
ModuleInfo temp;
bool
done
=
false
;
j
=
1
;
while
((j
<
list.Count)
&&
(
!
done))
{
done
=
true
;
for
(i
=
0
; i
<
list.Count
-
j; i
++
)
{
if
((list[i]
as
ModuleInfo).ModuleID
>
(list[i
+
1
]
as
ModuleInfo).ModuleID)
{
done
=
false
;
temp
=
list[i];
list[i]
=
list[i
+
1
];
list[i
+
1
]
=
temp;
}
}
}
}
#region
类公共表态方法
///
///
查找子菜单,深度搜索
///
public
static
ToolStripMenuItem GetMenuItem(ToolStrip mainMenu,
string
menuName)
{
ToolStripItem[] items
=
mainMenu.Items.Find(menuName,
true
);
if
(items.Length
>
0
&&
items[
0
]
is
ToolStripMenuItem)
return
(ToolStripMenuItem)items[
0
];
else
return
null
;
}
///
///
获取程序集自定义特性。是否用户自定义模块由AssemblyModuleEntry特性确定。
///
public
static
AssemblyModuleEntry GetModuleEntry(Assembly asm)
{
AssemblyModuleEntry temp
=
new
AssemblyModuleEntry(ModuleID.None,
""
,
""
);
if
(asm
==
null
)
return
temp;
object
[] list
=
asm.GetCustomAttributes(
typeof
(AssemblyModuleEntry),
false
);
if
(list.Length
>
0
)
return
(AssemblyModuleEntry)list[
0
];
else
return
temp;
}
///
///
获取模块主窗体名字空间
///
public
static
string
GetModuleEntryNameSpace(Assembly asm)
{
return
GetModuleEntry(asm).ModuleEntryNameSpace;
}
///
///
獲取模塊編號
///
public
static
ModuleID GetModuleID(Assembly asm)
{
return
ModuleLoader.GetModuleEntry(asm).ModuleID;
}
#endregion
}
转载请注明来自易学网 www.vjsdn.net 易学原创作品
模块控制类
1.管理ModuleLoader加载的模块.
2.动态创建菜单及导航条按钮.
3.将所有模块主窗体组合在XtraTabControl 控件内. 每个XtraTabPage对应一个模块.
代码
///
///
模块管理器
///
public
class
ModuleManager
{
//
程序主窗体的TabControl,用于放置模块主窗体
private
XtraTabControl _tabControlModules
=
null
;
//
程序主窗体
private
Form _MDIMainForm
=
null
;
private
static
IList
<
ModuleInfo
>
_Modules
=
null
;
///
///
获取回载的模块
///
public
static
IList
<
ModuleInfo
>
GetAvailableModules()
{
return
_Modules;
}
///
///
构造器
///
public
ModuleManager(Form mdiMainForm, XtraTabControl tabControlModules)
{
_tabControlModules
=
tabControlModules;
_MDIMainForm
=
mdiMainForm;
}
///
///
Navigator bar 导航条按鈕事件.
///
public
static
void
OnNavBarLinkClick(
object
sender, NavBarLinkEventArgs e)
{
if
(e.Link.Item.Tag
is
ToolStripItem)
{
ToolStripItem item
=
(ToolStripItem)(e.Link.Item.Tag);
if
(
null
!=
item) item.PerformClick();
//
執行菜單事件.
}
}
///
///
是否有子菜單.
///
private
bool
IsSubMenuOwner(ToolStripItem item)
{
if
(item
is
ToolStripMenuItem)
{
if
(((ToolStripMenuItem)item).DropDownItems.Count
>
0
)
return
true
;
}
return
false
;
}
///
///
由菜单创建导航条控件按钮
///
private
NavBarItem CreateNavBarItem(NavBarControl navBar, ToolStripItem item)
{
NavBarItem newItem
=
new
NavBarItem();
newItem.Caption
=
item.Text;
newItem.Tag
=
item;
//
綁定一個菜單項,newItem.Click事件會使用這個菜單項
newItem.LinkClicked
+=
new
NavBarLinkEventHandler(ModuleManager.OnNavBarLinkClick);
navBar.Items.Add(newItem);
return
newItem;
}
///
///
导航条控件按钮分组
///
private
NavBarGroup CreateNavBarGroup(NavBarControl navBar,
string
caption)
{
NavBarGroup group
=
navBar.Groups.Add();
//
增加一個Button組.
group.Caption
=
caption;
//
模塊的顯示名稱
group.LargeImageIndex
=
0
;
if
(group.Caption.Equals(
string
.Empty)) group.Caption
=
"
Unknown Name
"
;
return
group;
}
///
///
当点击导航条分组按钮时触发该事件
///
private
void
OnActiveGroupChanged(
object
sender, DevExpress.XtraNavBar.NavBarGroupEventArgs e)
{
try
{
string
moduleName
=
e.Group.Caption.ToString();
this
.ActiveModule(moduleName);
}
catch
(Exception ex) { Msg.ShowException(ex); }
}
///
///
显示指定的模块主窗体
///
public
void
ActiveModule(
string
moduleDisplayName)
{
foreach
(XtraTabPage page
in
this
._tabControlModules.TabPages)
{
if
(page.Text.Equals(moduleDisplayName))
{
_tabControlModules.SelectedTabPage
=
page;
return
;
}
}
}
///
///
创建导航条分组按钮 Navigator NavBarGroup
///
///
NavBarControl对象
///
模块主菜单
///
模块名称
public
NavBarGroup CreateNavBarButton(NavBarControl navBar, ToolStripMenuItem moduleMenu,
string
moduleDisplayName)
{
navBar.ActiveGroupChanged
+=
new
NavBarGroupEventHandler(OnActiveGroupChanged);
NavBarGroup group
=
CreateNavBarGroup(navBar, moduleDisplayName);
//
根据模块名称创建Group
if
(moduleMenu
==
null
)
return
group;
//
组没有菜单则返回,实为一个空组无子按钮.
foreach
(ToolStripItem menuItem
in
moduleMenu.DropDownItems)
{
if
(menuItem
is
ToolStripSeparator)
continue
;
if
(IsSubMenuOwner(menuItem))
continue
;
if
(menuItem.Enabled)
{
NavBarItem item
=
CreateNavBarItem(navBar, menuItem);
item.SmallImageIndex
=
1
;
//
Sub Function
group.ItemLinks.Add(item);
}
}
return
group;
}
///
///
初始化NavBar控件.绑定组NavGroup.ActiveGroupChanged事件
///
public
void
CreateNavBarButtons(NavBarControl navBar, MenuStrip mainMenu)
{
try
{
navBar.SuspendLayout();
navBar.Items.Clear();
navBar.Groups.Clear();
foreach
(XtraTabPage page
in
this
._tabControlModules.TabPages)
{
//
取主窗体对应的顶级菜单
ToolStripMenuItem moduleMenu
=
FindMenuItemByText(mainMenu, page.Text);
if
(moduleMenu
!=
null
&&
moduleMenu.Enabled)
//
创建该模块的NavBarButton.
this
.CreateNavBarButton(navBar, moduleMenu, page.Text);
}
navBar.ResumeLayout();
}
catch
(Exception ex) { Msg.ShowException(ex); }
}
private
ToolStripMenuItem FindMenuItemByText(MenuStrip mainMenu,
string
text)
{
foreach
(ToolStripMenuItem item
in
mainMenu.Items)
if
(item.Text
==
text)
return
(ToolStripMenuItem)item;
return
null
;
}
///
///
加载模块主方法
///
public
void
LoadModules(StatusLable msg)
{
try
{
ModuleLoader loader
=
new
ModuleLoader();
_Modules
=
loader.GetModuleList();
//
從目錄裝載模塊
foreach
(ModuleInfo m
in
_Modules)
//
枚舉文件名列表.
{
if
(
!
loader.LoadModule(m))
continue
;
msg.UpdateMessage(
"
正在加载:
"
+
loader.GetCurrentModuleName());
loader.LoadGUI(_tabControlModules);
loader.LoadMenu(_MDIMainForm.MainMenuStrip);
loader.ModuleMainForm.MdiParent
=
_MDIMainForm;
//
设置模块主窗体的父窗体.
}
GC.Collect();
}
catch
(Exception ex) { Msg.ShowException(ex); }
}
}
转载请注明来自易学网 www.vjsdn.net 易学原创作品
为了规范模块共有的特性,设计一个模块主窗体接口.
代码
///
///
模块主窗体接口
///
public
interface
IModuleBase
{
ModuleID GetModuleID();
//
获取模块编号
ModuleInfo GetModuleInfo();
//
Panel GetContainer();
//
模块主窗体容器
MenuStrip GetModuleMenu();
void
InitButton();
void
InitMenu();
}
转载请注明来自易学网 www.vjsdn.net 易学原创作品
定义一个模块主窗体基类来实现这个接口.
代码
///
///
模块主窗体基类
///
public
partial
class
frmModuleBase : frmBase, IModuleBase
{
public
frmModuleBase()
{
InitializeComponent();
}
#region
IModuleBase Members
//
模块的主菜单
public
virtual
MenuStrip GetModuleMenu()
{
return
null
;
}
//
模块编号
public
virtual
ModuleID GetModuleID()
{
return
ModuleID.None;
}
//
模块信息
public
virtual
ModuleInfo GetModuleInfo()
{
return
null
;
}
//
模块主窗体容器
public
virtual
Panel GetContainer()
{
return
this
.pnlContainer;
}
//
初始化按钮
public
virtual
void
InitButton()
{
}
//
初始化菜单
public
virtual
void
InitMenu()
{
}
#endregion
}
转载请注明来自易学网 www.vjsdn.net 易学原创作品