zoukankan      html  css  js  c++  java
  • (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编写一个自己要想的控件(以插件管理器中的导航面版为例):

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

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

  • 相关阅读:
    [CSP-S模拟测试]:Merchant(二分答案)
    [CSP-S模拟测试]:回文(hash+二维前缀和)
    [CSP-S模拟测试]:排列组合(数学 or 找规律)
    [CSP-S模拟测试]:X国的军队(贪心)
    BZOJ3714 [PA2014]Kuglarz 【最小生成树】
    BZOJ3922 Karin的弹幕 【线段树】
    BZOJ3495 PA2010 Riddle 【2-sat】
    BZOJ2597 [Wc2007]剪刀石头布 【费用流】
    hdu6184 Counting Stars 【三元环计数】
    BZOJ4815 [CQOI2017]小Q的表格 【数论 + 分块】
  • 原文地址:https://www.cnblogs.com/xpwang-blog/p/5060080.html
Copyright © 2011-2022 走看看