Actually I didn't know one can reliably operate upon chrome search bar. Thanks for sharing. It's too bad, however, that it requires such a huge library like acc. For that matter, and as for me - Windows 8.1; chrome up-to-date - injectJS func, most of time, fails to send Enter key in particular and in such a way that I must manually press enter in order to inject the js source.
Btw, here's a example of speech recognition feature by a hacky 2-way link using injectJS and without using any plugin: chrome send the speech recognition result or its recognition state to ahk by its title (retrieved by
Code: Select all
; note: the script will create two files in the script's current working directory (Dictation.Config.ini and HTMLFile.html)
#NoEnv
; #Warn
; #SingleInstance force
#Include %A_ScriptDir%\acc.ahk ; requires acc
injectJS(__js) { ; from https://github.com/sancarn/Small_AHK_Projects/blob/master/ChromeInjectJavascript/ChromeInjectJavascript.ahk
if (__js = "")
return false
if (WinExist("ahk_exe chrome.exe")) {
WinActivate
WinWaitActive
Acc_Get("Object", "4.1.2.2.3.5.2",, "ahk_exe chrome.exe").accValue(0) := "javascript:void((function(){" . __js . "})())"
ControlSend, Chrome Legacy Window, {F6}{Enter}
return !ErrorLevel
}
return false, ErrorLevel:=1
}
js =
(LTrim Join
var A_LastWidth = window.outerWidth, A_LastHeight = window.outerHeight;
Dictation = new function() {
document.getElementById("lang").setAttribute("onclick", "javascript:updateLang(this);return false;");
window.addEventListener("resize", function() {
var __width = window.outerWidth - A_LastWidth;
Dictation.winResizeEventMonitor(__width, !__width);
});
return {
recognitionState: 0,
set recognitionLanguage(__LID) {
if (__LID < 1) return;
console.info((document.getElementById("lang")[document.getElementById("lang").selectedIndex=__LID - 1]).value);
document.getElementById("lang").click();
},
start: function() {
this.recognitionState = 1, document.getElementById("btnClear").click(), document.getElementById("btn").click(), document.title = this.recognitionState;
console.log(arguments.callee.name);
this.titleUpdater = window.setInterval(function() {
document.title = document.getElementById("labnol").innerText + document.getElementById("notfinal").innerText;
}, 700);
},
stop: function() {
this.recognitionState = -1, document.getElementById("btn").click(), clearInterval(this.titleUpdater), document.title = this.recognitionState;
console.log(arguments.callee.name);
window.setTimeout(function(__Dictation) {
document.title = (__Dictation.recognitionState=0);
}, 700, this);
},
setRecognitionLanguage: function(__language) {
if (this.recognitionState) {
console.warn(arguments[0]);
return;
}
this.recognitionLanguage = __language;
},
winResizeEventMonitor: function(__width, __height) {
if (__height)
{
switch(this.recognitionState) {
case 1:
this.stop();
break;
case 0:
this.start();
break;
case -1:
break;
}
A_LastHeight = window.outerHeight;
}
else if (__width)
{
this.setRecognitionLanguage(__width);
A_LastWidth = window.outerWidth;
}
}
}
};
console.log(document.title="test_dictation");
)
global SpeechRecognition, WB
if not (SpeechRecognition:=new Dictation()) { ; create a new instance of Dictation
MsgBox, 64,, % "Dictation.LastError:" . {-3:"NO_INTERNET"
, -2:"CHROME_NOTFOUND"
, -1:"CHROME_RUN_ERRORLEVEL"
, 1:"INJECTJS_ERROR"
, 2:"INJECTJS_ERROR"
, 3:"SETRECOGNITIONLANGUAGE_ERROR"
, 4:"SETRECOGNITIONLANGUAGE_ERROR"}[Dictation.LastError]
ExitApp
}
; speech recognition callback function:
SpeechRecognition.onInterimResult := Func("updateInterimResults")
SpeechRecognition.onResult := Func("saveToClipboard")
Gui, 1:Add, DropDownList, % "vdropDownListControl x12 y9 w150 R10 Choose" . Dictation.startLanguage . " +AltSubmit gsetRecognitionLanguage", % Dictation.languages
Gui, 1:Add, Button, vbuttonControl x172 y9 w160 h20 grecognitionToogleState, start/stop &recognition
Gui, 1:Add, ActiveX, vWB x12 y39 w710 h100, Shell.Explorer
if not (FileExist(var:=A_ScriptDir . "/HTMLFile.html")) {
FileAppend,
(
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8" />
<title>HTMLFile</title>
<style>
.S2 {
vertical-align: sub;
font-size: 9px;
color: #666;
}
</style>
</head>
<body>
<span class="X" style="display: none;"></span>
<div class="C" style="padding: 15px;">
</div>
</body>
</html>
), % var, utf-8
}
WB.Navigate("file:///" . var)
while (WB.busy or WB.readyState <> 4)
sleep, 100
Gui, 1:Add, Progress, vprogressControl x12 y149 w710 h10 range0-100, 100
Gui, 1:Show, h170 w734, %A_ScriptName%
OnExit("ExitFunc")
return ; end of the auto-execurte part of the script
setRecognitionLanguage:
GuiControl, 1:Enable0, % A_GuiControl
GuiControl, 1:Enable0, buttonControl
GuiControlGet, var,, % A_GuiControl
SpeechRecognition.setRecognitionLanguage(var)
GuiControl, 1:Enable1, % A_GuiControl
GuiControl, 1:Enable1, buttonControl
return
recognitionToogleState:
GuiControl, 1:Enable0, % A_GuiControl
var := SpeechRecognition.recognizing
SpeechRecognition.recognitionToogleState()
GuiControl, 1:Enable%var%, dropDownListControl
GuiControl, 1:Enable1, % A_GuiControl
return
updateInterimResults(__dictation) {
GuiControl, 1:, progressControl, % ((__dictation.waitForInterimResultTimeRemaining*100)/__dictation.interimResultTimeout)
if (__dictation.waitForInterimResultTimeRemaining) {
VarSetCapacity(__str, 110*(__interimResultsOutputArray:=StrSplit(__dictation.lastInterimResult, A_Space)).MaxIndex())
Loop % __interimResultsOutputArray.MaxIndex()
__str .= "<span class=""S1"">" . __interimResultsOutputArray[a_index] . "</span><span class=""S2""> " . a_index . " </span>"
WB.document.getElementsByClassName("C")[0].innerHTML := __str
} else {
__dictation.recognitionToogleState()
GuiControl, 1:Enable, dropDownListControl
}
}
saveToClipboard(__dictation, __result) {
clipboard := __result
TrayTip, %A_ScriptName%, Result has been copied to clipboard.
}
GuiClose:
ExitApp
ExitFunc() {
return (SpeechRecognition:=0)
}
; ====================
Class Dictation {
static configFile := A_ScriptDir . "\Dictation.Config.ini"
, url := "https://dictation.io"
, LastError := 0
recognizing := false
, interimResultTimeout := 7
, lastInterimResultElapsedTime := 0
, lastInterimResult := ""
, onInterimResultFunc := this.updateInterimResults
, onResultFunc := this.saveToClipboard
Init() {
static __ := Dictation.Init()
if not (FileExist(Dictation.configFile)) {
FileAppend,
(LTrim
[start]
language=62
[languages]
Afrikaans=1
Bahasa Indonesia=2
Bahasa Melayu=3
Català=4
Čeština=5
Dansk=6
Deutsch=7
Australia=8
Canada=9
India=10
New Zealand=11
South Africa=12
English=13
United States=14
Argentina=15
Bolivia=16
Chile=17
Colombia=18
Costa Rica=19
Ecuador=20
El Salvador=21
Español=22
Estados Unidos=23
Guatemala=24
Honduras=25
México=26
Nicaragua=27
Panamá=28
Paraguay=29
Perú=30
Puerto Rico=31
República Dominicana=32
Uruguay=33
Venezuela=34
Euskara=35
Filipino=36
Français=37
Galego=38
हिन्दी=39
Hrvatski=40
IsiZulu=41
Íslenska=42
Italiano=43
Svizzera=44
Lietuvių=45
Magyar=46
Nederlands=47
Norsk bokmål=48
Polski=49
Brasil=50
Portugal=51
Română=52
Slovenščina=53
Slovenčina=54
Suomi=55
Svenska=56
Tiếng Việt=57
ภาษาไทย=58
Türkçe=59
Ελληνικά=60
български=61
Русский=62
Српски=63
Українська=64
한국어=65
普通话 (中国大陆)=66
普通话 (香港)=67
中文 (台灣)=68
粵語 (香港)=69
日本語=70
), % Dictation.configFile, utf-16
}
IniRead, __language, % Dictation.configFile, start, language
if (__language == "ERROR")
ExitApp
Dictation.startLanguage := __language
IniRead, __languages, % Dictation.configFile, languages
if (__languages == "ERROR")
ExitApp
Dictation.languages := RTrim(RegExReplace(__languages, "=.+?\n", "|"), "=" . StrSplit(__languages, "`n").length())
}
__New() {
if not (DllCall("Wininet.dll\InternetGetConnectedState", "Str", 0x40, "Int", 0)) ; check internet connection
return !Dictation.LastError:=-3
RegRead, __regKey, HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths\Chrome.exe ; retrieves chrome.exe path via registry
if (ErrorLevel)
return !Dictation.LastError:=-2
run % """" . __regKey . """ " . Dictation.url,, UseErrorLevel
if (ErrorLevel)
return !Dictation.LastError:=-1
WinWait % Dictation.__Class . A_Space . "ahk_exe chrome.exe"
this.HWND := "ahk_id " . WinExist()
sleep, 3000
global js
injectJS(js)
if (ErrorLevel)
return !Dictation.LastError:=1
sleep, 500
MsgBox, Can't run the js without entering manually {Enter}...
WinWait % "test_dictation" . A_Space . this.HWND,, 4
if (ErrorLevel)
return !Dictation.LastError:=2
WinMove, % this.HWND,,,,, % A_ScreenHeight
WinRestore, % this.HWND
this.setRecognitionLanguage(Dictation.startLanguage)
if (ErrorLevel)
return !Dictation.LastError:=ErrorLevel
return this
}
__Delete() {
if (Dictation.LastError >= 0) {
if (this.recognitionState())
this.recognitionToogleState()
PostMessage, % (WM_SYSCOMMAND:="0x112"), % (SC_CLOSE:="0xF060"),,, % this.HWND
}
}
recognitionToogleState() {
static __x := 0, __y := 1
IfEqual, __x, %__y%, return
__x := __y
if (__f:=this.boundIterator) {
SetTimer, % __f, off
SetTimer, % __f, delete
this.boundIterator := ""
}
WinMove, % this.HWND,,,,, % A_ScreenHeight - __y
WinWait % __y . A_Space . this.HWND,, 2
if (ErrorLevel)
ExitApp
if (this.recognizing:=__y) {
this.boundIterator := __f := this.updateResult.Bind(this)
SetTimer, % __f, % this.iteratorPeriod
} else this.onResultFunc.Bind(this, this.lastInterimResult).Call(), this.lastInterimResultElapsedTime := 0, this.lastInterimResult := ""
__y := !__y
return !ErrorLevel
}
recognitionState() {
return this.recognizing
}
setRecognitionLanguage(__language) {
static __l := StrSplit(Dictation.languages, "|").length()
if not (((__language:=abs(__language)) >= 1) and __language <= __l)
return !ErrorLevel:=3
SetWinDelay, -1
WinGetPos,,, __w1,, % "ahk_id " . WinExist(this.HWND)
WinMove,,,,, % __w1 - (__language)
WinGetPos,,, __w2
sleep, 100
WinMove,,,,, % __w1
WinGetPos,,, __w1
return ErrorLevel:=!((__w1 - __w2 == __language)*4)
}
iteratorPeriod {
set {
static ITERATOR_MIN_PERIOD := 250
if (value < ITERATOR_MIN_PERIOD)
return ITERATOR_MIN_PERIOD
return value
}
}
interimResult {
set {
if (this.lastInterimResult == value)
this.lastInterimResultElapsedTime += 0.5
else this.lastInterimResult := value, this.lastInterimResultElapsedTime := 0
this.waitForInterimResultTimeRemaining := this.interimResultTimeout - this.lastInterimResultElapsedTime
this.onInterimResultFunc.Bind(this).Call()
}
}
updateResult() {
WinGetTitle, __winTitle, % this.HWND
this.interimResult := InStr(__winTitle, Dictation.url) ? "" : StrSplit(__winTitle, " - Google Chrome")[1]
}
onInterimResult {
set {
if (value.maxParams > 0 or (value:=Func(value)).maxParams > 0) {
this.onInterimResultFunc := value
return !ErrorLevel:=0
}
this.onInterimResultFunc := this.updateInterimResults
return !ErrorLevel:=6
}
}
onResult {
set {
if (value.maxParams > 0 or (value:=Func(value)).maxParams > 0) {
this.onResultFunc := value
return !ErrorLevel:=0
}
this.onResultFunc := this.saveToClipboard
return !ErrorLevel:=7
}
}
updateInterimResults() {
if (this.waitForInterimResultTimeRemaining) {
TrayTip,, % this.lastInterimResult,, 0x1
} else this.recognitionToogleState()
}
saveToClipboard(__result) {
clipboard := __result
}
}