给duilib增加脚本支持(二)

上篇文章介绍了脚本响应duilib控件事件,以及脚本中调用duilib的函数。现在说一下具体的实现方式。

为了避免对duilib库太大的改动,使用插件方式载入。首先在CPaintManagerUI头部定义一个接口。

​

class UILIB_API IScriptEngine
{
public:
	virtual bool AddScriptCode(LPCTSTR pScriptCode) = 0;	//添加脚本段
	virtual bool AddScriptFile(LPCTSTR pstrFileName) = 0;	//添加脚本文件
	virtual bool ExecuteScript(LPCTSTR funName, CControlUI *pControl) = 0;	//执行脚本
	virtual bool ExecuteScript(LPCTSTR funName, CControlUI *pControl, TEventUI *ev) = 0; //执行脚本
};
typedef IScriptEngine* (__stdcall *CREATE_SCRIPT_ENGINE_INSTANCE)(); //插件接口,创建新的脚本引擎
typedef void (__stdcall *DELETE_SCRIPT_ENGINE_INSTANCE)(IScriptEngine *pEngine); //插件接口,删除脚本引擎

​

给CPaintManagerUI添加成员变量和函数,依然提供shared与否的方式。

//
// 脚本
//
public:
	static bool LoadScriptPlugin(LPCTSTR pstrModuleName);
	IScriptEngine *GetScriptEngine(bool bShared = false);
	void AddScriptCode(LPCTSTR pScriptCode, LPCTSTR pLanguageType, bool bShared = false);
	void AddScriptFile(LPCTSTR pstrFileName, LPCTSTR pLanguageType, bool bShared = false);
	bool ExecuteScript(LPCTSTR funName, CControlUI *pControl);
	bool ExecuteScript(LPCTSTR funName, CControlUI *pControl, TEventUI *ev);
private:
	IScriptEngine *m_pScriptEngine;
	static IScriptEngine *m_pSharedScriptEngine;
	static CREATE_SCRIPT_ENGINE_INSTANCE m_funCreateScriptEngine;
	static DELETE_SCRIPT_ENGINE_INSTANCE m_funDeleteScriptEngine;

UIManager.cpp的修改内容,别忘了在构造函数中初始化指针。

CPaintManagerUI::~CPaintManagerUI()
{
	//卸载脚本引擎
	if(m_funDeleteScriptEngine)
	{
		(*m_funDeleteScriptEngine)(m_pScriptEngine);
	}

    ..................
}

void CPaintManagerUI::Term()
{
	//卸载脚本引擎
	if(m_funDeleteScriptEngine){
		(*m_funDeleteScriptEngine)(m_pSharedScriptEngine);
	}

    .....................
 }

	CREATE_SCRIPT_ENGINE_INSTANCE CPaintManagerUI::m_funCreateScriptEngine = NULL;	//add by liqs99
	DELETE_SCRIPT_ENGINE_INSTANCE CPaintManagerUI::m_funDeleteScriptEngine = NULL;	//add by liqs99
	IScriptEngine* CPaintManagerUI::m_pSharedScriptEngine = NULL;					

	bool CPaintManagerUI::LoadScriptPlugin(LPCTSTR pstrModuleName)
	{
		ASSERT( !::IsBadStringPtr(pstrModuleName,-1) || pstrModuleName == NULL );
		if( pstrModuleName == NULL ) return false;
		HMODULE hModule = ::LoadLibrary(pstrModuleName);
		if( hModule != NULL ) 
		{
			m_funCreateScriptEngine = (CREATE_SCRIPT_ENGINE_INSTANCE)::GetProcAddress(hModule, "CreateScriptEngine");
			m_funDeleteScriptEngine = (DELETE_SCRIPT_ENGINE_INSTANCE)::GetProcAddress(hModule, "DeleteScriptEngine");
			if(m_funCreateScriptEngine != NULL || m_funDeleteScriptEngine != NULL)
			{
				return true;
			}
		}
		return false;
	}
	
	IScriptEngine *CPaintManagerUI::GetScriptEngine(bool bShared)
	{
		if(m_funCreateScriptEngine == NULL)	return NULL;

		if(bShared)
		{
			if(m_pSharedScriptEngine == NULL)
				m_pSharedScriptEngine = (*m_funCreateScriptEngine)();
			return m_pSharedScriptEngine;
		}

		if(m_pScriptEngine == NULL)
			m_pScriptEngine = (*m_funCreateScriptEngine)();
		return m_pScriptEngine;
	}

	void CPaintManagerUI::AddScriptCode(LPCTSTR pScriptCode, LPCTSTR pLanguageType, bool bShared)
	{
		IScriptEngine *pScriptEngine = GetScriptEngine(bShared);
		if(pScriptEngine == NULL) return;
		pScriptEngine->AddScriptCode(pScriptCode);
	}

	void CPaintManagerUI::AddScriptFile(LPCTSTR pstrFileName, LPCTSTR pLanguageType, bool bShared)
	{
		IScriptEngine *pScriptEngine = GetScriptEngine(bShared);
		if(pScriptEngine == NULL) return;
		pScriptEngine->AddScriptFile(pstrFileName);
	}

	bool CPaintManagerUI::ExecuteScript(LPCTSTR funName, CControlUI *pControl)
	{
		IScriptEngine *pScriptEngine = GetScriptEngine(false);
		if(pScriptEngine)
		{
			if(!pScriptEngine->ExecuteScript(funName, pControl))
			{
				pScriptEngine = GetScriptEngine(true);
				if(!pScriptEngine) return false;
				if(!pScriptEngine->ExecuteScript(funName, pControl)) return false;
			}
		}
		else return false;

		return true;
	}

	bool CPaintManagerUI::ExecuteScript(LPCTSTR funName, CControlUI *pControl, TEventUI *ev)
	{
		IScriptEngine *pScriptEngine = GetScriptEngine(false);
		if(pScriptEngine)
		{
			if(!pScriptEngine->ExecuteScript(funName, pControl, ev))
			{
				pScriptEngine = GetScriptEngine(true);
				if(!pScriptEngine) return false;
				if(!pScriptEngine->ExecuteScript(funName, pControl, ev)) return false;
			}
		}
		else return false;

		return true;
	}

接着,修改CControlUI::Event(TEventUI& event), 截获事件传递给脚本。

//在事件中执行脚本内容
void CControlUI::Event(TEventUI& event)
{
	if( OnEvent(&event) ) DoEvent(event);

	if( event.Type == UIEVENT_SETFOCUS ) 
	{
		if(!m_asOnSetFocus.IsEmpty()) GetManager()->ExecuteScript(m_asOnSetFocus, this);
	}
	if( event.Type == UIEVENT_KILLFOCUS ) 
	{
		if(!m_asOnKillFocus.IsEmpty()) GetManager()->ExecuteScript(m_asOnKillFocus, this);
	}
}

//增加属性定义
void CControlUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)

{
    ............
	else if( _tcscmp(pstrName, _T("OnSetFocus"))	== 0 )		m_asOnSetFocus = pstrValue;
	else if( _tcscmp(pstrName, _T("OnKillFocus"))	== 0 )		m_asOnKillFocus = pstrValue;
...............
}

m_asOnSetFocus和m_asOnKillFocus是两个CDuiString,保存脚本内容。

接下来,需要让duilib载入脚本内容,如上一篇在xml中定义或as文件定义的函数。language属性无用,只做预留。

                                else if( _tcsicmp(pstrClass, _T("Script")) == 0 ) 
				{
					nAttributes = node.GetAttributeCount();
					LPCTSTR pstrIncludeFile = NULL;
					LPCTSTR pstrLanguage = NULL;
					LPCTSTR pScriptCode = node.GetValue();
					bool shared = false;
					for( int i = 0; i < nAttributes; i++ ) 
					{
						pstrName = node.GetAttributeName(i);
						pstrValue = node.GetAttributeValue(i);
						if( _tcsicmp(pstrName, _T("include")) == 0 ) 
						{
							pstrIncludeFile = pstrValue;
						}
						else if( _tcsicmp(pstrName, _T("language")) == 0 ) 
						{
							pstrLanguage = pstrValue;
						}
						else if( _tcsicmp(pstrName, _T("shared")) == 0 ) 
						{
							shared = (_tcsicmp(pstrValue, _T("true")) == 0);
						}
					}

					if(pstrIncludeFile)
					{
						pManager->AddScriptFile(pstrIncludeFile, pstrLanguage, shared);
					}
					if(pScriptCode && pScriptCode[0] != '\0')
					{
						pManager->AddScriptCode(pScriptCode, pstrLanguage, shared);
					}
				}

现在万事俱备,只欠插件了。

 

代码共享地址:

https://gitee.com/Liqs99/DuiLib_DuiEditor

https://github.com/xfcanyue/DuiLib_DuiEditor

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值