Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9548454
  • 博文数量: 1227
  • 博客积分: 10026
  • 博客等级: 上将
  • 技术积分: 20273
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-16 12:40
文章分类

全部博文(1227)

文章存档

2010年(1)

2008年(1226)

我的朋友

分类: C/C++

2008-04-23 21:40:46

为应用程序添加脚本支持
作者: 翻译:PowerCPP



代码运行效果图如下:


介绍
有时我们并不需要提供完整的脚本支持,就像本文所要介绍的ActiveX脚本宿主(script hosting,可能称为脚本引擎更好理解),本文提供的ScriptControlMacro程序展示了使用Microsoft脚本控件简单地实现脚本支持功能,代码中还包括了以下一些技术:

用文件映射实现只允许一个应用实例.
如何用MFC存储读取二进制注册表数据
如何保存恢复应用程序窗口尺寸,位置
如何在CEditView派生类中使用不同地字体
如何捕捉OLE异常并显示错误信息
等...

开始前的准备
这篇文章假定你已经对COM、ActiveX控件、OLE自动化有所熟悉,并知道如何在MFC里使用他们。因为这些技术包含了相当多的内容,因此你应该先学习一下这些内容再来看本文。

基本步骤:
1、建立一个提供ActiveX控件支持的新的MFC工程
2、使用ClassWizard从脚本控件类型库中建立一个dispatch类
ClassWizard将为脚本控件接口生成头文件与执行文件。

// Machine generated IDispatch wrapper class(es) created with

// ClassWizard



////////////////////////////////////////////////////////////

// IScriptControl wrapper class



class IScriptControl : public COleDispatchDriver

{

// Operations

public:

  void SetLanguage(LPCTSTR lpszNewValue);

  void SetSitehWnd(HWND hWnd);

  LPDISPATCH GetError();

  void AddObject(LPCTSTR Name, LPDISPATCH Object,

                 BOOL AddMembers);

  void AddCode(LPCTSTR Code);

};



// Machine generated IDispatch wrapper class(es) created

// with ClassWizard



#include "stdafx.h"



#include "MSScriptControl.h"



#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif



////////////////////////////////////////////////////////////

// IScriptControl operations



void IScriptControl::SetLanguage(LPCTSTR lpszNewValue)

{

  static BYTE parms[] =

    VTS_BSTR;

  InvokeHelper(0x5dc, DISPATCH_PROPERTYPUT, VT_EMPTY,

               NULL, parms,

    lpszNewValue);

}



void IScriptControl::SetSitehWnd(HWND hWnd)

{

  static BYTE parms[] =

    VTS_I4;

  InvokeHelper(0x5de, DISPATCH_PROPERTYPUT, VT_EMPTY,

               NULL, parms,

    hWnd);

}



LPDISPATCH IScriptControl::GetError()

{

  LPDISPATCH result;

  InvokeHelper(0x5e3, DISPATCH_PROPERTYGET, VT_DISPATCH,

               (void*)&result, NULL);

  return result;

}



void IScriptControl::AddObject(LPCTSTR Name,

                               LPDISPATCH Object,

                               BOOL AddMembers)

{

  static BYTE parms[] =

    VTS_BSTR VTS_DISPATCH VTS_BOOL;

  InvokeHelper(0x9c4, DISPATCH_METHOD, VT_EMPTY, NULL, parms,

     Name, Object, AddMembers);

}



void IScriptControl::AddCode(LPCTSTR Code)

{

  static BYTE parms[] =

    VTS_BSTR;

  InvokeHelper(0x7d0, DISPATCH_METHOD, VT_EMPTY, NULL, parms,

    Code);

}



3、删除类中不需要的IDispatch封装的方法
4、如果你想自己添加函数,可以用ClassWizard添加一个自动化类。
ClasWizard将为IDispatch接口产生如下头文件与执行文件:
// ScriptControlMacroDispatch.h : interface of the

// CScriptControlMacroDispatch class

//

////////////////////////////////////////////////////////////



#if !defined(AFX_SCRIPTCONTROLMACRODISPATCH_H__FB55B5AF_

    00E5_47F5_B176_214B2C7BF19A__INCLUDED_)

#define AFX_SCRIPTCONTROLMACRODISPATCH_H__FB55B5AF_00E5_

        47F5_B176_214B2C7BF19A__INCLUDED_



#if _MSC_VER > 1000

#pragma once

#endif    // _MSC_VER > 1000



////////////////////////////////////////////////////////////

// CScriptControlMacroDispatch command target



class CScriptControlMacroDispatch : public CCmdTarget

{

  DECLARE_DYNCREATE(CScriptControlMacroDispatch)



  CScriptControlMacroDispatch();

           // protected constructor used by dynamic creation



// Overrides

  // ClassWizard generated virtual function overrides

  //{{AFX_VIRTUAL(CScriptControlMacroDispatch)

  //}}AFX_VIRTUAL



// Implementation



protected:

  //friend class CScriptControlMacroView;

  // Generated message map functions

  //{{AFX_MSG(CScriptControlMacroDispatch)

