2010-10-14 05:45 UTC+0300 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt)
* harbour/contrib/hbwin/axcore.c
+ added support for obtaining default callback event interface.
__AxRegisterHandler( pDisp, bHandler [, cIID ] ) parameter can be:
- event interface ID, i.e. "{...}";
- event interface name, ex., DWebBrowserEvents;
- otherwise default event interface is tried to obtain.
; NOTE: some regresions are possible. IDispatch is not the default
value for cIID. To force the previous behaviour, you should use
__AxRegisterHandler(,, "{00020420-0000-0000-C000-000000000046}"),
but I guess this should never be required.
; Don't ask me how I've wrote this code :)
* harbour/contrib/hbwin/tests/pdfcreat.prg
* changed to sync with new __AxRegisterHandler() behaviour
* harbour/contrib/hbwin/tests/testole.prg
+ added new Internet Explorer test to show OLE callback events
This commit is contained in:
@@ -16,6 +16,23 @@
|
||||
The license applies to all entries newer than 2009-04-28.
|
||||
*/
|
||||
|
||||
2010-10-14 05:45 UTC+0300 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt)
|
||||
* harbour/contrib/hbwin/axcore.c
|
||||
+ added support for obtaining default callback event interface.
|
||||
__AxRegisterHandler( pDisp, bHandler [, cIID ] ) parameter can be:
|
||||
- event interface ID, i.e. "{...}";
|
||||
- event interface name, ex., DWebBrowserEvents;
|
||||
- otherwise default event interface is tried to obtain.
|
||||
; NOTE: some regresions are possible. IDispatch is not the default
|
||||
value for cIID. To force the previous behaviour, you should use
|
||||
__AxRegisterHandler(,, "{00020420-0000-0000-C000-000000000046}"),
|
||||
but I guess this should never be required.
|
||||
; Don't ask me how I've wrote this code :)
|
||||
* harbour/contrib/hbwin/tests/pdfcreat.prg
|
||||
* changed to sync with new __AxRegisterHandler() behaviour
|
||||
* harbour/contrib/hbwin/tests/testole.prg
|
||||
+ added new Internet Explorer test to show OLE callback events
|
||||
|
||||
2010-10-14 00:31 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
|
||||
* harbour/contrib/rddads/ads1.c
|
||||
! casting
|
||||
|
||||
@@ -373,7 +373,206 @@ static const IDispatchVtbl ISink_Vtbl = {
|
||||
};
|
||||
|
||||
|
||||
HB_FUNC( __AXREGISTERHANDLER ) /* ( pDisp, bHandler [, cID] ) --> pSink */
|
||||
#if 0
|
||||
/* Debug helper function */
|
||||
static char * GUID2String( GUID * pID )
|
||||
{
|
||||
static char strguid[ 128 ];
|
||||
wchar_t olestr[ 128 ];
|
||||
int iLen;
|
||||
|
||||
StringFromGUID2( pID, olestr, 256 );
|
||||
iLen = WideCharToMultiByte( CP_ACP, 0, olestr, -1, strguid, 256, NULL, NULL );
|
||||
strguid[ iLen - 1 ] = 0;
|
||||
return strguid;
|
||||
}
|
||||
#endif
|
||||
|
||||
static HRESULT _get_default_sink( IDispatch * iDisp, const char * szEvent, IID * piid )
|
||||
{
|
||||
ITypeInfo * iTI;
|
||||
ITypeInfo * iTISink;
|
||||
TYPEATTR * pTypeAttr;
|
||||
HREFTYPE hRefType;
|
||||
HRESULT hr;
|
||||
int iFlags, i, j;
|
||||
|
||||
if( ! szEvent )
|
||||
{
|
||||
IProvideClassInfo2 * iPCI2;
|
||||
IProvideClassInfo * iPCI;
|
||||
|
||||
/* Method 1: using IProvideClassInfo2 */
|
||||
|
||||
hr = iDisp->lpVtbl->QueryInterface( iDisp, &IID_IProvideClassInfo2, ( void** ) ( void* ) &iPCI2 );
|
||||
if( hr == 0 )
|
||||
{
|
||||
HB_TRACE( HB_TR_DEBUG, ("_get_default_sink IProvideClassInfo2 OK") );
|
||||
hr = iPCI2->lpVtbl->GetGUID( iPCI2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, piid );
|
||||
iPCI2->lpVtbl->Release( iPCI2 );
|
||||
|
||||
if( hr == 0 )
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
HB_TRACE( HB_TR_DEBUG, ("_get_default_sink IProvideClassInfo2 obtain error %08X", hr) );
|
||||
|
||||
|
||||
/* Method 2: using IProvideClassInfo and searching for default source in ITypeInfo */
|
||||
|
||||
hr = iDisp->lpVtbl->QueryInterface( iDisp, &IID_IProvideClassInfo, ( void** ) ( void* ) &iPCI );
|
||||
if( hr == 0 )
|
||||
{
|
||||
HB_TRACE( HB_TR_DEBUG, ("_get_default_sink IProvideClassInfo OK") );
|
||||
|
||||
hr = iPCI->lpVtbl->GetClassInfo( iPCI, &iTI );
|
||||
if( hr == 0 )
|
||||
{
|
||||
hr = iTI->lpVtbl->GetTypeAttr( iTI, &pTypeAttr );
|
||||
if( hr == 0 )
|
||||
{
|
||||
for( i = 0; i < pTypeAttr->cImplTypes; i++ )
|
||||
{
|
||||
hr = iTI->lpVtbl->GetImplTypeFlags( iTI, i, &iFlags );
|
||||
if( hr == 0 && ( iFlags & IMPLTYPEFLAG_FDEFAULT ) && ( iFlags & IMPLTYPEFLAG_FSOURCE ) )
|
||||
{
|
||||
if( iTI->lpVtbl->GetRefTypeOfImplType( iTI, i, &hRefType ) == S_OK &&
|
||||
iTI->lpVtbl->GetRefTypeInfo( iTI, hRefType, &iTISink ) == S_OK )
|
||||
{
|
||||
HB_TRACE( HB_TR_DEBUG, ("_get_default_sink Method 2: default source is found") );
|
||||
|
||||
hr = iTISink->lpVtbl->GetTypeAttr( iTISink, &pTypeAttr );
|
||||
if( hr == 0 )
|
||||
{
|
||||
* piid = pTypeAttr->guid;
|
||||
iTISink->lpVtbl->ReleaseTypeAttr( iTISink, pTypeAttr );
|
||||
|
||||
iTI->lpVtbl->ReleaseTypeAttr( iTI, pTypeAttr );
|
||||
iPCI->lpVtbl->Release( iPCI );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
iTI->lpVtbl->ReleaseTypeAttr( iTI, pTypeAttr );
|
||||
}
|
||||
}
|
||||
iPCI->lpVtbl->Release( iPCI );
|
||||
}
|
||||
else
|
||||
HB_TRACE( HB_TR_DEBUG, ("_get_default_sink IProvideClassInfo obtain error %08X", hr) );
|
||||
}
|
||||
|
||||
|
||||
/* Method 3: using CoClass */
|
||||
|
||||
hr = iDisp->lpVtbl->GetTypeInfo( iDisp, 0, LOCALE_SYSTEM_DEFAULT, &iTI );
|
||||
if( hr == 0 )
|
||||
{
|
||||
ITypeLib * iTL;
|
||||
TYPEATTR * pTypeAttr2;
|
||||
|
||||
hr = iTI->lpVtbl->GetContainingTypeLib( iTI, &iTL, NULL );
|
||||
iTI->lpVtbl->Release( iTI );
|
||||
|
||||
if( hr == 0 )
|
||||
{
|
||||
int iCount = iTL->lpVtbl->GetTypeInfoCount( iTL );
|
||||
for( i = 0; i < iCount; i++ )
|
||||
{
|
||||
hr = iTL->lpVtbl->GetTypeInfo( iTL, i, &iTI );
|
||||
if( hr == S_OK )
|
||||
{
|
||||
hr = iTI->lpVtbl->GetTypeAttr( iTI, &pTypeAttr );
|
||||
if( hr == S_OK )
|
||||
{
|
||||
if( pTypeAttr->typekind == TKIND_COCLASS )
|
||||
{
|
||||
for( j = 0; j < pTypeAttr->cImplTypes; j++ )
|
||||
{
|
||||
if( szEvent )
|
||||
{
|
||||
if( iTI->lpVtbl->GetRefTypeOfImplType( iTI, j, &hRefType ) == S_OK &&
|
||||
iTI->lpVtbl->GetRefTypeInfo( iTI, hRefType, &iTISink ) == S_OK )
|
||||
{
|
||||
BSTR bstr;
|
||||
|
||||
hr = iTISink->lpVtbl->GetDocumentation( iTISink, -1, &bstr, NULL, NULL, NULL );
|
||||
if( hr == S_OK )
|
||||
{
|
||||
char str[ 256 ];
|
||||
int iLen;
|
||||
|
||||
iLen = WideCharToMultiByte( CP_ACP, 0, bstr, -1, str, sizeof( str ), NULL, NULL );
|
||||
str[ iLen - 1 ] = '\0';
|
||||
if( ! strcmp( szEvent, str ) )
|
||||
{
|
||||
hr = iTISink->lpVtbl->GetTypeAttr( iTISink, &pTypeAttr2 );
|
||||
if( hr == S_OK )
|
||||
{
|
||||
* piid = pTypeAttr2->guid;
|
||||
iTISink->lpVtbl->ReleaseTypeAttr( iTISink, pTypeAttr2 );
|
||||
|
||||
iTISink->lpVtbl->Release( iTISink );
|
||||
iTI->lpVtbl->ReleaseTypeAttr( iTI, pTypeAttr );
|
||||
iTI->lpVtbl->Release( iTI );
|
||||
iTL->lpVtbl->Release( iTL );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
iTISink->lpVtbl->Release( iTISink );
|
||||
}
|
||||
}
|
||||
else /* szEvent == NULL */
|
||||
{
|
||||
hr = iTI->lpVtbl->GetImplTypeFlags( iTI, j, &iFlags );
|
||||
if( hr == S_OK && ( iFlags & IMPLTYPEFLAG_FDEFAULT ) && ( iFlags & IMPLTYPEFLAG_FSOURCE ) )
|
||||
{
|
||||
if( iTI->lpVtbl->GetRefTypeOfImplType( iTI, j, &hRefType ) == S_OK &&
|
||||
iTI->lpVtbl->GetRefTypeInfo( iTI, hRefType, &iTISink ) == S_OK )
|
||||
{
|
||||
hr = iTISink->lpVtbl->GetTypeAttr( iTISink, &pTypeAttr2 );
|
||||
if( hr == S_OK )
|
||||
{
|
||||
#if 0
|
||||
/* Debug code. You can also comment out iFlags condition, to list more interfaces [Mindaugas] */
|
||||
BSTR bstr;
|
||||
char str[ 256 ];
|
||||
int iLen;
|
||||
|
||||
iTISink->lpVtbl->GetDocumentation( iTISink, -1, &bstr, NULL, NULL, NULL );
|
||||
iLen = WideCharToMultiByte( CP_ACP, 0, bstr, -1, str, sizeof( str ), NULL, NULL );
|
||||
str[ iLen - 1 ] = '\0';
|
||||
HB_TRACE( HB_TR_DEBUG, ("_get_default_sink Method 3: iFlags=%d guid=%s class=%s", iFlags, GUID2String( &( pTypeAttr2->guid ) ), str) );
|
||||
#endif
|
||||
* piid = pTypeAttr2->guid;
|
||||
iTISink->lpVtbl->ReleaseTypeAttr( iTISink, pTypeAttr2 );
|
||||
|
||||
iTI->lpVtbl->ReleaseTypeAttr( iTI, pTypeAttr );
|
||||
iTI->lpVtbl->Release( iTI );
|
||||
iTL->lpVtbl->Release( iTL );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
iTI->lpVtbl->ReleaseTypeAttr( iTI, pTypeAttr );
|
||||
}
|
||||
iTI->lpVtbl->Release( iTI );
|
||||
}
|
||||
}
|
||||
iTL->lpVtbl->Release( iTL );
|
||||
}
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
HB_FUNC( __AXREGISTERHANDLER ) /* ( pDisp, bHandler [, cIID] ) --> pSink */
|
||||
{
|
||||
IDispatch * pDisp = hb_oleParam( 1 );
|
||||
|
||||
@@ -385,18 +584,26 @@ HB_FUNC( __AXREGISTERHANDLER ) /* ( pDisp, bHandler [, cID] ) --> pSink */
|
||||
{
|
||||
IConnectionPointContainer* pCPC = NULL;
|
||||
IConnectionPoint* pCP = NULL;
|
||||
HRESULT lOleError = S_OK;
|
||||
IID rriid = IID_IDispatch;
|
||||
HRESULT lOleError;
|
||||
IID rriid;
|
||||
void* hCLSID;
|
||||
const wchar_t* wCLSID;
|
||||
const char * szIID;
|
||||
|
||||
wCLSID = hb_parstr_u16( 3, HB_CDP_ENDIAN_NATIVE, &hCLSID, NULL );
|
||||
if( wCLSID )
|
||||
szIID = hb_parc( 3 );
|
||||
if( szIID && szIID[ 0 ] == '{' )
|
||||
{
|
||||
const wchar_t * wCLSID;
|
||||
|
||||
wCLSID = hb_parstr_u16( 3, HB_CDP_ENDIAN_NATIVE, &hCLSID, NULL );
|
||||
lOleError = CLSIDFromString( ( wchar_t * ) wCLSID, &rriid );
|
||||
hb_strfree( hCLSID );
|
||||
hb_strfree( hCLSID );
|
||||
}
|
||||
else
|
||||
lOleError = _get_default_sink( pDisp, szIID, &rriid );
|
||||
|
||||
if( lOleError == S_OK )
|
||||
{
|
||||
HB_TRACE( HB_TR_DEBUG, ("__AXREGISTERHANDLER using sink %s", GUID2String( &rriid )) );
|
||||
lOleError = HB_VTBL( pDisp )->QueryInterface( HB_THIS_( pDisp ) HB_ID_REF( IID_IConnectionPointContainer ), ( void** ) ( void* ) &pCPC );
|
||||
|
||||
if( lOleError == S_OK )
|
||||
|
||||
@@ -31,7 +31,7 @@ LOCAL oPC, nTime, cDefaultPrinter, cFilename, oPrinter, nEvent := 0
|
||||
cFilename := HB_PROGNAME()
|
||||
|
||||
/* Setup event notification */
|
||||
oPC:__hSink := __AxRegisterHandler( oPC:__hObj, {|X| nEvent := X}, "{58B69879-9ED8-468D-879F-787161FA105F}")
|
||||
oPC:__hSink := __AxRegisterHandler( oPC:__hObj, {|X| nEvent := X} )
|
||||
|
||||
oPC:cStart( "/NoProcessingAtStartup" )
|
||||
oPC:_cOption( "UseAutosave", 1 )
|
||||
|
||||
@@ -34,6 +34,7 @@ PROCEDURE Main()
|
||||
? "a) Read ADODB table"
|
||||
? "b) SOAP Toolkit client"
|
||||
? "c) PocketSOAP client"
|
||||
? "d) Internet Explorer with callback"
|
||||
? "0) Quit"
|
||||
? "> "
|
||||
|
||||
@@ -64,6 +65,8 @@ PROCEDURE Main()
|
||||
Exm_SOAP()
|
||||
ELSEIF nOption == Asc( "c" )
|
||||
Exm_PocketSOAP()
|
||||
ELSEIF nOption == Asc( "d" )
|
||||
Exm_IExplorer2()
|
||||
ELSEIF nOption == Asc( "0" )
|
||||
EXIT
|
||||
ENDIF
|
||||
@@ -230,6 +233,23 @@ STATIC PROCEDURE Exm_IExplorer()
|
||||
RETURN
|
||||
|
||||
|
||||
STATIC PROCEDURE Exm_IExplorer2()
|
||||
LOCAL oIE
|
||||
|
||||
IF ( oIE := win_oleCreateObject( "InternetExplorer.Application" ) ) != NIL
|
||||
oIE:__hSink := __AxRegisterHandler( oIE:__hObj, {|...| QOUT(...)})
|
||||
oIE:Visible := .T.
|
||||
oIE:Navigate( "http://harbour-project.org" )
|
||||
WHILE oIE:ReadyState != 4
|
||||
HB_IDLESLEEP( 0 )
|
||||
ENDDO
|
||||
ELSE
|
||||
? "Error. IExplorer not available.", win_oleErrorText()
|
||||
ENDIF
|
||||
|
||||
RETURN
|
||||
|
||||
|
||||
STATIC PROCEDURE Exm_OOCalc()
|
||||
LOCAL oServiceManager, oDesktop, oDoc, oSheet
|
||||
|
||||
|
||||
Reference in New Issue
Block a user