Catching the context in MS Word

Get help with using AutoHotkey and its commands and hotkeys
jmasiak
Posts: 27
Joined: 06 Aug 2019, 08:43
Location: Gdańsk

Catching the context in MS Word

Post by jmasiak » 07 Sep 2020, 07:57

Hi!
I'd like to write an app which will be displaying different GUIs with tools depending on the active controls in MS Word. However, I don't know how to catch the context, e.g. how will my application know when a table or drawing is active. For example, in the MS Word interface, after selecting an image, the "Drawing Tools" ribbon appears. Is there any related event that I could catch?
Do you know what could I do?
Thanks in advice
User avatar
mikeyww
Posts: 3967
Joined: 09 Sep 2014, 18:38

Re: Catching the context in MS Word

Post by mikeyww » 07 Sep 2020, 09:31

The Word title bar changes according to the selected object, so you could run a Loop or SetTimer containing an ImageSearch or ControlGet. In my version of Word, for example, selecting an image enables the control, "NetUIHWND1", which has a tooltip called, "Repeat Format Object".
tmplinshi
Posts: 1600
Joined: 01 Oct 2013, 14:57

Re: Catching the context in MS Word

Post by tmplinshi » 07 Sep 2020, 13:04

Hello

You can catch COM events like this:

Code: Select all

; Open a MS Word window before running this script
wd := Word_Get()
ComObjConnect(wd, new catchComEvents)
Return

class catchComEvents
{
	__New() {
		this.info := new infoWindow("x0 y0", "Monitoring COM Events...")
	}

	__Call(Name, Params*) {
		Loop, % Params.MaxIndex() - 1 { ; Skip the last parameter (ComObject)
			sParams .= (A_Index>1 ? "," : "") . Params[A_Index]
		}
		this.info.add(Name " " sParams)
	}
}

class infoWindow
{
	__New(Options := "", Title := "") {
		preDefaultGui := A_DefaultGui
		RegExMatch(Options, "i)\bw\K\d+\b", w) ? "" : (w:=400)
		RegExMatch(Options, "i)\bh\K\d+\b", h) ? "" : (h:=200)

		Gui, New, +HWNDhGui +Resize +Label_infoWindow_On
		Gui, Margin, 0, 0
		Gui, Add, Edit, w%w% h%h% HWNDhEdit ReadOnly -Wrap +HScroll
		Gui, Show, w%w% h%h% %Options%, %Title%

		Gui, %preDefaultGui%:Default
		this.hEdit := hEdit
		this.hGui  := hGui
		Return this

		_infoWindow_OnClose:
			Gui, %A_Gui%:Destroy
		Return

		_infoWindow_OnSize:
			if (A_EventInfo != 1)
				GuiControl, %A_Gui%:Move, Edit1, w%A_GuiWidth% h%A_GuiHeight%
		Return
	}

	__Delete() {
		try
			Gui, % this.hGui ":Destroy"
	}

	Add(ByRef Text) {
		this.Edit_AppendLine(this.hEdit, Text)
	}

	Edit_AppendLine(hEdit, ByRef line) {
		pLine := &(line .= "`r`n")
		SendMessage, 0x000E, 0, 0,, ahk_id %hEdit% ; WM_GETTEXTLENGTH
		SendMessage, 0x00B1, %ErrorLevel%, %ErrorLevel%,, ahk_id %hEdit% ; EM_SETSEL
		SendMessage, 0x00C2, 0, %pLine%,, ahk_id %hEdit% ; EM_REPLACESEL
	}
}

; Word_Get.ahk: burque505, modified from
; Excel_Get by jethrow (modified)
; Forum:    https://autohotkey.com/boards/viewtopic.php?f=6&t=31840
; Github:   https://github.com/ahkon/MS-Office-COM-Basics/blob/master/Examples/Excel/Excel_Get.ahk
; With subsequent mods by opiuetasfd - thanks!
Word_Get(WinTitle:="ahk_class OpusApp", _WwG#:=1) {
    static h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
    WinGetClass, WinClass, %WinTitle%
    if !(WinClass == "OpusApp")
        return "Window class mismatch. (" WinClass ")"
    ControlGet, hwnd, hwnd,, _WwG%_WwG#%, %WinTitle%
    if (ErrorLevel)
        return "Error accessing the control hWnd. (" ErrorLevel ")"
    VarSetCapacity(IID_IDispatch, 16)
    NumPut(0x46000000000000C0, NumPut(0x0000000000020400, IID_IDispatch, "Int64"), "Int64")
    if (hr := DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", -16, "Ptr", &IID_IDispatch, "Ptr*", pacc)) != 0
        return "Error calling AccessibleObjectFromWindow. (" 
        . (hr = 0x80070057 ? "E_INVALIDARG" : hr = 0x80004002 ? "E_NOINTERFACE" : hr) ")"
    window := ComObject(9, pacc, 1)
    if ComObjType(window) != 9
        return "Error wrapping the window object."
    try return window.Application
    catch e
        return "Error accessing the application object. (" SubStr(e.message, 1, 10)  ")"
}

Then you can see there is an event "WindowSelectionChange".

Code: Select all

#Persistent
wd := Word_Get()
ComObjConnect(wd, WordEvent)
return

class WordEvent
{
	WindowSelectionChange(Selection) {
		static wdWithInTable := 12, wdSelectionShape := 8
		if Selection.Information(wdWithInTable)
			ToolTip, table active
		else if (Selection.type = wdSelectionShape)
			ToolTip, Shape active
	}
}

; Word_Get.ahk: burque505, modified from
; Excel_Get by jethrow (modified)
; Forum:    https://autohotkey.com/boards/viewtopic.php?f=6&t=31840
; Github:   https://github.com/ahkon/MS-Office-COM-Basics/blob/master/Examples/Excel/Excel_Get.ahk
; With subsequent mods by opiuetasfd - thanks!
Word_Get(WinTitle:="ahk_class OpusApp", _WwG#:=1) {
    static h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
    WinGetClass, WinClass, %WinTitle%
    if !(WinClass == "OpusApp")
        return "Window class mismatch. (" WinClass ")"
    ControlGet, hwnd, hwnd,, _WwG%_WwG#%, %WinTitle%
    if (ErrorLevel)
        return "Error accessing the control hWnd. (" ErrorLevel ")"
    VarSetCapacity(IID_IDispatch, 16)
    NumPut(0x46000000000000C0, NumPut(0x0000000000020400, IID_IDispatch, "Int64"), "Int64")
    if (hr := DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", -16, "Ptr", &IID_IDispatch, "Ptr*", pacc)) != 0
        return "Error calling AccessibleObjectFromWindow. (" 
        . (hr = 0x80070057 ? "E_INVALIDARG" : hr = 0x80004002 ? "E_NOINTERFACE" : hr) ")"
    window := ComObject(9, pacc, 1)
    if ComObjType(window) != 9
        return "Error wrapping the window object."
    try return window.Application
    catch e
        return "Error accessing the application object. (" SubStr(e.message, 1, 10)  ")"
}
User avatar
mikeyww
Posts: 3967
Joined: 09 Sep 2014, 18:38

Re: Catching the context in MS Word

Post by mikeyww » 07 Sep 2020, 13:10

That's cool!
Post Reply

Return to “Ask For Help”