A.ahk 创建菜单,B.ahk显示A的菜单或调用A的某个功能

问题:

A.ahk创建的菜单,如何通过B.ahk来显示A的菜单或直接调用A的某个功能?

例如,A.ahk

MyMenu := Menu()
MyMenu.Add('Item 1', MenuHandler)
MyMenu.Add('Item 2', MenuHandler)
MenuHandler(ItemName, ItemPos, MyMenu) {
    MsgBox "You selected " ItemName " (position " ItemPos ")"
    if(ItemName="Item 2")
		item2Action()
}
item2Action() {
    MsgBox "item2Action"
}

B.ahk

;显示菜单,由人来选择菜单项
#b::{
    a_script_obj.MyMenu.Show
}
;直接调用某个功能
#a::
{
a_script_obj.item2Action()
}

 

实现的方法可能有以下几种:

1、通过Include将两个脚本整合一个。本文是希望解耦,所以不讨论该法。

2、通过OnMessage,实现消息机制。类似TC或xyPlorer的机制,感兴趣可以参考
XYplorer论坛的ahk帖子

3、通过微软COM模型实现两个ahk进程间协同。

本文主要介绍 方案3。

实现方案

A.ahk:

#Requires AutoHotkey v2

Persistent
MyClsid := '{E020E44C-6F6B-43D9-9BA6-1CEE1005ED91}'
MyMenu := Menu()
MyMenu.Add('Item 1', MenuHandler)
MyMenu.Add('Item 2', MenuHandler)
MenuHandler(ItemName, ItemPos, MyMenu) {
    MsgBox "You selected " ItemName " (position " ItemPos ")"
    if(ItemName="Item 2")
		item2Action()
}
item2Action() {
    MsgBox "item2Action"
}
;ActiveObject.Register(MyMenu, MyClsid)
ActiveObject.Register(Adapter(), MyClsid)
class Adapter {
  __Call(name, args) {
    return %name%(args*)
  }
  __Get(Key, Params) {
    global
    return Params.Length ? %Key%[Params*] : %Key%
  }
  __Set(Key, Params, Value) {
    global
    if Params.Length
      %Key%[Params*] := Value
    else %Key% := Value
  }
  __delete() {
    ExitApp()
  }
}
class ActiveObject
{ ; based on https://www.autohotkey.com/boards/viewtopic.php?f=6&t=6148
    static objects := Map()

    static Register(obj, sCLSID?) {
        if this.objects.Has(obj) {
            return this.objects[obj].clsid
        }
        sCLSID ?? sCLSID := this.CreateCLSID()
        GUID := this.GUIDFromString(sCLSID)
        hReg := this.RegisterActiveObject(obj, GUID)
        this.objects[obj] := {clsid: sCLSID, reg: hReg}
        OnExit(ObjBindMethod(this, 'Revoke', sCLSID))
        return sCLSID
    }

    static Revoke(ObjOrClsid, *) {
        if !IsObject(ObjOrClsid) {
            for obj, info in this.objects {
                if info.clsid = ObjOrClsid {
                    ObjOrClsid := obj
                }
            } until IsObject(ObjOrClsid)
        }
        try (IsObject(ObjOrClsid) && hReg := this.objects.Delete(ObjOrClsid).reg)
        (IsSet(hReg) && DllCall('OleAut32\RevokeActiveObject', 'UInt', hReg, 'Ptr', 0))
    }

    static RegisterActiveObject(obj, GUID) {
        static flag := ACTIVEOBJECT_STRONG := 0
        DllCall('OleAut32\RegisterActiveObject', 'Ptr', ObjPtr(obj), 'Ptr', GUID, 'UInt', flag, 'UIntP', &hReg := 0)
        return hReg
    }

    static GUIDFromString(sCLSID) => (DllCall('Ole32\CLSIDFromString', 'Str', sCLSID, 'Ptr', GUID := Buffer(16)), GUID)
    
    static CreateCLSID() => ComObject('Scriptlet.TypeLib').GUID
}

B.ahk

#Requires AutoHotkey v2

MyClsid := '{E020E44C-6F6B-43D9-9BA6-1CEE1005ED91}'
try a_script_obj := ComObjActive(MyClsid)
catch {
    MsgBox 'Object not found'
    ExitApp
}

;显示菜单,由人来选择菜单项
#b:: 
{
a_script_obj.MyMenu.Show()

}

;直接调用某个功能
#a::
{
a_script_obj.item2Action()
}

如果不想使用这个 '{E020E44C-6F6B-43D9-9BA6-1CEE1005ED91}',可以用这个语句创建一个新的:

A_Clipboard := ComObject('Scriptlet.TypeLib').GUID

你可能感兴趣的:(AutoHotkey,AHK,ActiveObject,COM对象)