新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 C/C++编程思想 』 → 如何在自己的程序中加入宏的功能 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 3889 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 如何在自己的程序中加入宏的功能 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 如何在自己的程序中加入宏的功能

    实现功能:在程序中加入执行宏语句的功能,如Microsoft Word一样,可以在里面运行宏,利用宏实现一些特殊功能。

    使用技术:Automotion

    程序实现:1、新建对话框程序,加入编辑框,选中其Multiline属性。

                      2、给编辑框关联变量:CEdit m_edit1;

                      3、加入新类MyScriptObject,基类为CCmdTarget, 并选中下方的Automotion。

                      4、给新类增加方法:打开ClassWizard,选择Automotion标签,在Class Name中选择MyScriptObject,点击Add Methods,在External name中输入Add,在返回值一项中选择long,参数列表中添加参数如下:na long;na long。

                      5、在MyScriptObject类中将Add方法改为:return na+nb;

                      6、打开MyScriptObject.h,将析构函数改为public。

                      7、拦截按据IDOK的BN_CLICKED消息,增加如下代码,并去掉CDialog::OnOK(); :

                    g_iActiveScriptSite.m_pUnkScriptObject =

                  m_myScriptObject.GetInterface(&IID_IUnknown);

                    HRVERIFY(CoCreateInstance(CLSID_VBScript,NULL, CLSCTX_INPROC_SERVER,

                  IID_IActiveScript, (void **)&m_iActiveScript),

                   "CoCreateInstance() for CLSID_VBScript");

                      HRVERIFY(m_iActiveScript->QueryInterface(IID_IActiveScriptParse,

                   (void **)&m_iActiveScriptParse),

                   "QueryInterface() for IID_IActiveScriptParse");

                      HRVERIFY(m_iActiveScript->SetScriptSite(&g_iActiveScriptSite),

                     "IActiveScript::SetScriptSite()");

                      HRVERIFY(m_iActiveScriptParse->InitNew(),

                   "IActiveScriptParse::InitNew()");

                     HRVERIFY(m_iActiveScript->AddNamedItem(L"MyObject",

                  SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE),

                  "IActiveScript::AddNamedItem()");  

             CString csScriptText;

                    m_edit1.GetWindowText(csScriptText);

                    EXCEPINFO ei;

                     BSTR pParseText = csScriptText.AllocSysString();

                     m_iActiveScriptParse->ParseScriptText(pParseText, L"MyObject", NULL,

                  NULL, 0, 0, 0L, NULL, &ei);

      m_iActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);

    m_iActiveScriptParse->Release();

                    m_iActiveScript->Release();

                      8、在CMyDialog.h中的public加入如下代码:

                      CMyScriptObject m_myScriptObject;

                     IActiveScript *m_iActiveScript;

                    IActiveScriptParse *m_iActiveScriptParse;

    9、在CMyDialog.h中增加头文件:

    #include <activscp.h>

    #include "MyScriptObject.h"

    10、在OnOK()这前加入如下代码:

    class MyActiveScriptSite : public IActiveScriptSite {

    private:

       ULONG m_dwRef; // Reference count

    public:

       IUnknown *m_pUnkScriptObject; // Pointer to your object that is exposed

                                     // to the script engine in GetItemInfo().

       

       MyActiveScriptSite::MyActiveScriptSite() {m_dwRef = 1;}

       MyActiveScriptSite::~MyActiveScriptSite() {}

       

       virtual HRESULT _stdcall QueryInterface(REFIID riid, void **ppvObject) {

          *ppvObject = NULL;

          return E_NOTIMPL;

       }

       virtual ULONG _stdcall AddRef(void) {

          return ++m_dwRef;

       }

       virtual ULONG _stdcall Release(void) {

          if(--m_dwRef == 0) return 0;

          return m_dwRef;

       }

       

       virtual HRESULT _stdcall GetLCID(LCID *plcid) {

          return S_OK;

       }

       

       virtual HRESULT _stdcall GetItemInfo(LPCOLESTR pstrName,

          DWORD dwReturnMask, IUnknown **ppunkItem, ITypeInfo **ppti) {

          if(ppti) {

             *ppti = NULL;

             

             if(dwReturnMask & SCRIPTINFO_ITYPEINFO)

                return TYPE_E_ELEMENTNOTFOUND;

          }

          

          if(ppunkItem) {

             *ppunkItem = NULL;

             

             if(dwReturnMask & SCRIPTINFO_IUNKNOWN) {

                if (!_wcsicmp(L"MyObject", pstrName)) {

                   *ppunkItem = m_pUnkScriptObject;

                   m_pUnkScriptObject->AddRef();

                }

             }

          }

          

          return S_OK;

       }

       

       virtual HRESULT __stdcall GetDocVersionString(BSTR *pbstrVersion) {

          return S_OK;

       }

       

       virtual HRESULT __stdcall OnScriptTerminate(const VARIANT *pvarResult,

          const EXCEPINFO *pexcepInfo) {

          return S_OK;

       }

       

       virtual HRESULT __stdcall OnStateChange(SCRIPTSTATE ssScriptState) {

          return S_OK;

       }

       

       virtual HRESULT __stdcall OnScriptError(

          IActiveScriptError *pscriptError) {

          static BSTR pwcErrorText;

          pscriptError->GetSourceLineText(&pwcErrorText);

          AfxMessageBox(

             CString("IActiveScriptSite::OnScriptError()\n") +

             CString("Line: ") +

             CString(pwcErrorText),

             MB_SETFOREGROUND);

          ::SysFreeString(pwcErrorText);

          return S_OK;

       }

       

       virtual HRESULT __stdcall OnEnterScript(void) {

          return S_OK;

       }

       

       virtual HRESULT __stdcall OnLeaveScript(void) {

          return S_OK;

       }

    };

    MyActiveScriptSite g_iActiveScriptSite;

    #include <initguid.h>

    DEFINE_GUID(CLSID_VBScript, 0xb54f3741, 0x5b07, 0x11cf, 0xa4, 0xb0, 0x0,

       0xaa, 0x0, 0x4a, 0x55, 0xe8);

    DEFINE_GUID(CLSID_JScript, 0xf414c260, 0x6ac0, 0x11cf, 0xb6, 0xd1, 0x00,

       0xaa, 0x00, 0xbb, 0xbb, 0x58);

    class OleInitClass {

    public:

       OleInitClass() {

          OleInitialize(NULL);

       }

       ~OleInitClass() {

          OleUninitialize();

       }

    };

    OleInitClass g_OleInitClass;

    void HRVERIFY(HRESULT hr, char * msg)

    {

       if(FAILED(hr)) {

          CString str;

          str.Format("Error: 0x%08lx (%s)", hr, msg);

          AfxMessageBox(str, 0x10000);

          _exit(0);

       }

    }

                      

                      11、运行。找一断宏代码写入Edit,点确定就可以执行了。啊,还差一点忘说了,记得初始化COM接口呀!J


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/7/18 13:52:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客2
    发贴心情 
    相关参考:

    How to add support for hosing VBScript to your MFC application

    SUMMARY
    You can add VBA-like scripting capability to your MFC application with little overhead that uses Microsoft ActiveX Scripting technologies. This article demonstrates how to create a new MFC application, or modify an existing one, that incorporates support for VBScript.
    Back to the top

    MORE INFORMATION
    Follow the steps below to build and run the example:
    1. Create a new MFC dialog-based application, or use an application you already have to which you would like to add scripting support.
    2. Add an edit box and button to your dialog, and enable the "Want return" and "Multiline" styles in the properties for the edit box.
    3. Use ClassWizard (CTRL-W), under the Member Variables tab, to associate IDC_EDIT1 with a member variable of type CEdit named m_edit1.
    4. Use ClassWizard to create a new class called MyScriptObject, derived from CCmdTarget, with support for Automation. Click OK if you see a warning about an ODL file.
    5. Under the Automation tab in ClassWizard, select MyScriptObject, and add the following methods:

    long gcd(long a, long b);
    void HelpAbout();
    void ShowValue(LPCTSTR prompt, long n);

    6. Implement gcd, HelpAbout, and ShowValue as follows:   long MyScriptObject::gcd(long a, long b)
       {
          int l, h, t;
          if(a < b) {
             l = a;
             h = b;
          }
          else if(a > b) {
             l = b;
             h = a;
          }
          else return a;

          while(h%l != 0) {
             t = l;
             l = (h%l);
             h = t;
          }
          return l;
       }

       void MyScriptObject::HelpAbout()
       {
          AfxMessageBox("HelpAbout: My Script Object!", 0x10000);
       }

       void MyScriptObject::ShowValue(LPCTSTR prompt, long n)
       {
          CString str;
          str.Format("%s%d", prompt, n);
          AfxMessageBox(str, MB_SETFOREGROUND);
       }
         

    7. Open MyScriptObject.h, and move the virtual destructor ~MyScriptObject from the protected section of the class to a public section.
    8. Double-click the dialog button to create a handler function for it, and implement it as follows:   // Initialize our IActiveScriptSite implementation with your
       // script object's IUnknown interface...
       g_iActiveScriptSite.m_pUnkScriptObject =
          m_myScriptObject.GetInterface(&IID_IUnknown);

       // Start inproc script engine, VBSCRIPT.DLL
       HRVERIFY(CoCreateInstance(CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER,
          IID_IActiveScript, (void **)&m_iActiveScript),
          "CoCreateInstance() for CLSID_VBScript");

       // Get engine's IActiveScriptParse interface.
       HRVERIFY(m_iActiveScript->QueryInterface(IID_IActiveScriptParse,
          (void **)&m_iActiveScriptParse),
          "QueryInterface() for IID_IActiveScriptParse");

       // Give engine our IActiveScriptSite interface...
       HRVERIFY(m_iActiveScript->SetScriptSite(&g_iActiveScriptSite),
          "IActiveScript::SetScriptSite()");

       // Give the engine a chance to initialize itself...
       HRVERIFY(m_iActiveScriptParse->InitNew(),
          "IActiveScriptParse::InitNew()");

       // Add a root-level item to the engine's name space...
       HRVERIFY(m_iActiveScript->AddNamedItem(L"MyObject",
          SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE),
          "IActiveScript::AddNamedItem()"); 

       // Get script code...
       CString csScriptText;
       m_edit1.GetWindowText(csScriptText);

       // Parse the code scriptlet...
       EXCEPINFO ei;
       BSTR pParseText = csScriptText.AllocSysString();
       m_iActiveScriptParse->ParseScriptText(pParseText, L"MyObject", NULL,
          NULL, 0, 0, 0L, NULL, &ei);

       // Set the engine state. This line actually triggers the execution
       // of the script.
       m_iActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);

       // Release engine...
       m_iActiveScriptParse->Release();
       m_iActiveScript->Release();
         

    9. Open your [projectname]Dlg.h file and add the following member variables to a public section of your class:   MyScriptObject m_myScriptObject;
       IActiveScript *m_iActiveScript;
       IActiveScriptParse *m_iActiveScriptParse;
         

    10. Also in [projectname]Dlg.h, add the following #include statements, just before the declaration of your class:   // Include ActiveX Script definitions...
       #include <activscp.h>
       // Include definition for MyScriptObject...
       #include "MyScriptObject.h"
         

    11. Add the following code to your [projectname]Dlg.cpp file, just before the implementation of your button handler:// Your IActiveScriptSite implementation...
    class MyActiveScriptSite : public IActiveScriptSite {
    private:
       ULONG m_dwRef; // Reference count
    public:
       IUnknown *m_pUnkScriptObject; // Pointer to your object that is exposed
                                     // to the script engine in GetItemInfo().
       
       MyActiveScriptSite::MyActiveScriptSite() {m_dwRef = 1;}
       MyActiveScriptSite::~MyActiveScriptSite() {}
       
       // IUnknown methods...
       virtual HRESULT _stdcall QueryInterface(REFIID riid, void **ppvObject) {
          *ppvObject = NULL;
          return E_NOTIMPL;
       }
       virtual ULONG _stdcall AddRef(void) {
          return ++m_dwRef;
       }
       virtual ULONG _stdcall Release(void) {
          if(--m_dwRef == 0) return 0;
          return m_dwRef;
       }
       
       // IActiveScriptSite methods...
       virtual HRESULT _stdcall GetLCID(LCID *plcid) {
          return S_OK;
       }
       
       virtual HRESULT _stdcall GetItemInfo(LPCOLESTR pstrName,
          DWORD dwReturnMask, IUnknown **ppunkItem, ITypeInfo **ppti) {

          // Is it expecting an ITypeInfo?
          if(ppti) {
             // Default to NULL.
             *ppti = NULL;
             
             // Return if asking about ITypeInfo...
             if(dwReturnMask & SCRIPTINFO_ITYPEINFO)
                return TYPE_E_ELEMENTNOTFOUND;
          }
          
          // Is the engine passing an IUnknown buffer?
          if(ppunkItem) {
             // Default to NULL.
             *ppunkItem = NULL;
             
             // Is Script Engine looking for an IUnknown for our object?
             if(dwReturnMask & SCRIPTINFO_IUNKNOWN) {
                // Check for our object name...
                if (!_wcsicmp(L"MyObject", pstrName)) {
                   // Provide our object.
                   *ppunkItem = m_pUnkScriptObject;
                   // Addref our object...
                   m_pUnkScriptObject->AddRef();
                }
             }
          }
          
          return S_OK;
       }
       
       virtual HRESULT __stdcall GetDocVersionString(BSTR *pbstrVersion) {
          return S_OK;
       }
       
       virtual HRESULT __stdcall OnScriptTerminate(const VARIANT *pvarResult,
          const EXCEPINFO *pexcepInfo) {
          return S_OK;
       }
       
       virtual HRESULT __stdcall OnStateChange(SCRIPTSTATE ssScriptState) {
          return S_OK;
       }
       
       virtual HRESULT __stdcall OnScriptError(
          IActiveScriptError *pscriptError) {
          static BSTR pwcErrorText;
          pscriptError->GetSourceLineText(&pwcErrorText);

          AfxMessageBox(
             CString("IActiveScriptSite::OnScriptError()\n") +
             CString("Line: ") +
             CString(pwcErrorText),
             MB_SETFOREGROUND);
          ::SysFreeString(pwcErrorText);
          return S_OK;
       }
       
       virtual HRESULT __stdcall OnEnterScript(void) {
          return S_OK;
       }
       
       virtual HRESULT __stdcall OnLeaveScript(void) {
          return S_OK;
       }
    };

    // Global instance of our IActiveScriptSite implementation.
    MyActiveScriptSite g_iActiveScriptSite;

    // Script Engine CLSIDs...
    #include <initguid.h>
    DEFINE_GUID(CLSID_VBScript, 0xb54f3741, 0x5b07, 0x11cf, 0xa4, 0xb0, 0x0,
       0xaa, 0x0, 0x4a, 0x55, 0xe8);
    DEFINE_GUID(CLSID_JScript, 0xf414c260, 0x6ac0, 0x11cf, 0xb6, 0xd1, 0x00,
       0xaa, 0x00, 0xbb, 0xbb, 0x58);

    // Ole-initialization class.
    class OleInitClass {
    public:
       OleInitClass() {
          OleInitialize(NULL);
       }
       ~OleInitClass() {
          OleUninitialize();
       }
    };
    // This global class calls OleInitialize() at
    // application startup, and calls OleUninitialize()
    // at application exit...
    OleInitClass g_OleInitClass;

    void HRVERIFY(HRESULT hr, char * msg)
    {
       if(FAILED(hr)) {
          CString str;
          str.Format("Error: 0x%08lx (%s)", hr, msg);
          AfxMessageBox(str, 0x10000);
          _exit(0);
       }

    }
         

    12. Compile and run.

    After you build the project, run it, add the following VBScript to your application's edit box, then click the button:
       dim x
       dim y
       dim z
       x = 101*199
       y = 313*199
       z = gcd(x, y)

       ShowValue "gcd(" & x & ", " & y & ") = ", z

       HelpAbout
        


    The basic work flow is as follows:
    1. You start the VBScript engine, vbscript.dll, and obtain IActiveScript and IActiveScriptParse interfaces.
    2. You give the VBScript engine your implementation of IActiveScriptSite, which the engine uses later to obtain and call to your objects.
    3. You add the objects that you implement and want to make available to scripts by calling IActiveScript::AddNamedItem().
    4. You provide the script text to execute through IActiveScriptParse::ParseScriptText(). Note that this doesn't actually run the script yet.
    5. The script engine will now call into your IActiveScriptSite::GetItemInfo() for any objects it doesn't recognize, to get their interface pointers.
    6. You call IActiveScript::SetScriptState() with SCRIPT_STATE_CONNECTED to run the script.
    7. The VBScript engine parses the text in the script for you and when it encounters a method call or property reference, it delegates the implementation to your provided interfaces.

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/7/18 13:55:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/28 15:57:17

    本主题贴数2,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    125.000ms