ComObjActive passing long int to set a variable
Posted: 05 Jun 2020, 14:34
To all the great folks of AHK. Thanks for the forums and documentation.
Would someone please help me with this objective:
A) get current text insert position coordinates from Microsoft Word
B) draw a custom cursor overlay at that location (not part of this question b/c A isn't done yet)
C) update location of cursor overlay each time the cursor moves (should be easy once I know A)
Here is my initial approach:
1)
pLeft := 0
pTop := 0
pWidth := 0
pHeight := 0
wappdoc := ComObjActive("Word.Application").ActiveDocument
wappselrng := ComObjActive("Word.Application").Selection.Range
wappdoc.ActiveWindow.GetPoint(&pLeft, &pTop, &pWidth, &pHeight, wappselrng)
pLeft := wappdoc.ActiveWindow.Left
pWidth := wappdoc.ActiveWindow.Width
pTop := wappdoc.ActiveWindow.Top
pHeight := wappdoc.ActiveWindow.Height
MsgBox % "Left = " pLeft "\n Top = " pTop "\n Width = " pWidth "\n Height = " pHeight
wappdoc := ""
wappselrng :=
RESULTS: No errors, but Left = 0 Top =0 Width = 0 Height = 0 each time, so GetPoint isn't setting the variables pLeft, PTop...as expected. (see https://docs.microsoft.com/en-us/office/vba/api/word.window.getpoint)
Then I tried using the example from ComVar in the help file to see a working example:
1.1) "just a test of concept to see if I could get a ComObject to set an AHK variable that I passed to it"--didn't work
Preamble - ScriptControl requires a 32-bit version of AutoHotkey.
code =
(
Sub Example(Var)
MsgBox Var
Var = "out value!"
End Sub
)
sc := ComObjCreate("MSScriptControl.ScriptControl"), sc.Language := "VBScript", sc.AddCode(code)
; Example: Pass a VARIANT ByRef to a COM function.
var := ComVar()
var[] := "in value"
sc.Run("Example", var.ref)
MsgBox % var[]
; ComVar: Creates an object which can be used to pass a value ByRef.
; ComVar[] retrieves the value.
; ComVar[] := Val sets the value.
; ComVar.ref retrieves a ByRef object for passing to a COM function.
ComVar(Type=0xC)
{
static base := { __Get: "ComVarGet", __Set: "ComVarSet", __Delete: "ComVarDel" } ; For base, see Custom Objects.
; Create an array of 1 VARIANT. This method allows built-in code to take
; care of all conversions between VARIANT and AutoHotkey internal types.
arr := ComObjArray(Type, 1)
; Lock the array and retrieve a pointer to the VARIANT.
DllCall("oleaut32\SafeArrayAccessData", "ptr", ComObjValue(arr), "ptr*", arr_data)
; Store the array and an object which can be used to pass the VARIANT ByRef.
return { ref: ComObject(0x4000|Type, arr_data), _: arr, base: base }
}
ComVarGet(cv, p*) { ; Called when script accesses an unknown field.
if p.MaxIndex() = "" ; No name/parameters, i.e. cv[]
return cv._[0]
}
ComVarSet(cv, v, p*) { ; Called when script sets an unknown field.
if p.MaxIndex() = "" ; No name/parameters, i.e. cv[]:=v
return cv._[0] := v
}
ComVarDel(cv) { ; Called when the object is being freed.
; This must be done to allow the internal array to be freed.
DllCall("oleaut32\SafeArrayUnaccessData", "ptr", ComObjValue(cv._))
}
}
RESULTS: Error: not registered...after 1 hour of looking I gave up on how to get the example working on Win 7, so try something else.
2) Try to use ComVar to solve the issue inserting the below code into my original 1) solution:
;ComVar: Creates an object which can be used to pass a value ByRef.
ComVar[] retrieves the value.
ComVar[] := Val sets the value.
ComVar.ref retrieves a ByRef object for passing to a COM function.
ComVar(Type=0xC)
...
var := ComVar()
var[] := "in value"
...
wappdoc.ActiveWindow.GetPoint(var.ref, &pTop, &pWidth, &pHeight, wappselrng)
RESULTS: Error wrong type. Of course var is an array, however, I can't find an easy way to make var an integer because the example never worked?
QUESTION: How do I use ComVar for a long integer type? In my 1) solution I need 4 of these variables that Word.Application can write a number to. Please help.
Thanks in advance!
Jj
Would someone please help me with this objective:
A) get current text insert position coordinates from Microsoft Word
B) draw a custom cursor overlay at that location (not part of this question b/c A isn't done yet)
C) update location of cursor overlay each time the cursor moves (should be easy once I know A)
Here is my initial approach:
1)
pLeft := 0
pTop := 0
pWidth := 0
pHeight := 0
wappdoc := ComObjActive("Word.Application").ActiveDocument
wappselrng := ComObjActive("Word.Application").Selection.Range
wappdoc.ActiveWindow.GetPoint(&pLeft, &pTop, &pWidth, &pHeight, wappselrng)
pLeft := wappdoc.ActiveWindow.Left
pWidth := wappdoc.ActiveWindow.Width
pTop := wappdoc.ActiveWindow.Top
pHeight := wappdoc.ActiveWindow.Height
MsgBox % "Left = " pLeft "\n Top = " pTop "\n Width = " pWidth "\n Height = " pHeight
wappdoc := ""
wappselrng :=
RESULTS: No errors, but Left = 0 Top =0 Width = 0 Height = 0 each time, so GetPoint isn't setting the variables pLeft, PTop...as expected. (see https://docs.microsoft.com/en-us/office/vba/api/word.window.getpoint)
Then I tried using the example from ComVar in the help file to see a working example:
1.1) "just a test of concept to see if I could get a ComObject to set an AHK variable that I passed to it"--didn't work
Preamble - ScriptControl requires a 32-bit version of AutoHotkey.
code =
(
Sub Example(Var)
MsgBox Var
Var = "out value!"
End Sub
)
sc := ComObjCreate("MSScriptControl.ScriptControl"), sc.Language := "VBScript", sc.AddCode(code)
; Example: Pass a VARIANT ByRef to a COM function.
var := ComVar()
var[] := "in value"
sc.Run("Example", var.ref)
MsgBox % var[]
; ComVar: Creates an object which can be used to pass a value ByRef.
; ComVar[] retrieves the value.
; ComVar[] := Val sets the value.
; ComVar.ref retrieves a ByRef object for passing to a COM function.
ComVar(Type=0xC)
{
static base := { __Get: "ComVarGet", __Set: "ComVarSet", __Delete: "ComVarDel" } ; For base, see Custom Objects.
; Create an array of 1 VARIANT. This method allows built-in code to take
; care of all conversions between VARIANT and AutoHotkey internal types.
arr := ComObjArray(Type, 1)
; Lock the array and retrieve a pointer to the VARIANT.
DllCall("oleaut32\SafeArrayAccessData", "ptr", ComObjValue(arr), "ptr*", arr_data)
; Store the array and an object which can be used to pass the VARIANT ByRef.
return { ref: ComObject(0x4000|Type, arr_data), _: arr, base: base }
}
ComVarGet(cv, p*) { ; Called when script accesses an unknown field.
if p.MaxIndex() = "" ; No name/parameters, i.e. cv[]
return cv._[0]
}
ComVarSet(cv, v, p*) { ; Called when script sets an unknown field.
if p.MaxIndex() = "" ; No name/parameters, i.e. cv[]:=v
return cv._[0] := v
}
ComVarDel(cv) { ; Called when the object is being freed.
; This must be done to allow the internal array to be freed.
DllCall("oleaut32\SafeArrayUnaccessData", "ptr", ComObjValue(cv._))
}
}
RESULTS: Error: not registered...after 1 hour of looking I gave up on how to get the example working on Win 7, so try something else.
2) Try to use ComVar to solve the issue inserting the below code into my original 1) solution:
;ComVar: Creates an object which can be used to pass a value ByRef.
ComVar[] retrieves the value.
ComVar[] := Val sets the value.
ComVar.ref retrieves a ByRef object for passing to a COM function.
ComVar(Type=0xC)
...
var := ComVar()
var[] := "in value"
...
wappdoc.ActiveWindow.GetPoint(var.ref, &pTop, &pWidth, &pHeight, wappselrng)
RESULTS: Error wrong type. Of course var is an array, however, I can't find an easy way to make var an integer because the example never worked?
QUESTION: How do I use ComVar for a long integer type? In my 1) solution I need 4 of these variables that Word.Application can write a number to. Please help.
Thanks in advance!
Jj