导出SOUI对象到Lua
- 为了在SOUI中使用lua,需要使用lua内核实现一个SOUI::IScriptModuler接口。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | namespace SOUI {     class SWindow; /*! \brief     Abstract interface required for all scripting support modules to be used with     the SOUI system. */ struct IScriptModule : public IObjRef {     /**      * GetScriptEngine      * @brief    获得脚本引擎的指针      * @return   void * -- 脚本引擎的指针      * Describe        */         virtual void * GetScriptEngine () = 0;     /*************************************************************************         Abstract interface     *************************************************************************/     /*!     \brief         Execute a script file.     \param pszScriptFile         String object holding the filename of the script file that is to be executed     */     virtual void    executeScriptFile(LPCSTR pszScriptFile)  = 0;     /*!     \brief         Execute a script buffer.     \param buff         buffer of the script that is to be executed     \param sz         size of buffer     */     virtual    void    executeScriptBuffer(const char* buff, size_t sz)  = 0;     /*!     \brief         Execute script code contained in the given String object.     \param str         String object holding the valid script code that should be executed.     \return         Nothing.     */     virtual void executeString(LPCSTR str) = 0;     /*!     \brief         Execute a scripted global 'event handler' function.  The function should take some kind of EventArgs like parameter         that the concrete implementation of this function can create from the passed EventArgs based object.       \param handler_name         String object holding the name of the scripted handler function.     \param EventArgs *pEvt         SWindow based object that should be passed, by any appropriate means, to the scripted function.     \return         - true if the event was handled.         - false if the event was not handled.     */     virtual    bool    executeScriptedEventHandler(LPCSTR handler_name, EventArgs *pEvt)=0;     /*!     \brief         Return identification string for the ScriptModule.  If the internal id string has not been         set by the ScriptModule creator, a generic string of "Unknown scripting module" will be returned.     \return         String object holding a string that identifies the ScriptModule in use.     */     virtual LPCSTR getIdentifierString() const = 0;     /*!     \brief             Subscribes or unsubscribe the named Event to a scripted function     \param target             The target EventSet for the subscription.     \param uEvent             Event ID to subscribe to.     \param subscriber_name             String object containing the name of the script function that is to be subscribed to the Event.     \return      */     virtual bool subscribeEvent(SWindow* target, UINT uEvent, LPCSTR subscriber_name) = 0;     /**      * unsubscribeEvent      * @brief    取消事件订阅      * @param    SWindow * target --  目标窗口      * @param    UINT uEvent --  目标事件      * @param    LPCSTR subscriber_name --  脚本函数名      * @return   bool -- true操作成功      * Describe        */         virtual bool unsubscribeEvent(SWindow* target, UINT uEvent, LPCSTR subscriber_name ) = 0; }; struct IScriptFactory : public IObjRef {     virtual HRESULT CreateScriptModule(IScriptModule ** ppScriptModule) = 0; }; } | 
- 导出SOUI对象通常应该在IScriptModule的实现类的构造中执行
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | //导出基本结构体类型 UINT rgb(int r,int g,int b) {     return RGBA(r,g,b,255); } UINT rgba(int r,int g, int b, int a) {     return RGBA(r,g,b,a); } BOOL ExpLua_Basic(lua_State *L) {     try{         lua_tinker::def(L,"RGB",rgb);         lua_tinker::def(L,"RGBA",rgba);         //POINT         lua_tinker::class_add<POINT>(L,"POINT");         lua_tinker::class_mem<POINT>(L, "x", &POINT::x);         lua_tinker::class_mem<POINT>(L, "y", &POINT::y);         //RECT         lua_tinker::class_add<RECT>(L,"RECT");         lua_tinker::class_mem<RECT>(L, "left", &RECT::left);         lua_tinker::class_mem<RECT>(L, "top", &RECT::top);         lua_tinker::class_mem<RECT>(L, "right", &RECT::right);         lua_tinker::class_mem<RECT>(L, "bottom", &RECT::bottom);         //SIZE         lua_tinker::class_add<SIZE>(L,"SIZE");         lua_tinker::class_mem<SIZE>(L, "cx", &SIZE::cx);         lua_tinker::class_mem<SIZE>(L, "cy", &SIZE::cy);         //CPoint         lua_tinker::class_add<CPoint>(L,"CPoint");         lua_tinker::class_inh<CPoint,POINT>(L);         lua_tinker::class_con<CPoint>(L,lua_tinker::constructor<CPoint,LONG,LONG>);         //CRect         lua_tinker::class_add<CRect>(L,"CRect");         lua_tinker::class_inh<CRect,RECT>(L);         lua_tinker::class_con<CRect>(L,lua_tinker::constructor<CRect,LONG,LONG,LONG,LONG>);         lua_tinker::class_def<CRect>(L,"Width",&CRect::Width);         lua_tinker::class_def<CRect>(L,"Height",&CRect::Height);         lua_tinker::class_def<CRect>(L,"Size",&CRect::Size);         lua_tinker::class_def<CRect>(L,"IsRectEmpty",&CRect::IsRectEmpty);         lua_tinker::class_def<CRect>(L,"IsRectNull",&CRect::IsRectNull);         lua_tinker::class_def<CRect>(L,"PtInRect",&CRect::PtInRect);         lua_tinker::class_def<CRect>(L,"SetRectEmpty",&CRect::SetRectEmpty);         lua_tinker::class_def<CRect>(L,"OffsetRect",(void (CRect::*)(int,int))&CRect::OffsetRect);         //CSize         lua_tinker::class_add<CSize>(L,"CSize");         lua_tinker::class_inh<CSize,SIZE>(L);         lua_tinker::class_con<CSize>(L,lua_tinker::constructor<CSize,LONG,LONG>);         return TRUE;     }catch(...)     {         return FALSE;     } } | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #include <core/swnd.h> //定义一个从SObject转换成SWindow的方法 SWindow * toSWindow(SObject * pObj) {     return sobj_cast<SWindow>(pObj); } BOOL ExpLua_Window(lua_State *L) {     try{         lua_tinker::def(L,"toSWindow",toSWindow);         lua_tinker::class_add<SWindow>(L,"SWindow");         lua_tinker::class_inh<SWindow,SObject>(L);         lua_tinker::class_con<SWindow>(L,lua_tinker::constructor<SWindow>);         lua_tinker::class_def<SWindow>(L,"GetContainer",&SWindow::GetContainer);         lua_tinker::class_def<SWindow>(L,"GetRoot",&SWindow::GetRoot);         lua_tinker::class_def<SWindow>(L,"GetTopLevelParent",&SWindow::GetTopLevelParent);         lua_tinker::class_def<SWindow>(L,"GetParent",&SWindow::GetParent);         lua_tinker::class_def<SWindow>(L,"DestroyChild",&SWindow::DestroyChild);         lua_tinker::class_def<SWindow>(L,"GetChildrenCount",&SWindow::GetChildrenCount);         lua_tinker::class_def<SWindow>(L,"FindChildByID",&SWindow::FindChildByID);         lua_tinker::class_def<SWindow>(L,"FindChildByNameA",(SWindow* (SWindow::*)(LPCSTR,int))&SWindow::FindChildByName);         lua_tinker::class_def<SWindow>(L,"FindChildByNameW",(SWindow* (SWindow::*)(LPCWSTR,int ))&SWindow::FindChildByName);          lua_tinker::class_def<SWindow>(L,"CreateChildrenFromString",(SWindow* (SWindow::*)(LPCWSTR))&SWindow::CreateChildren);         lua_tinker::class_def<SWindow>(L,"GetTextAlign",&SWindow::GetTextAlign);         lua_tinker::class_def<SWindow>(L,"GetWindowRect",(void (SWindow::*)(LPRECT))&SWindow::GetWindowRect);         lua_tinker::class_def<SWindow>(L,"GetWindowRect2",(CRect (SWindow::*)())&SWindow::GetWindowRect);         lua_tinker::class_def<SWindow>(L,"GetClientRect",(void (SWindow::*)(LPRECT))&SWindow::GetClientRect);         lua_tinker::class_def<SWindow>(L,"GetClientRect2",(CRect (SWindow::*)())&SWindow::GetClientRect);         lua_tinker::class_def<SWindow>(L,"GetWindowText",&SWindow::GetWindowText);         lua_tinker::class_def<SWindow>(L,"SetWindowText",&SWindow::SetWindowText);         lua_tinker::class_def<SWindow>(L,"SendSwndMessage",&SWindow::SSendMessage);         lua_tinker::class_def<SWindow>(L,"GetID",&SWindow::GetID);         lua_tinker::class_def<SWindow>(L,"SetID",&SWindow::SetID);         lua_tinker::class_def<SWindow>(L,"GetUserData",&SWindow::GetUserData);         lua_tinker::class_def<SWindow>(L,"SetUserData",&SWindow::SetUserData);         lua_tinker::class_def<SWindow>(L,"GetName",&SWindow::GetName);         lua_tinker::class_def<SWindow>(L,"GetSwnd",&SWindow::GetSwnd);         lua_tinker::class_def<SWindow>(L,"InsertChild",&SWindow::InsertChild);         lua_tinker::class_def<SWindow>(L,"RemoveChild",&SWindow::RemoveChild);         lua_tinker::class_def<SWindow>(L,"IsChecked",&SWindow::IsChecked);         lua_tinker::class_def<SWindow>(L,"IsDisabled",&SWindow::IsDisabled);         lua_tinker::class_def<SWindow>(L,"IsVisible",&SWindow::IsVisible);         lua_tinker::class_def<SWindow>(L,"SetVisible",&SWindow::SetVisible);         lua_tinker::class_def<SWindow>(L,"EnableWindow",&SWindow::EnableWindow);         lua_tinker::class_def<SWindow>(L,"SetCheck",&SWindow::SetCheck);         lua_tinker::class_def<SWindow>(L,"SetOwner",&SWindow::SetOwner);         lua_tinker::class_def<SWindow>(L,"GetOwner",&SWindow::GetOwner);         lua_tinker::class_def<SWindow>(L,"Invalidate",&SWindow::Invalidate);         lua_tinker::class_def<SWindow>(L,"InvalidateRect",(void (SWindow::*)(LPCRECT))&SWindow::InvalidateRect);         lua_tinker::class_def<SWindow>(L,"AnimateWindow",&SWindow::AnimateWindow);         lua_tinker::class_def<SWindow>(L,"GetScriptModule",&SWindow::GetScriptModule);         lua_tinker::class_def<SWindow>(L,"Move2",(void (SWindow::*)(int,int,int,int))&SWindow::Move);         lua_tinker::class_def<SWindow>(L,"Move",(void (SWindow::*)(LPCRECT))&SWindow::Move);         lua_tinker::class_def<SWindow>(L,"FireCommand",&SWindow::FireCommand);         lua_tinker::class_def<SWindow>(L,"GetDesiredSize",&SWindow::GetDesiredSize);         lua_tinker::class_def<SWindow>(L,"GetWindow",&SWindow::GetWindow);         return TRUE;     }catch(...)     {         return FALSE;     } } | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // 类的静态函数 BOOL ExpLua_App(lua_State *L) {     try{         lua_tinker::class_add<SApplication>(L,"SApplication");         lua_tinker::class_def<SApplication>(L,"AddResProvider",&SApplication::AddResProvider);         lua_tinker::class_def<SApplication>(L,"RemoveResProvider",&SApplication::RemoveResProvider);         lua_tinker::class_def<SApplication>(L,"Init",&SApplication::Init);         lua_tinker::class_def<SApplication>(L,"GetInstance",&SApplication::GetInstance);         lua_tinker::class_def<SApplication>(L,"CreateScriptModule",&SApplication::CreateScriptModule);         lua_tinker::class_def<SApplication>(L,"SetScriptModule",&SApplication::SetScriptFactory);         lua_tinker::class_def<SApplication>(L,"GetTranslator",&SApplication::GetTranslator);         lua_tinker::class_def<SApplication>(L,"SetTranslator",&SApplication::SetTranslator);         lua_tinker::def(L,"theApp",&SApplication::getSingletonPtr);         return TRUE;     }catch(...)     {         return FALSE;     } } | 
- 在lua中使用
| 1 2 3 4 5 | function test(arg)      local rc = CRect(0,0,100,100);      local wid = rc:Width(); --访问成员函数Width()      local x1 = rc.left;--访问基类对象RECT的成员变量left end | 
事件分发处理
- 在MFC中,一个类要处理消息,这个类通常派生自CCmdTarget,主窗口收到的消息会自动路由到这个消息处理对象中。
- 在WTL中,WTL提供了一组消息映射宏:CHAIN_MSG_MAP,CHAIN_MSG_MAP_MEMBER等以便将消息分发到同样实现了消息映射表的任意C++对象。
- SOUI的事件分发采用了WTL消息分发类似的机制,同样采用事件映射宏的方式来构造事件映射表
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | #define EVENT_MAP_BEGIN()                           \ public:                                          \     virtual BOOL _HandleEvent(SOUI::EventArgs *pEvt)\     {                                               \         UINT      uCode = pEvt->GetID();            \ #define EVENT_MAP_DECLEAR()                         \ protected:                                          \     virtual BOOL _HandleEvent(SOUI::EventArgs *pEvt);\ #define EVENT_MAP_BEGIN2(classname)                 \     BOOL classname::_HandleEvent(SOUI::EventArgs *pEvt)\     {                                               \         UINT      uCode = pEvt->GetID();            \ #define EVENT_MAP_END()                             \         return __super::_HandleEvent(pEvt);         \     }                                               \ #define EVENT_MAP_BREAK()                           \     return FALSE;                                   \     }                                               \ #define CHAIN_EVENT_MAP(ChainClass)                 \         if(ChainClass::_HandleEvent(pEvt))          \             return TRUE;                            \ #define CHAIN_EVENT_MAP_MEMBER(theChainMember)      \     {                                               \     if(theChainMember._HandleEvent(pEvt))           \         return TRUE;                                \     } #define EVENT_CHECK_SENDER_ROOT(pRoot)              \     {                                               \     if(!pRoot) return FALSE;\     SOUI::SWindow *pWnd = SOUI::sobj_cast<SOUI::SWindow>(pEvt->sender);\     if(pWnd && pRoot != pWnd && !pWnd->IsDescendant(pRoot)) \         return FALSE;                               \     } // void OnEvent(EventArgs *pEvt) #define EVENT_HANDLER(cd, func)                     \     if(cd == uCode)                                 \     {                                               \         pEvt->bubbleUp = false; func(pEvt); return !pEvt->bubbleUp; \     }  // void OnEvent(EventArgs *pEvt) #define EVENT_ID_HANDLER(id, cd, func)              \     if(cd == uCode && id == pEvt->idFrom)           \     {                                               \         pEvt->bubbleUp = false; func(pEvt); return !pEvt->bubbleUp; \     } // void OnEvent(EventArgs *pEvt) #define EVENT_ID_RANGE_HANDLER(idMin, idMax , cd, func) \     if(cd == uCode  && idMin <= pEvt->idFrom && idMax >= pEvt->idFrom )\     {                                               \         pEvt->bubbleUp = false; func(pEvt); return !pEvt->bubbleUp; \     } // void OnEvent(EventArgs *pEvt) #define EVENT_NAME_HANDLER(name, cd, func)          \     if(cd == uCode && pEvt->nameFrom!= NULL && wcscmp(pEvt->nameFrom,name)==0) \     {                                               \         pEvt->bubbleUp = false; func(pEvt); return !pEvt->bubbleUp; \     } // void OnCommand(EventArgs *pEvt) #define EVENT_COMMAND(func)                                             \     if (SOUI::EVT_CMD == uCode)                                         \     {                                                                   \         pEvt->bubbleUp = false; func(pEvt); return !pEvt->bubbleUp; \     }                                                                   \ // void OnCommand() #define EVENT_ID_COMMAND(id, func)                                      \     if (SOUI::EVT_CMD == uCode && id == pEvt->idFrom)                   \     {                                                                   \         pEvt->bubbleUp = false; func(); return !pEvt->bubbleUp;         \     }                                                                   \ // void OnCommand(int nID) #define EVENT_ID_COMMAND_RANGE(idMin, idMax, func)                               \     if (SOUI::EVT_CMD == uCode && idMin <= pEvt->idFrom && idMax >= pEvt->idFrom )  \     {                                                                            \         pEvt->bubbleUp = false; func(pEvt->idFrom); return !pEvt->bubbleUp; \     }                                                                            \ // void OnCommand() #define EVENT_NAME_COMMAND(name, func)                                      \     if (SOUI::EVT_CMD == uCode && pEvt->nameFrom!= NULL && wcscmp(pEvt->nameFrom,name)==0)  \     {                                                                       \         pEvt->bubbleUp = false; func(); return !pEvt->bubbleUp;             \     }                                                                       \ // BOOL OnContextMenu(CPoint pt) #define EVENT_ID_CONTEXTMENU(id,func)                                      \     if (SOUI::EVT_CTXMENU == uCode && pEvt->idFrom==id)                    \ {                                                                          \     pEvt->bubbleUp = false;                                                \     SOUI::EventCtxMenu* pEvtCtxMenu = (SOUI::EventCtxMenu*)pEvt;           \     pEvtCtxMenu->bCancel=func(pEvtCtxMenu->pt);                            \     return !pEvt->bubbleUp;                                                \ }                                                                          \ // BOOL OnContextMenu(CPoint pt) #define EVENT_NAME_CONTEXTMENU(name,func)                                       \     if (SOUI::EVT_CTXMENU == uCode && pEvt->nameFrom!= NULL && wcscmp(pEvt->nameFrom,name)==0) \ {                                                                               \     pEvt->bubbleUp = false;                                                     \     SOUI::EventCtxMenu* pEvtCtxMenu = (SOUI::EventCtxMenu*)pEvt;                \     pEvtCtxMenu->bCancel=func(pEvtCtxMenu->pt);                                 \     return !pEvt->bubbleUp;                                                     \ }                                                                               \ | 
- CHAIN_EVENT_MAP_MEMBER宏将来自不同页面的控件事件传递到不同的事件处理对象中
| 1 2 3 4 5 6 7 8 9 10 11 12 | //soui消息     EVENT_MAP_BEGIN()         EVENT_NAME_COMMAND(L"btn_close", OnClose)         EVENT_NAME_COMMAND(L"btn_min", OnMinimize)         EVENT_NAME_COMMAND(L"btn_max", OnMaximize)         EVENT_NAME_COMMAND(L"btn_restore", OnRestore)         CHAIN_EVENT_MAP_MEMBER(m_imgMergerHandler)         CHAIN_EVENT_MAP_MEMBER(m_codeLineCounter)         CHAIN_EVENT_MAP_MEMBER(m_2UnicodeHandler)         CHAIN_EVENT_MAP_MEMBER(m_folderScanHandler)         CHAIN_EVENT_MAP_MEMBER(m_calcMd5Handler)     EVENT_MAP_END() | 
- 如果基类中没有事件处理函数,显然这个事件映射表编译不能通过,此时SOUI提供了另一个EVENT_MAP_BREAK()来代替。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | class CImageMergerHandler : public IFileDropHandler { friend class CMainDlg; public:     CImageMergerHandler(void);     ~CImageMergerHandler(void);     void OnInit(SWindow *pRoot);     void AddFile(LPCWSTR pszFileName); protected:     virtual void OnFileDropdown(HDROP hDrop);     void OnSave();     void OnClear();     void OnModeHorz();     void OnModeVert();     EVENT_MAP_BEGIN()         EVENT_CHECK_SENDER_ROOT(m_pPageRoot)         EVENT_NAME_COMMAND(L"btn_save", OnSave)         EVENT_NAME_COMMAND(L"btn_clear", OnClear)         EVENT_NAME_COMMAND(L"radio_horz", OnModeHorz)         EVENT_NAME_COMMAND(L"radio_vert", OnModeVert)             EVENT_MAP_BREAK()     SWindow *m_pPageRoot;     SImgCanvas *m_pImgCanvas; }; | 
- 如果在不同的页面中出现相同的控件名,要怎么处理:
- 响应WM_INITDIALOG,在OnInit里面保存一个页面的根节点的指针m_pPageRoot
- 在事件映射表的开始,采用EVENT_CHECK_SENDER_ROOT(M_pPageRoot)来识别那些来自本页面的事件,对其他页面的事件不处理。
 
自定义控件
- 选择合适的基类
- 添加控件标签
| 1 2 3 4 5 6 7 | class SRadioBox2 : public SRadioBox {     SOUI_CLASS_NAME(SRadioBox2,L"radio2")         public:     SRadioBox2(void);     ~SRadioBox2(void); } | 
- 有需要,添加消息映射表,并响应目标消息
- 有需要,添加属性映射表,添加相关属性的响应
| 1 2 3 | SOUI_ATTRS_BEGIN()             ATTR_CUSTOM(L"skin", OnAttrSkin) //为控件提供一个skin属性,用来接收SSkinObj对象的name SOUI_ATTRS_END() | 
图示
模块结构图
框架结构图
声明:本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Windows 核心编程 _ 进程五06/30
- ♥ Windows机制:物理内存、虚拟内存03/28
- ♥ C++_指针引用09/19
- ♥ STL_了解05/02
- ♥ CLion:配置C++下Nasm开发环境(debian)08/06
- ♥ WTL 概述03/10
 
				


