(C/C++)基于SharpUI控件库的插件式框架开发--第三篇框架基础服务库

  一个框架基础的东西,一般也是操作的最基础的类,比如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编写一个自己要想的控件(以插件管理器中的导航面版为例):

(C/C++)基于SharpUI控件库的插件式框架开发--第三篇框架基础服务库_第1张图片

 界面中所有菜单和工具按钮全是通过Base插件中自动生成。

本文版权所有,如转发和引用请注明。

你可能感兴趣的:((C/C++)基于SharpUI控件库的插件式框架开发--第三篇框架基础服务库)