(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插件中自動生成。

本文版權所有,如轉發和引用請注明。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM