在VC程序中支持脚本程序(-)

类别:VC语言 点击:0 评论:0 推荐:
程序中使用VBScript 以下是我从几个例程中总结出的基本方法,其中没有事件的处理功能,如果要源码的话可与我联系([email protected]) 1.头文件包含 #include #include 2.在类中声明以下两个成员 IActiveScript *m_pIActiveScript; IActiveScriptParse *m_pIActiveScriptParse; 3.在CMainFrame类声明中的DECLARE_MESSAGE_MAP()后加上以下代码 DECLARE_INTERFACE_MAP() BEGIN_INTERFACE_PART(ScriptSite, IActiveScriptSite) STDMETHOD(GetLCID)(LCID *plcid); STDMETHOD(GetItemInfo)(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti); STDMETHOD(GetDocVersionString)(BSTR *pszVersion); STDMETHOD(RequestItems)(void); STDMETHOD(RequestTypeLibs)(void); STDMETHOD(OnScriptTerminate)(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo); STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState); STDMETHOD(OnScriptError)(IActiveScriptError *pscripterror); STDMETHOD(OnEnterScript)(void); STDMETHOD(OnLeaveScript)(void); END_INTERFACE_PART(ScriptSite) BEGIN_INTERFACE_PART(ScriptSiteWindow, IActiveScriptSiteWindow) STDMETHOD(GetWindow)(HWND *phwnd); STDMETHOD(EnableModeless)(BOOL fEnable); END_INTERFACE_PART(ScriptSiteWindow) /********************************************* 加上以上代码后在CMainFrame类中会多两个成员 m_xScriptSite 与 m_xScriptSiteWindow **********************************************/ //以下是从上面移下来的 IActiveScript *m_pIActiveScript; IActiveScriptParse *m_pIActiveScriptParse; 4.实现3中的代码 1)在END_MESSAGE_MAP()后加上以下代码 BEGIN_INTERFACE_MAP(CMainFrame, CFrameWnd) INTERFACE_PART(CMainFrame, IID_IActiveScriptSite, ScriptSite) INTERFACE_PART(CMainFrame, IID_IActiveScriptSiteWindow, ScriptSiteWindow) END_INTERFACE_MAP() 2)实现m_xScriptSite中的成员方法 //COM interface implementation ULONG FAR EXPORT CMainFrame::XScriptSite::AddRef() { METHOD_PROLOGUE(CMainFrame, ScriptSite) return pThis->ExternalAddRef(); } ULONG FAR EXPORT CMainFrame::XScriptSite::Release() { METHOD_PROLOGUE(CMainFrame, ScriptSite) return pThis->ExternalRelease(); } HRESULT FAR EXPORT CMainFrame::XScriptSite::QueryInterface( REFIID iid, void FAR* FAR* ppvObj) { METHOD_PROLOGUE(CMainFrame, ScriptSite) return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj); } ULONG FAR EXPORT CMainFrame::XScriptSiteWindow::AddRef() { METHOD_PROLOGUE(CMainFrame, ScriptSiteWindow) return pThis->ExternalAddRef(); } ULONG FAR EXPORT CMainFrame::XScriptSiteWindow::Release() { METHOD_PROLOGUE(CMainFrame, ScriptSiteWindow) return pThis->ExternalRelease(); } HRESULT FAR EXPORT CMainFrame::XScriptSiteWindow::QueryInterface( REFIID iid, void FAR* FAR* ppvObj) { METHOD_PROLOGUE(CMainFrame, ScriptSiteWindow) return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj); } ///////////////////////////////////////////////////////////////////////////// // ActiveScript hosting // ##### BEGIN ACTIVEX SCRIPTING SUPPORT ##### //*************************************************************************** // IActiveScriptSite Interface //*************************************************************************** STDMETHODIMP CMainFrame::XScriptSite::GetLCID(LCID *plcid) { return E_NOTIMPL; // Use system settings } STDMETHODIMP CMainFrame::XScriptSite::GetItemInfo( LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown** ppunkItemOut, ITypeInfo** pptinfoOut ) { return TYPE_E_ELEMENTNOTFOUND; } STDMETHODIMP CMainFrame::XScriptSite::GetDocVersionString(BSTR *pbstrVersion) { return E_NOTIMPL; // UNDONE: Implement this method } STDMETHODIMP CMainFrame::XScriptSite::RequestItems(void) { return E_NOTIMPL; } STDMETHODIMP CMainFrame::XScriptSite::RequestTypeLibs(void) { METHOD_PROLOGUE(CMainFrame,ScriptSite); return E_NOTIMPL; } STDMETHODIMP CMainFrame::XScriptSite::OnScriptTerminate(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) { // UNDONE: Put up error dlg here return S_OK; } STDMETHODIMP CMainFrame::XScriptSite::OnStateChange(SCRIPTSTATE ssScriptState) { // Don't care about notification return S_OK; } //--------------------------------------------------------------------------- // Display the error //--------------------------------------------------------------------------- STDMETHODIMP CMainFrame::XScriptSite::OnScriptError(IActiveScriptError *pse) { METHOD_PROLOGUE(CMainFrame,ScriptSite); CString strError; CString strArrow; CString strDesc; CString strLine; EXCEPINFO ei; DWORD dwSrcContext; ULONG ulLine; LONG ichError; BSTR bstrLine = NULL; HRESULT hr; pse->GetExceptionInfo(&ei); pse->GetSourcePosition(&dwSrcContext, &ulLine, &ichError); hr = pse->GetSourceLineText(&bstrLine); if (hr) hr = S_OK; // Ignore this error, there may not be source available if (!hr) { strError=ei.bstrSource; strDesc=ei.bstrDescription; strLine=bstrLine; if (ichError > 0 && ichError < 255) { strArrow=CString(_T('-'),ichError); strArrow.SetAt(ichError-1,_T('v')); } CString strErrorCopy=strError; strError.Format(_T("Source:'%s'\nFile:'%s' Line:%d Char:%ld\nError:%d '%s'\n%s\n%s"), LPCTSTR(strErrorCopy), _T("File"), ulLine, ichError, (int)ei.wCode, LPCTSTR(strDesc), LPCTSTR(strArrow), LPCTSTR(strLine)); AfxMessageBox(strError); } if (bstrLine) SysFreeString(bstrLine); return hr; } STDMETHODIMP CMainFrame::XScriptSite::OnEnterScript(void) { // No need to do anything return S_OK; } STDMETHODIMP CMainFrame::XScriptSite::OnLeaveScript(void) { // No need to do anything return S_OK; } //*************************************************************************** // IActiveScriptSiteWindow Interface //*************************************************************************** STDMETHODIMP CMainFrame::XScriptSiteWindow::GetWindow(HWND *phwndOut) { if (!phwndOut) return E_INVALIDARG; METHOD_PROLOGUE(CMainFrame,ScriptSiteWindow); *phwndOut = pThis->GetSafeHwnd(); return S_OK; } STDMETHODIMP CMainFrame::XScriptSiteWindow::EnableModeless(BOOL fEnable) { return S_OK; } // ##### END ACTIVEX SCRIPTING SUPPORT ##### 5.添加两个全局变量 const IID CLSID_VBScript = {0xb54f3741, 0x5b07, 0x11cf, {0xa4, 0xb0, 0x0, 0xaa, 0x0, 0x4a, 0x55, 0xe8 } }; const TCHAR* szItemName=_T("Document"); szItemName 是指在脚本中可以直接创建的对象,例如照上面的值则可以如下使用: Document.MessageBox "sldfk" 'MessageBox 是Document的方法 如果 szItemName=_T("Document1") 则以上的应写为如下形式: Document1.MessageBox "sldfk" 'MessageBox 是Document1的方法 6.创建脚本对象 HRESULT CMainFrame::CreateScriptEngine(LPCOLESTR pstrItemName) { HRESULT hr; if (m_pIActiveScript) return S_FALSE; // Already created it // Create the ActiveX Scripting Engine hr = CoCreateInstance( CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER, IID_IActiveScript, (void **)&m_pIActiveScript); if (FAILED(hr)) { return E_FAIL; } // Script Engine must support IActiveScriptParse for us to use it hr = m_pIActiveScript->QueryInterface(IID_IActiveScriptParse, (void **)&m_pIActiveScriptParse); if (hr) { return hr; } hr = m_pIActiveScript->SetScriptSite(&m_xScriptSite); if (hr) return hr; // InitNew the object: hr=m_pIActiveScriptParse->InitNew(); //加入宿主对象名 USES_CONVERSION; LPCOLESTR lpostrApp = T2COLE(szItemName); hr=m_pIActiveScript->AddNamedItem(lpostrApp, SCRIPTITEM_ISVISIBLE); return hr; } // ##### END ACTIVEX SCRIPTING SUPPORT ##### 调用过程:一般在CMainFrame的OnCreate函数中调用 USES_CONVERSION; LPCOLESTR lpszT = T2COLE(szItemName); if(CreateScriptEngine(lpszT)!=S_OK) AfxMessageBox(_T("Can't load the VBScript Engine.")); 7.装入脚本 BOOL CMainFrame::LoadTextFile() { CFileDialog dlg(TRUE, _T("*.txt"), _T("*.txt"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("Text files (*.txt)")); if(dlg.DoModal()==IDOK) { m_strCode.Empty(); TCHAR szBuffer[256]; ifstream ifs(dlg.GetPathName()); while(ifs) { ifs.getline(szBuffer,256); m_strCode+=szBuffer; m_strCode+=_T("\r\n"); } // ##### BEGIN ACTIVEX SCRIPTING SUPPORT ##### USES_CONVERSION; EXCEPINFO ei; LPCOLESTR lpszCode = T2COLE(LPCTSTR(m_strCode)); HRESULT hr=m_pIActiveScriptParse->ParseScriptText(lpszCode, NULL, NULL, NULL, 0, 0, 0L, NULL, &ei); // ##### END ACTIVEX SCRIPTING SUPPORT ##### if(hr) { AfxMessageBox(_T("Can't compile the program.")); return FALSE; } return TRUE; } return FALSE; } 8.运行与停止脚本 m_pIActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED); m_pIActiveScript->SetScriptState(SCRIPTSTATE_DISCONNECTED); 9.支持脚本宿主 在STDMETHODIMP CMainFrame::XScriptSite::GetItemInfo是得到当前宿主可支持的对象: LPCOLESTR pstrName 对象名称,如在 5 中定义的const TCHAR* szItemName=_T("Document") DWORD dwReturnMask IUnknown** ppunkItemOut ITypeInfo** pptinfoOut 返回对象 实现代码 STDMETHODIMP CMainFrame::XScriptSite::GetItemInfo( LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown** ppunkItemOut, ITypeInfo** pptinfoOut ) { METHOD_PROLOGUE(CMainFrame, ScriptSite) USES_CONVERSION; LPCTSTR lpstrApplication=szItemName; if (dwReturnMask & SCRIPTINFO_ITYPEINFO) { if (!pptinfoOut) return E_INVALIDARG; *pptinfoOut = NULL; } if (dwReturnMask & SCRIPTINFO_IUNKNOWN) { if (!ppunkItemOut) return E_INVALIDARG; *ppunkItemOut = NULL; LPTSTR lpszName = OLE2T(pstrName); if(!_tcsicmp(lpstrApplication, lpszName)) { //在应用类中加入相应的Document类,并在应用的构造函数中初始化为NULL, 再在Document的构造函 //数中初始化为当前Document : theApp.m_pDoc = this ; *ppunkItemOut = theApp.m_pDoc->GetIDispatch(TRUE); return S_OK; } } return TYPE_E_ELEMENTNOTFOUND; } 10.为脚本宿主对象添加方法 在ClassView页面中右击向导自动生成的接口(假设应用程序名是AxHost,则接口是IAxHoxt),选择Add Method,在弹出的对话框中输入方法名,如GetDocumentName.其实现代码在相应的Document类中 11.添加接口对象 从ClassWizard中添加类,基类选择CCmdTarget, 并选中Automation选项,假设这里添加的类名是CMyBox,则会自动生成一个IMyBox的接口 12.访问接口对象 在脚本宿主对象的接口上添加一个生成接口对象的方法,具体同10,方法应返回 LPDISPATCH ,例程如下: LPDISPATCH CAXHostDoc::GetMyBox() { CMyBox* pSprite=(CMyBox*)RUNTIME_CLASS(CMyBox)->CreateObject(); return pSprite->GetIDispatch(FALSE); } 脚本中的代码如下: dim w Document1.MessageBox "sldfk" Dim MyBox set MyBox = Document1.GetMyBox MyBox.MessageBox "这是从MyBox中弹出的消息"

本文地址:http://com.8s8s.com/it/it3711.htm