    // NOTE - the ClassWizard will add and remove member

    // functions here.

  //}}AFX_MSG



  DECLARE_MESSAGE_MAP()

  // Generated OLE dispatch map functions

  //{{AFX_DISPATCH(CScriptControlMacroDispatch)

  afx_msg void Test1();

  afx_msg void Test2();

  //}}AFX_DISPATCH

  DECLARE_DISPATCH_MAP()

  DECLARE_INTERFACE_MAP()

};



// Note: we add support for IID_IScriptControlMacroDispatch

// to support typesafe binding from VBA. This IID must match

// the GUID that is attached to the dispinterface in the

// .ODL file.



// {69AA5686-41AF-4CD9-AEAE-9DB88130E7C1}

static const IID IID_IScriptControlMacroDispatch =

{0x69AA5686, 0x41AF, 0x4CD9, {0xAE, 0xAE, 0x9D, 0xB8,

 0x81, 0x30, 0xE7, 0xC1}};



////////////////////////////////////////////////////////////



//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C   will insert additional declarations

// immediately before the previous line.



#endif    // !defined(AFX_SCRIPTCONTROLMACRODISPATCH_H__

          // FB55B5AF_00E5_47F5_B176_214B2C7BF19A__INCLUDED_)



// ScriptControlMacroDispatch.cpp : implementation of the

// CScriptControlMacroDispatch class

//



#include "stdafx.h"

#include "ScriptControlMacroDispatch.h"



#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif



////////////////////////////////////////////////////////////

// CScriptControlMacroDispatch



IMPLEMENT_DYNCREATE(CScriptControlMacroDispatch, CCmdTarget)



CScriptControlMacroDispatch::CScriptControlMacroDispatch()

{

  EnableAutomation();

}



BEGIN_MESSAGE_MAP(CScriptControlMacroDispatch, CCmdTarget)

  //{{AFX_MSG_MAP(CScriptControlMacroDispatch)

    // NOTE - the ClassWizard will add and remove mapping

    // macros here.

  //}}AFX_MSG_MAP

END_MESSAGE_MAP()



BEGIN_DISPATCH_MAP(CScriptControlMacroDispatch, CCmdTarget)

  //{{AFX_DISPATCH_MAP(CScriptControlMacroDispatch)

  DISP_FUNCTION(CScriptControlMacroDispatch,

                "Test1", Test1, VT_EMPTY, VTS_NONE)

  DISP_FUNCTION(CScriptControlMacroDispatch,

                "Test2", Test2, VT_EMPTY, VTS_NONE)

  //}}AFX_DISPATCH_MAP

END_DISPATCH_MAP()



BEGIN_INTERFACE_MAP(CScriptControlMacroDispatch, CCmdTarget)

  INTERFACE_PART(CScriptControlMacroDispatch,

                 IID_IScriptControlMacroDispatch, Dispatch)

END_INTERFACE_MAP()



////////////////////////////////////////////////////////////

// CScriptControlMacroDispatch message handlers



void CScriptControlMacroDispatch::Test1()

{

  // TODO: Add your dispatch handler code here



  AfxMessageBox(CString(_T("\""))   GetDispatchMap()->

                lpEntries->lpszName   _T("\" method call of

                the \"")   RUNTIME_CLASS(

                CScriptControlMacroDispatch)->m_lpszClassName

                  _T("\" class"), MB_ICONASTERISK);

}



void CScriptControlMacroDispatch::Test2()

{

  // TODO: Add your dispatch handler code here



  AfxMessageBox(CString(_T("\""))   GetDispatchMap()->

                lpEntries[1].lpszName   _T("\" method

                call of the \"")   RUNTIME_CLASS(

                CScriptControlMacroDispatch)->m_lpszClassName

                  _T("\" class"), MB_ICONASTERISK);

}



5、这样在产生的代码中已经实现了一些自定义的东西
a. 不必要的声名和代码已经删除
b. 全局的应用程序对象已经声名:extern CScriptControlMacroApp theApp
c. MFC隐含函数声名已经添加:CString AFXAPI AfxStringFromCLSID( REFCLSID ).
d. 为了使用AfxStringFromCLSID,IID_IScriptControlMacroDispatch定义已经移到了头文件中

6、为了在所有MFC程序中方便地提供Unicode支持,在AFX.H头文件中作了如下定制:
////////////////////////////////////////////////////////////

// Win32 libraries



// Start of customization

#ifdef _UNICODE

    #pragma comment(linker, "/entry:wWinMainCRTStartup")

#endif

// End of customization



7、为了在所有MFC工程中使用 _WIN32_WINDOWS=0x500 这个预定义,在AFXV_W32.H头文件中作了如下定制:
#ifndef ALL_WARNINGS

#pragma warning(disable: 4201)

    // winnt.h uses nameless structs

#endif



// Start of customization

#ifndef _WIN32_WINDOWS

// End of customization

#define _WIN32_WINDOWS 0x0500

// Start of customization

#endif

// End of customization




更多信息可以查看源代码或访问微软WINDOWS脚本技术网页
阅读(320) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~