Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

COM Object Reference [AutoHotkey v1.1+]


  • Please log in to reply
233 replies to this topic
majkinetor
  • Moderators
  • 4512 posts
  • Last active: Jul 29 2016 12:40 AM
  • Joined: 24 May 2006

You would need to pass in an IDispatch interface, such as created by DispatchObj.

Thx Lexikos. That is exactly what I hopped for.

EDIT: One thing, how do I use it for html control ? I don't see on the msdn how to access AddObject method aside from instantiating ScriptControl.

EDIT2: Seems this one: <!-- m -->http://msdn.microsof... ... 42(v=VS.85<!-- m -->).aspx
Posted Image

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
I think that'll just give you the document object, which you probably already have. You just need to store the object somewhere. Below is an updated version of my example in the DispatchObj thread; it assumes ieWin is the WebBrowser or window object of the HTML control and obj is the wrapped DispatchObj:
; Create 'ahk' variable. (var=''; also works)
ieWin.execScript("var ahk;","JScript")
; Assign dispatch object to ahk variable.
ieWin.ahk := obj
The declaration is necessary because we're interacting with the object via the IDispatch interface, which wasn't designed for dynamic objects. It is possible to add members to dynamic objects via the IDispatchEx interface, assuming they implement it:
Expando(obj, name)
{
    ; Allow obj to be either a ComObj or interface pointer.
    ptr := IsObject(obj) ? ComObjUnwrap(obj) : obj
    ; Retrieve IDispatchEx interface pointer.
    if dspEx := COM_QueryInterface(ptr, "{A6EF9860-C720-11d0-9337-00A0C90DCAA9}")
    {
        ; dspEx->GetDispID(name, fdexNameCaseSensitive|fdexNameEnsure, &id)
        if !hr := DllCall(NumGet(NumGet(dspEx+0)+7*A_PtrSize), "ptr", dspEx
              , "ptr", COM_SysString(wname,name), "uint", 3, "int*", id, "uint")
        {
            ; Although fdexNameEnsure "requests that the member be created",
            ; obj[name]:=x still causes an "Unknown name" error unless we
            ; do this first: store an empty value in the member.
            VarSetCapacity(args, 16+n:=A_PtrSize*2+8, 0)
            NumPut(1, NumPut(&args+n, args), A_PtrSize, "uint")
            ; dspEx->InvokeEx(id, LOCALE_USER_DEFAULT, DISPATCH_PUT, &args ...)
            hr := DllCall(NumGet(NumGet(dspEx+0)+8*A_PtrSize), "ptr", dspEx
              , "int", id, "uint", 0x400, "uint", 4, "ptr", &args
              , "ptr", 0, "ptr", 0, "ptr", 0, "uint")
        }
        ObjRelease(dspEx)
    }
    else hr := 1*0x80004002 ; E_NOINTERFACE
    IsObject(obj) ? ObjRelease(ptr) : ""
    return hr
}
Example:
Expando(Document, "foo")
Document.foo := "bar"
See also: expando Property.


While testing, I realized that because x.y and x.y() both use a combination of DISPATCH_PROPERTYGET and DISPATCH_METHOD, you can't call JavaScript functions directly. For instance, having declared a function "myfunc" in a <script>, Document.parentWindow.myfunc() only retrieves a reference to the function; doesn't call it. Similarly, if you use ...myfunc.call(), it retrieves a reference to the call function. This will be changed in the next release so that x.y() is always a method-call. For convenience, x.y will retain its current behaviour.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: Jul 29 2016 12:40 AM
  • Joined: 24 May 2006
Thx lexikos. Ill see what I can do with all that info if I manage to rewrite DispatchObj.

It seems that not all events work according to docs.

onkeyup and onkeydown set either via ahk code or javascript code don't work. The same html code loaded into IE works.

onkeypress works for most keys. It doesn't report arrows, enter, pageup/down (even if I disable scrollbars via document.body.scroll := "no")
#SingleInstance, force
	CreateWindow()
	LoadHtml() 
	Gui, Show, autosize
