#include "..\Direct2D.au3" #include "..\DirectWrite.au3" #include "..\Direct2D_1.au3" ;~ #include "ObjectFromTag.au3" #include #include #include Local $hKernel32 = DllOpen("Kernel32.dll") Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc") Func _ErrFunc() ConsoleWrite("COM Error, ScriptLine(" & $oError.ScriptLine & ") : Number 0x" & Hex($oError.Number, 8) & " - " & $oError.WinDescription & @CRLF) EndFunc ;==>_ErrFunc Global $pOldFuncTest, $pIDWriteTextRenderer_Old, $pRenderer_QueryInterfaceDefault Local $sString = "One line more text even more" Local $hGui = GUICreate("Direct2D test", 805, 450) GUISetState() Local $oFactory = _D2D_Factory_Create() Local $oRender = _D2D_Factory_CreateHwndRenderTarget($oFactory, $hGui) Local $oBrush = _D2D_RenderTarget_CreateSolidColorBrush($oRender, 0.2, 0.3, 1, 0.8) Local $oDW_Factory = _DWrite_Factory_Create() Local $oDW_Format = _DWrite_Factory_CreateTextFormat($oDW_Factory, "Arial", 36, $DWRITE_FONT_WEIGHT_REGULAR, $DWRITE_FONT_STYLE_ITALIC) Local $oDW_Layout = _DWrite_Factory_CreateTextLayout($oDW_Factory, $sString, $oDW_Format, 300, 450) ;max width, max height Global $tStruct Global $oMyRenderer = ObjectFromTag("MyRenderer_", $tagIDWriteTextRenderer, $tStruct, False, False, True, $sIID_IDWriteTextRenderer) ;IDWriteTxtRenderer ;replace Draw method of $oDW_Layout with our own so that custom text renderer can be used ;~ Local $hLayoutDrawCallback_New = DllCallbackRegister("Draw", "long", "ptr;ptr;ptr;float;float") ;Draw hresult(struct*;struct*;float;float)-https://docs.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritetextlayout-draw $hLayoutDrawCallback_New = DllCallbackRegister("Draw", "long", "ptr;ptr;ptr;float;float") If @error Then MsgBox(0,"Error 1",@error) Local $pLayoutDrawCallback_New = DllCallbackGetPtr($hLayoutDrawCallback_New) Local $pDW_Layout = Ptr($oDW_Layout()),$pTextLayout_Draw_Original $pTextLayout_Draw_Original = ReplaceVTableFuncPtr($pDW_Layout, (56 + 3 - 1) * 4, $pLayoutDrawCallback_New) ;set some properties for text $oDW_Layout.SetFontWeight($DWRITE_FONT_WEIGHT_EXTRA_BOLD, 10, 20) $oDW_Layout.SetFontSize(20, 10, 5) $oDW_Layout.SetUnderline(1, 9, 15) Local $pRenderer = Ptr($oRender()) Local $hRenderer_DrawTextLayout_New=DllCallbackRegister("DrawTextLayout","none","ptr;ptr;ptr;ptr;uint");DrawTextLayout none(struct;struct*;struct*;uint) - ORIGINAL;fixed none(ptr;ptr;ptr;uint) ;~ Local $hRenderer_DrawTextLayout_New = DllCallbackRegister("DrawTextLayout", "none", "ptr;float;float;ptr;ptr;uint") ;DrawTextLayout none(float;float;struct*;struct*;uint) - allowed Local $pRenderer_DrawTextLayout_New = DllCallbackGetPtr($hRenderer_DrawTextLayout_New) Global $pRenderer_DrawTextLayout_Old ;~ $pRenderer_DrawTextLayout_Old = ReplaceVTableFuncPtr($pRenderer, (26 + 3 - 1) * 4, $pRenderer_DrawTextLayout_New) ;26 - DrawTextLayout Local $tMatrix_Scale = _D2D_Matrix3x2_Scale(2, 1, -150, 200) ;~ $oRender.SetTransform($tMatrix_Scale) $oRender.BeginDraw() _D2D_RenderTarget_Clear($oRender, 1, 0.9, 0.9) $tPoint=_D2D1_POINT_2F(20,40) $oRender.DrawTextLayout(20,40, $oDW_Layout, $oBrush, 2) $oRender.EndDraw(0, 0) While GUIGetMsg() <> -3 WEnd $oDW_Layout = 0 $oDW_Typography = 0 $oDW_Format = 0 $oDW_Factory = 0 $oBrush = 0 $oRender = 0 $oFactory = 0 GUIDelete($hGui) Func ObjGetVTablePointers($pObj, $sdTagDescription, ByRef $aMethods, ByRef $tMethods) $tBasePointer = DllStructCreate("ptr", $pObj) $pBasePointer = DllStructGetData($tBasePointer, 1) $aMethods=Split_dTag($sdTagDescription) $iNumOfMethods=UBound($aMethods) $tMethods = DllStructCreate("ptr[" & $iNumOfMethods & "]", $pBasePointer) EndFunc ;==>ObjGetVTablePointers Func dTagGetIndex($adTag,$sMethodName) $iPos=_ArraySearch($adTag,$sMethodName) If @error Then MsgBox(0,"ArraySearch error",@error) Else Return $iPos+1 EndIf EndFunc Func Split_dTag($sdTag) ;~ ConsoleWrite("Split tag" & @CRLF) $aSplit = StringSplit($sdTag, ");", BitOR(1, 2)) $iNumOfElements = UBound($aSplit) If $aSplit[$iNumOfElements - 1] = "" Then _ArrayDelete($aSplit, $iNumOfElements - 1) For $i = 0 To UBound($aSplit) - 1 $aSplit[$i] = StringRegExpReplace($aSplit[$i], " .+", "") Next Local $aResult[UBound($aSplit)+3]=["QueryInterface","AddRef","Release"];add IUnknown For $i=3 To UBound($aResult)-1 $aResult[$i]=$aSplit[$i-3] Next Return $aResult EndFunc ;==>Split_dTag Func DereferencePointer($pPointer, $sType = "ptr") $hStruct = DllStructCreate($sType, $pPointer) Return DllStructGetData($hStruct, 1) EndFunc ;==>DereferencePointer Func Draw($pSelf, $pClientDrawingContext, $pRenderer, $fOriginX, $fOriginY) ConsoleWrite("Draw called" & @CRLF) ConsoleWrite("x=" & $fOriginX & ",y=" & $fOriginY & @CRLF) ConsoleWrite("$pClientDrawingContext=" & $pClientDrawingContext & @CRLF) ConsoleWrite("$pRenderer=" & $pRenderer & @CRLF) $ptest=DllStructCreate("ptr", $pRenderer) $firstPointer=DllStructGetData($ptest,1) Local $pPointers=DllStructCreate("ptr[10]",$firstPointer) If @error Then MsgBox(0,"DllStructCreate 3 error",@error) For $i=1 To 10 $pointer=DllStructGetData($pPointers,1,$i); ;$pointer2=DllStructGetData(DllStructCreate("ptr", $pointer), 1) ConsoleWrite($i & "=" & $pointer & @CRLF) Next ;~ Local $bIsDisabled ;~ $pIsPixelSnappingDisabled=DllStructGetData($pPointers,1,4) ;~ $aRet=DllCallAddress("long",$pIsPixelSnappingDisabled,"ptr",$pRenderer,"ptr",$pClientDrawingContext,"int*",$bIsDisabled) ;~ If @error Then ;~ MsgBox(0,"DllCallbackRegister 2 error",@error) ;~ Else ;~ MsgBox(0,"Call result",$bIsDisabled) ;~ EndIf Local $pTransformationMatrix $pGetCurrentTransform=DllStructGetData($pPointers,1,5) ConsoleWrite("Getting transformation matrix of original renderer" & @CRLF) $aRet=DllCallAddress("long",$pGetCurrentTransform,"ptr",$pRenderer,"ptr",$pClientDrawingContext,"ptr*",$pTransformationMatrix) If @error Then MsgBox(0,"DllCallbackRegister 2 error",@error) Else MsgBox(0,"Call result",$aRet[0]) ConsoleWrite(@TAB & "Type(expecting pointer)=" & VarGetType($pTransformationMatrix) & @CRLF) EndIf $aResult = DllCallAddress("long", $pTextLayout_Draw_Original, "ptr", $pSelf, "ptr", $pClientDrawingContext, "ptr", $oMyRenderer, "float", $fOriginX, "float", $fOriginY) ;uncomment next line to see text ;~ $aResult = DllCallAddress("long", $pTextLayout_Draw_Original, "ptr", $pSelf, "ptr", $pClientDrawingContext, "ptr", $pRenderer, "float", $fOriginX, "float", $fOriginY) If @error Then MsgBox(0,"DLLCallAddress error",@error) ;~ Return $aResult[0] EndFunc ;==>Draw ;~ HRESULT DrawGlyphRun( ;~ void *clientDrawingContext, ;~ FLOAT baselineOriginX, ;~ FLOAT baselineOriginY, ;~ DWRITE_MEASURING_MODE measuringMode, ;~ [in] DWRITE_GLYPH_RUN const *glyphRun, ;~ [in] DWRITE_GLYPH_RUN_DESCRIPTION const *glyphRunDescription, ;~ IUnknown *clientDrawingEffect ;~ ); Func MyRenderer_DrawGlyphRun($pSelf, $pClientDrawingContext, $fBaselineOriginX, $fBaselineOriginY, $iMeasuringMode, $pGlyphRun, $pGlyphRunDescription, $pClientDrawingEffect); Ret: long Par: struct*;float;float;uint;struct*;struct*;struct* ConsoleWrite("MyRenderer_DrawGlyphRun()" & @CRLF & @CRLF) ConsoleWrite(@TAB & "$pClientDrawingContext=" & $pClientDrawingContext & @CRLF) ConsoleWrite(@TAB & "x:" & $fBaselineOriginX & ", y:" & $fBaselineOriginY & @CRLF) ConsoleWrite(@TAB & "$pClientDrawingEffect=" & $pClientDrawingEffect & @CRLF) ConsoleWrite(@TAB & "$pGlyphRun=" & $pGlyphRun & @CRLF) $tData = DllStructCreate($tagDWRITE_GLYPH_RUN, $pGlyphRun) $tData2=DllStructCreate($tagDWRITE_GLYPH_RUN_DESCRIPTION, $pGlyphRunDescription) ConsoleWrite(@TAB & "StringLen=" & DllStructGetData($tData2,"StringLength") & @CRLF) $tStringPtr=DllStructGetData($tData2,"String") ConsoleWrite(@TAB & "type of $tStrigPtr is " & VarGetType($tStringPtr) & @CRLF) ConsoleWrite(@TAB & "value of String is " & $tStringPtr & @CRLF) $tTag="struct;wchar" & " Text[" & DllStructGetData($tData2,"StringLength") & "];endstruct" ConsoleWrite(@TAB & "Tag=" & $tTag & @CRLF) $tString=DllStructCreate($tTag,$tStringPtr) If @error Then ConsoleWrite(@TAB & "!DllStructCreate error:" & @error & ", ptr=" & $pGlyphRun & @CRLF) Else ConsoleWrite(@TAB & "FontEmSize:" & DllStructGetData($tData, "FontEmSize") & @CRLF) EndIf ConsoleWrite(@TAB & "Text=" & DllStructGetData($tString,"Text") & @CRLF) ;issues start here ;get transformation matrix Local $tPointers, $aTags ObjGetVTablePointers($pClientDrawingContext,$tagID2D1DeviceContext, $aTags, $tPointers) ConsoleWrite("Num of methods:" & UBound($aTags) & @CRLF) $iGetTransform=dTagGetIndex($aTags,"GetTransform") $pGetTransform=DllStructGetData($tPointers,1,$iGetTransform) ;issues Local $tMatrix ;~ MsgBox(0,"Test before","") ;~ $aRet=DllCallAddress("none",$pGetTransform,"ptr",$pClientDrawingContext,"ptr",$tMatrix) ;~ If @error Then ;~ MsgBox(0,"Error 4",@error) ;~ Else ;~ MsgBox(0,"Result",VarGetType($aRet[0])) ;~ EndIf ;~ $oClientDrawingContext=ObjCreateInterface($pClientDrawingContext,$sIID_ID2D1DeviceContext,$tagID2D1DeviceContext,True) ;~ If @error Then MsgBox(0,"Error DeviceContext",@error) Return 0 ; S_OK = 0x00000000 EndFunc ;==>MyRenderer_DrawGlyphRun ;~ HRESULT DrawUnderline( ;~ void *clientDrawingContext, ;~ FLOAT baselineOriginX, ;~ FLOAT baselineOriginY, ;~ [in] DWRITE_UNDERLINE const *underline, ;~ IUnknown *clientDrawingEffect ;~ ); ;~ https://github.com/HackerFantastic/Terminal/blob/master/src/renderer/dx/CustomTextRenderer.cpp ;~ https://www.autoitscript.com/forum/topic/153859-objevent-possible-with-addfocuschangedeventhandler/?tab=comments#comment-1111701 Func MyRenderer_DrawUnderline($pSelf, $pClientDrawingContext, $fBaselineOriginX, $fBaselineOriginY, $pUnderline, $pClientDrawingEffect);DrawUnderline hresult(struct*;float;float;struct*;struct*);) ;$pSelf, $pClientDrawingContext, $fBaselineOriginX, $fBaselineOriginY, $fWidth, $fThickness, $fOffset, $fRunHeight, $iReadingDirection, $iFlowDirection, $ptr, $iMeasuringMode, $struct2 ConsoleWrite("MyRenderer_DrawUnderline()" & @CRLF & @CRLF) ConsoleWrite(@TAB & "$pClientDrawingContext=" & $pClientDrawingContext & @CRLF) ;~ MsgBox(0,"Test","test") ConsoleWrite(@TAB & "x=" & $fBaselineOriginX & ", y=" & $fBaselineOriginY & @CRLF) ConsoleWrite(@TAB & "$pUnderline=" & $pUnderline & @CRLF) $tUnderline=DllStructCreate($tagDWRITE_UNDERLINE,$pUnderline) ConsoleWrite(@TAB & "width=" & DllStructGetData($tUnderline,"Width") & @CRLF) Local $tagIUnknown = _ ; IUnknown interface description "QueryInterface hresult(ptr;ptr*);" & _ "AddRef dword();" & _ "Release dword();" ConsoleWrite(@TAB & "$pClientDrawingEffect=" & $pClientDrawingEffect & @CRLF) $oEffect=ObjCreateInterface($pClientDrawingEffect,"{00000000-0000-0000-C000-000000000046}",$tagIUnknown & $tagID2D1Effect,False);"{00000000-0000-0000-C000-000000000046}" If @error Then MsgBox(0,"Error","object") ;~ ConsoleWrite(@TAB & "Effect input count=" & $oEffect.GetInputCount() & @CRLF) ;~ uncomment following lines to crash script ;~ $tUnderline=DllStructCreate($tagDWRITE_UNDERLINE,$pUnderline) ;~ If @error Then ;~ ConsoleWrite("$tUnderline error:" & @error & @CRLF) ;~ Else ;~ MsgBox(0,"Underline OK", DllStructGetData($tUnderline, "Width")) ;~ EndIf Return 0 ; S_OK = 0x00000000 EndFunc ;==>MyRenderer_DrawUnderline Func _ConvertPointSizeToDIP($fPointSize) Return ($fPointSize / 72) * 96 EndFunc ;==>_ConvertPointSizeToDIP ;https://www.autoitscript.com/forum/topic/174105-solved-help-with-event-notifications-for-imbnpinmanagerevents-interface/?do=findComment&comment=1259863 Func DrawTextLayout($pSelf, $fX, $fY, $pTextLayout, $pDefaultFillBrush, $iOptions);$pSelf, $pOrigin, $pTextLayout, $pDefaultFillBrush, $iOptions ConsoleWrite("DrawTextLayout caught" & @CRLF) ConsoleWrite("$iOptions=" & $iOptions & @CRLF) ;~ $tData=DllStructCreate($tagD2D1_POINT_2F,$pOrigin) ;~ MsgBox(0,"Coord",DllStructGetData( ;~ $iResult=DllCallAddress("none",$pRenderer_DrawTextLayout_Old,"ptr",$pSelf,"struct",$tData,"ptr",$pTextLayout,"ptr",$pDefaultFillBrush,"uint", $iOptions) ;~ If @error Then MsgBox(0,"Error",@error) $iResult = DllCallAddress("none", $pRenderer_DrawTextLayout_Old, "ptr", $pSelf, "float", $fX, "float", $fY, "ptr", $pTextLayout, "ptr", $pDefaultFillBrush, "uint", $iOptions) EndFunc ;==>DrawTextLayout Func MyRenderer_QueryInterface($pSelf, $pRIID, $pObj) ; Ret: long Par: ptr;ptr* ConsoleWrite("MyRenderer_QueryInterface()" & @CRLF & @CRLF) $sRIIDQuery = _WinAPI_StringFromGUID($pRIID) ConsoleWrite(@TAB & "$sIID=" & $sRIIDQuery & @CRLF) ;~ Local $tStruct = DllStructCreate("ptr", $pObj);https://www.autoitscript.com/forum/topic/141876-solved-com-sink-objectiunknown-events-i-dont-know-s/?tab=comments#comment-998113 ;~ DllStructSetData($tStruct, 1, $pSelf) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $pRIID, $pObj EndFunc ;==>MyRenderer_QueryInterface Func MyRenderer_AddRef($pSelf) ; Ret: dword ConsoleWrite("MyRenderer_AddRef()" & @CRLF & @CRLF) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc ;==>MyRenderer_AddRef Func MyRenderer_Release($pSelf) ; Ret: dword ConsoleWrite("MyRenderer_Release()" & @CRLF & @CRLF) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc ;==>MyRenderer_Release Func MyRenderer_IsPixelSnappingEnabled($pSelf, $struct, $bool) ; Ret: long Par: struct*;bool* ConsoleWrite("MyRenderer_IsPixelSnappingEnabled()" & @CRLF & @CRLF) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $struct, $bool EndFunc ;==>MyRenderer_IsPixelSnappingEnabled Func MyRenderer_GetCurrentTransform($pSelf, $struct1, $struct2) ; Ret: long Par: struct*;struct* ConsoleWrite("MyRenderer_GetCurrentTransform()" & @CRLF & @CRLF) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $struct1, $struct2 EndFunc ;==>MyRenderer_GetCurrentTransform Func MyRenderer_GetPixelsPerDip($pSelf, $struct, $float) ; Ret: long Par: struct*;float* ConsoleWrite("MyRenderer_GetPixelsPerDip()" & @CRLF & @CRLF) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $struct, $float EndFunc ;==>MyRenderer_GetPixelsPerDip Func MyRenderer_DrawStrikethrough($pSelf, $struct1, $float1, $float2, $struct2, $struct3) ; Ret: long Par: struct*;float;float;struct*;struct* ConsoleWrite("MyRenderer_DrawStrikethrough()" & @CRLF & @CRLF) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $struct1, $float1, $float2, $struct2, $struct3 EndFunc ;==>MyRenderer_DrawStrikethrough Func MyRenderer_DrawInlineObject($pSelf, $struct1, $float1, $float2, $struct2, $bool1, $bool2, $struct3) ; Ret: long Par: struct*;float;float;struct*;bool;bool;struct* ConsoleWrite("MyRenderer_DrawInlineObject()" & @CRLF & @CRLF) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $struct1, $float1, $float2, $struct2, $bool1, $bool2, $struct3 EndFunc ;==>MyRenderer_DrawInlineObject ; Copied from "Hooking into the IDispatch interface" by monoceres ;~ ; https://www.autoitscript.com/forum/index.php?showtopic=107678 Func ReplaceVTableFuncPtr($pVTable, $iOffset, $pNewFunc) Local $pPointer = DllStructGetData(DllStructCreate("ptr", $pVTable), 1) + $iOffset, $PAGE_EXECUTE_READWRITE = 0x40 Local $pOldFunc = DllStructGetData(DllStructCreate("ptr", $pPointer), 1) ; Get the original function pointer in VTable Local $aRet = DllCall("Kernel32.dll", "int", "VirtualProtect", "ptr", $pPointer, "long", @AutoItX64 ? 8 : 4, "dword", $PAGE_EXECUTE_READWRITE, "dword*", 0) ; Unprotect memory DllStructSetData(DllStructCreate("ptr", $pPointer), 1, $pNewFunc) ; Replace function pointer in VTable with $pNewFunc function pointer $aRet2 = DllCall("Kernel32.dll", "int", "VirtualProtect", "ptr", $pPointer, "long", @AutoItX64 ? 8 : 4, "dword", $aRet[4], "dword*", 0) ; Protect memory Return $pOldFunc ; Return original function pointer EndFunc ;==>ReplaceVTableFuncPtr ;https://www.autoitscript.com/forum/topic/206615-convert-getref-function-from-vbscript-to-autoit/?tab=comments#comment-1489832 ;https://www.autoitscript.com/forum/topic/205154-using-objcreateinterface-and-objectfromtag-functions/?tab=comments#comment-1475246 Func ObjectFromTag( $sFunctionPrefix, $tagInterface, ByRef $tInterface, $bObject = True, $bPrint = False, $bIsUnknown = True, $sIID = "{00000000-0000-0000-C000-000000000046}" ) ; Last param is IID_IUnknown by default Local $sInterface = $tagInterface ; Copy interface description Local $tagIUnknown = _ ; IUnknown interface description "QueryInterface hresult(ptr;ptr*);" & _ "AddRef dword();" & _ "Release dword();" If $bIsUnknown Then $tagInterface = $tagIUnknown & $tagInterface ; Adding IUnknown methods Local $aMethods = StringSplit( StringTrimRight( StringReplace( StringRegExpReplace( $tagInterface, "\h*(\w+)\h*(\w+\*?)\h*(\(\h*(.*?)\h*\))\h*(;|;*\z)", "$1\|$2\|$4" & @LF ), ";" & @LF, @LF ), 1 ), @LF, 3 ) Local $iMethods = UBound( $aMethods ), $aSplit, $aSplit2, $iSplit2, $sParams, $sParams2, $oParams = ObjCreate( "Scripting.Dictionary" ), $oParams2 = ObjCreate( "Scripting.Dictionary" ), $hCallback, $iPar, $s, $t $tInterface = DllStructCreate( "int RefCount;int Size;ptr Object;ptr Methods[" & $iMethods & "];int_ptr Callbacks[" & $iMethods & "];ulong_ptr Slots[16]" ) ; 16 pointer sized elements more to create space for possible private props If @error Then Return SetError( 1, 0, 0 ) For $i = 0 To $iMethods - 1 $aSplit = StringSplit( $aMethods[$i], "|", 2 ) $aSplit[0] = $sFunctionPrefix & $aSplit[0] ; Method name If $aSplit[1] = "hresult" Then $aSplit[1] = "long" ; Return type $sParams = $aSplit[2] ? "ptr;" & StringReplace( StringReplace( StringReplace( StringReplace( $aSplit[2], "object", "idispatch" ), "bstr", "ptr" ), "variant", "ptr" ), "hresult", "long" ) : "ptr" ; Params ;~ $sParams=StringReplace($sParams,"struct*","ptr*") If $bPrint Then $iPar = StringInStr( $sParams, ";", 2 ) If $iPar Then $sParams2 = StringRight( $sParams, StringLen( $sParams ) - $iPar ) If StringInStr( $aSplit[0], "_QueryInterface", 2 ) Then $s = ", $pRIID, $pObj" Else $oParams.RemoveAll() $oParams2.RemoveAll() $aSplit2 = StringSplit( $sParams2, ";", 2 ) $iSplit2 = UBound( $aSplit2 ) For $j = 0 To $iSplit2 - 1 $aSplit2[$j] = StringRegExpReplace( $aSplit2[$j], "\*$", "" ) $oParams( $aSplit2[$j] ) += 1 Next $s = "" For $j = 0 To $iSplit2 - 1 $s &= ", $" & $aSplit2[$j] If $oParams.Item( $aSplit2[$j] ) > 1 Then $oParams2( $aSplit2[$j] ) += 1 $s &= $oParams2( $aSplit2[$j] ) EndIf Next EndIf EndIf $t = $iPar ? "Ret: " & $aSplit[1] & " " & "Par: " & $sParams2 : "Ret: " & $aSplit[1] ConsoleWrite( "Func " & $aSplit[0] & ( $iPar ? "( $pSelf" & $s & " ) ; " : "( $pSelf ) ; " ) & $t & @CRLF ) ConsoleWrite( " ConsoleWrite( """ & $aSplit[0] & "()"" & @CRLF & @CRLF )" & @CRLF ) ConsoleWrite( " Return " & ( ( StringInStr( $aSplit[0], "_AddRef", 2 ) Or StringInStr( $aSplit[0], "_Release", 2 ) ) ? "1 ; For AddRef/Release" : "0 ; S_OK = 0x00000000" ) & @CRLF ) ConsoleWrite( " #forceref" & ( $iPar ? " $pSelf" & $s : " $pSelf" ) & @CRLF & "EndFunc" & @CRLF ) EndIf $hCallback = DllCallbackRegister( $aSplit[0], $aSplit[1], $sParams ) ;~ ConsoleWrite($aSplit[0] & " "& $aSplit[1] & "(" & $sParams & ")" & @CRLF) If $bPrint Then ConsoleWrite( "@error = " & @error & @CRLF & @CRLF ) DllStructSetData( $tInterface, "Methods", DllCallbackGetPtr( $hCallback ), $i + 1 ) ; Save callback pointer DllStructSetData( $tInterface, "Callbacks", $hCallback, $i + 1 ) ; Save callback handle Next DllStructSetData( $tInterface, "RefCount", 1 ) ; Initial ref count is 1 DllStructSetData( $tInterface, "Size", $iMethods ) ; Number of interface methods DllStructSetData( $tInterface, "Object", DllStructGetPtr( $tInterface, "Methods" ) ) ; Interface method pointers Return $bObject ? ObjCreateInterface( DllStructGetPtr( $tInterface, "Object" ), $sIID, $sInterface, $bIsUnknown ) : DllStructGetPtr( $tInterface, "Object" ) EndFunc ; Pointer that's wrapped into object ; Pointer ( = $pSelf ) Func DeleteObjectFromTag( ByRef $tInterface ) For $i = 1 To DllStructGetData( $tInterface, "Size" ) DllCallbackFree( DllStructGetData( $tInterface, "Callbacks", $i ) ) Next $tInterface = 0 EndFunc