/*
* Events for OLE
* (c) 2008 Carlos Mora (carlosantoniomora@yahoo.es - harbouradvisor.blogspot.com )
* based on the work of Oscar Lira Lira for ActiveX
* (oscarlira78@hotmail.com - http://_...net)
*/#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>
#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 hDll =
NULL;
LPAtlAxWinInit AtlAxWinInit;
LPAtlAxGetControl AtlAxGetControl;
LPAtlAxCreateControl AtlAxCreateControl;
static void LoadAtl
( void
){ if( ! hDll
) { hDll = LoadLibrary
( "Atl.dll" );
AtlAxWinInit =
( LPAtlAxWinInit
) GetProcAddress
( hDll,
"AtlAxWinInit" );
AtlAxGetControl =
( LPAtlAxGetControl
) GetProcAddress
( hDll,
"AtlAxGetControl" );
AtlAxCreateControl =
( LPAtlAxCreateControl
) GetProcAddress
( hDll,
"AtlAxCreateControl" );
AtlAxWinInit
();
}}HB_FUNC( OLEWECREATE
){ HWND hWndCtrl;
LoadAtl
();
hWndCtrl = CreateWindowEx
( (DWORD
) 0 ,
// nExStyle (LPCTSTR
) "AtlAxWin" ,
// cClsName (LPCTSTR
) hb_parc
( 1 ) ,
// cProgId (DWORD
) WS_OVERLAPPEDWINDOW ,
// style CW_USEDEFAULT ,
// nLeft CW_USEDEFAULT ,
// nTop 0 ,
// nWidth 0 ,
// nHeight HWND_DESKTOP ,
// oParent:handle 0,
0,
NULL );
hb_retnl
( (long
) hWndCtrl
);
}HB_FUNC( OLEWEDESTROY
){ DestroyWindow
( (HWND
) hb_parnl
( 1 ) );
}HB_FUNC( OLEGETDISP
){ IUnknown *pUnk;
IDispatch *pDisp;
LoadAtl
();
AtlAxGetControl
( (HWND
) hb_parnl
( 1 ), &pUnk
);
if (pUnk
) { pUnk->lpVtbl->QueryInterface
( pUnk, &IID_IDispatch,
( void **
) &pDisp
);
pUnk->lpVtbl->Release
( pUnk
);
hb_retnl
( (long
) pDisp
);
}}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 );
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
) ) { itmRef->item.asRefer.value = ulParam
+1;
hb_vmPush
( itmRef
);
} else { hb_vmPush
( (*pItems
)[ulParam
] );
} } hb_itemRelease
( itmRef
);
}}#undef
INTERFACE#define INTERFACE IEventHandler
DECLARE_INTERFACE_
( INTERFACE, IDispatch
){ STDMETHOD
( QueryInterface
) ( THIS_ REFIID, void **
) PURE;
STDMETHOD_
( ULONG, AddRef
) ( THIS
) PURE;
STDMETHOD_
( ULONG,
Release ) ( THIS
) PURE;
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;
};
typedef struct
{ IEventHandler* lpVtbl;
DWORD
count;
IConnectionPoint* pIConnectionPoint;
DWORD dwEventCookie;
IID device_event_interface_iid;
PHB_ITEM pEvents;
PHB_ITEM pEventsExec;
} MyRealIEventHandler;
static HRESULT STDMETHODCALLTYPE QueryInterface
( IEventHandler *this, REFIID vTableGuid, void **ppv
){ if ( IsEqualIID
( vTableGuid, &IID_IUnknown
) ) { *ppv =
(IUnknown*
) this;
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;
} *ppv =
0;
return(E_NOINTERFACE
);
}static ULONG STDMETHODCALLTYPE AddRef
(IEventHandler *this
){ return(++
((MyRealIEventHandler *
) this
)->count
);
}static ULONG STDMETHODCALLTYPE
Release(IEventHandler *this
){ if (--
((MyRealIEventHandler *
) this
)->count ==
0) { GlobalFree
(this
);
return(0);
} return(((MyRealIEventHandler *
) this
)->count
);
}static ULONG STDMETHODCALLTYPE GetTypeInfoCount
(IEventHandler *this, UINT *pCount
){ HB_SYMBOL_UNUSED
(this
);
HB_SYMBOL_UNUSED
(pCount
);
return E_NOTIMPL;
}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;
}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;
}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;
USHORT iArg, i;
PHB_ITEM pItemArray
[32];
PHB_ITEM *pItems;
ULONG ulRefMask =
0;
ULONG ulPos;
PHB_ITEM Key;
BOOL bDefault =
FALSE;
Key = hb_itemNew
( NULL );
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
);
ulPos = hb_arrayScan
( ((MyRealIEventHandler*
) this
)->pEvents, hb_itemPutNL
( Key, dispid
),
NULL,
NULL,
0 #ifdef __XHARBOUR__
,
0 #endif
);
if ( !ulPos
) { ulPos = hb_arrayScan
( ((MyRealIEventHandler*
) this
)->pEvents, hb_itemPutNL
( Key,
0 ),
NULL,
NULL,
0 #ifdef __XHARBOUR__
,
0 #endif
);
bDefault =
TRUE;
};
if ( ulPos
) { PHB_ITEM pExec = hb_arrayGetItemPtr
( ((MyRealIEventHandler*
) this
)->pEventsExec, ulPos
);
if ( pExec
) { hb_vmPushState
();
switch ( hb_itemType
( pExec
) ) { case HB_IT_BLOCK:
{ hb_vmPushSymbol
( &hb_symEval
);
hb_vmPush
( pExec
);
break;
} case HB_IT_STRING:
{ hb_vmPushSymbol
( hb_dynsymSymbol
( hb_dynsymFindName
( hb_itemGetCPtr
( pExec
) ) ) );
hb_vmPushNil
();
break;
} case HB_IT_POINTER:
{ hb_vmPushSymbol
( hb_dynsymSymbol
( ( (PHB_SYMB
) pExec
) -> pDynSym
) );
hb_vmPushNil
();
break;
} } if( bDefault
) { // in default event manager (0), first param will be the EventId hb_vmPushLong
( dispid
);
} iArg =
(USHORT
) params->cArgs;
for( i =
1; i<= iArg; i++
) { pItem = hb_itemNew
(NULL);
hb_oleVariantToItem
( pItem, &
(params->rgvarg
[iArg-i
]) );
pItemArray
[i
-1] = pItem;
ulRefMask |=
( 1L <<
(i
-1) );
} if( iArg
) { pItems = pItemArray;
hb_itemPushList
( ulRefMask, iArg, &pItems
);
} hb_vmDo
( (USHORT
) ( iArg +
( bDefault ?
1 :
0 ) ) );
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_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] ) ?
(USHORT
) 0xFFFF :
(USHORT) 0;
break;
case VT_DATE|VT_BYREF:
*((&
(params->rgvarg
[iArg-i
]))->n1.n2.n3.pdate
) =
(DATE
) (double
) (hb_itemGetDL
(pItemArray
[i
-1])-2415019 );
break;
} } } hb_vmPopState
();
} } hb_itemRelease
( Key
);
return S_OK;
}static const IEventHandlerVtbl IEventHandler_Vtbl =
{ QueryInterface,
AddRef,
Release,
GetTypeInfoCount,
GetTypeInfo,
GetIDsOfNames,
Invoke
};
typedef IEventHandler device_interface;
//-----------------------------------------------HB_FUNC( OLECONNECTEVENTS
)//-----------------------------------------------{ 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;
thisobj =
( IEventHandler *
) GlobalAlloc
( GMEM_FIXED, sizeof
( MyRealIEventHandler
) );
if ( thisobj
) { thisobj->lpVtbl =
(IEventHandlerVtbl *
) &IEventHandler_Vtbl;
((MyRealIEventHandler *
) thisobj
)->count =
0;
((MyRealIEventHandler *
) thisobj
)->device_event_interface_iid = IID_IDispatch;
hr = thisobj->lpVtbl->QueryInterface
( thisobj, &IID_IUnknown,
(void**
) &pIUnknown
);
if ( hr == S_OK && pIUnknown
) { hr = pdevice_interface->lpVtbl->QueryInterface
( pdevice_interface,
&IID_IConnectionPointContainer,
(void**
) &pIConnectionPointContainerTemp
);
if ( hr == S_OK && pIConnectionPointContainerTemp
) { 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
);
} pIConnectionPointContainerTemp->lpVtbl->Release
( pIConnectionPointContainerTemp
);
pIConnectionPointContainerTemp =
NULL;
} if ( hr == S_OK && m_pIConnectionPoint
) { if( hr == S_OK
) { ((MyRealIEventHandler *
) thisobj
)->device_event_interface_iid = rriid;
};
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;
pThis->pEvents = hb_itemNew
( hb_param
( 2, HB_IT_ANY
) );
pThis->pEventsExec = hb_itemNew
( hb_param
( 3, HB_IT_ANY
) );
hb_retnl
( (LONG
) pThis
);
} else { hb_ret
();
};
}//-----------------------------------------------HB_FUNC( OLEDISCONNECTEVENTS
)//-----------------------------------------------{ MyRealIEventHandler *this =
( MyRealIEventHandler *
) hb_parnl
( 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( OLEFREEDISPATCH
)//-----------------------------------------------{ IDispatch * pObj;
pObj =
( IDispatch *
) hb_parnl
( 1 );
pObj->lpVtbl->Release
( pObj
);
}