return


LoadHtml() {
	global

	html =
	(
	<html>
	<script>
		document.onkeyup = KeyCheck;  
		//alert(document.onkeyup);
		function KeyCheck()	{ alert('Key code: ' + event.keyCode); }
	</script>
	<body>
		press key to see code
	</body>
	</html>
	)

	FileDelete _out.html
	FileAppend %html%, _out.html
	htmlDoc.write(html)

	;x := htmlDoc.onkeyup
	;m(ComObjType(x, "Name"))
}


CreateWindow() {
	global 
	Gui, +LastFound
	hForm := WinExist()

	Gui, Add, Text, HWNDhCtrl w400 h400

	htmlDoc := COM_AtlAxCreateControl( hCtrl, "HTMLfile" ) ; http://msdn.microsoft.com/en-us/library/da181h29 
	NativeCom(htmlDoc) ; ensures the "doc" object uses Native COM 

	ComObjConnect(htmlDoc, "htmlDoc_")
}	
		
htmlDoc_onkeyup(p){
	msgbox % A_ThisFunc
}

NativeCom( ByRef obj ) { ; ensures the "obj" object uses Native COM 
   if Not IsObject(obj) 
      return 
   ComObjError(false) 
   if Not ComObjType(obj,"iid") 
      obj := ComObjEnwrap(COM_Unwrap(obj)) 
   ComObjError(true) 
}

#include COM.ahk

Now, part of the interface I am making is html table. User should be able to select rows using arrows and launch the action via Enter. Its easily done in javascript but the problem is that arrows and enter do not fire correctly once the html runs inside the gui control. If i change keys to something else, lets say , j, k and space, it works.

Now, onkeypress on arows also doesn't work in browser. So, the solution is to make gui control being able to fire keydown or keyup events which do fire correctly in browser and can handle 'special' keys. I didn't yet found solution to this problem. Is there anything here I am missing ?
Posted Image

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

Document.parentWindow.myfunc() only retrieves a reference to the function; doesn't call it. Similarly, if you use ...myfunc.call(), it retrieves a reference to the call function.

You can call it like this.
; Document.parentWindow.myfunc("")
ftn := Document.parentWindow.myfunc
ftn.call(ftn)

This will be changed in the next release so that x.y() is always a method-call. For convenience, x.y will retain its current behaviour.

I don't think it's a good idea as it may break some codes ported from VBScript. If it has to be done, I suppose it better be restricted to no argument case.
IS_INVOKE_SET ? DISPATCH_PROPERTYPUT : !aParamCount && IS_INVOKE_CALL ? DISPATCH_METHOD : DISPATCH_PROPERTYGET | DISPATCH_METHOD


Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

Is there anything here I am missing ?

There's a known issue with hosting the IE control which has been discussed at least a few times already. The solution is to hook WM_(SYS)KEYDOWN/UP and have them call IOleInPlaceActiveObject::TranslateAccelerator(). For instance, see Sean's post. I'm not sure if it's the only problem, though.

You can call it like this.

ftn := Document.parentWindow.myfunc
ftn.call(ftn)

