Leaderboard
Popular Content
Showing content with the highest reputation on 02/16/2021 in all areas
-
The ObjectFromTag() function is used to implement COM callback interfaces, pointers and objects. This is documentation for using the function. When talking about ObjectFromTag(), you cannot get around ObjCreateInterface(). ObjCreateInterface() was introduced in AutoIt version 3.3.8.0 (2011-12-23). The function is coded in the C/C++ language by trancexx. At the top of the official documentation there is a large warning box. A few comments on this warning: "This feature is experimental". No it's not. A function that has been used for more than 9 years to implement advanced code like the following is no longer experimental but has long proven its worth: IUIAutomation MS framework automate chrome, FF, IE, .... created by junkew August 2013 Newer versions of UIA code in this and other threads Using .NET library with AutoIt, possible? and several derived and advanced examples Implementing IRunningObjectTable Interface File/Windows Explorer examples Microsoft Edge - WebView2 As well as a myriad of other examples "It may not work, may contain bugs". The function works and it contains no bugs. This has long been proven by the examples above. "may be changed or removed without notice". On what grounds? The function works, contains no bugs, and adds lots of value to the AutoIt language. "DO NOT REPORT BUGS OR REQUEST NEW FEATURES FOR THIS FEATURE". There's really no reason for that. ObjectFromTag() is implemented as pure AutoIt code and is also made by trancexx. One of the first versions of the function is available in the Ribbon example. One of the latest versions of the function coded by trancexx is found in this post. Description tagsBoth ObjCreateInterface() and ObjectFromTag() use description tags to create objects with methods and properties. A description tag is a string that looks like this (the example of ObjCreateInterface()) $dTag_ITaskbarList = _ "HrInit hresult();" & _ "AddTab hresult(hwnd);" & _ "DeleteTab hresult(hwnd);" & _ "ActivateTab hresult(hwnd);" & _ "SetActiveAlt hresult(hwnd);" Here, the description tag is split into substrings for each method/property. ITaskbarList is the name of the COM interface. The name to the left of each substring is the name of the method/property. hresult in the middle is the method/property return type (always hresult for COM methods/properties), and the data types to the right in parentheses are parameter data types. If there are several parameters, the data types must be separated by a semi colon. Methods/properties of the description tag string must be in correct Vtable order. Vtable order In the Microsoft documentation for the ITaskbarList interface, methods/properties are listed in alphabetical order. But it's not possible to determine the correct Vtable order from this alphabetical list. The only way to determine the correct Vtable order is to study the interface in the appropriate C/C++ header file (shobjidl_core.h for ITaskbarList). All Microsoft header files are included in the Windows SDK. To access the header files, it's necessary to install the Windows SDK on your PC. The header files are located in the folder "E:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0" or similar. When you need a specific header file, it's easiest to search for it. shobjidl_core.h is found in the um subfolder. This is the definition of ITaskbarList in shobjidl_core.h: /* interface ITaskbarList */ /* [object][uuid] */ EXTERN_C const IID IID_ITaskbarList; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("56FDF342-FD6D-11d0-958A-006097C9A090") ITaskbarList : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE HrInit( void) = 0; virtual HRESULT STDMETHODCALLTYPE AddTab( /* [in] */ __RPC__in HWND hwnd) = 0; virtual HRESULT STDMETHODCALLTYPE DeleteTab( /* [in] */ __RPC__in HWND hwnd) = 0; virtual HRESULT STDMETHODCALLTYPE ActivateTab( /* [in] */ __RPC__in HWND hwnd) = 0; virtual HRESULT STDMETHODCALLTYPE SetActiveAlt( /* [in] */ __RPC__in HWND hwnd) = 0; }; #else /* C style interface */ typedef struct ITaskbarListVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ITaskbarList * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ITaskbarList * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ITaskbarList * This); HRESULT ( STDMETHODCALLTYPE *HrInit )( __RPC__in ITaskbarList * This); HRESULT ( STDMETHODCALLTYPE *AddTab )( __RPC__in ITaskbarList * This, /* [in] */ __RPC__in HWND hwnd); HRESULT ( STDMETHODCALLTYPE *DeleteTab )( __RPC__in ITaskbarList * This, /* [in] */ __RPC__in HWND hwnd); HRESULT ( STDMETHODCALLTYPE *ActivateTab )( __RPC__in ITaskbarList * This, /* [in] */ __RPC__in HWND hwnd); HRESULT ( STDMETHODCALLTYPE *SetActiveAlt )( __RPC__in ITaskbarList * This, /* [in] */ __RPC__in HWND hwnd); END_INTERFACE } ITaskbarListVtbl; interface ITaskbarList { CONST_VTBL struct ITaskbarListVtbl *lpVtbl; }; The upper part of the definition is used in the C++ language. The lower part is used in the C language. When translating the definition to AutoIt, it's easiest to look at the C++ definition: /* interface ITaskbarList */ /* [object][uuid] */ EXTERN_C const IID IID_ITaskbarList; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("56FDF342-FD6D-11d0-958A-006097C9A090") ITaskbarList : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE HrInit( void) = 0; virtual HRESULT STDMETHODCALLTYPE AddTab( /* [in] */ __RPC__in HWND hwnd) = 0; virtual HRESULT STDMETHODCALLTYPE DeleteTab( /* [in] */ __RPC__in HWND hwnd) = 0; virtual HRESULT STDMETHODCALLTYPE ActivateTab( /* [in] */ __RPC__in HWND hwnd) = 0; virtual HRESULT STDMETHODCALLTYPE SetActiveAlt( /* [in] */ __RPC__in HWND hwnd) = 0; }; Note that the order of the methods in the description tag string above corresponds to the order of the methods in the C++ definition. Names of methods/properties and the correct Vtable order can be copied directly from the C++ definition. Parameter data types The parameter data types that can be used in the description tag string are listed in the ObjCreateInterface() documentation. Both the header file and the Microsoft documentation can be used to help you find the right data types. In many cases, the data type in the header file or Microsoft documentation corresponds directly to one of the data types in the ObjCreateInterface() documentation. In other cases, it's necessary to translate the data type to one of the valid AutoIt data types. Filling in the parameter data types is the most time consuming task of creating the description tag string. Fortunately, it's enough to fill in the data types for the methods/properties you actually need. For methods/properties you don't need, you can simply enter an empty parenthesis, as is the case in the "HrInit hresult();" substring (in this case because HrInit doesn't actually take any parameters). You can omit the parameter data types for methods/properties that are not to be used in the first place, but all methods/properties must be specified in the correct Vtable order. IUnknown interface All COM interfaces inherits from the IUnknown interface. It's indicated in the C++ definition by this line ITaskbarList : public IUnknown Because all COM interfaces inherits from the IUnknown interface, don't specify IUnknown methods/properties in the description tag string. IUnknown methods/properties are added automatically in both ObjCreateInterface() and ObjectFromTag() functions. $sIID and $sCLSID Note that this line in the AutoIt code $sIID_ITaskbarList = "{56FDF342-FD6D-11D0-958A-006097C9A090}" corresponds to this line in the C++ definition MIDL_INTERFACE("56FDF342-FD6D-11D0-958A-006097C9A090") And that this line in the AutoIt code $sCLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}" corresponds to these lines in the C++ definition (further down in the header file) class DECLSPEC_UUID("56FDF344-FD6D-11D0-958A-006097C9A090") TaskbarList; ObjectFromTag() functionThe version of ObjectFromTag() that I'm using is based on this version by trancexx. My first version is contained in the 7z-file below and coded in ObjectFromTag-a.au3 dated 2014-01-14. My current version is coded in ObjectFromTag.au3 dated 2021-02-06. The function is defined as follows: Func ObjectFromTag( _ $sFunctionPrefix, _ ; Presents methods/properties with the same prefix name $tagInterface, _ ; Interface description tag string ByRef $tInterface, _ ; Interface struct (DllStruct) $bObject = True, _ ; Return object or object pointer $bPrint = False, _ ; Print information in SciTE console $bIsUnknown = True, _ ; Inherits from the IUnknown interface $sIID = "{00000000-0000-0000-C000-000000000046}" ) ; $sIID_IUnknown ObjectFromTag() exampleAs an example of using the function, I'll show how to create the first part of the WebView2-1.au3 example here (WebView2-1-0.au3, all required code and files are contained in the 7z-file below). According to the Getting started with WebView2 example, the prerequisites for running the code are installing the Microsoft Edge Chromium version and the WebView2 Runtime (Evergreen Bootstrapper). #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=y Opt( "MustDeclareVars", 1 ) #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <WinAPICom.au3> #include <WinAPI.au3> Global $hGui ; Project includes #include "..\Includes\WV2Interfaces.au3" WebView2() Func WebView2() ; Create WebView2 GUI $hGui = GUICreate( "WebView2 Sample", 1200, 900, -1, -1, $WS_OVERLAPPEDWINDOW ) ; Initialize COM _WinAPI_CoInitialize( $COINIT_APARTMENTTHREADED ) ; Create callback interfaces and functions CoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerCreate( True ) ; DllCall CreateCoreWebView2EnvironmentWithOptions Local $hWebView2Loader = DllOpen( @AutoItX64 ? "WebView2Loader-x64.dll" : "WebView2Loader-x86.dll" ) Local $aRet = DllCall( $hWebView2Loader, "long", "CreateCoreWebView2EnvironmentWithOptions", "wstr", "", "wstr", "", _ "ptr", NULL, "ptr", $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler ) ; Forces CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke() below to be executed If @error Or $aRet[0] Then Return ConsoleWrite( "CreateCoreWebView2EnvironmentWithOptions ERR" & @CRLF ) ConsoleWrite( "CreateCoreWebView2EnvironmentWithOptions OK" & @CRLF & @CRLF ) ; Show WebView2 GUI GUISetState( @SW_SHOW ) ; Loop While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Cleanup CoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerDelete() DllClose( $hWebView2Loader ) EndFunc ; Copied from WV2Interfaces.au3 ; Executed as a consequence of the DllCall() function above Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke( $pSelf, $long, $ptr ) ; Ret: long Par: long;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke" & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $long, $ptr EndFunc The code can be run without errors. However, since it's only about half of all the code, an empty window without web content is displayed. A crucial point, of course, is to create this code from scratch. I've read the WebView2 documentation and especially the API reference documentation and studied the HelloWebView.cpp and WebView2.ahk examples (contained in the 7z-file). By running the examples and adding "ConsoleWrites" to the code, I've found that the examples can be translated to AutoIt code as shown. Because the WebView2 code is new code that's still under development, the WebView2.h header file isn't included in the Windows SDK. WebView2.h can instead be downloaded in a NuGet package as described in the WebView2 documentation. I'll focus on this part of the code: ; Create callback interfaces and functions CoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerCreate( True ) The code creates the CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler callback interface and its functions. CoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerCreate() in WV2Interfaces.au3: Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerCreate( $bPrint = False ) $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = _ ObjectFromTag( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_", _ $dtag_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, _ $tCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, False, $bPrint ) If $bPrint Then ConsoleWrite( "$pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = " & _ $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler & @CRLF & @CRLF ) EndFunc The function executes ObjectFromTag(), which creates the callback interface and its functions. Note the False parameter just before $bPrint. False means that ObjectFromTag() returns an object pointer instead of the object itself. It seems that all WebView2 callback interfaces are created from an object pointer and not the object itself. Implement these steps to create the callback interface and its functions: Step 1: Create the description tag for ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler callback interface Step 2: Execute ObjectFromTag() with the $bPrint = True parameter Step 3: Copy the functions printed in the SciTE console into the code and run the code again Step 4: Continue executing ObjectFromTag() and copy the functions until there are no more errors Step 5: Test the code to check if the interface functions are called as expected Step 1The $dtag for the ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler callback interface can be created based on the information in WebView2.h (search the interface) and the Microsoft documentation (google the interface): Global Const $dtag_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = _ "Invoke hresult(hresult;ptr*);" Step 2Execute ObjectFromTag() with the $bPrint = True parameter this way (WebView2-1-1.au3) #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=y Opt( "MustDeclareVars", 1 ) #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <WinAPICom.au3> #include <WinAPI.au3> Global $hGui Global $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, _ $tCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler Global Const $dtag_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = _ "Invoke hresult(hresult;ptr*);" ; Project includes ;#include "..\Includes\WV2Interfaces.au3" #include "..\Includes\ObjectFromTag.au3" WebView2() Func WebView2() ; Create WebView2 GUI $hGui = GUICreate( "WebView2 Sample", 1200, 900, -1, -1, $WS_OVERLAPPEDWINDOW ) ; Initialize COM _WinAPI_CoInitialize( $COINIT_APARTMENTTHREADED ) ; Create callback interfaces and functions $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = _ ObjectFromTag( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_", _ $dtag_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, _ $tCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, False, True ) ; $bPrint = True ; Show WebView2 GUI GUISetState( @SW_SHOW ) ; Loop While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Cleanup EndFunc SciTE console output: Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface( $pSelf, $pRIID, $pObj ) ; Ret: long Par: ptr;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface()" & @CRLF & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $pRIID, $pObj EndFunc @error = 3 Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef( $pSelf ) ; Ret: dword ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef()" & @CRLF & @CRLF ) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc @error = 3 Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release( $pSelf ) ; Ret: dword ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release()" & @CRLF & @CRLF ) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc @error = 3 Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke( $pSelf, $long, $ptr ) ; Ret: long Par: long;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke()" & @CRLF & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $long, $ptr EndFunc @error = 3 @error = 3 is an error code from DllCallbackRegister() in the ObjectFromTag() function and apparently means that the functions don't exist. Step 3Copy the four functions into the code and run the code again (WebView2-1-2.au3, delete @error = 3 lines): #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=y Opt( "MustDeclareVars", 1 ) #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <WinAPICom.au3> #include <WinAPI.au3> Global $hGui Global $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, _ $tCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler Global Const $dtag_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = _ "Invoke hresult(hresult;ptr*);" ; Project includes ;#include "..\Includes\WV2Interfaces.au3" #include "..\Includes\ObjectFromTag.au3" WebView2() Func WebView2() ; Create WebView2 GUI $hGui = GUICreate( "WebView2 Sample", 1200, 900, -1, -1, $WS_OVERLAPPEDWINDOW ) ; Initialize COM _WinAPI_CoInitialize( $COINIT_APARTMENTTHREADED ) ; Create callback interfaces and functions $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = _ ObjectFromTag( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_", _ $dtag_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, _ $tCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, False, True ) ; $bPrint = True ; Show WebView2 GUI GUISetState( @SW_SHOW ) ; Loop While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Cleanup EndFunc Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface( $pSelf, $pRIID, $pObj ) ; Ret: long Par: ptr;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface()" & @CRLF & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $pRIID, $pObj EndFunc Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef( $pSelf ) ; Ret: dword ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef()" & @CRLF & @CRLF ) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release( $pSelf ) ; Ret: dword ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release()" & @CRLF & @CRLF ) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke( $pSelf, $long, $ptr ) ; Ret: long Par: long;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke()" & @CRLF & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $long, $ptr EndFunc SciTE console output: Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface( $pSelf, $pRIID, $pObj ) ; Ret: long Par: ptr;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface()" & @CRLF & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $pRIID, $pObj EndFunc @error = 0 Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef( $pSelf ) ; Ret: dword ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef()" & @CRLF & @CRLF ) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc @error = 0 Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release( $pSelf ) ; Ret: dword ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release()" & @CRLF & @CRLF ) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc @error = 0 Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke( $pSelf, $long, $ptr ) ; Ret: long Par: long;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke()" & @CRLF & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $long, $ptr EndFunc @error = 0 Step 4No more errors. We're done. The callback interface and its functions are implemented. Step 5Check if the interface functions are called as expected (WebView2-1-3.au3) #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=y Opt( "MustDeclareVars", 1 ) #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <WinAPICom.au3> #include <WinAPI.au3> Global $hGui Global $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, _ $tCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler Global Const $dtag_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = _ "Invoke hresult(hresult;ptr*);" ; Project includes ;#include "..\Includes\WV2Interfaces.au3" #include "..\Includes\ObjectFromTag.au3" WebView2() Func WebView2() ; Create WebView2 GUI $hGui = GUICreate( "WebView2 Sample", 1200, 900, -1, -1, $WS_OVERLAPPEDWINDOW ) ; Initialize COM _WinAPI_CoInitialize( $COINIT_APARTMENTTHREADED ) ; Create callback interfaces and functions $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = _ ObjectFromTag( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_", _ $dtag_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, _ $tCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, False, True ) ; $bPrint = True ; DllCall CreateCoreWebView2EnvironmentWithOptions Local $hWebView2Loader = DllOpen( @AutoItX64 ? "WebView2Loader-x64.dll" : "WebView2Loader-x86.dll" ) Local $aRet = DllCall( $hWebView2Loader, "long", "CreateCoreWebView2EnvironmentWithOptions", "wstr", "", "wstr", "", _ "ptr", NULL, "ptr", $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler ) ; Forces CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke() below to be executed If @error Or $aRet[0] Then Return ConsoleWrite( "CreateCoreWebView2EnvironmentWithOptions ERR" & @CRLF ) ConsoleWrite( "CreateCoreWebView2EnvironmentWithOptions OK" & @CRLF & @CRLF ) ; Show WebView2 GUI GUISetState( @SW_SHOW ) ; Loop While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Cleanup DllClose( $hWebView2Loader ) EndFunc Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface( $pSelf, $pRIID, $pObj ) ; Ret: long Par: ptr;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface()" & @CRLF & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $pRIID, $pObj EndFunc Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef( $pSelf ) ; Ret: dword ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef()" & @CRLF & @CRLF ) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release( $pSelf ) ; Ret: dword ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release()" & @CRLF & @CRLF ) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke( $pSelf, $long, $ptr ) ; Ret: long Par: long;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke()" & @CRLF & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $long, $ptr EndFunc SciTE console output: Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface( $pSelf, $pRIID, $pObj ) ; Ret: long Par: ptr;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface()" & @CRLF & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $pRIID, $pObj EndFunc @error = 0 Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef( $pSelf ) ; Ret: dword ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef()" & @CRLF & @CRLF ) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc @error = 0 Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release( $pSelf ) ; Ret: dword ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release()" & @CRLF & @CRLF ) Return 1 ; For AddRef/Release #forceref $pSelf EndFunc @error = 0 Func CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke( $pSelf, $long, $ptr ) ; Ret: long Par: long;ptr* ConsoleWrite( "CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke()" & @CRLF & @CRLF ) Return 0 ; S_OK = 0x00000000 #forceref $pSelf, $long, $ptr EndFunc @error = 0 CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_AddRef() CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke() CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Release() CreateCoreWebView2EnvironmentWithOptions OK Output looks as expected - even if CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_QueryInterface() isn't called. If you get a CreateCoreWebView2EnvironmentWithOptions ERR from the DllCall() function and you're sure that the function is coded correctly, read this post by Chimp for a description and solution to the problem. Note that for all WebView2 callback interfaces, it seems that the Invoke() method is interesting, while the other methods/properties aren't so interesting. To proceed with the WebView2-1.au3 example (included as WebView2-1-a.au3) add code in the CoreWebView2CreateCoreWebView2EnvironmentCompletedHandler_Invoke() function. 7z-fileThe 7z-file contains source code for the UDF and examples and other files needed to run the code. You need AutoIt 3.3.12 or later. Tested on Windows 7 and Windows 10. Comments are welcome. Let me know if there are any issues. ObjectFromTag.7z5 points
-
GUICtrlCreatePic in WMPlayer.ocx
pixelsearch and one other reacted to Nine for a topic
Here something you could use : #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <Constants.au3> #include <Misc.au3> #include <GDIPlus.au3> #include <Array.au3> Opt("MustDeclareVars", 1) Local $tImage _GDIPlus_Startup() Local $hImage = _ConvertStringToImage($tImage, 18, 18) Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() Local $hGui = GUICreate("WMPlayer.OCX", 400, 75, -1, -1) Local $idSongName = GUICtrlCreateButton("", 0, 0, 400, 20) GUICtrlSetState(-1, $GUI_DISABLE) Local $Shuttle = GUICtrlCreatePic("", 0, 0, 18, 18) GUICtrlSendMsg(-1, $STM_SETIMAGE, $IMAGE_BITMAP, $hBitmap) _WinAPI_DeleteObject($hBitmap) Local $Pause = GUICtrlCreateButton("Pause", 160, 40, 80, 20) Local $Progress = GUICtrlCreateLabel("0:00", 4, 25, 45, 20, $SS_LEFT) ; current media position Local $Length = GUICtrlCreateLabel("0:00", 350, 25, 45, 20, $SS_RIGHT) ; media length GUISetState(@SW_SHOW) Local $aPlayList[2] ; Put your own mp3 file paths in this playlist $aPlayList[0] = 1 ; number of files in the playlist $aPlayList[1] = "Don Henley - The Boys of Summer.mp3" For $i = $aPlayList[0] To 1 Step -1 If Not FileExists($aPlayList[$i]) Then _ArrayDelete($aPlayList, $i) $aPlayList[0] -= 1 EndIf Next If Not $aPlayList[0] Then Exit MsgBox(0, "WMPlayer.ocx", "None of the files listed in $aPlayList array exists.", 5) Local $oPlayer = ObjCreate("WMPlayer.OCX") If Not IsObj($oPlayer) Then Exit MsgBox(0, "WMPlayer.OCX", "Cannot create a WMP object.", 5) Local $iPos = 0 ; x coordinate of $Shuttle cntrol in progress bar Local $hDLL = DllOpen("user32.dll") ; to dectect mouse down on the $Shuttle control Local $sliderLength = 380 ; in pixels Local $adlibInterval = 250 ; in milliseconds $oPlayer.Settings.Volume = 100 Local $nFile = 0, $sFullPath, $hTimer, $sFile, $mediaLength, $x, $mediaPos, $xOffset While 1 $nFile += 1 If $nFile > $aPlayList[0] Then $nFile = 1 $sFullPath = $aPlayList[$nFile] $oPlayer.URL = $sFullPath $hTimer = TimerInit() While $oPlayer.playState <> 3 ; 1 - stopped, 2 - paused, 3 - playing If TimerDiff($hTimer) > 3000 Then MsgBox(0, "WMPlayer.OCX", $sFullPath & @CRLF & @CRLF & "Cannot play this file.", 5) ExitLoop EndIf Sleep(10) WEnd If $oPlayer.playState <> 3 Then ContinueLoop $sFile = StringMid($sFullPath, StringInStr($sFullPath, "\", 0, -1) + 1) GUICtrlSetData($idSongName, $sFile) $mediaLength = Int($oPlayer.currentMedia.Duration) ; in seconds GUICtrlSetData($Length, Int($mediaLength / 60) & ":" & StringFormat("%02i", Mod($mediaLength, 60))) AdlibRegister("Slider", $adlibInterval) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE $oPlayer.Close() Exit Case $Pause If GUICtrlRead($Pause) = "Pause" Then $oPlayer.Controls.Pause AdlibUnRegister() GUICtrlSetData($Pause, "Resume") Else $oPlayer.Controls.Play AdlibRegister("Slider") GUICtrlSetData($Pause, "Pause") EndIf Case $Shuttle AdlibUnRegister() $x = MouseGetPos(0) $xOffset = $x - $iPos While _IsPressed("01", $hDLL) = 1 $x = MouseGetPos(0) If $x > 380 + $xOffset Then $x = 380 + $xOffset ElseIf $x < $xOffset Then $x = $xOffset EndIf $iPos = $x - $xOffset GUICtrlSetPos($Shuttle, $iPos) Sleep(10) WEnd $mediaPos = $iPos / $sliderLength * $mediaLength $oPlayer.Controls.currentPosition = $mediaPos $oPlayer.Controls.Play AdlibRegister("Slider", $adlibInterval) GUICtrlSetData($Pause, "Pause") EndSwitch If $oPlayer.playState = 1 Then ExitLoop WEnd WEnd Func Slider() $mediaPos = $oPlayer.Controls.currentPosition $iPos = $mediaPos * $sliderLength / $mediaLength GUICtrlSetPos($Shuttle, $iPos) GUICtrlSetData($Progress, Int($mediaPos / 60) & ":" & StringFormat("%02i", Mod($mediaPos, 60))) EndFunc ;==>Slider ; based on https://www.autoitscript.com/forum/topic/204254-saveretrieve-images-tofrom-text-string/ Func _ConvertStringToImage(ByRef $tBuffer, $iWidth, $iHeight) Local Const $IMAGE = "FFF6DAFFFFF1D7FF4E341CFF44311CFF40311EFF493726FF4A3020FF563525FF533121FF52331EFF4E331EFF4B351CFF49351CFF4B351CFF52321FFF473125FFF6F5F7FFE2EDF5FFFFF6DCFF54361DFF78634DFF716350FF7D7361FF746757FF745F50FF7F6557FF836657FF816756FF7C6954FF786A53FF786A54FF7A6954FF806856FF7C6758FF2E271EFFF6F7EEFF4E341CFF826D57FF736A56FF6B6957FF616153FF636156FF756C62FF77695DFF746457FF726555FF6E6655FF6B6754FF6B6755FF6D6655FF726557FF776653FF897455FF4D3610FF4E3B26FF6F614EFF6B6957FF707566FF5C6459FF6E736AFF67655DFF666059FF6F685FFF6D695EFF686A5EFF666A5EFF646B5EFF686A5EFF6D685FFF786A58FF876A43FF5E3B09FF3C2D1AFF786E5CFF656557FF5A6257FF5F6963FF545D5AFF5F6260FF696766FF676362FF656460FF5F6560FF5C675FFF5C6660FF5E6560FF636462FF6F6659FF836A48FF5F3E11FF4B3928FF766959FF615F54FF6A6F66FF5B6461FF666E6EFF5D5F60FF6D6A6CFF696466FF656565FF606665FF5C6765FF5C6666FF5E6666FF636468FF70675EFF826A4CFF573910FF472D1DFF7C6758FF797066FF605E56FF5C5F5DFF636566FF696269FF615960FF6A5F67FF676166FF616266FF5F6364FF5E6366FF5F6266FF656167FF6F635FFF82694FFF53360FFF563526FF785E50FF76685CFF6B655EFF676564FF6B686AFF665E65FF70656FFF6D6068FF6B6068FF666267FF626367FF606368FF646268FF69606AFF746360FF836A50FF563912FF543222FF826556FF756558FF6F685FFF686463FF686365FF6C6169FF6D6068FF6F6068FF6B6068FF666267FF626465FF626367FF646367FF696168FF746360FF846A4CFF583A11FF543320FF7F6554FF736656FF6D695EFF666561FF646464FF696267FF6B6068FF6B6068FF696267FF626465FF606465FF606465FF626465FF686267FF72645EFF826A4EFF563912FF4F341FFF7A6752FF6F6756FF6A6A5EFF606661FF5F6564FF646367FF666267FF666267FF626465FF5F6564FF5B6664FF5B6664FF5F6564FF646365FF6F655EFF7D6852FF513818FF4C361DFF766851FF6C6856FF666A5EFF5F6760FF5D6564FF606367FF626367FF626367FF606465FF5B6664FF596763FF596763FF5D6663FF646563FF6D665DFF7D6852FF513818FF4A361DFF766851FF6C6856FF646B5EFF5D6761FF5B6664FF5F6467FF606367FF626367FF606465FF5B6664FF596763FF5B6761FF5D6761FF646561FF70665CFF806A4EFF563914FF4D351FFF786752FF6E6756FF686A5EFF5F6661FF5D6565FF606368FF646268FF646268FF626465FF5F6564FF5D6663FF5F6661FF626661FF686561FF74665AFF846B4BFF5A3A11FF533320FF7E6654FF736658FF6D685FFF646563FF626465FF666268FF696168FF696168FF686267FF646365FF626563FF646561FF686561FF6F6361FF79655AFF866A4CFF583912FF513322FF7F6554FF766656FF74685CFF6D665DFF6D655EFF706361FF726361FF726361FF726360FF6F6460FF6D655EFF6F665DFF72665CFF77645CFF7D6657FF82694FFF513816FFFFF8E7FF463220FF83705BFF7B6952FF7B6650FF7F6950FF7F674FFF7E664EFF816854FF806854FF7E6954FF7E6954FF7E6954FF806953FF836951FF816953FF483520FFFFF4DEFFFFEFDEFFFFF1DEFF442F19FF483117FF5A4121FF4F3412FF563815FF583C1AFF533617FF523618FF50351AFF50351AFF50351AFF503618FF533518FF4E361AFFF9E9D8FFFFFFF4FF" Return _ReadImageFromText($tBuffer, $IMAGE, $iWidth, $iHeight) EndFunc ;==>_ConvertStringToImage Func _ReadImageFromText(ByRef $tByte, $sString, $iWidth, $iHeight, $bFileName = False) ; Recreate image from text file If $bFileName Then $sString = FileRead($sString) Local $dData = Binary("0x" & $sString) $tByte = DllStructCreate("byte string[" & $iWidth * $iHeight * 4 & "]") DllStructSetData($tByte, 1, $dData) Return _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $GDIP_PXF32ARGB, $iWidth * 4, DllStructGetPtr($tByte, "string")) EndFunc ;==>_ReadImageFromText2 points -
Generate interactive line graphics, pie charts and much more with IE and chart.js
argumentum reacted to qsek for a topic
Just wanted to share a quick proof of concept with some performance testing. GraphGDIPlus lacked performance and interactivity for me so i searched new way to generate graphs. Potential is huge especially when you consider using d3.js instead of chart.js #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <Array.au3> #include <File.au3> #include <Date.au3> #include <IE.au3> Opt("GuiOnEventMode", 1) $oIE = ObjCreate("Shell.Explorer.2") $Form1 = GUICreate("Embedded Web control Test", 1140, 380, _ (@DesktopWidth - 1140) / 2, (@DesktopHeight - 380) / 2, _ $WS_OVERLAPPEDWINDOW + $WS_CLIPSIBLINGS + $WS_CLIPCHILDREN) GUICtrlCreateObj($oIE, 10, 10, 1120, 360) GUICtrlSetResizing ( -1, 1 ) GUISetOnEvent(-3, "_MyExit", $Form1) GUISetState() Func _MyExit() Exit EndFunc ConsoleWrite("generating dataset..." & @CRLF) ; generate a 5k line dataset ; string $datastr = "" For $i = 0 To 2000 $date = _DateAdd("n", $i, "2021/02/14 00:00:00") $datastr &= $date&","&Random(1,500,1)& @CRLF next $datastr = StringTrimRight($datastr, 2) ; array Dim $dataarr[0][2] _ArrayAdd ( $dataarr, $datastr, 0, ",", @CRLF) ConsoleWrite("finished." & @CRLF& @CRLF) $oIE.navigate( "about:blank") $html = "" Sethtml() _IEDocWriteHTML($oIE, $html) _IEAction ( $oIE, "refresh" ) _IELoadWait($oIE) ;~ ; watch your variable/function case with that notation! $ohJS = $oIE.document.parentwindow.JSglobal ;~ ; need to eval [0], javascript arrays are not compatible with autoit arrays or object collections $dset = $ohJS.eval("myChart.data.datasets[0]") $dset.label = "Test1: init dataset with jsvariable.push()" $ohJS.myChart.update() ConsoleWrite("Test1: init dataset with jsvariable.push()"& @CRLF) $ti = TimerInit() ; Test1 $glabels = $ohJS.myChart.data.labels For $i = 0 To UBound($dataarr)-1 If Mod($i,1000) = 0 then ConsoleWrite($i & @CRLF) $glabels.push($dataarr[$i][0]) $dset.data.push($dataarr[$i][1]) next $ohJS.myChart.update() ConsoleWrite("Test1: "&Round(TimerDiff($ti),1)&" ms"& @CRLF) Sleep(2000) $ohJS.GraphClearData() Sleep(1000) ConsoleWrite("Test2: init dataset with passing datastring to js function"& @CRLF) $ti = TimerInit() ; Test2 $ohJS.InitGraphWithData($datastr) $ohJS.myChart.update() ConsoleWrite("Test2: "&Round(TimerDiff($ti),1)&" ms"& @CRLF) Sleep(2000) $ohJS.GraphClearData() $dset.label = "Test3: add data with jsvariable.push()" $ohJS.myChart.update() ConsoleWrite("Test3: add data with jsvariable.push()"& @CRLF) $ti = TimerInit() ; Test3 $glabels = $ohJS.myChart.data.labels For $i = 0 To 500 If Mod($i,100) = 0 then $dset.label = "Test3: add data with jsvariable.push() ("&$i&"/500)" $date = _DateAdd("n", $i, "2021/02/14 00:00:00") $glabels.push($date) $dset.data.push(Random(1,500+$i,1)) $ohJS.myChart.update() Next ConsoleWrite("Test3: "&Round(TimerDiff($ti),1)&" ms"& @CRLF) $ohJS.GraphClearData() ConsoleWrite("Test4: add data with passing datastring to js function" & @CRLF) $ti = TimerInit() ; Test4 For $i = 0 To 500 If Mod($i,100) = 0 then $dset.label = "Test4: add data with passing datastring to js function ("&$i&"/500)" $date = _DateAdd("n", $i, "2021/02/14 00:00:00") $ohJS.GraphAddData($date&","&Random(1,500+$i,1)) If Mod($i,100) = 0 then $dset.label = "Test4: add data with passing datastring to js function ("&$i&"/500)" Next ConsoleWrite("Test4: "&Round(TimerDiff($ti),1)&" ms"& @CRLF) ConsoleWrite("testing ended" & @CRLF) $dset.label = "You can click on points" $ohJS.myChart.update() While 1 For $i = 0 To $ohJS.clickedPoints.length -1 $label = $ohJS.eval("myChart.data.labels[clickedPoints["&$i&"]._index].format('YYYY/MM/DD hh:mm:ss');") $value = $ohJS.eval("myChart.data.datasets[clickedPoints["&$i&"]._datasetIndex].data[clickedPoints["&$i&"]._index];") ConsoleWrite("You clicked at " & $label & ", "&$value & @CRLF) Next $ohJS.clickedPoints = "" Sleep(10) WEnd exit Func Sethtml() $html = "<!DOCTYPE html>" & @CRLF & _ "<html lang='en'>" & @CRLF & _ "" & @CRLF & _ "<head>" & @CRLF & _ " <meta charset='UTF-8'>" & @CRLF & _ " <meta http-equiv='X-UA-Compatible' content='IE=edge' >" & @CRLF & _ " <script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script>" & @CRLF & _ " <script src='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js'></script>" & @CRLF & _ " <script src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js'></script>" & @CRLF & _ " <title>My Chart</title>" & @CRLF & _ "</head>" & @CRLF & _ "" & @CRLF & _ "<body>" & @CRLF & _ " <div class='container'> <canvas id='myChart' width='100' height='30'></canvas></div>" & @CRLF & _ "" & @CRLF & _ " <script>" & @CRLF & _ " var JSglobal = (1,eval)('this');" & @CRLF & _ " var au3data = ['test','123'];" & @CRLF & _ " var clickedPoints = '';" & @CRLF & _ " Chart.defaults.global.animation.duration = 0;" & @CRLF & _ " Chart.defaults.global.hover.animationDuration = 0;" & @CRLF & _ " Chart.defaults.global.animation.easing = 'linear';" & @CRLF & _ " Chart.defaults.global.elements.line.tension = 0;" & @CRLF & _ " Chart.defaults.global.elements.line.backgroundColor = 'rgba(255, 99, 132, 0.2)';" & @CRLF & _ " Chart.defaults.global.elements.line.borderColor = 'rgba(255, 99, 132, 1)';" & @CRLF & _ "" & @CRLF & _ " Chart.defaults.global.responsiveAnimationDuration = 0;" & @CRLF & _ " //Chart.defaults.line.showLines = false;" & @CRLF & _ " Chart.defaults.line.spanGaps = false;" & @CRLF & _ "" & @CRLF & _ " function GraphClearData() {" & @CRLF & _ " myChart.data.datasets[0].data = [];" & @CRLF & _ " myChart.data.labels = [];" & @CRLF & _ " myChart.update(0);" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " function InitGraphWithData(datastring, rowdelim, coldelim) {" & @CRLF & _ " rowdelim = typeof rowdelim !== 'undefined' ? rowdelim : '\n';" & @CRLF & _ " coldelim = typeof coldelim !== 'undefined' ? coldelim : ',';" & @CRLF & _ " GraphClearData();" & @CRLF & _ "" & @CRLF & _ " var allLinesArray = datastring.split('\n');" & @CRLF & _ " if (allLinesArray.length > 0) {" & @CRLF & _ " for (var i = 0; i < allLinesArray.length; i++) {" & @CRLF & _ " var rowData = allLinesArray[i].split(',');" & @CRLF & _ " if (rowData[0] != '') {" & @CRLF & _ " myChart.data.labels.push(moment(rowData[0], 'YYYY/MM/DD hh:mm:ss'));" & @CRLF & _ " myChart.data.datasets[0].data.push(rowData[1]);" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " myChart.update();" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ "" & @CRLF & _ " function GraphAddData(datastring, rowdelim, coldelim) {" & @CRLF & _ " rowdelim = typeof rowdelim !== 'undefined' ? rowdelim : '\n';" & @CRLF & _ " coldelim = typeof coldelim !== 'undefined' ? coldelim : ',';" & @CRLF & _ "" & @CRLF & _ " var allLinesArray = datastring.split('\n');" & @CRLF & _ " if (allLinesArray.length > 0) {" & @CRLF & _ " for (var i = 0; i < allLinesArray.length; i++) {" & @CRLF & _ " var rowData = allLinesArray[i].split(',');" & @CRLF & _ " if (rowData[0] != '') {" & @CRLF & _ " //alert('adding '+rowData[0]+', '+rowData[1]);" & @CRLF & _ " myChart.data.labels.push(moment(rowData[0], 'YYYY/MM/DD hh:mm:ss'));" & @CRLF & _ " myChart.data.datasets[0].data.push(rowData[1]);" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " myChart.update();" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " var ctx = document.getElementById('myChart').getContext('2d');" & @CRLF & _ "" & @CRLF & _ " document.getElementById('myChart').onclick = function(evt) {" & @CRLF & _ " clickedPoints = myChart.getElementsAtEvent(evt);" & @CRLF & _ " };" & @CRLF & _ "" & @CRLF & _ " var myChart = new Chart(ctx, {" & @CRLF & _ " type: 'line'," & @CRLF & _ " data: {" & @CRLF & _ " datasets: [{" & @CRLF & _ " label: ''," & @CRLF & _ " }]" & @CRLF & _ " }," & @CRLF & _ " options: {" & @CRLF & _ " responsive: 'true'," & @CRLF & _ " scales: {" & @CRLF & _ " xAxes: [{" & @CRLF & _ " type: 'time'," & @CRLF & _ " time: {" & @CRLF & _ " displayFormats: {" & @CRLF & _ " minute: 'DD.MMM H:m'" & @CRLF & _ " }" & @CRLF & _ " }," & @CRLF & _ " distribution: 'linear'," & @CRLF & _ " ticks: {" & @CRLF & _ " source: 'auto'" & @CRLF & _ " }," & @CRLF & _ " bounds: 'bounds'" & @CRLF & _ " }]" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " });" & @CRLF & _ "" & @CRLF & _ " myChart.update();" & @CRLF & _ "" & @CRLF & _ " <!-- setInterval(function() { -->" & @CRLF & _ " <!-- updateChart() -->" & @CRLF & _ " <!-- }, 5000); -->" & @CRLF & _ " </script>" & @CRLF & _ "</body>" & @CRLF & _ "" & @CRLF & _ "</html>" & @CRLF EndFunc1 point -
Very Simple Inter-Process Communication (using AutoItObject_Internal)
jaberwacky reacted to SEuBo for a topic
Hi there, while I created an example script to generate and execute a function during runtime, I stumbled across a neat way to share data between running autoit scripts. This is done using the amazing magic of AutoItObject_Internal . (You'll need at least Version 3.0.0 of AutoItObject_Internal) Using this UDF, you can create a shared data storage, basically an empty "AutoitObject_Internal-"Object which you can then use to write / read data Inline. no set/get methods, just #include "AutoItSharedData.au3" $oShare = _AutoIt_SharedData_CreateOrAttach("MyCustomID") $oShare.some_data = 'foo' and you're done. any other script accessing this data will have to do: #include "AutoItSharedData.au3" $oShare = _AutoIt_SharedData_CreateOrAttach("MyCustomID") ConsoleWrite($oShare.some_data & @LF) Basically it's Larsj's Implementing IRunningObjectTable Interface, but you dont have a Dictionary, but an IDIspatch Object instead. There are already a bunch of IPC options available - and this is another one. AutoItSharedData.au3 Example Script 1 Example Script 2 Output: To test: run Example Script 1, Then run example Script 2.. or the other way around. Example Script 3 Example_sharedata3.au3 Example_sharedata3_Controlsend.au3 Example_sharedata3_Tooltip.au3 To test: run Example_sharedata3.au3. Output: Example SharedData4: Output: /Edit: Please note that there's a limitation with the Running object table : The Script accessing a variable first, will be the "server" for this variable. This means, access to that variable from other scripts should only be possible, as long the "server" script is running! Use appropriate Object Error handlers in case you don't want the surviving "clients" to crash. Feedback and/or improvements appreciated changelog version 2.0 Removed need for AutoItObject, as AutoItObject_Internal now comes with ROT support Added UDF Header Fixed typo on "#include AutoItObjectInternal.au3" -> "#include AutoItObject_Internal.au3" Added ObjGet() after registering the object fails (in case 2 programs tried to register the same ID simultaneously) Updated Examples & zip archive. Cheers, AutoItSharedData.zip1 point -
GUICtrlCreatePic in WMPlayer.ocx
Emanoel reacted to pixelsearch for a topic
Hi Nine, I got a little request if you don't mind. In your 1st script (the one with GUICtrlCreatePic), do you think it would be possible to click anywhere in the button zone area ($idSongName) to move immediately the shuttle at the clicked position ? This new feature, added to the already existant "shuttle drag" feature, would make this script even more fantastic Thanks in advance.1 point -
@Nine, Thank you very much, I appreciate your efforts 🙏🏻🙏🏻♥1 point
-
GUICtrlCreatePic in WMPlayer.ocx
argumentum reacted to Nine for a topic
I do not understand why it is easier to work with a button, but here you go : #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <Constants.au3> #include <Misc.au3> #include <GDIPlus.au3> #include <Array.au3> #include <GuiButton.au3> #include <GuiImageList.au3> Opt("MustDeclareVars", 1) Local $tImage _GDIPlus_Startup() Local $hImage = _ConvertStringToImage($tImage, 18, 18) Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() Local $hGui = GUICreate("WMPlayer.OCX", 400, 75, -1, -1) Local $idSongName = GUICtrlCreateButton("", 0, 0, 400, 20) GUICtrlSetState(-1, $GUI_DISABLE) Local $Shuttle = GUICtrlCreateButton("", 0, 0, 20, 20) Local $hImageList=_GUIImageList_Create() _GUIImageList_Add($hImageList, $hBitmap) _GUICtrlButton_SetImageList($Shuttle, $hImageList) _WinAPI_DeleteObject($hBitmap) Local $Pause = GUICtrlCreateButton("Pause", 160, 40, 80, 20) Local $Progress = GUICtrlCreateLabel("0:00", 4, 25, 45, 20, $SS_LEFT) ; current media position Local $Length = GUICtrlCreateLabel("0:00", 350, 25, 45, 20, $SS_RIGHT) ; media length GUISetState(@SW_SHOW) Local $aPlayList[2] ; Put your own mp3 file paths in this playlist $aPlayList[0] = 1 ; number of files in the playlist $aPlayList[1] = "Don Henley - The Boys of Summer.mp3" For $i = $aPlayList[0] To 1 Step -1 If Not FileExists($aPlayList[$i]) Then _ArrayDelete($aPlayList, $i) $aPlayList[0] -= 1 EndIf Next If Not $aPlayList[0] Then Exit MsgBox(0, "WMPlayer.ocx", "None of the files listed in $aPlayList array exists.", 5) Local $oPlayer = ObjCreate("WMPlayer.OCX") If Not IsObj($oPlayer) Then Exit MsgBox(0, "WMPlayer.OCX", "Cannot create a WMP object.", 5) Local $iPos = 0 ; x coordinate of $Shuttle cntrol in progress bar Local $hDLL = DllOpen("user32.dll") ; to dectect mouse down on the $Shuttle control Local $sliderLength = 380 ; in pixels Local $adlibInterval = 250 ; in milliseconds $oPlayer.Settings.Volume = 100 Local $nFile = 0, $sFullPath, $hTimer, $sFile, $mediaLength, $x, $mediaPos, $xOffset While 1 $nFile += 1 If $nFile > $aPlayList[0] Then $nFile = 1 $sFullPath = $aPlayList[$nFile] $oPlayer.URL = $sFullPath $hTimer = TimerInit() While $oPlayer.playState <> 3 ; 1 - stopped, 2 - paused, 3 - playing If TimerDiff($hTimer) > 3000 Then MsgBox(0, "WMPlayer.OCX", $sFullPath & @CRLF & @CRLF & "Cannot play this file.", 5) ExitLoop EndIf Sleep(10) WEnd If $oPlayer.playState <> 3 Then ContinueLoop $sFile = StringMid($sFullPath, StringInStr($sFullPath, "\", 0, -1) + 1) GUICtrlSetData($idSongName, $sFile) $mediaLength = Int($oPlayer.currentMedia.Duration) ; in seconds GUICtrlSetData($Length, Int($mediaLength / 60) & ":" & StringFormat("%02i", Mod($mediaLength, 60))) AdlibRegister("Slider", $adlibInterval) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE $oPlayer.Close() Exit Case $Pause If GUICtrlRead($Pause) = "Pause" Then $oPlayer.Controls.Pause AdlibUnRegister() GUICtrlSetData($Pause, "Resume") Else $oPlayer.Controls.Play AdlibRegister("Slider") GUICtrlSetData($Pause, "Pause") EndIf Case $GUI_EVENT_PRIMARYDOWN If GUIGetCursorInfo()[4] = $Shuttle Then AdlibUnRegister() $x = MouseGetPos(0) $xOffset = $x - $iPos While _IsPressed("01", $hDLL) = 1 $x = MouseGetPos(0) If $x > 380 + $xOffset Then $x = 380 + $xOffset ElseIf $x < $xOffset Then $x = $xOffset EndIf $iPos = $x - $xOffset GUICtrlSetPos($Shuttle, $iPos) Sleep(10) WEnd $mediaPos = $iPos / $sliderLength * $mediaLength $oPlayer.Controls.currentPosition = $mediaPos $oPlayer.Controls.Play AdlibRegister("Slider", $adlibInterval) GUICtrlSetData($Pause, "Pause") EndIf EndSwitch If $oPlayer.playState = 1 Then ExitLoop WEnd WEnd Func Slider() $mediaPos = $oPlayer.Controls.currentPosition $iPos = $mediaPos * $sliderLength / $mediaLength GUICtrlSetPos($Shuttle, $iPos) GUICtrlSetData($Progress, Int($mediaPos / 60) & ":" & StringFormat("%02i", Mod($mediaPos, 60))) EndFunc ;==>Slider ; based on https://www.autoitscript.com/forum/topic/204254-saveretrieve-images-tofrom-text-string/ Func _ConvertStringToImage(ByRef $tBuffer, $iWidth, $iHeight) Local Const $IMAGE = "FFF6DAFFFFF1D7FF4E341CFF44311CFF40311EFF493726FF4A3020FF563525FF533121FF52331EFF4E331EFF4B351CFF49351CFF4B351CFF52321FFF473125FFF6F5F7FFE2EDF5FFFFF6DCFF54361DFF78634DFF716350FF7D7361FF746757FF745F50FF7F6557FF836657FF816756FF7C6954FF786A53FF786A54FF7A6954FF806856FF7C6758FF2E271EFFF6F7EEFF4E341CFF826D57FF736A56FF6B6957FF616153FF636156FF756C62FF77695DFF746457FF726555FF6E6655FF6B6754FF6B6755FF6D6655FF726557FF776653FF897455FF4D3610FF4E3B26FF6F614EFF6B6957FF707566FF5C6459FF6E736AFF67655DFF666059FF6F685FFF6D695EFF686A5EFF666A5EFF646B5EFF686A5EFF6D685FFF786A58FF876A43FF5E3B09FF3C2D1AFF786E5CFF656557FF5A6257FF5F6963FF545D5AFF5F6260FF696766FF676362FF656460FF5F6560FF5C675FFF5C6660FF5E6560FF636462FF6F6659FF836A48FF5F3E11FF4B3928FF766959FF615F54FF6A6F66FF5B6461FF666E6EFF5D5F60FF6D6A6CFF696466FF656565FF606665FF5C6765FF5C6666FF5E6666FF636468FF70675EFF826A4CFF573910FF472D1DFF7C6758FF797066FF605E56FF5C5F5DFF636566FF696269FF615960FF6A5F67FF676166FF616266FF5F6364FF5E6366FF5F6266FF656167FF6F635FFF82694FFF53360FFF563526FF785E50FF76685CFF6B655EFF676564FF6B686AFF665E65FF70656FFF6D6068FF6B6068FF666267FF626367FF606368FF646268FF69606AFF746360FF836A50FF563912FF543222FF826556FF756558FF6F685FFF686463FF686365FF6C6169FF6D6068FF6F6068FF6B6068FF666267FF626465FF626367FF646367FF696168FF746360FF846A4CFF583A11FF543320FF7F6554FF736656FF6D695EFF666561FF646464FF696267FF6B6068FF6B6068FF696267FF626465FF606465FF606465FF626465FF686267FF72645EFF826A4EFF563912FF4F341FFF7A6752FF6F6756FF6A6A5EFF606661FF5F6564FF646367FF666267FF666267FF626465FF5F6564FF5B6664FF5B6664FF5F6564FF646365FF6F655EFF7D6852FF513818FF4C361DFF766851FF6C6856FF666A5EFF5F6760FF5D6564FF606367FF626367FF626367FF606465FF5B6664FF596763FF596763FF5D6663FF646563FF6D665DFF7D6852FF513818FF4A361DFF766851FF6C6856FF646B5EFF5D6761FF5B6664FF5F6467FF606367FF626367FF606465FF5B6664FF596763FF5B6761FF5D6761FF646561FF70665CFF806A4EFF563914FF4D351FFF786752FF6E6756FF686A5EFF5F6661FF5D6565FF606368FF646268FF646268FF626465FF5F6564FF5D6663FF5F6661FF626661FF686561FF74665AFF846B4BFF5A3A11FF533320FF7E6654FF736658FF6D685FFF646563FF626465FF666268FF696168FF696168FF686267FF646365FF626563FF646561FF686561FF6F6361FF79655AFF866A4CFF583912FF513322FF7F6554FF766656FF74685CFF6D665DFF6D655EFF706361FF726361FF726361FF726360FF6F6460FF6D655EFF6F665DFF72665CFF77645CFF7D6657FF82694FFF513816FFFFF8E7FF463220FF83705BFF7B6952FF7B6650FF7F6950FF7F674FFF7E664EFF816854FF806854FF7E6954FF7E6954FF7E6954FF806953FF836951FF816953FF483520FFFFF4DEFFFFEFDEFFFFF1DEFF442F19FF483117FF5A4121FF4F3412FF563815FF583C1AFF533617FF523618FF50351AFF50351AFF50351AFF503618FF533518FF4E361AFFF9E9D8FFFFFFF4FF" Return _ReadImageFromText($tBuffer, $IMAGE, $iWidth, $iHeight) EndFunc ;==>_ConvertStringToImage Func _ReadImageFromText(ByRef $tByte, $sString, $iWidth, $iHeight, $bFileName = False) ; Recreate image from text file If $bFileName Then $sString = FileRead($sString) Local $dData = Binary("0x" & $sString) $tByte = DllStructCreate("byte string[" & $iWidth * $iHeight * 4 & "]") DllStructSetData($tByte, 1, $dData) Return _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $GDIP_PXF32ARGB, $iWidth * 4, DllStructGetPtr($tByte, "string")) EndFunc ;==>_ReadImageFromText1 point -
only 2 cents: Reading this web page I have copied/pasted some information from there, to here in this larsj's snippet trying to understand something more. ; To initialize the web view we must call the CreateCoreWebView2EnvironmentWithOptions() method with the following arguments: ; (1) The path to the installation folder of Edge. ; If this is null, the component should automatically locate the installation of Edge and use that. ; In practice, providing null does not work well, and the component is not able to detect the browser. ; ; (2) The path to the user data folder. ; If this is null, a subfolder in the current folder will be created. ; Beware that if your application is installed in Program Files, it will not be able to create it. ; Invoking this method will result in an access denied error (0x80070005 which is a HRESULT value for ERROR_ACCESS_DENIED). ; Therefore, make sure you provide a user folder to a writable location. ; ; (3) Optional environment options (as ICoreWebView2EnvironmentOptions*) to change the behavior of the web view. ; ; (4) A handler for the result of the asynchronous operation, that will be invoked if the environment was successfully created. ; Local $aRet = DllCall($hWebView2Loader, "long", "CreateCoreWebView2EnvironmentWithOptions", _ "wstr", "", _ ; (1) "wstr", @ScriptDir, _ ; (2) "ptr", Null, _ ; (3) "ptr", $pCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) ; (4) Well, if we set the parameter (2) with a path that is convenient for us, for example @ScriptDir, we don't have to worry about enabling read/write on the WebView2 user data folder within the AutoIt path.1 point
-
fixed. can be deleted
Exit reacted to kawumm3000 for a topic
Sorry. I didn't fixed it with autoit. I just changed the template.1 point -
fixed. can be deleted
Musashi reacted to alienclone for a topic
or you could have left your question, and then shared how you fixed it so that it may help someone else in the future when they are searching for answers.1 point -
Excel fill empty cells
kawumm3000 reacted to Subz for a topic
Why not just use _Excel_RangeReplace i.e. replace "" with "xyz"?1 point -
GOTO
Skysnake reacted to JockoDundee for a topic
Actually, the problem with GOTO is not where it goes to; it’s that it doesn’t come BACK FROM1 point -
I hope soon I find time to provide new features and examples based on the knowledge which I gather thanks to this above mentioned book. btw. Today I also buy this one: I hope it will be delivered to me sometime in a month, so it is possible that after the summer vacation, sometime in about half a year, I will have the opportunity to present new curiosities.1 point
-
Hi @SEuBo. Thanks! happy to know you like it. Pretty cool idea. I've got work in progress for adding ROT functionality with my AutoObject_Internal, so if i work out the kinks, you won't need AutoItObject also I can't seem to reproduce the problems you seem to describe (tested on win10). IPC with AutoObject_Internal is unstable and very unpredictable currently. Your usage, besides using it between processes seems to be fine While current version is mostly stable, many edge cases makes the code more like a beta release currently. The issue for me is shallow COM interface documentation from MSDN and not many seems to report errors with the project (if more than a handful of people are using it). My best guesses currently for the problem would be: The reference count may reach 0 and trigger the object to release the memory (a bug with IPC i am looking into) Currently i return no info from the TypeInfo part of IDispatch interface. This seems to cause no problems most of the time, but i suspect it may be the cause for crashes in some cases. I will be happy to try and look into it, if I'm able to reproduce the bug reliably1 point
-
It was a real P.I.T.A to figure out what it is doing, and I'm still not certain why it caused an issue, but since the text string already included a '"' (double quote), this was being passed into the Window function on top of the variable, which.... I was not adding. This seems to lack some elegance but it makes sense.\ So by either excluding quotes on the INI values or using replace, it works (e.g.,): Local $var = "[TITLE:" & StringReplace($WindowTexts[$winNum], """", "") & "]"1 point
-
Delete all empty rows in Excel - one line of code
kawumm3000 reacted to Jfish for a topic
I recently >posted a question in the general help and support about how the best way to find the last non-empty cell in a workbook. @Water was kind enough to help me find several solutions. During that thread we also posted a snippet that I find to be very useful. It was slightly off topic from the OP so I thought I would post it here so it has a home in case anyone needs it. That said, this is one way to delete all blank rows in a spreadsheet: $oWorkbook.ActiveSheet.Columns("A:A").SpecialCells($xlCellTypeBlanks).EntireRow.Delete The $xlCellTypeBlanks is a constant in the Excel constants include so you don't need to pre-define it. "A:A" is the range. So this would look for any blank rows in Col A and delete those rows from the workbook. Hope somebody finds it useful.1 point -
Jadog, You assign it to a variable like this: $sString = GUICtrlRead($hInput)If you want to store the value betwen runs then you need to save it to disk - the Ini* functions could be a useful tool for that. Koda does not help you here - this is not creating a GUI, this is real coding. Perhaps the excellent AutoIt tutorials that you will find here and here might be of use. M231 point
-
0 points