分享

DirectUI界面技术和lua脚本

 quasiceo 2014-01-03
分类: 脚本 2012-01-17 14:42 2190人阅读 评论(5) 收藏 举报

Duilib库地址

http://duilib./files/duilib%20v1.1.zip

类图结构(删除了接口):




类图2:

(1)window类可以用来host那些UI控件, CWindowWnd使用DialogBuilder放置所有的UI控件在它上面。

(2)也可以被UI控件作为部件组合,比如CEditWnd,就是被CEditUi组合。

为什么Edit控件是这样设计呢,以及acitvex控件:

“Native Win32 controls are used only for the EDIT control. This control contains so much functionalitythat it would take ages to do a decent replacement. Single-line edit controls are created on the fly (when you click on theframe) and multi-line edits are always visible. So the framework does have the ability to embed native Win32 controlsand even ActiveX controls, but at the expense of screen flickering and severe restrictions in the visual effects I'm planning.”

http://www./code/windowless1.htm



Lua官方地址, for windows.

http://luaforwindows./files/LuaForWindows_v5.1.4-45.exe


  1. // LuaUiFrame.cpp : Defines the exported functions for the DLL application.  
  2. //  
  3. #include <windows.h>  
  4. #include <objbase.h>  
  5. #include <string>  
  6.   
  7. /*dui include*/  
  8. #include <UIlib.h>  
  9. using namespace DuiLib;  
  10.   
  11. /*lua include*/  
  12. #ifdef __cplusplus  
  13. extern "C" {  
  14. #endif  
  15. #include <lua.h>  
  16. #include <lualib.h>  
  17. #include <lauxlib.h>  
  18. #ifdef __cplusplus  
  19. };  
  20. #endif  
  21.   
  22.   
  23. #define MSGBOX(title,content) MessageBoxA(GetActiveWindow(), content, title, MB_YESNOCANCEL | MB_ICONQUESTION);  
  24.   
  25.   
  26. // 声明宿主的5个函数给脚本使用  
  27. #ifdef __cplusplus  
  28. extern "C"  
  29. {  
  30. #endif  
  31.           
  32.     int FindControl(lua_State * l);  
  33.   
  34.     int SetAttr(lua_State * l);  
  35.   
  36.     int GetAttr(lua_State * l);  
  37.   
  38.     int SetCallback(lua_State * l);  
  39.   
  40.     int MsgBox(lua_State * l);  
  41.   
  42. #ifdef __cplusplus  
  43. };  
  44. #endif  
  45.   
  46. // 用这5个函数定义一个导出数组  
  47. const static struct luaL_reg LuaUiFrameExports [] = {  
  48.     {"FindControl", &FindControl},  
  49.     {"SetAttr", &SetAttr},  
  50.     {"GetAttr", &GetAttr},  
  51.     {"SetCallback", &SetCallback},  
  52.     {"MsgBox", &MsgBox},  
  53.     {NULL,NULL} //required!  
  54. };  
  55.   
  56. class CFrameWindowWnd : public CWindowWnd, public INotifyUI  
  57. {  
  58. public:  
  59.     CFrameWindowWnd(const char * xmlPath  
  60.         , const char * luaPath)   
  61.         : m_xmlPath(xmlPath)  
  62.         , m_luaPath(luaPath)  
  63.         , m_L(NULL){   
  64.         if (!m_L) m_L = lua_open();  
  65.         if (m_L)  luaL_openlibs(m_L);  
  66.     }  
  67.     ~CFrameWindowWnd(){  
  68.         if (m_L) lua_close(m_L);  
  69.     }  
  70.   
  71.     LPCTSTR GetWindowClassName() const {   
  72.         return _T("LuaUIFrame");   
  73.     };  
  74.   
  75.     UINT GetClassStyle() const {   
  76.         return CS_DBLCLKS;   
  77.     };  
  78.   
  79.     void OnFinalMessage(HWND /*hWnd*/) {   
  80.         delete this;   
  81.     };  
  82.   
  83.     void Init()   
  84.     {  
  85.         /** 
  86.         * 把这5个函数注册成lua的一个库,叫做frame 
  87.         **/  
  88.         luaL_register(m_L, "frame", LuaUiFrameExports);  
  89.         char szPath[MAX_PATH] = "";  
  90.         GetModuleFileNameA(NULL, szPath, MAX_PATH-1);  
  91.         strrchr(szPath, '\\')[1] = '\0';  
  92.         strcat_s(szPath, MAX_PATH, m_luaPath.c_str());  
  93.         luaL_dofile(m_L, szPath);  
  94.     }  
  95.   
  96.     bool OnHChanged(void* param) {  
  97.         TNotifyUI* pMsg = (TNotifyUI*)param;  
  98.         if( pMsg->sType == _T("valuechanged") ) {  
  99.             short H, S, L;  
  100.             CPaintManagerUI::GetHSL(&H, &S, &L);  
  101.             CPaintManagerUI::SetHSL(true, (static_cast<CSliderUI*>(pMsg->pSender))->GetValue(), S, L);  
  102.         }  
  103.         return true;  
  104.     }  
  105.   
  106.     bool OnSChanged(void* param) {  
  107.         TNotifyUI* pMsg = (TNotifyUI*)param;  
  108.         if( pMsg->sType == _T("valuechanged") ) {  
  109.             short H, S, L;  
  110.             CPaintManagerUI::GetHSL(&H, &S, &L);  
  111.             CPaintManagerUI::SetHSL(true, H, (static_cast<CSliderUI*>(pMsg->pSender))->GetValue(), L);  
  112.         }  
  113.         return true;  
  114.     }  
  115.   
  116.     bool OnLChanged(void* param) {  
  117.         TNotifyUI* pMsg = (TNotifyUI*)param;  
  118.         if( pMsg->sType == _T("valuechanged") ) {  
  119.             short H, S, L;  
  120.             CPaintManagerUI::GetHSL(&H, &S, &L);  
  121.             CPaintManagerUI::SetHSL(true, H, S, (static_cast<CSliderUI*>(pMsg->pSender))->GetValue());  
  122.         }  
  123.         return true;  
  124.     }  
  125.   
  126.     bool OnAlphaChanged(void* param) {  
  127.         TNotifyUI* pMsg = (TNotifyUI*)param;  
  128.         if( pMsg->sType == _T("valuechanged") ) {  
  129.             m_pm.SetTransparent((static_cast<CSliderUI*>(pMsg->pSender))->GetValue());  
  130.         }  
  131.         return true;  
  132.     }  
  133.   
  134.     void Notify(TNotifyUI& msg)  
  135.     {  
  136.         if( msg.sType == _T("windowinit") ) {  
  137.             CSliderUI* pSilder = static_cast<CSliderUI*>(m_pm.FindControl(_T("alpha_controlor")));  
  138.             if( pSilder )   
  139.                 pSilder->OnNotify += MakeDelegate(this, &CFrameWindowWnd::OnAlphaChanged);  
  140.   
  141.             pSilder = static_cast<CSliderUI*>(m_pm.FindControl(_T("h_controlor")));  
  142.             if( pSilder )   
  143.                 pSilder->OnNotify += MakeDelegate(this, &CFrameWindowWnd::OnHChanged);  
  144.   
  145.             pSilder = static_cast<CSliderUI*>(m_pm.FindControl(_T("s_controlor")));  
  146.             if( pSilder )   
  147.                 pSilder->OnNotify += MakeDelegate(this, &CFrameWindowWnd::OnSChanged);  
  148.   
  149.             pSilder = static_cast<CSliderUI*>(m_pm.FindControl(_T("l_controlor")));  
  150.             if( pSilder )   
  151.                 pSilder->OnNotify += MakeDelegate(this, &CFrameWindowWnd::OnLChanged);  
  152.         }  
  153.         else if( msg.sType == _T("click") ) {  
  154.             if( msg.pSender->GetName() == _T("insertimagebtn") ) {  
  155.                 CRichEditUI* pRich = static_cast<CRichEditUI*>(m_pm.FindControl(_T("testrichedit")));  
  156.                 if( pRich ) {  
  157.                     pRich->RemoveAll();  
  158.                 }  
  159.             }  
  160.             else if( msg.pSender->GetName() == _T("changeskinbtn") ) {  
  161.                 if( CPaintManagerUI::GetResourcePath() == CPaintManagerUI::GetInstancePath() )  
  162.                     CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("skin\\FlashRes"));  
  163.                 else  
  164.                     CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());  
  165.                 CPaintManagerUI::ReloadSkin();  
  166.             }  
  167.         }  
  168.     }  
  169.   
  170.     LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)  
  171.     {  
  172.         if( uMsg == WM_CREATE ) {  
  173.             // 设置窗口无边框样式  
  174.             LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);  
  175.             styleValue &= ~WS_CAPTION ; //& ~WS_BORDER & ~WS_THICKFRAME;  
  176.             ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);  
  177.   
  178.             m_pm.Init(m_hWnd);  
  179.             CDialogBuilder builder;  
  180.             //CDialogBuilderCallbackEx cb;  
  181.             wchar_t szXmlPath [MAX_PATH] = L"";  
  182.             MultiByteToWideChar(CP_ACP, 0, m_xmlPath.c_str(), -1, szXmlPath, _countof(szXmlPath));  
  183.             CControlUI* pRoot = builder.Create(szXmlPath, (UINT)0, NULL, &m_pm);  
  184.             ASSERT(pRoot && "Failed to parse XML");  
  185.             m_pm.AttachDialog(pRoot);  
  186.             m_pm.AddNotifier(this);  
  187.   
  188.             // 圆角  
  189.             SIZE szRoundCorner = m_pm.GetRoundCorner();  
  190.             if( !::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0) ) {  
  191.                 CRect rcWnd;  
  192.                 ::GetWindowRect(*this, &rcWnd);  
  193.                 rcWnd.Offset(-rcWnd.left, -rcWnd.top);  
  194.                 rcWnd.right++; rcWnd.bottom++;  
  195.                 HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right,rcWnd.bottom  
  196.                     , szRoundCorner.cx, szRoundCorner.cy);  
  197.                 ::SetWindowRgn(*this, hRgn, TRUE);  
  198.                 ::DeleteObject(hRgn);  
  199.             }  
  200.   
  201.             Init();  
  202.             return 0;  
  203.         }  
  204.         else if( uMsg == WM_DESTROY ) {  
  205.             ::PostQuitMessage(0L);  
  206.         }  
  207.         else if( uMsg == WM_ERASEBKGND ) {  
  208.             return 1;  
  209.         }  
  210.   
  211.         LRESULT lRes = 0;  
  212.         if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) )   
  213.             return lRes;  
  214.   
  215.         return CWindowWnd::HandleMessage(uMsg, wParam, lParam);  
  216.     }  
  217.   
  218. public:  
  219.     // 绘制管理器  
  220.     CPaintManagerUI m_pm;  
  221.     // 布局文件  
  222.     std::string m_xmlPath;  
  223.     // 控制脚本  
  224.     std::string m_luaPath;  
  225. protected:  
  226.     // lua脚本状态机  
  227.     lua_State * m_L;  
  228. };  
  229.   
  230. int APIENTRY WinMain(  
  231.                      __in  HINSTANCE hInstance,  
  232.                      __in  HINSTANCE hPrevInstance,  
  233.                      __in  LPSTR lpCmdLine,  
  234.                      __in  int nCmdShow  
  235.                      )  
  236. {     
  237.     CPaintManagerUI::SetInstance((HINSTANCE)hInstance);  
  238.     CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());  
  239.   
  240.     HRESULT Hr = ::CoInitialize(NULL);  
  241.     if( FAILED(Hr) ) return 0;  
  242.   
  243.     CFrameWindowWnd* pFrame = new CFrameWindowWnd("LuaUiFrame.xml"  
  244.         , "LuaUiFrame.lua");  
  245.   
  246.     if( pFrame == NULL )   
  247.         return 0;  
  248.   
  249.     pFrame->Create(NULL  
  250.                 , _T("LuaUiFrameApp")  
  251.                 , WS_VISIBLE | WS_POPUPWINDOW  
  252.                 //, WS_VISIBLE | WS_POPUPWINDOW| WS_OVERLAPPEDWINDOW  
  253.                 , 0L, 0, 0, 1, 1);  
  254.   
  255.     pFrame->CenterWindow();  
  256.     pFrame->ShowWindow(true);  
  257.     CPaintManagerUI::MessageLoop();  
  258.   
  259.     ::CoUninitialize();  
  260.     return 0;  
  261. }  
  262.   
  263.   
  264. int FindControl(lua_State * l)  
  265. {  
  266.     return 0;  
  267. }  
  268.   
  269.   
  270. int SetAttr(lua_State * L)  
  271. {  
  272.     return 0;  
  273. }  
  274.   
  275.   
  276. int GetAttr(lua_State * l)  
  277. {  
  278.     return 0;  
  279. }  
  280.   
  281. int SetCallback(lua_State * l)  
  282. {  
  283.     const char * pCallbackName = lua_tostring(l,1);  
  284.     //MSGBOX(pCallbackName, pCallbackName);  
  285.     lua_getglobal(l, pCallbackName);  
  286.     //lua_pushnumber(l, 0);   /* push 1st argument */  
  287.     //lua_pushnumber(l, 0);   /* push 2nd argument */  
  288.     lua_pcall(l, 0, 0, 0);  
  289.     return 0;  
  290. }  
  291.   
  292. int MsgBox(lua_State * l)  
  293. {  
  294.     int argc = lua_gettop(l);  
  295.     MSGBOX(lua_tostring(l, 1), lua_tostring(l, 2));  
  296.     lua_pushnumber(l, 0x00000000);  // return value  
  297.     return 1;   // count of ret val  
  298. }  

