ahmet Posted January 9, 2022 Share Posted January 9, 2022 Hello, I am trying to make a custom text renderer using DirectWrite. According to this I have made a custom renderer using ObjectFromTag. Global $oMyRenderer = ObjectFromTag("MyRenderer_", $tagIDWriteTextRenderer, $tStruct, False, False, True, $sIID_IDWriteTextRenderer) This renderer is then used in subcalssed Draw method of IDWriteTextLayout. ;create IDWriteTextLayout object Local $oDW_Layout = _DWrite_Factory_CreateTextLayout($oDW_Factory, $sString, $oDW_Format, 300, 450) ;max width, max height ;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 Local $pLayoutDrawCallback_New = DllCallbackGetPtr($hLayoutDrawCallback_New) Local $pDW_Layout = Ptr($oDW_Layout()) $pTextLayout_Draw_Original = ReplaceVTableFuncPtr($pDW_Layout, (56 + 3 - 1) * 4, $pLayoutDrawCallback_New) Right now I am having two issues. First one is as it seems there is some issue with pointers. 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 & "x:" & $fBaselineOriginX & ", y:" & $fBaselineOriginY & @CRLF) ConsoleWrite(@TAB & "$pClientDrawingEffect=" & $pClientDrawingEffect & @CRLF) $tData = DllStructCreate($tagDWRITE_GLYPH_RUN_DESCRIPTION, $pGlyphRun) If @error Then ConsoleWrite(@TAB & "!DllStructCreate error:" & @error & ", ptr=" & $pGlyphRun & @CRLF) Else ConsoleWrite(@TAB & "FontEmSize:" & DllStructGetData($tData, "FontEmSize") & @CRLF) EndIf Return 0 ; S_OK = 0x00000000 EndFunc ;==>MyRenderer_DrawGlyphRun For $pGlyphRunI keep getting 0. Same situation happens with MyRenderer_DrawUnderline and pointers there. If the default renderer is used in subclassed Draw method then text draws fine. Floating point values are fine. I have checked tag generation in ObjectFromTag. That looks good. Func Draw($pSelf, $oClientDrawingContext, $oRenderer, $fOriginX, $fOriginY) ConsoleWrite("Draw called" & @CRLF) ConsoleWrite("x=" & $fOriginX & ",y=" & $fOriginY & @CRLF) $aResult = DllCallAddress("long", $pTextLayout_Draw_Original, "ptr", $pSelf, "ptr", $oClientDrawingContext, "ptr", $oMyRenderer, "float", $fOriginX, "float", $fOriginY) ;~ If @error Then MsgBox(0,"Error at draw",@error) ;uncomment next line to see text $aResult = DllCallAddress("long", $pTextLayout_Draw_Original, "ptr", $pSelf, "ptr", $oClientDrawingContext, "ptr", $oRenderer, "float", $fOriginX, "float", $fOriginY) ;~ Return $aResult[0] EndFunc ;==>Draw Maybe I have done something wrong in those callbacks. Second issue I am having is with *clientDrawingContext. I am not sure whether I should define that and then use in custom renderer. Microsoft's documentation says "clientDrawingContext Type: void* The application-defined drawing context passed to IDWriteTextLayout::Draw". HRESULT DrawUnderline( void *clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, [in] DWRITE_UNDERLINE const *underline, IUnknown *clientDrawingEffect ); I am attaching full script here. DirectWrite UDF can be downloaded from https://autoit.de/wcf/attachment/82843-direct2d-7z/. _DWrite_IDWriteTextRenderer.au3 Link to comment Share on other sites More sharing options...
markyrocks Posted January 10, 2022 Share Posted January 10, 2022 (edited) I don't have alot of time to look at this and try to glean what you're trying to do. I will say that theres got to be easier ways to do whatever it is that you're attempting. You've departed so far from the typical style of writing in autoit that you'd honestly be better off just learning a different one. I'm not saying not to continue but i've found doing things outside of the box to be an exercise if futility at best. All that I mind dllcallback functions don't just automatically work if you just send them out. The dll usually has a declaration for that function but not a body... the callbackregister is basically saying "hey I have a function body for your declaration". That function body needs to match the signature of the declaration, in otherwords the parameters and return type have to match. Like I said I havn't done a deep dive into what you're doing here but the callbacks arent' just a free floating function that materializes out of thin air. <~~~~~~at least to the best of my understanding If you're interested in an easy to learn graphics library check out gdi+ or this... https://www.raylib.com/ I havn't used raylib on autoit but I believe that they have an autoit build? I know they make mention of it on their website somewhere. Once you get it up and running you can do some pretty cool stuff with it. I used it to make a simple tic tac toe game for the purposes of building an unbeatable ai. It works pretty good. Kinda a pita to get in the mindset of doing all the draw calls and input grabs etc in one while loop but it seems much easier than the deep weeds that you're currently in. Good luck Edit: I'd also like to add that a callback function usually gets called by a function within the dll that you're registering to and by registering your basically populating the variable in that dll that is uninitialized otherwise. Callbacks typically return bool so that that calling function knows when to stop calling it. Besides that not every function ends up on the vtable. The only functions that end up in the vtable are purely virtual. Not every dll is a com object. A com object is essentially a service that runs on your machine constantly and it's whole point is to field queries to produce objects that have reference counters in them so that the service knows when a particular object is free and can be cleaned up. It's alot more complicated than that but that's the gist of it. Edited January 10, 2022 by markyrocks Spoiler "I Believe array math to be potentially fatal, I may be dying from array math poisoning" Link to comment Share on other sites More sharing options...
LarsJ Posted January 11, 2022 Share Posted January 11, 2022 Have you verified that your callback object is working properly before you start replacing the vtable functions? Ie. that the original Microsoft code works in a 1-1 AutoIt translation. Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
ahmet Posted January 11, 2022 Author Share Posted January 11, 2022 @markyrocks it is nice exercise at least. @LarsJ I did have trouble with one method from vtable, others method I have not tested. The method I had trouble was DrawTextLayout from ID2D1RenderTarget. Definition says void DrawTextLayout( D2D1_POINT_2F origin, [in] IDWriteTextLayout *textLayout, [in] ID2D1Brush *defaultFillBrush, D2D1_DRAW_TEXT_OPTIONS options ); Based on the post I had to change AutoIt's definition to "DrawTextLayout none(float;float;struct*;struct*;uint);" & _;DrawTextLayout none(struct;struct*;struct*;uint);"- This is original ... ;Following would be new callbacek then Local $hRenderer_DrawTextLayout_New = DllCallbackRegister("DrawTextLayout", "none", "ptr;float;float;ptr;ptr;uint") Right now I had to change DrawGlyphRun and DrawUnderline definition and I am able to access structures Global Const $tagIDWriteTextRenderer = $tagIDWritePixelSnapping & _ "DrawGlyphRun hresult(struct*;float;float;uint;ptr;ptr;struct*);" & _;DrawGlyphRun hresult(struct*;float;float;uint;struct*;struct*;struct*)_-ORIGINAL "DrawUnderline hresult(struct*;float;float;ptr;struct*);" & _;DrawUnderline hresult(struct*;float;float;struct*;struct*)-ORIGINAL "DrawStrikethrough hresult(struct*;float;float;struct*;struct*);" & _ "DrawInlineObject hresult(struct*;float;float;struct*;bool;bool;struct*);" I have tried to access objects used in those callbacks using ObjCreateInterface. It did create objects, but I have not done anything with them yet, but it looks promising. Link to comment Share on other sites More sharing options...
markyrocks Posted January 11, 2022 Share Posted January 11, 2022 To access the structure create a struct tag that is the same as the struct your receiving and create the new struct at the pointer that you receive and you should be able to view the underlying data. i.e DllStructCreate("relevant tag", pointer) creating a struct in this method doesn't alter the underlying data. Spoiler "I Believe array math to be potentially fatal, I may be dying from array math poisoning" Link to comment Share on other sites More sharing options...
ahmet Posted January 11, 2022 Author Share Posted January 11, 2022 (edited) That is how I am doing it now. initial issue was that I was getting 0 as the pointer. Cause of that issue was in the definition of DrawUnderline which was "DrawUnderline hresult(struct*;float;float;struct*;struct*)" After replacing that with following I am able to use DllStructCreate successfully. "DrawUnderline hresult(struct*;float;float;ptr;struct*);";there is ptr at fourth pos instead struct* As it seems struct* does work for objects, but I need to do more tests. Edited January 11, 2022 by ahmet Link to comment Share on other sites More sharing options...
markyrocks Posted January 11, 2022 Share Posted January 11, 2022 I've found that anytime you need to use virtually any kind of pointer in a tag just using "ptr" works. ahmet 1 Spoiler "I Believe array math to be potentially fatal, I may be dying from array math poisoning" Link to comment Share on other sites More sharing options...
ahmet Posted January 14, 2022 Author Share Posted January 14, 2022 @LarsJ since I have been having issues while trying to create objects from pointers from callback I went back I checked how does original Draw code works when called from AutoIt. Definition says HRESULT Draw( void *clientDrawingContext, IDWriteTextRenderer *renderer, FLOAT originX, FLOAT originY ); VTable entry from AutoIt is " Draw hresult(struct*;struct*;float;float); ". I tried changng it to " Draw hresult(ptr;ptr;float;float); but I could not see any difference. My code for registering callback is $hLayoutDrawCallback_New = DllCallbackRegister("Draw", "long", "ptr;ptr;ptr;float;float") Two floats I get as expected. I can not create CliendDrawingContext and Renderer object. I tried to create Renderer object with following code 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) ;$oRenderer=ObjCreateInterface($pRenderer,$sIID_IDWriteTextRenderer,$tagIDWriteTextRenderer);attempt to create renderer object ;$pTextLayout_Draw_Original - address to original Draw method $aResult = DllCallAddress("long", $pTextLayout_Draw_Original, "ptr", $pSelf, "ptr", $pClientDrawingContext, "ptr", $pRenderer, "float", $fOriginX, "float", $fOriginY) EndFunc When I call original Draw code from my callback then the text gets drawn as expected. Pointer to $pClientDrawingContext shows 0 at the console. Am I creating object correctly? Link to comment Share on other sites More sharing options...
LarsJ Posted January 15, 2022 Share Posted January 15, 2022 I'll take a closer look, but I cannot promise a quick answer, because I don't have much time for AutoIt programming at the moment. Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
ahmet Posted January 15, 2022 Author Share Posted January 15, 2022 Thank you, sorry for bothering you. Link to comment Share on other sites More sharing options...
ahmet Posted January 16, 2022 Author Share Posted January 16, 2022 (edited) I did some more tests. Now I subclassed DrawRectangle from ID2D1HwndRenderTarget. I was able to access brush methods there. Methods are being called via DllCallAddress. Addresses are obtained using technique from ReplaceVTableFuncPtr. I was able to get and set brush opacity using this method. One question remains regarding this. Is there some other way of obtaining object from pointer inside callback? If try to use ObjCreateInterface then the script crashes with STATUS_ACCESS_VIOLATION. expandcollapse popupFunc 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*);" $ptest=DllStructCreate("ptr", $pBrush) ;~ ConsoleWrite("$pZeroPointer=" & DllStructGetData($ptest, 1)+0*4 & @CRLF) $firstPointer=DllStructGetData($ptest,1) Local $pPointers=DllStructCreate("ptr[10]",$firstPointer);get pointers to method addresses If @error Then MsgBox(0,"DllStructCreate 3 error",@error) ;print all pointers to console For $i=1 To 10 $pointer=DllStructGetData($pPointers,1,$i); ;$pointer2=DllStructGetData(DllStructCreate("ptr", $pointer), 1) ConsoleWrite($i & "=" & $pointer & @CRLF) Next ;get current opcity $pGetOpacity=DllStructGetData($pPointers,1,7);4+3 from IUnknown $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 Local $pSetOpacity = DllStructGetData($pPointers,1,5);2+3 from IUnknown ConsoleWrite("$pSetOpacity=" & $pSetOpacity & @CRLF) $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) EndFunc I was not able to access render object inside Draw callback from above post using this technique. I will try to find some other method that has two pointers to objects as consecutive parameters and try with that. _DWrite_Drawrectangle_Subclass.au3 Direct2DConstants.au3 Edited January 16, 2022 by ahmet Added attacments Link to comment Share on other sites More sharing options...
ahmet Posted January 16, 2022 Author Share Posted January 16, 2022 I have made some helper functions regarding getting vTable pointers. ;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 What I did not mention in the last post is that in order for the original DrawRctangle code to work I had to make a following code 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) When specifying $pBrush I had to use "ptr[10]" insetad of "ptr". Now to the Draw method of IDWriteTextLayout (second script). I am attaching script that I am using for testing. Functions of interest are: Draw, MyRenderer_DrawGlyphRun and MyRenderer_DrawUnderline. Firstly the Draw method is subclassed and then from there the subclass procedure should continue with new Renderer which is created by ObjectFromTag function. When the original renderer is used then the script finishes fine. Same is for my custom renderer if I do not process its QueryInterface as shown here. If I process QueryInterface then the script crashes, which is probably of wrong pointers. If I do nothing inside QueryInterface then $pClientDrawingContext inside Draw function shows as zero, while inside custom renderer which is called by Draw function $pClientDrawingContext shows as other value. Here is also console output. It appears that it shows correct values for everything except for objects. I tried manually following coordinates from DrawGlyphRun once the text is drawn and they are good. expandcollapse popupDraw called x=20,y=40 $pClientDrawingContext=0x00000000 $pRenderer=0x05270140 1=0x6BD7EE10 2=0x6BDA4450 3=0x6BD75DA0 4=0x6BD7C660 5=0x6BD7C6E0 6=0x6BD7C790 7=0x6BE8E2B0 8=0x6BE8E5A0 9=0x6BE8E350 10=0x6BE8E300 Getting transformation matrix of original renderer Type(expecting pointer)=String MyRenderer_QueryInterface() $sIID={D3E0E934-22A0-427E-AAE4-7D9574B59DB1} MyRenderer_IsPixelSnappingEnabled() MyRenderer_GetPixelsPerDip() MyRenderer_GetCurrentTransform() MyRenderer_DrawGlyphRun() $pClientDrawingContext=0x03A317A8 x:20, y:73.767578125 $pClientDrawingEffect=0x0100E990 $pGlyphRun=0x0100E970 StringLen=9 type of $tStrigPtr is Ptr value of String is 0x052780E8 Tag=struct;wchar Text[9];endstruct FontEmSize:36 Text=One line Num of methods:92 MyRenderer_DrawGlyphRun() $pClientDrawingContext=0x03A317A8 x:164.087890625, y:73.767578125 $pClientDrawingEffect=0x0100E990 $pGlyphRun=0x0100E970 StringLen=1 type of $tStrigPtr is Ptr value of String is 0x052780FA Tag=struct;wchar Text[1];endstruct FontEmSize:36 Text=m Num of methods:92 MyRenderer_DrawGlyphRun() $pClientDrawingContext=0x03A317A8 x:194.076171875, y:73.767578125 $pClientDrawingEffect=0x0100E990 $pGlyphRun=0x0100E970 StringLen=5 type of $tStrigPtr is Ptr value of String is 0x052780FC Tag=struct;wchar Text[5];endstruct FontEmSize:20 Text=ore t Num of methods:92 MyRenderer_DrawGlyphRun() $pClientDrawingContext=0x03A317A8 x:237.416015625, y:73.767578125 $pClientDrawingEffect=0x0100E990 $pGlyphRun=0x0100E970 StringLen=3 type of $tStrigPtr is Ptr value of String is 0x05278106 Tag=struct;wchar Text[3];endstruct FontEmSize:36 Text=ext Num of methods:92 MyRenderer_DrawGlyphRun() $pClientDrawingContext=0x03A317A8 x:289.447265625, y:73.767578125 $pClientDrawingEffect=0x0100E990 $pGlyphRun=0x0100E970 StringLen=1 type of $tStrigPtr is Ptr value of String is 0x0527810C Tag=struct;wchar Text[1];endstruct FontEmSize:36 Text= Num of methods:92 MyRenderer_DrawGlyphRun() $pClientDrawingContext=0x03A317A8 x:20, y:115.1640625 $pClientDrawingEffect=0x0100E990 $pGlyphRun=0x0100E970 StringLen=5 type of $tStrigPtr is Ptr value of String is 0x0527810E Tag=struct;wchar Text[5];endstruct FontEmSize:36 Text=even Num of methods:92 MyRenderer_DrawGlyphRun() $pClientDrawingContext=0x03A317A8 x:112.056640625, y:115.1640625 $pClientDrawingEffect=0x0100E990 $pGlyphRun=0x0100E970 StringLen=4 type of $tStrigPtr is Ptr value of String is 0x05278118 Tag=struct;wchar Text[4];endstruct FontEmSize:36 Text=more Num of methods:92 MyRenderer_DrawUnderline() $pClientDrawingContext=0x03A317A8 x=164.087890625, y=73.767578125 $pUnderline=0x0100E918 width=125.359375 $pClientDrawingEffect=0x0100E918 MyRenderer_DrawUnderline() $pClientDrawingContext=0x03A317A8 x=20, y=115.1640625 $pUnderline=0x0100E918 width=92.056640625 $pClientDrawingEffect=0x0100E918 _DWrite_Drawrectangle_Subclass_v2.au3 _DWrite_IDWriteTextRenderer_v2.au3 Link to comment Share on other sites More sharing options...
ahmet Posted January 21, 2022 Author Share Posted January 21, 2022 I managed to create and use successfully Brush object in DrawRectangle method above using ObjectCreateInterface. In my previous attempt I failed because I have not been using AddRef. Now the code inside subclass is following Func DrawRectangle($pSelf, $pRect, $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("$pSelf=" & $pSelf & @CRLF) ConsoleWrite("Width=" & $fWidth & @CRLF) ConsoleWrite("style=" & $pStyle & @CRLF) ConsoleWrite("brush=" & $pBrush & @CRLF) ConsoleWrite("VarGetType($pRect)=" & VarGetType($pRect) & @CRLF) $tRect=DllStructCreate($tagD2D1_RECT_F,$pRect) ConsoleWrite("Left=" & $tRect.Left & @CRLF) ConsoleWrite("Top=" & $tRect.Top & @CRLF) ConsoleWrite("Right=" & $tRect.Right & @CRLF) ConsoleWrite("Bottom=" & $tRect.Bottom & @CRLF) $oTest=ObjCreateInterface($pBrush,$sIID_ID2D1SolidColorBrush,$tagID2D1SolidColorBrush) $oTest.AddRef() $oTest.SetColor(_D2D1_COLOR_F(1,1,0)) $oTest2=ObjCreateInterface($pSelf,$sIID_ID2D1HwndRenderTarget,$tagID2D1HwndRenderTarget) $oTest2.AddRef() $hWnd=HWnd($oTest2.GetHWnd()) MsgBox(0,$hGui,WinGetTitle($hWnd)) DllCallAddress("none",$pDrawRectangle_Old,"ptr",$pSelf,"ptr",$pRect,"ptr", $pBrush, "float", $fWidth, "ptr", $pStyle) $oTest=0 $oTest2=0 ;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 Also I reverted definition of DrawRectangle to its original form and now I am able to use it successfully. I really do not know what I did wrong earlier. Global Const $tagID2D1RenderTarget = $tagID2D1Resource & _ "CreateBitmap hresult(struct;struct*;uint;struct*;ptr*);" & _ "CreateBitmapFromWicBitmap hresult(struct*;struct*;ptr*);" & _ "CreateSharedBitmap hresult(struct*;struct*;struct*;ptr*);" & _ "CreateBitmapBrush hresult(struct*;struct*;struct*;ptr*);" & _ "CreateSolidColorBrush hresult(struct*;struct*;ptr*);" & _ "CreateGradientStopCollection hresult(struct*;uint;uint;uint;ptr*);" & _ "CreateLinearGradientBrush hresult(struct*;struct*;struct*;ptr*);" & _ "CreateRadialGradientBrush hresult(struct*;struct*;struct*;ptr*);" & _ "CreateCompatibleRenderTarget hresult(struct*;struct*;struct*;uint;ptr*);" & _ "CreateLayer hresult(struct*;ptr*);" & _ "CreateMesh hresult(ptr*);" & _ "DrawLine none(struct;struct;struct*;float;struct*);" & _ "DrawRectangle none(struct*;struct*;float;struct*);" & _;;DrawRectangle none(float;float;float;float;struct*;float;struct*) "FillRectangle none(struct*;struct*);" & _ _DWrite_Drawrectangle_Subclass.au3 Link to comment Share on other sites More sharing options...
ahmet Posted January 23, 2022 Author Share Posted January 23, 2022 I managed to solve issues that I was having with the Draw method of IDWriteTextLayout. I was subclassing it instead of calling that method directly with custom text renderer as parameter. Here is an example call. $oRender.BeginDraw() _D2D_RenderTarget_Clear($oRender, 1, 0.9, 0.9) $tPoint=_D2D1_POINT_2F(20,40) $oDW_Layout.Draw($pMyContext,$oMyRenderer,20,40);>>>Here the Draw method is called, and only bounding rectangle are drawn for now $oRender.DrawTextLayout(20,40, $oDW_Layout, $oBrush, 2);now draw text $oRender.EndDraw(0, 0) $oDW_Layout.Draw() does processing using custom text renderer and I can now use something for clientDrawingContext. I had to change definition of Draw in $tagIDWriteTextLayout. Draw hresult(ptr;struct*;float;float);" & _;Draw hresult(struct*;struct*;float;float)-original Here is an image of the output I am attaching my test script and modified DirectWriteConstants.au3. _DWrite_IDWriteTextRenderer.au3 DirectWriteConstants.au3 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now