Hi Mindaugas/Viktor

I am trying to test the new OLE implementation with the latest SVN. I must confess I have fallen out of my depth quite quickly.

The attached Clipper class and supporting C file is taken from hwgui.prg and they are used to manage the event handlers which an ActiveX object can trigger.

I don't think there is anything which is not generic (that is, specific to hwgui) and it completes the picture with ActiveX for me. For example in the current implementation in Harbour there is no window creation and normally an ActiveX control will have a window.

An example is in samples\rmchart in hwgui, but of course you would need hwgui to test that example, and the rmchart ActiveX (http://www.rmchart.com/).

Please, if this is not your cup of tea at the moment, ignore this e-mail.

Regards
Alex


Example of my usage:

CLASS BPTI FROM HActiveX

    METHOD terminalDSPEvent(p1, p2, p3, p4) ;
            INLINE ::Event("terminalDSPEvent", p1, p2, p3, p4)
    METHOD infoEvent(p1, p2, p3, p4) ;
            INLINE ::Event("infoEvent", p1, p2, p3, p4)
    METHOD exceptionEvent(p1, p2, p3, p4) ;
            INLINE ::Event("exceptionEvent", p1, p2, p3, p4)
    METHOD txnResultEvent(p1, p2, p3, p4) ;
            INLINE ::Event("txnResultEvent", p1, p2, p3, p4)
    METHOD referralEvent(p1, p2, p3, p4) ;
            INLINE ::Event("referralEvent", p1, p2, p3, p4)
    METHOD lppCmdFailedEvent(p1, p2, p3, p4) ;
            INLINE ::Event("lppCmdFailedEvent", p1, p2, p3, p4)
    METHOD cardDataEvent(p1, p2, p3, p4) ;
            INLINE ::Event("cardDataEvent", p1, p2, p3, p4)
    METHOD resultDataEvent(p1, p2, p3, p4) ;
            INLINE ::Event("resultDataEvent", p1, p2, p3, p4)
    METHOD terminatedEvent(p1, p2, p3, p4) ;
            INLINE ::Event("terminatedEvent", p1, p2, p3, p4)
    METHOD statusChangeEvent(p1, p2, p3, p4) ;
            INLINE ::Event("statusChangeEvent", p1, p2, p3, p4)
    METHOD New()
    METHOD Event()

ENDCLASS


//
// The event numbers are taken from the Type Library - ICoBpTiEvents
//

METHOD New(oWnd, cProgId, nTop, nLeft, nWidth, nHeight) CLASS BPTI

    ::EventMap(1, "terminalDSPEvent", self)
    ::EventMap(2, "infoEvent", self)
    ::EventMap(3, "exceptionEvent", self)
    ::EventMap(4, "txnResultEvent", self)
    ::EventMap(5, "referralEvent", self)
    ::EventMap(6, "lppCmdFailedEvent", self)
    ::EventMap(7, "cardDataEvent", self)
    ::EventMap(8, "resultDataEvent", self)
    ::EventMap(9, "terminatedEvent", self)
    ::EventMap(10, "statusChangeEvent", self)

return Super:New(oWnd, cProgId, nTop, nLeft, nWidth, nHeight)


METHOD Event(cEvent, p2, p3, p4, p5) CLASS BPTI

    local cApproval
    local cMessage

        // do stuff
    if cEvent == "terminalDSPEvent"
    elseif cEvent == "infoEvent"
    elseif cEvent == "exceptionEvent"
    endif

return nil




/*
 * $Id: h_activex.prg,v 1.1 2008/03/31 23:07:57 fperillo Exp $
 */
/*
 * ooHG source code:
 * ActiveX control
 *
 *  Marcelo Torres, Noviembre de 2006.
 *  TActiveX para [x]Harbour Minigui.
 *  Adaptacion del trabajo de:
 *  ---------------------------------------------
 *  Lira Lira Oscar Joel [oSkAr]
 *  Clase TActiveX_FreeWin para Fivewin
 *  Noviembre 8 del 2006
 *  email: oscarlir...@hotmail.com
 *  http://freewin.sytes.net
 *  @CopyRight 2006 Todos los Derechos Reservados
 *  ---------------------------------------------
 *  Implemented by ooHG team.
 *
 * + Soporte de Eventos para los controles activeX [oSkAr] 20070829
 *
 * + Ported to hwgui by FP 20080331
 *
 */

#include "windows.ch"
#include "hbclass.ch"

//-----------------------------------------------------------------------------------------------//
CLASS HActiveX FROM HControl
  CLASS VAR winclass    INIT "ACTIVEX"
   DATA oOle      INIT nil
   DATA hSink     INIT nil
   DATA hAtl      INIT nil
   DATA hObj      INIT nil

   METHOD Release
   METHOD New

   DELEGATE Set TO oOle
   DELEGATE Get TO oOle
   ERROR HANDLER __Error

   DATA aAxEv        INIT {}              // oSkAr 20070829
   DATA aAxExec      INIT {}              // oSkAr 20070829
   METHOD EventMap( nMsg, xExec, oSelf )  // oSkAr 20070829

ENDCLASS

METHOD New( oWnd, cProgId, nTop, nLeft, nWidth, nHeight, bSize ) CLASS HActiveX
   LOCAL nStyle, nExStyle, cClsName, hSink
   LOCAL i,a,h,n
   LOCAL oError, bErrorBlock

   nStyle   := WS_CHILD + WS_VISIBLE + WS_CLIPCHILDREN
   nExStyle := 0
   cClsName := "AtlAxWin"

   Super:New( oWnd, , nStyle, nLeft, nTop, nWidth, nHeight )   // ,,,,bSize)
   ::title = cProgId

   ::handle = CreateActivex(  nExStyle, cClsName, cProgId, ::style, ;
                              ::nLeft, ::nTop, ::nWidth, ::nHeight, ;
                              ::oParent:handle, ::Id     ;
                            )

   ::Init()

   ::hObj   := AtlAxGetDisp( ::handle )

   bErrorBlock := ErrorBlock( { |x| break( x ) } )
   #ifdef __XHARBOUR__
      TRY
         ::oOle := ToleAuto():New( ::hObj )
      CATCH oError
         MsgInfo( oError:Description )
      END
   #else
      BEGIN SEQUENCE
         ::oOle := ToleAuto():New( ::hObj )
      RECOVER USING oError
         MsgInfo( oError:Description )
      END
   #endif
   ErrorBlock( bErrorBlock )

   SetupConnectionPoint( ::hObj, @hSink, ::aAxEv , ::aAxExec )
   ::hSink := hSink

   RETURN SELF

*-----------------------------------------------------------------------------*
METHOD Release() CLASS HActiveX
*-----------------------------------------------------------------------------*
   SHUTDOWNCONNECTIONPOINT( ::hSink )
   ReleaseDispatch( ::hObj )
Return ::Super:Release()

*-----------------------------------------------------------------------------* 
METHOD __Error( ... ) CLASS HActiveX 
*-----------------------------------------------------------------------------* 
Local cMessage, uRet 
cMessage := __GetMessage() 

   IF SubStr( cMessage, 1, 1 ) == "_"
      cMessage := SubStr( cMessage, 2 )
   ENDIF

   RETURN HB_ExecFromArray( ::oOle, cMessage, HB_aParams() )

//-----------------------------------------------------------------------------------------------//
METHOD EventMap( nMsg, xExec, oSelf ) CLASS HActiveX
   LOCAL nAt
   nAt := AScan( ::aAxEv, nMsg )
   IF nAt == 0
      AAdd( ::aAxEv, nMsg )
      AAdd( ::aAxExec, { NIL, NIL } )
      nAt := Len( ::aAxEv )
   ENDIF
   ::aAxExec[ nAt ] := { xExec, oSelf }
RETURN NIL

/*
 * $Id: c_activex.c,v 1.3 2008/11/20 16:58:48 lculik Exp $
 */
/*
 * ooHG source code:
 * ActiveX control
 *
 *  Marcelo Torres, Noviembre de 2006.
 *  TActiveX para [x]Harbour Minigui.
 *  Adaptacion del trabajo de:
 *  ---------------------------------------------
 *  Lira Lira Oscar Joel [oSkAr]
 *  Clase TActiveX_FreeWin para Fivewin
 *  Noviembre 8 del 2006
 *  email: oscarlir...@hotmail.com
 *  http://freewin.sytes.net
 *  @CopyRight 2006 Todos los Derechos Reservados
 *  ---------------------------------------------
 *  Implemented by ooHG team.
 *
 * + Soporte de Eventos para los controles activeX [oSkAr] 20070829
 *
 * + Ported to hwgui by FP 20080331
 *
 */

#ifndef NONAMELESSUNION
   #define NONAMELESSUNION
#endif

#ifndef _HB_API_INTERNAL_
   #define _HB_API_INTERNAL_
#endif

#include <hbvmopt.h>
#include <windows.h>
#include <commctrl.h>
#include <hbapi.h>
#include <hbvm.h>
#include <hbstack.h>
#include <ocidl.h>
#include <hbapiitm.h>
#include "guilib.h"
#ifdef HB_ITEM_NIL
   #define hb_dynsymSymbol( pDynSym )        ( ( pDynSym )->pSymbol )
#endif

PHB_SYMB s___GetMessage = NULL;

typedef HRESULT ( WINAPI *LPAtlAxWinInit )       ( void );
typedef HRESULT ( WINAPI *LPAtlAxGetControl )    ( HWND, IUnknown** );
typedef HRESULT ( WINAPI *LPAtlAxCreateControl ) ( LPCOLESTR, HWND, IStream*, 
IUnknown** );

HMODULE hAtl = NULL;
LPAtlAxWinInit       AtlAxWinInit;
LPAtlAxGetControl    AtlAxGetControl;
LPAtlAxCreateControl AtlAxCreateControl;

static void _Ax_Init( void )
{
   if( ! hAtl )
   {
      hAtl = LoadLibrary( "Atl.Dll" );
      AtlAxWinInit       = ( LPAtlAxWinInit )       GetProcAddress( hAtl, 
"AtlAxWinInit" );
      AtlAxGetControl    = ( LPAtlAxGetControl )    GetProcAddress( hAtl, 
"AtlAxGetControl" );
      AtlAxCreateControl = ( LPAtlAxCreateControl ) GetProcAddress( hAtl, 
"AtlAxCreateControl" );
      ( AtlAxWinInit )();
   }
}

HB_FUNC( CREATEACTIVEX )
{
   HWND hWndCtrl;

   _Ax_Init();
   hWndCtrl = CreateWindowEx(
      (DWORD)  ISNIL(  1 ) ? 0                   : hb_parni( 1 ),   // nExStyle
      (LPCTSTR)ISNIL(  2 ) ? "A3434_CLASS"       : hb_parc( 2 ) ,   // cClsName
      (LPCTSTR)ISNIL(  3 ) ? ""                  : hb_parc( 3 ) ,   // cProgId
      (DWORD)  ISNIL(  4 ) ? WS_OVERLAPPEDWINDOW : hb_parni( 4 ),   // style
               ISNIL(  5 ) ? CW_USEDEFAULT       : hb_parni( 5 ),   // nLeft
               ISNIL(  6 ) ? CW_USEDEFAULT       : hb_parni( 6 ),   // nTop
               ISNIL(  7 ) ? 544                 : hb_parni( 7 ),   // nWidth
               ISNIL(  8 ) ? 375                 : hb_parni( 8 ),   // nHeight
               ISNIL(  9 ) ? HWND_DESKTOP        : (HWND) hb_parnl( 9 ),    // 
oParent:handle
               // ISNIL( 10 ) ? NULL                : (HMENU) hb_parnl( 10 ),  
// Id
               // GetModuleHandle( 0 ),
               0,
               0,
               NULL );

   HB_RETHANDLE( hWndCtrl );

}


HB_FUNC( ATLAXGETDISP ) // hWnd -> pDisp
{
   IUnknown *pUnk;
   IDispatch *pDisp;
   _Ax_Init();
   AtlAxGetControl( (HWND) HB_PARHANDLE( 1 ), &pUnk );
   pUnk->lpVtbl->QueryInterface( pUnk, &IID_IDispatch, ( void ** ) &pDisp );
   pUnk->lpVtbl->Release( pUnk );
   HB_RETHANDLE( pDisp );
}

/*
 *   oskar 20070829
 *   Soporte de Eventos :)
 */
/*-----------------------------------------------------------------------------------------------*/

//   #define __USEHASHEVENTS

#ifdef __USEHASHEVENTS
   #include <hashapi.h>
#endif

   
//------------------------------------------------------------------------------
   HRESULT hb_oleVariantToItem( PHB_ITEM pItem, VARIANT *pVariant );

   
//------------------------------------------------------------------------------
   static void HB_EXPORT hb_itemPushList( ULONG ulRefMask, ULONG ulPCount, 
PHB_ITEM** pItems )
   {
      PHB_ITEM itmRef;
      ULONG ulParam;

      if( ulPCount )
      {
         itmRef = hb_itemNew( NULL );

         // initialize the reference item
         itmRef->type = HB_IT_BYREF;
         itmRef->item.asRefer.offset = -1;
         itmRef->item.asRefer.BasePtr.itemsbasePtr = pItems;
         for( ulParam = 0; ulParam < ulPCount; ulParam++ )
         {
            if( ulRefMask & ( 1L << ulParam ) )
            {
               // when item is passed by reference then we have to put
               // the reference on the stack instead of the item itself
               itmRef->item.asRefer.value = ulParam+1;
               hb_vmPush( itmRef );
            }
            else
            {
               hb_vmPush( (*pItems)[ulParam] );
            }
         }

         hb_itemRelease( itmRef );
      }
   }

   
//------------------------------------------------------------------------------
   //this is a macro which defines our IEventHandler struct as so:
   //
   // typedef struct {
   //    IEventHandlerVtbl  *lpVtbl;
   // } IEventHandler;

   #undef  INTERFACE
   #define INTERFACE IEventHandler

   DECLARE_INTERFACE_ ( INTERFACE, IDispatch )
   {
      // IUnknown functions
      STDMETHOD  ( QueryInterface          ) ( THIS_ REFIID, void **            
                                              ) PURE;
      STDMETHOD_ ( ULONG, AddRef           ) ( THIS                             
                                              ) PURE;
      STDMETHOD_ ( ULONG, Release          ) ( THIS                             
                                              ) PURE;
      // IDispatch functions
      STDMETHOD_ ( ULONG, GetTypeInfoCount ) ( THIS_ UINT *                     
                                              ) PURE;
      STDMETHOD_ ( ULONG, GetTypeInfo      ) ( THIS_ UINT, LCID, ITypeInfo **   
                                              ) PURE;
      STDMETHOD_ ( ULONG, GetIDsOfNames    ) ( THIS_ REFIID, LPOLESTR *, UINT, 
LCID, DISPID *                                 ) PURE;
      STDMETHOD_ ( ULONG, Invoke           ) ( THIS_ DISPID, REFIID, LCID, 
WORD, DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT * ) PURE;
   };

   // In other words, it defines our IEventHandler to have nothing
   // but a pointer to its VTable. And of course, every COM object must
   // start with a pointer to its VTable.
   //
   // But we actually want to add some more members to our IEventHandler.
   // We just don't want any app to be able to know about, and directly
   // access, those members. So here we'll define a MyRealIEventHandler that
   // contains those extra members. The app doesn't know that we're
   // really allocating and giving it a MyRealIEventHAndler object. We'll
   // lie and tell it we're giving a plain old IEventHandler. That's ok
   // because a MyRealIEventHandler starts with the same VTable pointer.
   //
   // We add a DWORD reference count so that this IEventHandler
   // can be allocated (which we do in our IClassFactory object's
   // CreateInstance()) and later freed. And, we have an extra
   // BSTR (pointer) string, which is used by some of the functions we'll
   // add to IEventHandler

   typedef struct {

      IEventHandler*          lpVtbl;
      DWORD                   count;
      IConnectionPoint*       pIConnectionPoint;  // Ref counted of course.
      DWORD                   dwEventCookie;
      IID                     device_event_interface_iid;
      PHB_ITEM                pEvents;

#ifndef __USEHASHEVENTS
      PHB_ITEM                pEventsExec;
#endif

   } MyRealIEventHandler;

   
//------------------------------------------------------------------------------
   // Here are IEventHandler's functions.
   
//------------------------------------------------------------------------------
   // Every COM object's interface must have the 3 functions QueryInterface(),
   // AddRef(), and Release().

   // IEventHandler's QueryInterface()
   static HRESULT STDMETHODCALLTYPE QueryInterface( IEventHandler *this, REFIID 
vTableGuid, void **ppv )
   {
      // Check if the GUID matches IEvenetHandler VTable's GUID. We gave the C 
variable name
      // IID_IEventHandler to our VTable GUID. We can use an OLE function called
      // IsEqualIID to do the comparison for us. Also, if the caller passed a
      // IUnknown GUID, then we'll likewise return the IEventHandler, since it 
can
      // masquerade as an IUnknown object too. Finally, if the called passed a
      // IDispatch GUID, then we'll return the IExample3, since it can 
masquerade
      // as an IDispatch too

      if ( IsEqualIID( vTableGuid, &IID_IUnknown ) )
      {
         *ppv = (IUnknown*) this;
         // Increment the count of callers who have an outstanding pointer to 
this object
         this->lpVtbl->AddRef( this );
         return S_OK;
      }

      if ( IsEqualIID( vTableGuid, &IID_IDispatch ) )
      {
         *ppv = (IDispatch*) this;
         this->lpVtbl->AddRef( this );
         return S_OK;
      }

      if ( IsEqualIID( vTableGuid, &(((MyRealIEventHandler*) 
this)->device_event_interface_iid ) ) )
      {
         *ppv = (IDispatch*) this;
         this->lpVtbl->AddRef( this );
         return S_OK;
      }

      // We don't recognize the GUID passed to us. Let the caller know this,
      // by clearing his handle, and returning E_NOINTERFACE.
      *ppv = 0;
      return(E_NOINTERFACE);
   }

   
//------------------------------------------------------------------------------
   // IEventHandler's AddRef()
   static ULONG STDMETHODCALLTYPE AddRef(IEventHandler *this)
   {
      // Increment IEventHandler's reference count, and return the updated 
value.
      // NOTE: We have to typecast to gain access to any data members. These
      // members are not defined  (so that an app can't directly access them).
      // Rather they are defined only above in our MyRealIEventHandler
      // struct. So typecast to that in order to access those data members
      return(++((MyRealIEventHandler *) this)->count);
   }

   
//------------------------------------------------------------------------------
   // IEventHandler's Release()
   static ULONG STDMETHODCALLTYPE Release(IEventHandler *this)
   {
      if (--((MyRealIEventHandler *) this)->count == 0)
      {
         GlobalFree(this);
         return(0);
      }
      return(((MyRealIEventHandler *) this)->count);
   }

   
//------------------------------------------------------------------------------
   // IEventHandler's GetTypeInfoCount()
   static ULONG STDMETHODCALLTYPE GetTypeInfoCount(IEventHandler *this, UINT 
*pCount)
   {
      HB_SYMBOL_UNUSED(this);
      HB_SYMBOL_UNUSED(pCount);
      return E_NOTIMPL;
   }

   
//------------------------------------------------------------------------------
   // IEventHandler's GetTypeInfo()
   static ULONG STDMETHODCALLTYPE GetTypeInfo(IEventHandler *this, UINT itinfo, 
LCID lcid, ITypeInfo **pTypeInfo)
   {
      HB_SYMBOL_UNUSED(this);
      HB_SYMBOL_UNUSED(itinfo);
      HB_SYMBOL_UNUSED(lcid);
      HB_SYMBOL_UNUSED(pTypeInfo);
      return E_NOTIMPL;
   }

   
//------------------------------------------------------------------------------
   // IEventHandler's GetIDsOfNames()
   static ULONG STDMETHODCALLTYPE GetIDsOfNames(IEventHandler *this, REFIID 
riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid)
   {
      HB_SYMBOL_UNUSED(this);
      HB_SYMBOL_UNUSED(riid);
      HB_SYMBOL_UNUSED(rgszNames);
      HB_SYMBOL_UNUSED(cNames);
      HB_SYMBOL_UNUSED(lcid);
      HB_SYMBOL_UNUSED(rgdispid);
      return E_NOTIMPL;
   }

   
//------------------------------------------------------------------------------
   // IEventHandler's Invoke()
   // this is where the action happens
   // this function receives events (by their ID number) and distributes the 
processing
   // or them or ignores them
   static ULONG STDMETHODCALLTYPE Invoke( IEventHandler *this, DISPID dispid, 
REFIID riid,
      LCID lcid, WORD wFlags, DISPPARAMS *params, VARIANT *result, EXCEPINFO 
*pexcepinfo,
      UINT *puArgErr )
   {
      PHB_ITEM pItem;
      int iArg, i;
      PHB_ITEM pItemArray[32]; // max 32 parameters?
      PHB_ITEM *pItems;
      ULONG ulRefMask = 0;
      ULONG ulPos;
      PHB_ITEM Key;

      Key = hb_itemNew( NULL );

      // We implement only a "default" interface
      if ( !IsEqualIID( riid, &IID_NULL ) )
         return( DISP_E_UNKNOWNINTERFACE );

      HB_SYMBOL_UNUSED(lcid);
      HB_SYMBOL_UNUSED(wFlags);
      HB_SYMBOL_UNUSED(result);
      HB_SYMBOL_UNUSED(pexcepinfo);
      HB_SYMBOL_UNUSED(puArgErr);

      // delegate work to somewhere else in PRG
      //***************************************

#ifdef __USEHASHEVENTS

      if ( hb_hashScan( ((MyRealIEventHandler* ) this)->pEvents, hb_itemPutNL( 
Key, dispid ),
         &ulPos ) )
      {
         PHB_ITEM pArray = hb_hashGetValueAt( ((MyRealIEventHandler* ) 
this)->pEvents, ulPos );

#else

      ulPos = hb_arrayScan( ((MyRealIEventHandler* ) this)->pEvents, 
hb_itemPutNL( Key, dispid ),
         NULL, NULL, 0
            #ifdef __XHARBOUR__
               , 0
            #endif
         );

      if ( ulPos )
      {
         PHB_ITEM pArray = hb_arrayGetItemPtr( ((MyRealIEventHandler* ) 
this)->pEventsExec, ulPos );

#endif

         PHB_ITEM pExec  = hb_arrayGetItemPtr( pArray, 01 );

         if ( pExec )
         {

            hb_vmPushState();

            switch ( hb_itemType( pExec ) )
            {

               case HB_IT_BLOCK:
               {
                  hb_vmPushSymbol( &hb_symEval );
                  hb_vmPush( pExec );
                  break;
               }

               case HB_IT_STRING:
               {
                  PHB_ITEM pObject = hb_arrayGetItemPtr( pArray, 2 );
                  hb_vmPushSymbol( hb_dynsymSymbol( hb_dynsymFindName( 
hb_itemGetCPtr( pExec ) ) ) );

                  if ( HB_IS_OBJECT( pObject ) )
                     hb_vmPush( pObject );
                  else
                     hb_vmPushNil();
                  break;

               }

               case HB_IT_POINTER:
               {
                  hb_vmPushSymbol( hb_dynsymSymbol( ( (PHB_SYMB) pExec ) -> 
pDynSym ) );
                  hb_vmPushNil();
                  break;
               }

            }

            iArg = params->cArgs;
            for( i = 1; i<= iArg; i++ )
            {
               pItem = hb_itemNew(NULL);
               hb_oleVariantToItem( pItem, &(params->rgvarg[iArg-i]) );
               pItemArray[i-1] = pItem;
               // set bit i
               ulRefMask |= ( 1L << (i-1) );
            }

            if( iArg )
            {
               pItems = pItemArray;
               hb_itemPushList( ulRefMask, iArg, &pItems );
            }

            // execute
            hb_vmDo( iArg );

            // En caso de que los parametros sean pasados por referencia
            for( i=iArg; i > 0; i-- )
            {
               if( (&(params->rgvarg[iArg-i]))->n1.n2.vt & VT_BYREF == VT_BYREF 
)
               {

                  switch( (&(params->rgvarg[iArg-i]))->n1.n2.vt )
                  {

                     //case VT_UI1|VT_BYREF:
                     //   *((&(params->rgvarg[iArg-i]))->n1.n2.n3.pbVal) = 
va_arg(argList,unsigned char*);  //pItemArray[i-1]
                     //   break;
                     case VT_I2|VT_BYREF:
                        *((&(params->rgvarg[iArg-i]))->n1.n2.n3.piVal)    = 
(short)          hb_itemGetNI(pItemArray[i-1]);
                        break;
                     case VT_I4|VT_BYREF:
                        *((&(params->rgvarg[iArg-i]))->n1.n2.n3.plVal)    = 
(long)           hb_itemGetNL(pItemArray[i-1]);
                        break;
                     case VT_R4|VT_BYREF:
                        *((&(params->rgvarg[iArg-i]))->n1.n2.n3.pfltVal)  = 
(float)          hb_itemGetND(pItemArray[i-1]);
                        break;
                     case VT_R8|VT_BYREF:
                        *((&(params->rgvarg[iArg-i]))->n1.n2.n3.pdblVal)  = 
(double)         hb_itemGetND(pItemArray[i-1]);
                        break;
                     case VT_BOOL|VT_BYREF:
                        *((&(params->rgvarg[iArg-i]))->n1.n2.n3.pboolVal) =     
             hb_itemGetL( pItemArray[i-1] ) ? 0xFFFF : 0;
                        break;
                     //case VT_ERROR|VT_BYREF:
                     //   *((&(params->rgvarg[iArg-i]))->n1.n2.n3.pscode) = 
va_arg(argList, SCODE*);
                     //   break;
                     case VT_DATE|VT_BYREF:
                        *((&(params->rgvarg[iArg-i]))->n1.n2.n3.pdate)    = 
(DATE) (double) (hb_itemGetDL(pItemArray[i-1])-2415019 );
                        break;
                     //case VT_CY|VT_BYREF:
                     //   *((&(params->rgvarg[iArg-i]))->n1.n2.n3.pcyVal) = 
va_arg(argList, CY*);
                     //   break;
                     //case VT_BSTR|VT_BYREF:
                     //   *((&(params->rgvarg[iArg-i]))->n1.n2.n3.pbstrVal = 
va_arg(argList, BSTR*);
                     //   break;
                     //case VT_UNKNOWN|VT_BYREF:
                     //   pArg->ppunkVal = va_arg(argList, LPUNKNOWN*);
                     //   break;
                     //case VT_DISPATCH|VT_BYREF:
                     //   pArg->ppdispVal = va_arg(argList, LPDISPATCH*);
                     //   break;

                  } // EOF switch( (&(params->rgvarg[iArg-i]))->n1.n2.vt )

               } // EOF if( (&(params->rgvarg[iArg-i]))->n1.n2.vt & VT_BYREF == 
VT_BYREF )

            } // EOF for( i=iArg; i > 0; i-- )

            hb_vmPopState();

         } // EOF if ( pExec )

      }  // EOF If Scan

      hb_itemRelease( Key );

      return S_OK;

   }  // EOF invoke

   
//------------------------------------------------------------------------------
   // Here's IEventHandler's VTable. It never changes so we can declare it 
static
   static const IEventHandlerVtbl IEventHandler_Vtbl = {
      QueryInterface,
      AddRef,
      Release,
      GetTypeInfoCount,
      GetTypeInfo,
      GetIDsOfNames,
      Invoke
   };

   
//------------------------------------------------------------------------------
   // constructor
   // params:
   // device_interface        - refers to the interface type of the COM object 
(whose event we are trying to receive).
   // device_event_interface  - indicates the interface type of the outgoing 
interface supported by the COM object.
   //                           This will be the interface that must be 
implemented by the Sink object.
   //                           is essentially derived from IDispatch, our Sink 
object (this IEventHandler)
   //                           is also derived from IDispatch.

   typedef IEventHandler device_interface;

   // Hash  // SetupConnectionPoint( oOle:hObj, @hSink, hEvents )             
-> nError
   // Array // SetupConnectionPoint( oOle:hObj, @hSink, aEvents, aExecEvent ) 
-> nError

   HB_FUNC( SETUPCONNECTIONPOINT )
   {
      IConnectionPointContainer*  pIConnectionPointContainerTemp = NULL;
      IUnknown*                   pIUnknown = NULL;
      IConnectionPoint*           m_pIConnectionPoint;
      IEnumConnectionPoints*      m_pIEnumConnectionPoints;
      HRESULT                     hr; //,r;
      IID                         rriid;
      register IEventHandler *    thisobj;
      DWORD                       dwCookie = 0;

      device_interface*           pdevice_interface = (device_interface*) 
hb_parnl( 1 );
      MyRealIEventHandler*        pThis;

      // Allocate our IEventHandler object (actually a MyRealIEventHandler)
      // intentional misrepresentation of size

      thisobj = ( IEventHandler *) GlobalAlloc( GMEM_FIXED, sizeof( 
MyRealIEventHandler ) );

      if ( ! thisobj )
      {
         hr = E_OUTOFMEMORY;
      }
      else
      {
         // Store IEventHandler's VTable in the object
         thisobj->lpVtbl = (IEventHandlerVtbl *) &IEventHandler_Vtbl;

         // Increment the reference count so we can call Release() below and
         // it will deallocate only if there is an error with QueryInterface()
         ((MyRealIEventHandler *) thisobj)->count = 0;

         //((MyRealIEventHandler *) thisobj)->device_event_interface_iid = 
&riid;
         ((MyRealIEventHandler *) thisobj)->device_event_interface_iid = 
IID_IDispatch;

         // Query this object itself for its IUnknown pointer which will be used
         // later to connect to the Connection Point of the device_interface 
object.
         hr = thisobj->lpVtbl->QueryInterface( thisobj, &IID_IUnknown, (void**) 
&pIUnknown );
         if ( hr == S_OK && pIUnknown )
         {

            // Query the pdevice_interface for its connection point.
            hr = pdevice_interface->lpVtbl->QueryInterface( pdevice_interface,
               &IID_IConnectionPointContainer, (void**) 
&pIConnectionPointContainerTemp );

            if ( hr == S_OK && pIConnectionPointContainerTemp )
            {
               // start uncomment
               hr = 
pIConnectionPointContainerTemp->lpVtbl->EnumConnectionPoints( 
pIConnectionPointContainerTemp, &m_pIEnumConnectionPoints );

               if ( hr == S_OK && m_pIEnumConnectionPoints )
               {
                  do
                  {
                     hr = m_pIEnumConnectionPoints->lpVtbl->Next( 
m_pIEnumConnectionPoints, 1, &m_pIConnectionPoint , NULL);
                     if( hr == S_OK )
                     {
                        if ( 
m_pIConnectionPoint->lpVtbl->GetConnectionInterface( m_pIConnectionPoint, 
&rriid ) == S_OK )
                        {
                           break;
                        }
                     }

                  } while( hr == S_OK );
                  
m_pIEnumConnectionPoints->lpVtbl->Release(m_pIEnumConnectionPoints);
               }
               // end uncomment

               //hr = pIConnectionPointContainerTemp 
->lpVtbl->FindConnectionPoint(pIConnectionPointContainerTemp ,  &IID_IDispatch, 
&m_pIConnectionPoint);
               pIConnectionPointContainerTemp->lpVtbl->Release( 
pIConnectionPointContainerTemp );
               pIConnectionPointContainerTemp = NULL;
            }

            if ( hr == S_OK && m_pIConnectionPoint )
            {
               //OutputDebugString("getting iid");
               //Returns the IID of the outgoing interface managed by this 
connection point.
               //hr = 
m_pIConnectionPoint->lpVtbl->GetConnectionInterface(m_pIConnectionPoint, &rriid 
);
               //OutputDebugString("called");

               if( hr == S_OK )
               {
                  ((MyRealIEventHandler *) thisobj)->device_event_interface_iid 
= rriid;
               }
               else
                  OutputDebugString("error getting iid");

               //OutputDebugString("calling advise");
               hr = m_pIConnectionPoint->lpVtbl->Advise( m_pIConnectionPoint, 
pIUnknown, &dwCookie );
               ((MyRealIEventHandler *) thisobj)->pIConnectionPoint = 
m_pIConnectionPoint;
               ((MyRealIEventHandler *) thisobj)->dwEventCookie = dwCookie;

            }

            pIUnknown->lpVtbl->Release(pIUnknown);
            pIUnknown = NULL;

         }
      }

      if( thisobj )
      {
         pThis = (void*) thisobj;

#ifndef __USEHASHEVENTS
         pThis->pEventsExec = hb_itemNew( hb_param( 4, HB_IT_ANY ) );
#endif

         pThis->pEvents     = hb_itemNew( hb_param( 3, HB_IT_ANY ) );
         hb_stornl( (LONG) pThis, 2 );

      }

      hb_retnl( hr );

   }

//------------------------------------------------------------------------------
HB_FUNC( SHUTDOWNCONNECTIONPOINT )
{
   MyRealIEventHandler *this = ( MyRealIEventHandler * ) HB_PARHANDLE( 1 );
   if( this->pIConnectionPoint )
   {
      this->pIConnectionPoint->lpVtbl->Unadvise( this->pIConnectionPoint, 
this->dwEventCookie );
      this->dwEventCookie = 0;
      this->pIConnectionPoint->lpVtbl->Release( this->pIConnectionPoint );
      this->pIConnectionPoint = NULL;
   }
}

//------------------------------------------------------------------------------
HB_FUNC( RELEASEDISPATCH )
{
   IDispatch * pObj;
   pObj = ( IDispatch * ) HB_PARHANDLE( 1 );
   pObj->lpVtbl->Release( pObj );
}
_______________________________________________
Harbour mailing list
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to