xml布局文件

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <Window mininfo="10,10" size="200,200">  
  3.     <Font name="幼圆" size="16" default="true" />  
  4.     <Font name="微软雅黑" size="18" />  
  5.   <!-- Slider的外观定义 -->  
  6.   <Default name="Slider" value="thumbsize="10,10" bkimage="file='bg.bmp' corner='6,0,6,0' mask='#FFFF00FF'" fgimage="file='fg.bmp' corner='6,0,6,0' mask='#FFFF00FF'" thumbimage="file='thumb.bmp' source='30,0,40,10' mask='#FFDAEBF9'" thumbhotimage="file='thumb.bmp' source='10,0,20,10' mask='#FFDAEBF9'" " />  
  7.   <!-- Button的外观定义 -->  
  8.   <Default name="Button" value="normalimage="file='button_nor.bmp' corner='4,2,4,2' fade='200' hsl='true'" hotimage="file='button_over.bmp' corner='4,2,4,2' fade='200' hsl='true'" pushedimage="file='button_down.bmp' corner='4,2,4,2' fade='200' hsl='true' " " />  
  9.     
  10.   <!-- 使用垂直布局放置以下4个ui组件 -->  
  11.   <VerticalLayout inset="10,6,10,6" bkcolor="#FFEA679F" colorhsl="true" borderround="18,18">  
  12.         <!-- 如果richedit在窗口内是第一个获得焦点的,会出现一个光标刷新bug,暂无解决办法 -->  
  13.       
  14.     <!-- 定义3个slider -->  
  15.         <Slider name="alpha_controlor" min="20" max="255" value="255"/>  
  16.         <Slider name="h_controlor" max="360" value="180"/>  
  17.         <Slider name="s_controlor" max="200" value="100"/>  
  18.         <Slider name="l_controlor" max="200" value="100"/>  
  19.       
  20.     <!-- 定义1个按钮 -->  
  21.         <Button name="changeskinbtn" height="20" text="换肤" maxwidth="120" />  
  22.     </VerticalLayout>  
  23. </Window>  

