#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) $pRender = Ptr($oRender()) ;~ ConsoleWrite("$pRender=" & $pRender & @CRLF) Local $oBrush = _D2D_RenderTarget_CreateSolidColorBrush($oRender, 0.2, 0.3, 1, 0.8) Local $pBrush = Ptr($oBrush()), $pBrush2 = Ptr($pBrush) ;~ ConsoleWrite("$pBrush=" & $pBrush & @CRLF) ;~ ConsoleWrite("$pBrush2=" & $pBrush2 & @CRLF) $oBrush.SetOpacity(0.3) ;~ MsgBox(0,"Opacity",$oBrush.GetOpacity()) 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 ;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) $hDrawRectangle_New = DllCallbackRegister("DrawRectangle", "none", "ptr;float;float;float;float;ptr;float;ptr") ;none(struct*;struct*;float;struct*) If @error Then MsgBox(0, "DllCallbackregister error", @error) $pDrawRectangle_New = DllCallbackGetPtr($hDrawRectangle_New) $pDrawRectangle_Old = ReplaceVTableFuncPtr($pRender, (14 + 3 - 1) * 4, $pDrawRectangle_New) 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) ;~ $oRender.DrawRectangle(_D2D1_RECT_F(10, 10, 300, 200), $oBrush, 5, Null) $oRender.DrawRectangle(10, 10, 300, 200, $oBrush, 5.5, Null) ;~ $oRender.DrawTextLayout(40, 20, $oDW_Layout, $oBrush, 2) $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 DrawRectangle($pSelf, $fLeft, $fTop, $fRight, $fBottom, $pBrush, $fWidth, $pStyle) ConsoleWrite("Draw rectangle caught" & @CRLF) ;~ ConsoleWrite("Left=" & $fLeft & @CRLF) ;~ ConsoleWrite("Top=" & $fTop & @CRLF) ;~ ConsoleWrite("Right=" & $fRight & @CRLF) ;~ ConsoleWrite("Bottom=" & $fBottom & @CRLF) ConsoleWrite("Width=" & $fWidth & @CRLF) ;~ ConsoleWrite("style=" & $pStyle & @CRLF) ;~ ConsoleWrite("brush=" & $pBrush & @CRLF) ;$tagID2D1SolidColorBrush= ;"GetFactory none(ptr*)" ;"SetOpacity none(float);" & _2nd ;"SetTransform none(struct*);" & _ ;"GetOpacity float();" & _4th ;"GetTransform none(struct*);" ;"SetColor none(struct*);" & _ ;"GetColor ptr(struct*);" Local $tPointers, $aTags ObjGetVTablePointers($pBrush,$tagID2D1SolidColorBrush, $aTags, $tPointers) $iSetOpacity=dTagGetIndex($aTags,"SetOpacity") $iGetOpacity=dTagGetIndex($aTags,"GetOpacity") $pGetOpacity=DllStructGetData($tPointers,1,$iGetOpacity) $pSetOpacity=DllStructGetData($tPointers,1,$iSetOpacity) ;get current opcity $aRet = DllCallAddress("float", $pGetOpacity, "ptr", $pBrush) If @error Then MsgBox(0, "DllCallAddress 2 error", @error) Else MsgBox(0, "Opacity", $aRet[0]) EndIf ;set new opacity value $aRet = DllCallAddress("none", $pSetOpacity, "ptr", $pBrush, "float", 1) ;SetOpacity If @error Then MsgBox(0, "Error", @error) ;get current opacity value $aRet = DllCallAddress("float", $pGetOpacity, "ptr", $pBrush) MsgBox(0, "New opacity", $aRet[0]) ;~ $oTest=ObjCreateInterface($pBrush,$sIID_ID2D1SolidColorBrush,$tagID2D1SolidColorBrush) ;~ MsgBox(0,"","Done") DllCallAddress("none", $pDrawRectangle_Old, "ptr", $pSelf, "float", $fLeft, "float", $fTop, "float", $fRight, "float", $fBottom, "ptr[10]", $pBrush, "float", $fWidth, "ptr", $pStyle) ;ptr[10] is because $tagID2D1SolidColorBrush has 10 entries including 3 from IUnknown interface ;follwing line crashes the script ;DllCallAddress("none",$pDrawRectangle_Old,"ptr",$pSelf,"float",$fLeft,"float",$fTop,"float",$fRight,"float",$fBottom,"ptr",$pBrush,"float",$fWidth,"ptr",$pStyle) EndFunc ;==>DrawRectangle ;returns pointers to all vTable entries Func ObjGetVTablePointers($pVTable, $sdTagDescription, ByRef $aMethods, ByRef $tMethods) $tBasePointer = DllStructCreate("ptr", $pVTable) $pBasePointer = DllStructGetData($tBasePointer, 1) $aMethods=Split_dTag($sdTagDescription) $iNumOfMethods=UBound($aMethods) $tMethods = DllStructCreate("ptr[" & $iNumOfMethods & "]", $pBasePointer) EndFunc ;==>ObjGetVTablePointers ;searches for position of specific vTable entry at the vTable pointers 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 ; 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 ;~ ConsoleWrite("$pVTable=" & $pVTable & @CRLF) ;~ ConsoleWrite("Address:" & $pOldFunc-$iOffset & @CRLF) 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 Func DereferencePointer($pPointer, $sType = "ptr") $hStruct = DllStructCreate($sType, $pPointer) Return DllStructGetData($hStruct, 1) EndFunc ;==>DereferencePointer