zoukankan      html  css  js  c++  java
  • MFC Activex OCX Javascript 互相访问问题,线程回调javascript

    //比较好的教程 
     
    ocx 在 win7 系统会出现注册需要管理员权限的问题,这时候需要用管理员身份运行 cmd,然后运行 regsvr32注册。
     
    很麻烦
     
    尝试使用 nsis 做成安装包, 采用 regdll 注册 ocx, 成功。
     
     

    ocx和外面的程序交互主要通过提供方法属性 + 事件

    方法属性可以提供给js调用,

    事件可以给js 通过下面的方式进行回调注入
    <object id="xxx"></object>
    <script language="JavaScript" for="xx" Event="eventFunction(x)"> 
    alert(x);
    </script> 
     
    或者
    document.getElementByIdx_x(xx).attachEvent("eventFunction",function(x,y){
    alert(x);
    });


    这两种功能都可以在类视图里面选择  XXXCtrl,右键选择 add ,会出现 方法属性事件
    按照wizard进行添加就好。

    主要记录一下如果ocx创建了线程,想通过事件回调js的话,会出现问题。
    这时候解决方法就是通过 PostMessage(WM_THREADFIREEVENT,(WPARAM)NULL,(LPARAM)NULL); 下面的看看应该懂了

    //-------------------------
    SAMPLE:   Firing   Events   From    Second   Thread   
        
      ---------------------------------------------------------------------   
      The   information   in   this   article   applies   to:   
        
         Microsoft   Visual   C++,   32-bit   Edition   versions   4.0,   4.1,   4.2   
      ---------------------------------------------------------------------   
        
      SUMMARY   
      =======   
        
      MFC   based   ActiveX   controls   typically   fire   their   events   from   the   same   thread   
      that   implements   the   sink   interface   of   the   container   that   the   events   are     
      being   fired   to.   
        
      Sometimes,   it   is   desirable   to   start    second   thread   in   an   ActiveX   control   
      which   will   fire   events   to   the   container.   Since   MFC   ActiveX   controls   
      use   the   Apartment   threading   model,   special   consideration   must   be   taken   
      into   account   when   firing   events   from    secondary   thread.   
        
      MORE   INFORMATION   
      ================   
        
      An   MFC   based   ActiveX   control   supports   events   by   implementing   the   
      IConnectionPointContaine  and   IConnectionPoint   interfaces,   as   well   as   
      supplying   information   about   it's   event   interface   in   it's   type   information.   
      When   an   MFC   based   ActiveX   control   is   embedded   in    container   that   supports   
      events,   that   container   will   dynamically   construct    sink   interface   that   has   
      all   of   the   methods   specified   in   the   control's   type   information   for   it's   
      event   interface.   Once   the   container   constructs   it's   sink   interface,   it   
      will   pass    pointer   to   that   interface   to   the   ActiveX   control.   The   ActiveX   
      control   will   use   it's   implementation   of   IConnectionPoint   to   communicate   
      through   the   now   hooked   up   sink   interface   that   was   constructed   by   the   
      container.   This   sample   will   demonstrate   how   to   call   methods   of   the   
      container's   sink   interface   from    second   thread.   
        
      The   two   most   important   things   to   consider   when   starting    new   thread   to   
      fire   events   from   in   an   ActiveX   control   are:   
        
      1.   MFC   based   ActiveX   controls   are   in-process   objects   (implemented   in      
            DLL).     
      2.   MFC   based   ActiveX   controls   use   the   Apartment   threading   model.   
        
      The   Apartment   threading   model   specifies   that   all   threads   that   want   to   use   
      OLE   services   must   initialize   OLE   in   their   thread   prior   to   using   OLE   
      services.   Also,   if    thread   wants   to   use    pointer   to   an   interface   that   is   
      either   implemented   by    different   thread   of   the   same   process   or   has   been   
      previously   marshaled   to    different   thread   of   the   same   process,   that   
      pointer   must   be   marshaled   to   the   requesting   thread.   In   the   Apartment   
      threading   model,   hidden   windows   are   created   to   synchronize   requests   from   
      other   threads   to   the   thread   being   called.   This   means   that   all   
      communication   between   threads   will   be   done   by   using   hidden   windows   and   
      Windows   messages   in   the   Apartment   model.   
        
      There   are   two   possible   ways   to   fire   events   from    second   thread   in   an   
      ActiveX   control   (or   any   other   in-proc   server   that   implements   connection   
      points)   under   the   Apartment   threading   model.   The   first   is   to   make   the   
      interface   call   from   the   second   thread   by   calling   the   event   sink's   method   
      from   the   second   thread.   The   second   is   to   have   the   second   thread   post    
      message   to   the   first   thread   when   it   is   ready   to   fire   the   event,   and   have   
      the   first   thread   fire   the   event.   
        
      The   first   method   mentioned   above   is   not   the   optimal   way   to   fire   an   event   
      from    second   thread.   This   is   because   for   the   second   thread   to   fire   the     
      event,   it   must   make    call   on   an   interface   pointer   that   is   held   by   the     
      thread   that   initialized   the   control.   This   means   that   the   interface   pointer     
      that   will   be   used   to   fire   the   event   must   be   marshaled   to   the   second   thread     
      which   will   cause   OLE   to   set   up   hidden   windows   to   communicate   between   the     
      threads.   Windows   messages   will   be   used   to   communicate   between   the   threads.     
      The   MFC   ActiveX   control   framework   is   not   set   up   to   easily   fire   events   from    
       second   thread.   It   is   possible   to   override   the   default   MFC   code   to   marshal     
      the   sink   interface   pointers   to   the   second   thread,   but   this   is   not     
      recommended.   The   reason   this   is   not   recommended   is   that   since   Windows   is    
      going   to   create   hidden   windows   and   use   PostMessage   to   send   messages   between     
      threads   anyway,   it   makes   more   sense   for   the   second   thread   to   post   it's   own     
      messages   to   the   first   thread   and   have   that   thread   fire   the   event.   This   code    
      can   be   easily   set   up   in   an   MFC   ActiveX   control.   Take   the   following   steps   to     
      add    second   thread   which   fires   events   to   the   container   in   an   MFC   ActiveX    
      control.   
        
      1.   Create   your   control   project.   
        
      2.   Using   ClassWizard,   add    method   that   will   start    second   thread   and   
            return.   The   code   for    method   that   starts    second   thread   and   returns   
            immediatly   in   an   MFC   ActiveX   control   is   shown   below.    global   function     
            to   serve   as   the   second   thread's   work   function   is   also   declared:   
        
            LONG   ThreadProc(LPVOID   pParam);   
        
            void   CFireeventCtrl::StartLengthyProcess()   
             
                DWORD   dwID;   
                HANDLE   threadHandle    CreateThread(NULL,NULL,   
                                                            (LPTHREAD_START_ROUTINE)ThreadProc,   
                                                            (LPVOID)this,   NULL,   &dwID);   
                TRACE("Started   the   thread   %x/n",dwID);   
             
        
      3.   Add   any   events   you   wish   to   fire   from   the   second   thread   using     
            ClassWizard.   
        
      4.   Define    custom   message   to   be   sent   from   the   second   thread.   Also,   add    
            message   map   entry   to   the   control's   message   map   which   will   call   the     
            message   handling   function   when   the   custom   message   is   received.   This   
            message   handler   will   fire   the   desired   event.    sample   of   how   to   do   this   
            in   an   MFC   ActiveX   control   is   shown   below:   
        
            //define    custom   message:   
            #define   WM_THREADFIREEVENT   WM_USER+101   
        
            //add   an   entry   for   the   message   to   the   message   map   of   the   control   
            BEGIN_MESSAGE_MAP(CFireeventCtrl,   COleControl)   
            //{{AFX_MSG_MAP(CFireeventCtrl)   
            //}}AFX_MSG_MAP   
            ON_OLEVERB(AFX_IDS_VERB_PROPERTIES,   OnProperties)   
            ON_MESSAGE(WM_THREADFIREEVENT,OnFireEventForThread)   //custom   handler     
            END_MESSAGE_MAP()   
        
            //add    handler   for   the   custom   message   that   will   fire   our   event   
            LRESULT   CFireeventCtrl::OnFireEventForThread(WPARAM   wParam,   
                    LPARAM   lParam)   
             
                FireLengthyProcessDone();   
                return   TRUE;   
             
        
      5.   In   the   thread   procedure   for   the   second   thread,   when   it's   time   for   the   
            second   thread   to   fire   the   event,   post   the   custom   message   defined   in   step     
             back   to   the   main   thread.   The   event   will   be   fired.   The   following   code     
            demonstrates   this:   
        
            LONG   ThreadProc(LPVOID   pParam)   
             
                Sleep(2000);   //simulate   lengthy   processing   
                CFireeventCtrl   *pCtrl    (CFireeventCtrl*)pParam;   
                PostMessage(pCtrl->m_hWnd,   
                                        WM_THREADFIREEVENT,   
                                        (WPARAM)NULL,   
                                        (LPARAM)NULL);   
                return   TRUE;   
             
        
      Notice   in   the   sample   code   above   that   the   window   handle   of   the   ActiveX     
      control   is   used   as   the   target   to   which   the   message   from   the   second   thread   
      will   be   posted.   In   most   cases,   an   MFC   based   ActiveX   control   will   be   in-   
      place   active   when   it's   methods   are   called   and   will   have    window   handle.       
      It   is   possible,   however   for   an   ActiveX   control   to   not   have    window   handle,   
      such   as   in   the   case   of    windowless   control.   One   way   to   work   around   this   
      is   to   create    hidden   window   that   could   be   used   to   communicate   between   
      threads.   That   window   could   then   be   destroyed   when   the   thread   terminated.   
      The   FIREEV   sample   has   code   which   is   commented   out   in   it's   
      StartLengthyProcess   method   and   ThreadProc   thread   work   function   which   
      demonstrates   creating    window   which   is   wrapped   by   the   CMyWindow   class   that   
      serves   this   purpose.   Also   notice   that   PostMessage   is   used   instead   of   
      PostThreadMessage.   MFC's   message   maps   are   set   up   to   intercept   thread   
      messages   in   CWinThread   derived   classes   only.   Since   MFC   ActiveX   controls   
      are   derived   from   CWnd,   they   will   not   have   messages   sent   with   
      PostThreadMessage   routed   to   them.   Messages   sent   with   PostThreadMessage   will   
      have    NULL   hWnd.

    ----------------------------------//

    里面提到的 hWnd,如果在IE使用空间,这个窗口句柄是空的,会导致回调照样失败,
    这时候需要重载OnSetClientSite

    void CMyControl::OnSetClientSite()
    {
    // It doesn't matter who the parent window is or what the size of
    // the window is because the control's window will be reparented
    // and resized correctly later when it's in-place activated.
    if (m_pClientSite)
        VERIFY (CreateControlWindow (::GetDesktopWindow(), CRect(0,0,0,0), CRect(0,0,0,0)));
    COleControl::OnSetClientSite();
    }

    这样,整个流程就走通了。
    js调用 ocx, ocx回调js 全部走通。

    在Windows   XP中,可以在任务栏上看到控件的窗口
    解决的方法是尽可能用GetForegroundWindow替代GetDesktopWindow(GetForegroundWindow有时返回NULL)

    //参考
  • 相关阅读:
    环境搭建-----IntelliJ idea之resin配置
    Maven的pom.xml文件详解------Build Settings
    JVM调优总结
    JAVA基础-栈与堆,static、final修饰符、内部类和Java内存分配
    JVM之字节码——Class文件格式
    java中的深复制和浅复制
    java创建对象的四种方式
    iOS获取所有机型
    博客已停止更新,请移步简书
    NSCache的简单使用
  • 原文地址:https://www.cnblogs.com/lidabo/p/2815059.html
Copyright © 2011-2022 走看看