lua脚本文件
  1. function onButtonClick() // frame 这个库已经注册到lua脚本虚拟机里面了,可以直接使用  
  2.     frame.MsgBox("Hello", "ButtonClicked");  
  3. end  
  4.   
  5. frame.MsgBox("title", "text");  
  6.   
  7. frame.SetCallback("onButtonClick");  

一些看法:

1) 作者当尝试dui和lua的结合是仅仅是一次探索,该技术的跨平台是一个大问题。dui是关于windows的技术。

2) 以前也关注过xul,属于mozila的跨平台界面技术实现,这个比较有意思,脚本是js,moziila在html标签之外重新定义了一套标签专门用于app的开发,确实煞费苦心,为什么不直接增强html标签呢?当然也是可以xmlns引入xhtml标签,但是一个app里面使用2中ns的标签有些奇怪,另外mozilla也不建议在xulrunner里面使用xhtml标签。

3)html5和js未来应该是一个大的趋势,浏览器编程和本地编程应该可以融合。


更多 0
  • 上一篇:GDB调试
  • 下一篇:WinDbg调试器
  • 查看评论
    3楼 tornodo 2013-11-05 14:11发表 [回复]
    放一张截图看下
    2楼 zbx91 2013-04-01 21:30发表 [回复]
    求开发这样的工具啊!
    Re: wuzh1230 2013-04-02 10:15发表 [回复]
    回复zbx91:可以考虑使用qt界面,当然qt有自己的脚本qtscript【ecmascript】。大家也可以封装一份lua接口。还没有调研是否lua项目组有过类似的项目?
    Re: wuzh1230 2013-04-02 10:11发表 [回复]
    回复zbx91:有兴趣的话,大家一起研究吧,lua的源代码还比较容易调试,关于状态机的部分也很清晰,另外lua的c模块扩展比js要容易一些。lua本身也比js小巧。

      本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
      转藏 分享 献花(0

      0条评论

      发表

      请遵守用户 评论公约