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
tinku99
  • Members
  • 560 posts
  • Last active: Feb 08 2015 12:54 AM
  • Joined: 03 Aug 2007

COM Object: Microsoft Outlook
Purpose: Read and Write Appointments from calendar
System Requirements: Microsoft Outlook: tested with 2010 and 2007
Documentation: http://support.microsoft.com/kb/220595
Other Links: following is a translation of this vb.net script.
 


olFolderCalendar := 9   ; Outlook.OlDefaultFolders.olFolderContacts
olFolderContacts := 10  ; get constants from visual studio
olAppointmentItem = 1
                        
profileName := "Outlook"
Outlook := ComObjCreate("Outlook.Application")
namespace := Outlook.GetNamespace("MAPI")
namespace.Logon(profileName)  
calendar :=  namespace.GetDefaultFolder(olFolderCalendar)
items := calendar.Items
count := items.Count
msgbox % "calendar items: " count
item := calendar.Items(1)
item1 :=  "subject: " item.Subject . "`n"
item1 .=  "Start: " item.Start . "`n"
item1 .=  "Duration: " item.Duration . "`n"
item1 .=  "Body: " item.Body "`n"
msgbox % "item1" item1
date := "9/1/2010 9:00:00 AM" ; this works, although the recommended
                              ; format is year/month/date
			      ; hours:minutes:seconds AM/PM

date := "2010/9/1 9:00:00 AM"
msgbox % makeAppointment(Outlook, "auto", "autohotkey rocks", date, "60", "2")

!r::reload
!q::exitapp

makeAppointment(outlook, subject, body, startTime, duration, busyStatus)
{
   static olAppointmentItem = 1
       ,  olFree        = 0
       ,  olTentative   = 1
       ,  olBusy        = 2
       ,  olOutOfOffice = 3
   item := outlook.CreateItem(olAppointmentItem)
   item.Body := body
   item.BusyStatus := busyStatus ; olBusy
   msgbox % startTime
   item.Start := startTime ; 9/1/2010 9:00:00 AM
   item.Duration := duration ; 60
   item.Subject := subject
   return item.save()  ; warns about programmatic access with normal settings
}


tinku99
  • Members
  • 560 posts
  • Last active: Feb 08 2015 12:54 AM
  • Joined: 03 Aug 2007

COM Object: Google Desktop
Purpose: manually feed items for google desktop to index
System Requirements: Google Desktop
Documentation Link: http://code.google.c...s/indexapi.html
Other Links: following is a translation of this python plugin: kongulo.


registerAhkIndexer()
Loop, %A_ScriptDir%\*.ahk
{
  FileRead, content, %A_LoopFileFullPath%
  gdsIndex(A_LoopFileFullPath, content)
  tooltip, %A_LoopFileFullPath%
}
return

variantDate(time)
{
  beginning := "18991230"
  now := time ; A_YYYY . A_MM . A_DD
  EnvSub, now, beginning, days
  stringtrimleft, hours, time, 8
  stringleft, hours, hours, 2
  fraction := hours / 24
  now := now . fraction

  VT_DATE := 0x0007
  vnow := ComObjParameter(VT_DATE, now)
  return vnow
}


gdsIndex(uri, content)
{
  global _GUID
  static eventFactory

  if !eventFactory
    eventFactory := comobjcreate("GoogleDesktopSearch.EventFactory")

  event := eventFactory.CreateEvent(_GUID, "Google.Desktop.File")
  time := variantDate(A_Now)
  event.AddProperty("format", "text/plain")
  event.AddProperty("content", content)
  event.AddProperty("uri", uri)
  event.AddProperty("last_modified_time", time)
  event.Send(0x01)
}


registerAhkIndexer()
{
  global _GUID
  oSC := ComObjCreate("ScriptControl")
  oSC.Language := "JScript"
  script =
  (
    obj = ['Title', 'ahkKongulo', 'Description', 'A simple ahk indexer', 'Icon', 'c:\windows\system32\SHELL32.dll,134' ];
  )
  oSC.ExecuteStatement(script)
  obj := oSC.Eval("obj")

  _GUID := "{D8FCC944-C8E9-4E56-83E7-61FC30D98E2B}" ; generate your own please
  gds := comobjcreate("GoogleDesktopSearch.Register")
  ComObjError(False) ; ignore reregistration error
  gds.RegisterIndexingComponent(_GUID, obj)
  ComObjError(True)
}

unregisterAhkIndexer()
{
  _GUID := "{D8FCC944-C8E9-4E56-83E7-61FC30D98E2B}"
  gds := comobjcreate("GoogleDesktopSearch.Register")
  gds.UnRegisterIndexingComponent(_GUID)
}


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

COM Object: InternetExplorer.Application

Purpose: Explore Websites

System Requirements: General