I see; the presence of a parameter removes the ambiguity (since DISPATCH_PROPERTYGET for that member doesn't accept parameters). This also works:
Document.parentWindow.myfunc(1)

If it has to be done, I suppose it better be restricted to no argument case.

Good idea.

If it has to be done,

What's the point of having different syntaxes if they're all ambiguous?

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

What's the point of having different syntaxes if they're all ambiguous?

Yes, actually how to interpret the flags is completely up to the Server/engine. I felt sorry that we could not fully utilize AHK_L's capability to unambiguously differentiate between CALL & GET, due to the notational incompatibility between JScript and VBScript. If we impose the strict syntax, I reckon a lot of users, especially from VBScript, will be utterly confused.

PS. I once tempted about this syntax.
value := obj.name[color=red]([/color]...[color=red])[/color] ; DISPATCH_METHOD
value := obj.name[color=red][[/color]...[color=red]][/color] ; DISPATCH_PROPERTYGET
obj.name[color=red][[/color]...[color=red]][/color] := value ; DISPATCH_PROPERTYPUT
obj.name[color=red]([/color]...[color=red])[/color] := value ; DISPATCH_PROPERTYPUTREF


majkinetor
  • Moderators
  • 4512 posts
  • Last active: Jul 29 2016 12:40 AM
  • Joined: 24 May 2006

There's a known issue with hosting the IE control which has been discussed at least a few times already. The solution is to hook WM_(SYS)KEYDOWN/UP and have them call IOleInPlaceActiveObject::TranslateAccelerator(). For instance, see Sean's post. I'm not sure if it's the only problem, though.

Thanks. This worked.

Now that both js event and ahkl COM attachment work, how can I get in ahkl the key that was pressed. In doc_onkeydown(p) argument p is of type DispHTMLDocument.
Posted Image

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009

COM Object: SAPI.SpVoice

Purpose: Text-to-Speech

System Requirements: General

Documentation Link: SpVoice Interface

Code Example:

Text := "Hello World!"

SAPI := ComObjCreate("SAPI.SpVoice")
MsgBox,, Rate: 0, Speak the Text
SAPI.speak(Text)

MsgBox,, Rate: -7, Slow down the Speech
SAPI.rate := -7
SAPI.speak(Text)

MsgBox,, Rate: 7, Speed up the Speech
SAPI.rate := 7
SAPI.speak(Text)

SAPI.rate := 0 ;// set to default rate

MsgBox,, Volume: 50, Lower the Volume (ranges 0-100)
SAPI.volume := 50
SAPI.speak(Text)


olfen
  • Members
  • 115 posts
  • Last active: Dec 25 2012 09:48 AM
  • Joined: 04 Jun 2005
[*:1d2c1b3y]COM Object: ImageMagickObject COM+ Object[*:1d2c1b3y]Purpose: ImageMagick® is a software suite to create, edit, and compose bitmap images.[*:1d2c1b3y]System Requirements: ImageMagickObject COM+ Object[*:1d2c1b3y]Documentation Link: <!-- m -->Other Links: <!-- m --><a class="postlink" href="http://www.imagemagick.org/script/binary-releases.php#windows]http://www.imagemagick.org/script/binar ... hp#windows<!-- m -->[*:1d2c1b3y]Basic Code Example:
oI := ComObjCreate("ImageMagickObject.MagickImage.1") 

imgs := Object() 
    
Loop, 16 { 
   filename := "plasma" . A_Index . ".jpg" 
   oI.convert("-size", "200x200", "plasma:", filename) 
   imgs.Insert(filename)    
} 

imgs.Insert("montage.jpg")    
stitch(oI, imgs*) 

stitch(obj, params*) { 
   obj.montage("-geometry", "+0+0", params*) 
} 

oI.convert("montage.jpg", "-verbose", "info:image_info.txt") 
oI.convert("montage.jpg", "-define", "histogram:unique-colors=false", "histogram:histogram.gif") ; create histogram
FileRead, info, image_info.txt 
FileDelete, image_info.txt 
MsgBox % info

Convert image to text:
oI := ComObjCreate("ImageMagickObject.MagickImage.1") 
oI.convert("montage.jpg", "montage.txt")
Output:
# ImageMagick pixel enumeration: 40,40,255,rgb 
0,0: (235,241,255)  #EBF1FF  rgb(235,241,255) 
1,0: (221,242,237)  #DDF2ED  rgb(221,242,237) 
2,0: (219,253,226)  #DBFDE2  rgb(219,253,226) 
3,0: (192,225,208)  #C0E1D0  rgb(192,225,208) 
4,0: (202,224,237)  #CAE0ED  rgb(202,224,237) 
5,0: (223,232,255)  #DFE8FF  rgb(223,232,255) 
6,0: (224,220,245)  #E0DCF5  rgb(224,220,245) 
7,0: (240,223,239)  #F0DFEF  rgb(240,223,239) 
8,0: (255,240,251)  #FFF0FB  rgb(255,240,251) 
9,0: (244,253,255)  #F4FDFF  rgb(244,253,255) 
10,0: (188,228,230)  #BCE4E6  rgb(188,228,230) 
11,0: (192,239,245)  #C0EFF5  rgb(192,239,245) 
12,0: (209,236,255)  #D1ECFF  rgb(209,236,255) 
13,0: (232,235,255)  #E8EBFF  rgb(232,235,255) 
14,0: (235,237,255)  #EBEDFF  rgb(235,237,255) 
15,0: (213,225,237)  #D5E1ED  rgb(213,225,237) 
16,0: (230,237,245)  #E6EDF5  rgb(230,237,245) 
17,0: (230,249,255)  #E6F9FF  rgb(230,249,255) 
...

Get information about a single pixel of an image:
; http://www.imagemagick.org/script/fx.php 
oI := ComObjCreate("ImageMagickObject.MagickImage.1") 
r := oI.identify("-format", "%[fx]", "montage.jpg") 
MsgBox % r

Notes:
I sometimes need to automatically stitch images together.
I used GflAx previously, but there had to calculate canvas size and positioning myself.
Now ImageMagick does the job for me.

The scope of ImageMagick is endless. Explore!

Tested with AHK v1.0.48.05.L61.

BTW: Thanks Lexikos for all the great changes!

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
BTW, IsObject check is not necessary. Error message will be popped up if creation fails.

olfen
  • Members
  • 115 posts
  • Last active: Dec 25 2012 09:48 AM
  • Joined: 04 Jun 2005

BTW, IsObject check is not necessary. Error message will be popped up if creation fails.

Thank you, Sean. Removed.

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009

COM Object: Word.Application
Purpose: create and edit various documents
System Requirements: Microsoft Office Word application
Documentation Link: <!-- m -->http://msdn.microsof...ry ... 12).aspx<!-- m -->
Other Links:
Basic Code Example:


oWord := ComObjCreate("Word.Application") ; create MS Word object
oWord.Documents.Add ; create new document

oWord.Selection.Font.Bold := 1 ; bold
oWord.Selection.TypeText("Visit ") ; type text
oWord.ActiveDocument.Hyperlinks.Add(oWord.Selection.Range, "http://www.autohotkey.com/forum/topic61509.html"
,"","","COM Object Reference [AutoHotkey_L]") ; insert hyperlink
oWord.Selection.TypeText("and learn how to work with ") ; type text
oWord.Selection.Font.Italic := 1 ; italic
oWord.Selection.TypeText("COM objects") ; type text
oWord.Selection.Font.Bold := 0, oWord.Selection.Font.Italic := 0 ; bold and italic off
oWord.Selection.TypeText(".") ; type text
oWord.Selection.TypeParagraph ; type paragraph (enter, new line)

oWord.Visible := 1, oWord.Activate ; make it visible and activate it.
ExitApp


tank
  • Administrators
  • 4345 posts
  • AutoHotkey Foundation
  • Last active: Oct 13 2016 01:04 AM
  • Joined: 21 Dec 2007
Very cool olfen i am often in need of a way to do some behind the sceens manipulation of images. thanks for locating the documentation
Never lose.
WIN or LEARN.

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
olfen - thanks for the example. However, call me ignorant, but I cannot get imagemagick registered on my computer. I downloaded ImageMagick-6.6.5-2-Q16-windows-dll.exe & installed it, but ImageMagickObject.MagickImage.1 still isn't a valid class on my computer. I'm running XP SP3 (<512 MB RAM). I noticed the notes state you may have to install Visual C++ 2010 Redistributable Package (x86). Would this be what's causing my problems? Also, do you know if there's a single DLL you can download and register to use this COM object?

olfen
  • Members
  • 115 posts
  • Last active: Dec 25 2012 09:48 AM
  • Joined: 04 Jun 2005
I am using XP SP3, too.
Have you tried this (in app dir)?
regsvr32 /c /s ImageMagickObject.dll
There is no single DLL, ImageMagickObject.dll has several dependencies.