一直在寻找一款lua作为界面开发语言脚本框架,类似于web开发,使用html做界面,
lua作为脚本语言进行行为控制,htmlayout是不二选择,但是其搭配的默认脚本并不是lua,这里找到一个
开源的框架,将htmlayout进行了改造,使其支持lua脚本作为逻辑控制语言;
本系列文章将对mfcui源码进行简要分析,并试图将其改造为自己的界面开发框架,该框架使用的是lua5.1;
我们从作者提供的test/demo.lua说起,该文件源代码如下:
require('mfc');
mfc.register('exctrl.dll');--加载扩展控件
mfc.init(); --初始化
local fn = arg[1]
or
string.format('file://%s/demo.htm', mfc.workdir());
local w = mfc.NewWindow(fn,
true); --启动模态窗口
最后调用了mfc.NewWindow(fn, true)函数来创建一个模态窗口,就显示出来一个窗口;
逐个函数去分析,先从mfc.register('exctrl.dll')函数来,该函数是C库中实现的函数,实现代码如下:
//注册扩展控件
static
int
register_exctrl(lua_State* L)
{
#ifndef
_AFXDLL
return 0;
#endif
HINSTANCE
hInstance = LoadLibrary(PAS(L, 1));//加载 exctrl.dll
if(hInstance == NULL)
return 0;
do
{
pfnOpenExCtrl
pfnFunc = (pfnOpenExCtrl)GetProcAddress(hInstance, "open_mfc_exctrl");
if(pfnFunc == NULL)
break;
CControlType** pList = pfnFunc(L);//调用 open_mfc_exctrl(L) 函数
if(pList == NULL)
break;
lua_newtable(L);
int
nIndex = 0;
for(CControlType* pCtrl = pList[nIndex]; pCtrl != NULL; pCtrl = pList[++nIndex])
{
RegisterWidget(pCtrl);
lua_pushstring(L, pCtrl->GetTypeName());
lua_rawseti(L, -2, nIndex + 1);
}
return 1;
}while(0);
FreeLibrary(hInstance);
return 0;
}
该函数先去加载exctrl.dll动态库,然后获取动态库导出函数open_mfc_exctrl,接着就调用了该函数,该函数代码如下:
extern
"C"
CControlType** WINAPI
open_mfc_exctrl(lua_State* L)
{
if(s_ControlList.empty())
return
NULL;
CExctrlWrappedWnd::Register();
lua_getglobal(L, "require");
lua_pushstring(L, "exctrl");
lua_pcall(L, 1, -1, 0);
return &s_ControlList[0];
}
这里继续调用了CExctrlWrappedWnd::Register()函数,实现如下,CExctrlWrappedWnd类继承自CWnd,CWnd是MFC中的窗口类,
static
BOOL Register()
{
HINSTANCE
hInstance;
hInstance = AfxGetInstanceHandle();
WNDCLASS
wc;
if (!(::GetClassInfo(hInstance, EXCTRL_WRAPPED_HWND, &wc))) {
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = ::DefWindowProc;
wc.lpszClassName = EXCTRL_WRAPPED_HWND;
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
if (!AfxRegisterClass(&wc)) {
return
FALSE;
}
}
return
TRUE;
}
以上代码对窗口的样式进行了设置;