Documentation Link: Reference for Developers

Other Links: NavConstants, CMD IDs, Basic Webpage Controls

Code Example:

;// open Standard Internet Explorer
wb := ComObjCreate("InternetExplorer.Application") ;// create IE
wb.Visible := true ;// show IE
wb.GoHome() ;// Navigate Home

;// the ReadyState will be 4 when the page is loaded
while wb.ReadyState <> 4
    continue

;// get the Name & URL of the site
MsgBox % "Name: " wb.LocationName
    . "`nURL: " wb.LocationURL
    . "`n`nLet's Navigate to Autohotkey.com..."

;// get the Document - which is the webpage
document := wb.document
 
;// Navigate to AutoHotkey.com
wb.Navigate("www.AutoHotkey.com") ;// 2nd param - see NavConstants

;// the Busy property will be true while the page is loading
while wb.Busy
    continue
MsgBox Page Loaded...Going Back Now

;// Go Back
wb.GoBack()

while wb.Busy
    continue
MsgBox The page is loaded - now we will refresh it...

;// Refresh the page
wb.Refresh()
while wb.Busy
    continue
MsgBox Now that the page is Refreshed, we will Select All (^a)...

;// Execute Commands with ExecWB()
SelectAll := 17 ;// see CMD IDs
wb.ExecWB(SelectAll,0) ;// second param as "0" uses default options

Sleep 2000
MsgBox Now that we are done, we will exit Interent Explorer

;// Quit Internet Explorer
wb.Quit()

Note - Internet Explorer uses the iWebBrowser2 interface



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

COM Object: Shell.Application

Purpose: Access Explorer & IE Windows/Tabs; Open & Manipulate Windows

System Requirements: General

Documentation Link: Shell Object

Other Links: ShellWindows Collection

Code Example:

The Windows Property returns the ShellWindows Collection, which is extremely helpful for accessing Explorer/IE Windows. This example Enumerates all the Explorer & IE Windows/Tabs:

SetFormat, IntegerFast, Hex ;// display HWND in Hex

for Item in ComObjCreate("Shell.Application").Windows ;// loop through the ShellWindows Collection
   data .= "Name:`t" Item.LocationName "`n"
        . "URL:`t"   Item.LocationURL  "`n"
        . "Prog:`t"  Item.Name         "`n"
        . "`t"       Item.FullName     "`n"
        . "HWND:`t"  Item.HWND         "`n`n"

MsgBox %data%


Several of the methods/properties for the Shell.Application object are simple to do with AHK's commands - such as showing certain Dialog boxes or Minimizing all windows. However, here are a few examples for moving windows around:

shell := ComObjCreate("Shell.Application")

MsgBox Cascade Windows
shell.CascadeWindows()
Sleep 2000

MsgBox Tile Windows Horizontally
shell.TileHorizontally()
Sleep 2000

MsgBox Tile Windows Vertically
shell.TileVertically()


majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
Since html controlinterface specifies clear() as not implemented and specifies alternative, I wanted to extend local interface to support it. I wrote:

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

Clear( this ) {
	this.write(), this.close()
}

However, this isn't supported or I am missing something. Can it be done ?
Posted Image

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

I'm no object expert, so I may be off base here, but it's my understanding that the com object is wrapped using all the metafunctions. Therefore, you aren't actually setting the base, but setting a key - which invokes the "__Set" metafunction, which redirects the key-call to the COM_Invoke function. Therefore, you are actually trying to do:

COM_Invoke(htmlDoc.prm_, "base", Object("clear", "Clear"))

, which will definitely throw a com error, & shouldn't work correctly. This might illustrate:

obj := object("base",object("__Get","_Getter","__Set","_Setter"))
obj.base := Object("clear", "Clear")
obj.clear

_Getter(this, key) {
   MsgBox, Called "__Get"
}
_Setter(this, key, val) {
   MsgBox, Called "__Set"
   return
}
Clear(this) {
   MsgBox, Called "Clear"
}


fincs
  • Moderators
  • 1662 posts
  • Last active:
  • Joined: 05 May 2007

Here's one I'm heavily using:
COM Object: MSXML2.DOMDocument.6.0
Purpose: XML parser
System Requirements: Windows XP SP3, Vista, 7
Documentation Link: MSDN
Other Links: A Beginner's Guide to the XML DOM, DOM Reference
Basic Code Example:

xmldata =
(
  <?xml version="1.0"?>
    <compactdiscs>
      <compactdisc>
        <artist type="individual">Frank Sinatra</artist>
        <title numberoftracks="4">In The Wee Small Hours</title>
        <tracks>
          <track>In The Wee Small Hours</track>
          <track>Mood Indigo</track>
          <track>Glad To Be Unhappy</track>
          <track>I Get Along Without You Very Well</track>
        </tracks>
        <price>$12.99</price>
      </compactdisc>
      <compactdisc>
        <artist type="band">The Offspring</artist>
        <title numberoftracks="5">Americana</title>
        <tracks>
          <track>Welcome</track>
          <track>Have You Ever</track>
          <track>Staring At The Sun</track>
          <track>Pretty Fly (For A White Guy)</track>
        </tracks>
        <price>$12.99</price>
      </compactdisc>
    </compactdiscs>
)

doc := loadXML(xmldata)

; XPath
msgbox % doc.selectSingleNode("/compactdiscs/compactdisc[artist=""Frank Sinatra""]/title").text

; Manually retrieving nodes and values
msgbox % DisplayNode(doc.childNodes)

DisplayNode(nodes, indent=0)
{
  for node in nodes
  {
    if node.nodeName != "#text"
      text .= spaces(indent) node.nodeName ": " node.nodeValue "`n"
    else
      text .= spaces(indent) node.nodeValue "`n"
    if node.hasChildNodes
      text .= DisplayNode(node.childNodes, indent+2)
  }
  return text
}

spaces(n)
{
  Loop, %n%
    t .= " "
  return t
}

loadXML(ByRef data)
{
  o := ComObjCreate("MSXML2.DOMDocument.6.0")
  o.async := false
  o.loadXML(data)
  return o
}

This renders xpath() obsolete, except for vanilla scripts or Win2000 scripts.



majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
Can anybody link or show the best way to realize ahk<->javascript data sharing using IHTMLDocument2?
Posted Image

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

Well, the javascript variables should be available from the window object. For example:

pwb.Navigate("javascript: str='AutoHotkey_L'; void 0")
;// ~ or ~ 
pwb.document.parentWindow.execScript("str='AutoHotkey_L'")

;// get variable contents:
j_str :=  pwb.document.parentWindow.str

If that's not what you mean, could you give an example?



majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
Yes, but what about calling ahk function from the javascript? How can javasript set variable and call ahk function afterwards. I am using currently onclick notification and click simulation (checking from AHK for concrete hidden element javascript clicked to distinguish from javascript call and arbitrary click).
Posted Image

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
I'm not 100% sure what you're asking. Of course javascript can create a Wscript.Shell object & run AHK code, but I doubt that's what you mean.

How is your javascript going to be called in the first place? My first thought is to attach your ahk function to that event. Otherwise, I suppose you could wait for a variable to be a certain value.

tank
  • Administrators
  • 4345 posts
  • AutoHotkey Foundation
  • Last active: May 02 2019 09:16 PM
  • Joined: 21 Dec 2007
You mean for a hosted control?
so a html control clicked fires some ahk code. If so please confirm and I will post an example.
Never lose.
WIN or LEARN.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
Yes, hosted control. Lets say I have javascript timer, which checks some things, like innerText content of some element and calls ahk function when content is set to specific value only (I am making this up obviously).

This is already explained from the ahk -> js side. I just want to know is this possible in js -> ahk manner. The question is, I beleive, what is the appropriate IHTMLDocument2 notification to monitor from ahk which would js fire when it wants to communicate. I am using onclick now, but is there some better/safer method ?
Posted Image

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
You would need to pass in an IDispatch interface, such as created by DispatchObj. Working example (on the ANSI build):
dobj := DispatchObj_Create("test")
sc := ComObjCreate("ScriptControl"), sc.Language := "JScript"
sc.AddObject("foo", ComObjEnwrap(dobj)), ObjRelease(dobj), dobj:=""
sc.Eval("foo.test()")
test() {
    MsgBox Hello, world!
}
DisatchObj isn't compatible with Unicode or x64, but it would be best to rewrite the script to take advantage of object support anyway.

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

COM Object: MSXML2.DOMDocument.6.0
Purpose: XML parser
System Requirements: Windows XP SP3, Vista, 7


Thanks for the example fincs happy.png - I was hoping someone would post something for XML soon. It might be worth mentioning that you can use the Version Independent MSXML2.DOMDocument on older version of XP by simply removing the For-Loop:

;// ...

DisplayNode(nodes, indent=0)
{
;// for node in nodes
   Loop % nodes.length
   {
      node := nodes.item(A_Index-1)
      if node.nodeName != "#text"
         text .= spaces(indent) node.nodeName ": " node.nodeValue "`n"
      else
         text .= spaces(indent) node.nodeValue "`n"
      if node.hasChildNodes
         text .= DisplayNode(node.childNodes, indent+2)
   }
   return text
}

;// ...

loadXML(ByRef data)
{
   o := ComObjCreate("MSXML2.DOMDocument")
   o.async := false
   o.loadXML(data)
   return o
}

I only mention this because it was frustrating trying to figure out the errors on my pc at work - which is XP SP2 :? .