一个框架基础的东西,一般也是操作的最基础的类,比如char、int、bool等,有时出现内存泄露的问题导致错误的抛出,但是C++开发有的时候就算是抛出异常,那也是靠经验来积累才能非常快速准确的找出错误所在,这就需要在框架中需要添加日志管理的接口,日志管理的好处就是开发者自身在找异常时提供参考,另一个就是如果用户操作时出现问题,也可将日志反馈,帮助快速解决问题;总之了为了更好的扩展完善我的框架,我详细列一下这个基础服务库(XPCore)包含内容:
- 虽说sharpui控件库内封闭好string类,但是不够满足需求,我就新定义了xstring类,这个字条串类中,涉及常用的所有操作,比如:查找、去空、大小写转换、取指定的字符串、连接、操作符运算、编码转换、与其他基础类间的转换、删除、替换等等;头文件如下:
1 //xstring 常用编码格式
2 enum XPCORE_API XEncodings
3 {
4 //默认编码
5 encoding_gb2312=0,
6 //wchar_t
7 encoding_wchart=1,
8 //Unicode
9 encoding_unicode=2,
10 //Unicode 的一种表达形式
11 encoding_utf8=3
12
13 };
14
15 //自定义字符串类 xstring的最大长度
16 #define _xstring_max_Length_ 4096
17 //自定义字符串类 默认编码为GB2312,支持与Unicode wchar_t Utf-8转换
18 class XPCORE_API xstring:implements XPCore::Object
19 {
20 public:
21 xstring();
22 xstring(const char* value);
23 xstring(const wchar_t* value);
24 xstring(const xstring &other);
25 ~xstring();
26
27 const char* c_str() const;
28 char* c_str();
29
30 const wchar_t* w_str() const;
31 wchar_t* w_str();
32
33 int Lendth() const;
34 bool Empty() const;
35
36 XEncodings Encoding() const;
37 void SetEncoding(int encoding);
38
39 bool StartsWith(const xstring& value) const;
40 bool EndsWith(const xstring& value) const;
41 bool Contains(const xstring& value,int &startIndex) const;
42 bool StartsWith(const char value) const;
43 bool EndsWith(const char value) const;
44 bool Contains(const char value,int &startIndex) const;
45 bool Equals(const xstring& value) const;
46
47 static xstring FromInt(int value);
48 static xstring FromFloat(float value,int numofDigits=10);
49 static xstring FromBool(bool value);
50
51 int ToInt() const;
52 float ToFloat() const;
53 bool ToBool() const;
54
55 int IndexOf(char value, int startIndex) const;
56 int IndexOf(const xstring& value) const;
57 int IndexOf(const xstring& value, int startIndex) const;
58 int IndexOf(char value, int startIndex, int count) const;
59 int IndexOf(const xstring& value, int startIndex, int count) const;
60
61 bool Remove(int startIndex);
62 bool Remove(int startIndex, int count);
63 bool Replace(char oldChar, char newChar);
64 bool Replace(const xstring& oldValue, const xstring& newValue);
65
66 xstring Insert(int startIndex, const xstring& insertValue);
67
68 xstring Substring(int startIndex) const;
69 xstring Substring(int startIndex, int length) const;
70 xstring Substring(int startIndex,int count, char sz) const;
71
72 xstring ToLower();
73 xstring ToString();
74 xstring ToUpper();
75 xstring Trim();
76 xstring TrimLeft();
77 xstring TrimRight();
78
79 bool IsDigital() const;
80 bool IsBool() const;
81 bool IsCharacter() const;
82
83 void Clear();
84
85 char& operator[](int index);
86 const char& operator[](int index) const;
87
88 xstring operator=(const xstring &other);
89 xstring operator=(const char* val);
90 xstring operator=(const wchar_t* val);
91 xstring operator+(const xstring &other);
92 void operator+=(const xstring &other);
93 bool operator==(const xstring &other);
94 bool operator>(const xstring &other);
95 bool operator<(const xstring &other);
96 /////////////////////////////////////////////////
97
98 static xstring FromUtf8(const xstring &other);
99 static xstring FromUnicode(const xstring &other);
100 static xstring FromGB2312(const xstring &other);
101
102 xstring ToUtf8();
103 xstring ToUnicode();
104 xstring ToGB2312();
105 protected:
106 char* _ptr;
107 int _encoding;
108 };
View Code
- 内嵌了编码转换跨平台开源代码(Iconv,详细大家可以网上找对应资源),引用头文件“iconv.h”,定义共有方法:int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen),实现编码间转换,Iconv在转码方面还是很强大的,首先跨平台这优势就不言而喻了,其次方法简单,就只需要刚才定义的方法就可以如:xstring中定义的ToUtf8方法
xstring xstring::ToUtf8()
{
char* _out=new char[_xstring_max_Length_];
code_convert("GB2312","UTF-8",_ptr,strlen(_ptr),_out,_xstring_max_Length_);
xstring _temStr=_out;
_temStr.SetEncoding(XEncodings::encoding_utf8);
return _temStr;
}
View Code
- 常用的宏,如类似接口的定义、释放内存等等
//********************************************
// Interface.h
//主要是宏定义一些关键词,可以形成接口类
//********************************************
#ifndef _XPCOREINTERFACE_H
#define _XPCOREINTERFACE_H
#define _Interface_ class
//继承接口
#define implements public
//声明接口起始
#define DeclareInterface(name) _Interface_ name { \
public: \
virtual ~name() {}; \
//声明带基类接口起始
#define DeclareBasedInterface(name, base) _Interface_ name : \
public base{ \
public: \
virtual ~name() {}; \
//#ifdef FRAMEWORKCORE_EXPORTS
//声明带输出接口起始
#define DeclareAPIInterface(name) \
_Interface_ name { \
public: \
virtual ~name() {}; \
//声明带基类带输出接口起始
#define DeclareBasedAPIInterface(name, base) _Interface_ name : \
public base { \
public: \
virtual ~name() {}; \
//声明带基类带输出接口起始
#define DeclareBasedAPIInterface2(name, base1,base2) _Interface_ name : \
public base1,public base2 { \
public: \
virtual ~name() {}; \
//声明带基类带输出接口起始
#define DeclareBasedAPIInterface3(name, base1,base2,base3) _Interface_ name : \
public base1,public base2 ,public base3{ \
public: \
virtual ~name() {}; \
//声明接口结束
#define EndInterface };
View Code
- 另外为了能唯一标识某些类或标识添加的一个按钮,这就需要GUID;但是为了能灵活用GUID,这里也定义了下GUIDHelper
class XPCORE_API GuidHelper
{
public:
static const GUID NewGUID();
static const char* GUIDToChar(const GUID &guid);
static bool CharToGUID(const char* str,GUID &guid);
};
//新建GUID
#define _NEW_GUID_ GuidHelper::NewGUID()
//源
const GUID GuidHelper::NewGUID()
{
GUID guid;
#ifdef WIN32
CoCreateGuid(&guid);
#else
uuid_generate(reinterpret_cast<unsigned char *>(&guid));
#endif
return guid;
}
const char* GuidHelper::GUIDToChar(const GUID &guid)
{
char buf[128] = {0};
#ifdef __GNUC__
snprintf(
#else // MSVC
_snprintf_s(
#endif
buf,
sizeof(buf),
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1],
guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5],
guid.Data4[6], guid.Data4[7]);
return buf;
}
bool GuidHelper::CharToGUID(const char* str,GUID &guid)
{
memset(&guid, 0, sizeof(GUID));
int nRet=sscanf_s(
str,
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
&(guid.Data1),
&(guid.Data2),
&(guid.Data3),
&(guid.Data4[0]),
&(guid.Data4[1]),
&(guid.Data4[2]),
&(guid.Data4[3]),
&(guid.Data4[4]),
&(guid.Data4[5]),
&(guid.Data4[6]),
&(guid.Data4[7])
);
return (nRet == 11)? true : false ;
}
View Code
- 因为是插件式管理框架,所以需要定义每个插件对应的配置,这里选择用LUA角本语言来定义插件配置,因此,在这个库里也内嵌了LUA的源代码,不过只用到了一种方法就是将定义好的C++类绑定到Lua角本编译器的虚拟机中,实现对配置信息的读入和加载
//单个插件 struct
typedef struct tagPluginInfo
{
char name[MAX_PATH];
char url[MAX_PATH];
char description[MAX_PATH];
char author[MAX_PATH];
bool isHiddenInManager;
bool isLoadAutoStart;
bool isUnload;
}_pluginInfo,*P_pluginInfo;
//单个插件
class XPCORE_API plugin:implements XPCore::Object
{
public:
plugin();
plugin(plugin &other);
plugin(_pluginInfo &other);
~plugin();
public://插件描述信息
char* GetName();
void SetName(const char* val);
char* GetAuthor();
void SetAuthor(const char* val);
char* GetURL();
void SetURL(const char* val);
char* GetDescription();
void SetDescription(const char* des);
bool IsHiddenInManager();
void SetIsHiddenInManager(bool val);
bool IsLoadAutoStart();
void SetIsLoadAutoStart(bool val);
bool IsUnload();
void SetIsUnload(bool val);
protected:
char name[MAX_PATH];
char url[MAX_PATH];
char description[MAX_PATH];
char author[MAX_PATH];
bool isHiddenInManager;
bool isLoadAutoStart;
bool isUnload;
public:
VectorArray<pluginItem> Items;
};
//Lua角本中编写
local pin=plugin.create() --初始化插件
plugin.setName(pin,"Base")--设置插件名
plugin.setAuthor(pin,"Xp.W")--设置插件作者
plugin.setUrl(pin,"http://www.ruitesen.com")--设置插件网址
plugin.setDescription(pin,"基础插件,构建了基本的菜单项和工具条,该插件不可卸载。")--设置插件描述
plugin.setIsHiddenInManager(pin,false)--设置插件是否插件管理中隐藏
plugin.setIsLoadAutoStart(pin,true)--设置插件是否有自启动项
--插件中的控件集合,注意这里的集合名必须与c项目中一致
--集合中的每一项的索引标识固定,且顺序固定,更改会导致异常
--plugin.addItem(pin,"index@parentIndex@name@type@size@label@shortcut@tooltip@icon@functionName@conditioName")
--添加一级菜单 类型有:Menu MenuCommand CheckMenuCommand MenuSeparator
plugin.addItem(pin,"0@-1@base_File@Menu@size@base_File@shortcut@base_File@icon@functionName@conditioName")
plugin.addItem(pin,"1@-1@base_Edit@Menu@size@base_Edit@shortcut@base_Edit@icon@functionName@conditioName")
plugin.addItem(pin,"2@-1@base_View@Menu@size@base_View@shortcut@base_View@icon@functionName@conditioName")
plugin.addItem(pin,"3@-1@base_Option@Menu@size@base_Option@shortcut@base_Option@icon@functionName@conditioName")
plugin.addItem(pin,"4@-1@base_Tool@Menu@size@base_Tool@shortcut@base_Tool@icon@functionName@conditioName")
plugin.addItem(pin,"5@-1@base_Plugin@Menu@size@base_Plugin@shortcut@base_Plugin@icon@functionName@conditioName")
plugin.addItem(pin,"6@-1@base_Help@Menu@size@base_Help@shortcut@base_Help@icon@functionName@conditioName")
--添加二级菜单
plugin.addItem(pin,"0@0@base_File_OpenRMP@MenuCommand@size@base_File_OpenRMP@shortcut@base_File_OpenRMP@Icon_Base_Map_Open@OpenRmpProjectCommand@MapOpenedConditionEvaluator")
plugin.addItem(pin,"1@0@MenuSeparator_File1@MenuSeparator@size@MenuSeparator_File1@shortcut@tooltip@icon@functionName@conditioName")
plugin.addItem(pin,"2@0@base_File_Exit@MenuCommand@size@base_File_Exit@shortcut@base_File_Exit@icon@ExitCommand@conditioName")
plugin.addItem(pin,"0@5@base_Plugin_Manager@MenuCommand@size@base_Plugin_Manager@shortcut@base_Plugin_Manager@icon@ShowPluginManagerCommand@conditioName")
plugin.addItem(pin,"0@6@base_Plugin_Progress@MenuCommand@size@base_Plugin_Progress@shortcut@base_Plugin_Progress@icon@ShowProgressWindowCommand@conditioName")
--添加默认工具条
plugin.addItem(pin,"0@-1@base_Toolbar_Default@Toolbar@size@base_Toolbar_Default@shortcut@base_Toolbar_Default@icon@functionName@conditioName")
--添加工具条按钮 类型有:Button ToggleButton SplitButton DropdownButton RadioButton CheckBox ComboBox TextBox TextBlock ToolbarSeparator
plugin.addItem(pin,"0@0@base_Toolbar_Default_FullExtent@Button@Large@base_Toolbar_Default_FullExtent@shortcut@base_Toolbar_Default_FullExtent@Icon_Base_MapFullExtent@MapFullExtentCommand@MapOpenedConditionEvaluator")
plugin.addItem(pin,"1@0@base_Toolbar_Default_PanMap@ToggleButton@Large@base_Toolbar_Default_PanMap@shortcut@base_Toolbar_Default_PanMap@Icon_Base_Map_Pan@MapPanMapCommand@MapOpenedConditionEvaluator")
plugin.addItem(pin,"2@0@name@ToolbarSeparator@size@label@shortcut@tooltip@icon@functionName@conditioName")
plugin.addItem(pin,"3@0@name@ComboBox@size@label@shortcut@tooltip@icon@functionName@conditioName")
plugin.load(pin)--导入到插件管理
View Code
- 同样的插件式管理框架也需要对dll的动态加载和函数获取
// dll库管理类
class XPCORE_API DLLManager
{
public:
DLLManager();
virtual ~DLLManager(void){FreeALLDll();}
//注册Dll库
bool AddDll(char* dllFileName);
//是否包含对应GUID的Dl库
bool ContainsDll(char* dllFileName);
//是否包含对应GUID的Dl库,并返回对应索引
bool ContainsDll(char* dllFileName,int &index);
//反注册Dll库,释放对应内存
bool FreeDll(char* dllFileName);
//获取对应GUID的dll模块
HMODULE &GetMoudle(char* dllFileName);
HMODULE &GetMoudle(const int index);
//反注册所有Dll库,释放对应内存
void FreeALLDll();
protected:
VectorDic<char*,HMODULE> _modeules;
};
//DllMAnager 源
DLLManager::DLLManager()
{
}
bool DLLManager::AddDll(char* dllFileName)
{
HMODULE hModule;
if(!ContainsDll(dllFileName))
{
#ifdef UNICODE
wchar_t fileName[MAX_PATH];
wchar_t* _fileName=fileName;
CharToUnicode(dllFileName,_fileName);
hModule=::LoadLibrary(_fileName);
#else
char _fileName[MAX_PATH];
strcpy(_fileName,dllFileName);
hModule=::LoadLibrary(_fileName);
#endif
_modeules.Add(dllFileName,hModule);
return true;
}
return false;
}
bool DLLManager::ContainsDll(char* dllFileName)
{
return _modeules.ContainsKey(dllFileName);
}
bool DLLManager::ContainsDll(char* dllFileName,int &index)
{
return _modeules.ContainsKey(dllFileName,index);
}
bool DLLManager::FreeDll(char* dllFileName)
{
int index=0;
if(_modeules.ContainsKey(dllFileName,index))
{
::FreeLibrary(_modeules.GetValue(index));
_modeules.RemoveAt(index);
return true;
}
return false;
}
HMODULE &DLLManager::GetMoudle(char* dllFileName)
{
int index=0;
if(_modeules.ContainsKey(dllFileName,index))
{
return _modeules.GetValue(index);
}
HMODULE _nullModule;
return _nullModule;
}
HMODULE &DLLManager::GetMoudle(const int index)
{
if(_modeules.Count()>index && index>-1)
{
return _modeules.GetValue(index);
}
HMODULE _nullModule;
return _nullModule;
}
void DLLManager::FreeALLDll()
{
for(int i=0;i<_modeules.Count();i++)
{
::FreeLibrary(_modeules.GetValue(i));
}
_modeules.Clear();
}
//函数获取类 模板定义
//从指定的DLL模块中实例化对应对象的指针
template<typename T>
T *GetPtrFromMoudle(HMODULE &moudle,const char *moudleName)
{
return (T*)::GetProcAddress(moudle,moudleName);
}
template<typename T>
T GetObjFromMoudle(HMODULE &moudle,const char *moudleName)
{
return (T)::GetProcAddress(moudle,moudleName);
}
View Code
- 资源的管理
class XPCORE_API ResourceService
{
public:
//获取字符资源从资源字典(返回的为字符串的转换名或Imge的全路径)
static char *ParseStringFormDic(char *val);
//获取命令从资源字典
static XPCore::ICommand* ParseCommandFromDic(char *val);
//获取条件命令从资源字典
static XPCore::IConditionEvaluator* ParseConditionEvaluatorFromDic(char *val);
};
View Code
- 基本命令接口,用于绑定到控件触发事件中
namespace XPCore
{
/// <summary>
/// A basic command interface. A command has simply an owner which "runs" the command
/// and a Run method which invokes the command.
/// </summary>
DeclareBasedAPIInterface(ICommand,XPCore::Object)
virtual bool IsEnabled()=0;
virtual void SetIsEabled(bool val){};
virtual XPCore::Object* Owner()=0;
virtual void SetOwner(XPCore::Object *val){};
virtual void OnOwnerChanged(){};
virtual void Run(){};
EndInterface
/// <summary>
/// A basic checked command interface. A command has simply an owner which "runs" the command
/// and a Run method which invokes the command.
/// </summary>
DeclareBasedAPIInterface(ICheckedCommand,XPCore::ICommand)
virtual bool IsChecked()=0;
virtual void SetIsChecked(bool val){};
EndInterface
}
View Code
- 基本条件命令接口,用于返回需要对控件状态刷新的条件操作动作
//条件执行动作
enum XPCORE_API ConditionAction
{
//非激活
disable_action,
//隐藏
hide_action,
//无
null_action
};
namespace XPCore
{
/// <summary>
/// ConditionEvaluator
/// </summary>
DeclareBasedAPIInterface(IConditionEvaluator,XPCore::Object)
//返回值 为枚举型的整数值
virtual int ConditionEvaluator()=0;
EndInterface
}
View Code
以上基本就是基础服务库中的全部内容,当然由于篇幅原因,并没有将全部代码贴出来;
写到这,相信应该明白为什么要写这个库了,这是这个插件式框架的基石,有了它我就可以扩展了:这个插件式框架的主要思想就是:框架的开发与插件的开发要完全独立,插件间也要完全独立,框架要能实现动态加载插件中定义的方法和界面的对应的资源加载,所以用LUA角本定义配置信息,插件Dll开放指定两个方法:AutoStart(加载命令和条件绑定资源)和LoadStringResource(加载字符和图标资源)两个方法就可以,具体调用可以上面提到的DLLManager,来调用定两个方法,实现资源加载,动态生成控件和根据绑定条件刷新状态,所有的绑定都是通过字符串来实现。
最后赋上运行图片(主界面和插件管理界面),下一篇将写一下如何基于SharpUI编写一个自己要想的控件(以插件管理器中的导航面版 |
请发表评论