;--------------------------------------------------------------------------------------------------------------- ; CHANGELOG: ; ; Feb 23 2022: Initial release by Glisense ltd ; ; Current script is designed for use together with Keyboard Extension® (https://keyboardextension.com) ; ; For the latest version, description and licensing terms go to https://keyboardextension.com/plugins/542b17ad ; ;--------------------------------------------------------------------------------------------------------------- #NoTrayIcon ; Hide tray icon delim := GetDecimalDelimiter() Msg := new Messaging("OnMsg") Msg.SendParam("delimiter", delim) Return OnMsg(param, value) { global delim if (param = "SendDelimiter") Send, % "{Text}" . delim } GetDecimalDelimiter() { static LOCALE_USER_DEFAULT := 0x00000400 , LOCALE_SDECIMAL := 0x0000000E VarSetCapacity(delim, 8) DllCall("GetLocaleInfo", "UInt", LOCALE_USER_DEFAULT, "UInt", LOCALE_SDECIMAL, "Str", delim, "UInt", 4) Return delim } class Messaging { /* The Messaging class implements messaging between Keyboard Extension® for Windows (KEW) and the script. When the instance of the class Messaging is created, a Func Object or a function name can optionally be passed to the constructor of the class. This object or function is required to process incoming messages from KEW. In order to send messages to KEW, SendParam(param, value) method is used, where param is the name of the outgoing parameter value is its corresponding value UserOnMessageFunc — a custom Func Object or a function name that will be called when messages are received from KEW It accepts two mandatory parameters: param - the name of the incoming parameter value - the value of the incoming parameter */ __New(UserOnMessageFunc := "") { if UserOnMessageFunc { UserFunc := IsObject(UserOnMessageFunc) ? UserOnMessageFunc : Func(UserOnMessageFunc) this.OnMessageReceive := new this.Receiving(UserFunc) } } __Delete() { if this.OnMessageReceive { this.OnMessageReceive.Clear() this.OnMessageReceive := "" } } SendParam(param, value) { ; these gobal variables get values ​​when the plugin starts, they are required to send messages to KEW global HostWindowHandle, HostEngineThreadId while !(HostWindowHandle && HostEngineThreadId) Sleep, 10 this._SendData(HostWindowHandle, HostEngineThreadId, param . ":" . value) } _SendData(hWnd, EngineThreadId, StringData) { VarSetCapacity(message, size := StrPut(StringData, "UTF-16")*2, 0) StrPut(StringData, &message, "UTF-16") VarSetCapacity(COPYDATASTRUCT, A_PtrSize*3, 0) NumPut(EngineThreadId, COPYDATASTRUCT, 0, "UInt") NumPut(size, COPYDATASTRUCT, A_PtrSize, "UInt") NumPut(&message, COPYDATASTRUCT, A_PtrSize*2) DllCall("SendMessage", Ptr, hWnd, UInt, WM_COPYDATA := 0x4A, Ptr, 0, Ptr, ©DATASTRUCT) } class Receiving { WM_COPYDATA := 0x4A __New(UserFunc) { this.dataArr := [] this.UserFunc := UserFunc this.timer := ObjBindMethod(this, "MessageProcessing") this.OnMsg := ObjBindMethod(this, "CopyDataRead") OnMessage(this.WM_COPYDATA, this.OnMsg) } CopyDataRead(wp, lp) { data := StrGet(NumGet(lp + A_PtrSize*2), "UTF-16") this.dataArr.Push(data) timer := this.timer SetTimer, % timer, -10 Return true } MessageProcessing() { while this.dataArr[1] != "" { data := this.dataArr.RemoveAt(1) RegExMatch(data, "^(.*?):(.*)", m) param := m1, value := m2 this.UserFunc.Call(param, value) } } Clear() { OnMessage(this.WM_COPYDATA, this.OnMsg, 0) this.OnMsg := "" this.timer := "" } } }