теоретически должна заставлять скрипт завершаться по Ctrl+` при условии, что Ctrl+` является горячей клавишей для скрипта. Но на практике это не работает Вызов
/**********************************************************************
* KeySubst.js v.0.3 *
* (C) DV, May 2011 *
* Thanks to: Instructor, FeyFre *
**********************************************************************/
var alph = [
/* eng=0 */ [ "`1234567890-=\\qwertyuiop[]asdfghjkl;\'zxcvbnm,./",
"~!@#$%^&*()_+|QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?" ],
/* rus=1 */ [ "ё1234567890-=\\йцукенгшщзхъфывапролджэячсмитьбю.",
"Ё!\"№;%:?*()_+/ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ," ],
/* ukr=2 */ [ "\'1234567890-=\\йцукенгшщзхїфівапролджєячсмитьбю.",
"\'!\"№;%:?*()_+/ЙЦУКЕНГШЩЗХЇФІВАПРОЛДЖЄЯЧСМИТЬБЮ," ] ];
var eng = 0;
var rus = 1;
var ukr = 2;
var hWndEdit = AkelPad.GetEditWnd();
var oSys = AkelPad.SystemFunction();
AkelPad.ScriptNoMutex();
var hMutex;
if (hMutex = oSys.Call("kernel32::CreateMutex" + _TCHAR, 0, 1, "KeySubst_js_" + hWndEdit))
{
if (oSys.GetLastError() == 183 /*ERROR_ALREADY_EXISTS*/)
{
oSys.Call("kernel32::CloseHandle", hMutex);
oSys.Call("user32::SendMessage" + _TCHAR, hWndEdit, 0x100 /*WM_KEYDOWN*/, 0xC0, 0);
WScript.Quit();
}
}
var lpOldEditProc;
if (lpOldEditProc = AkelPad.WindowSubClass(hWndEdit, EditCallback))
{
//Message loop
AkelPad.WindowGetMessage();
AkelPad.WindowUnsubClass(hWndEdit);
oSys.Call("kernel32::CloseHandle", hMutex);
}
function EditCallback(hWnd, uMsg, wParam, lParam)
{
if (uMsg == 0x102 /*WM_CHAR*/)
{
var ch = String.fromCharCode(wParam);
var nLangId = getEditLangId(hWndEdit);
var nLangFrom = eng;
var nLangTo = rus;
if (nLangId == 1049) /* rus */
{
nLangFrom = rus;
nLangTo = eng;
}
else if (nLangId == 1058) /* ukr */
{
nLangFrom = ukr;
nLangTo = eng;
}
var nCase = 0;
var i = alph[nLangFrom][nCase].indexOf(ch);
if (i < 0)
{
nCase = 1;
i = alph[nLangFrom][nCase].indexOf(ch);
}
if (i >= 0)
{
if (i < alph[nLangTo][nCase].length)
{
ch = alph[nLangTo][nCase].charAt(i);
oSys.Call("user32::CallWindowProc" + _TCHAR, lpOldEditProc, hWnd, uMsg, ch.charCodeAt(0), lParam);
AkelPad.SendMessage(hWnd, 3377 /*AEM_UPDATECARET*/, 0, 0);
//Skip internal CallWindowProc
return 1;
}
}
}
else if (uMsg == 0x100 /*WM_KEYDOWN*/)
{
if (wParam == 0xC0 /*VK_OEM_3: (`~)*/)
{
var nCtrlState = oSys.Call("user32::GetKeyState", 0x11 /*VK_CONTROL: Ctrl*/);
var nAltState = oSys.Call("user32::GetKeyState", 0x12 /*VK_MENU: Alt*/)
if ((lParam == 0) || ((nCtrlState & 0x80) && !(nAltState & 0x80)))
{
//Exit message loop
oSys.Call("user32::PostQuitMessage", 0);
//Skip internal CallWindowProc
return 1;
}
}
}
else if (uMsg == 0x0002 /*WM_DESTROY*/)
{
//Exit message loop
oSys.Call("user32::PostQuitMessage", 0);
}
}
function getEditLangId(hEdit)
{
var nEditThreadId = oSys.Call("user32::GetWindowThreadProcessId", hEdit, 0);
var nLang = oSys.Call("user32::GetKeyboardLayout", nEditThreadId);
return (nLang & 0xFFFF);
}
. И этот скрипт лучше сохранять как UTF-16 LE.
Posted: Mon May 30, 2011 2:44 pm
by FeyFre
Вроде бы работает. Сохранял в UTF8.
Парочка замечаний:
1. WM_KEYDOWN лучше сделать POST-ом, а не SEND-ом. MSDN пишет что они Posted(и другие клавиатуропричастные сообщения), и лучше что-бы так и оставалось(мало ли, вдруг кто-то что-то будет писать фильтрующее).
2. А как его заставить набирать на той раскладке, на которой я хочу. Оно мне предлагает на русской, а я хочу укр?(Да, локализация винды русская, локализация системы - Украина).
3. Нужно использовать имя для мютекса уникальнее. Иначе возможно параллельно два скрипта в двух сессиях работать не будут.
4. Воспользоваться ToUnicodeEx не пробовали?
Important: The Google Translate API has been officially deprecated as of May 26, 2011. Due to the substantial economic burden caused by extensive abuse, the number of requests you may make per day will be limited and the API will be shut off completely on December 1, 2011. For website translations, we encourage you to use the Google Translate Element.
/*************************************************************************
* KeySubst.js v.0.4 *
* (C) DV, May 2011 *
* Thanks to: Instructor, FeyFre *
*************************************************************************/
/* Examples: *
* -"Eng as Rus" Call("Scripts::Main", 1, "KeySubst.js") *
* -"Eng as Rus" Call("Scripts::Main", 1, "KeySubst.js", `-to=rus`) *
* -"Eng as Ukr" Call("Scripts::Main", 1, "KeySubst.js", `-to=ukr`) *
*************************************************************************/
var alph = [
/* eng=0 */ [ "`1234567890-=\\qwertyuiop[]asdfghjkl;\'zxcvbnm,./`",
"~!@#$%^&*()_+|QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?~" ],
/* rus=1 */ [ "ё1234567890-=\\йцукенгшщзхъфывапролджэячсмитьбю.ё",
"Ё!\"№;%:?*()_+/ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,Ё" ],
/* ukr=2 */ [ "\'1234567890-=\\йцукенгшщзхїфівапролджєячсмитьбю.ё",
"\'!\"№;%:?*()_+/ЙЦУКЕНГШЩЗХЇФІВАПРОЛДЖЄЯЧСМИТЬБЮ,Ё" ] ];
// Note: trailing 'ё' is needed for Ukrainian because of ` to ' hack.
var eng = 0;
var rus = 1;
var ukr = 2;
var argTo = (getScriptArg("-to").toLowerCase() == "ukr") ? ukr : rus;
//var argTo = (getScriptArg("-to").toLowerCase() == "rus") ? rus : ukr;
var hWndMain = AkelPad.GetMainWnd();
var hWndEdit = AkelPad.GetEditWnd();
var oSys = AkelPad.SystemFunction();
AkelPad.ScriptNoMutex();
var mutexName = "KeySubst_js_" + hWndMain + "_" + hWndEdit;
var hMutex;
if (hMutex = oSys.Call("kernel32::CreateMutex" + _TCHAR, 0, 1, mutexName))
{
if (oSys.GetLastError() == 183 /*ERROR_ALREADY_EXISTS*/)
{
oSys.Call("kernel32::CloseHandle", hMutex);
oSys.Call("user32::SendMessage" + _TCHAR, hWndEdit, 0x100 /*WM_KEYDOWN*/, 0xC0, 0);
WScript.Quit();
}
}
var lpOldEditProc;
if (lpOldEditProc = AkelPad.WindowSubClass(hWndEdit, EditCallback))
{
//Message loop
AkelPad.WindowGetMessage();
AkelPad.WindowUnsubClass(hWndEdit);
oSys.Call("kernel32::CloseHandle", hMutex);
}
function EditCallback(hWnd, uMsg, wParam, lParam)
{
if (uMsg == 0x102 /*WM_CHAR*/)
{
var ch = String.fromCharCode(wParam);
var nLangId = getEditLangId(hWndEdit);
var nLangFrom = eng;
var nLangTo = argTo;
if (nLangId == 1049) /* rus */
{
nLangFrom = rus;
nLangTo = eng;
}
else if (nLangId == 1058) /* ukr */
{
nLangFrom = ukr;
nLangTo = eng;
}
var nCase = 0;
var i = alph[nLangFrom][nCase].indexOf(ch);
if (i < 0)
{
nCase = 1;
i = alph[nLangFrom][nCase].indexOf(ch);
}
if (i >= 0)
{
if (i < alph[nLangTo][nCase].length)
{
ch = alph[nLangTo][nCase].charAt(i);
oSys.Call("user32::CallWindowProc" + _TCHAR, lpOldEditProc, hWnd, uMsg, ch.charCodeAt(0), lParam);
AkelPad.SendMessage(hWnd, 3377 /*AEM_UPDATECARET*/, 0, 0);
//Skip internal CallWindowProc
return 1;
}
}
}
else if (uMsg == 0x100 /*WM_KEYDOWN*/)
{
if (wParam == 0xC0 /*VK_OEM_3: (`~)*/)
{
var nCtrlState = oSys.Call("user32::GetKeyState", 0x11 /*VK_CONTROL: Ctrl*/);
var nAltState = oSys.Call("user32::GetKeyState", 0x12 /*VK_MENU: Alt*/)
if ((lParam == 0) || ((nCtrlState & 0x80) && !(nAltState & 0x80)))
{
//Exit message loop
oSys.Call("user32::PostQuitMessage", 0);
//Skip internal CallWindowProc
return 1;
}
}
}
else if (uMsg == 0x0002 /*WM_DESTROY*/)
{
//Exit message loop
oSys.Call("user32::PostQuitMessage", 0);
}
}
function getEditLangId(hEdit)
{
var nEditThreadId = oSys.Call("user32::GetWindowThreadProcessId", hEdit, 0);
var nLang = oSys.Call("user32::GetKeyboardLayout", nEditThreadId);
return (nLang & 0xFFFF);
}
function getScriptArg(argName)
{
var s = "";
argName = argName.toLowerCase();
for (var n = 0; n < WScript.Arguments.length; n++)
{
var t = WScript.Arguments(n);
var a = t.split("=");
if (a[0].toLowerCase() == argName)
{
s = a[1];
break;
}
}
return s;
}
. FeyFre,
1. WM_KEYDOWN лучше сделать POST-ом, а не SEND-ом.
Если сделать Post, то временами весь AkelPad валится. Судя по всему, из-за характера PostMessage, приводящего к отсутствию синхронизации между моментами завершения скрипта и принятия сообщения.
2. А как его заставить набирать на той раскладке, на которой я хочу.
Добавлен параметр -to=ukr. Пока что ничего изящнее не придумал.
3. Нужно использовать имя для мютекса уникальнее.
Сделано
4. Воспользоваться ToUnicodeEx не пробовали?
Тут моя позиция такова: зачем её использовать, если и без неё всё хорошо?
Posted: Tue May 31, 2011 9:26 am
by FeyFre
Если сделать Post, то временами весь AkelPad валится. Судя по всему, из-за характера PostMessage, приводящего к отсутствию синхронизации между моментами завершения скрипта и принятия сообщения.
Падает изза чего-то другого. Скрипты работают независимо друг от друга(каждый в своем потоке), после PostMessage Вы не пользуетесь никаими данными которые получили из первого экземпляра скрипта, и вообще к нему не обращаетесь. Так что падение нужно ловить, желательно отладчиком. Возможно даже глюк плагина.
Добавлен параметр -to=ukr. Пока что ничего изящнее не придумал.
Так вполне нормально. Других наворотов просить не будем - не та структура скрипта.
Тут моя позиция такова: зачем её использовать, если и без неё всё хорошо?
У меня на Укр раскладке на комбинации Alt+Ctrl+u(или Alt+Ctrl+г) забинден ввод буква "ґ"(а если добавить Shift - "Ґ"), естественно Ваш скрипт не в крусе этого и ничего не делает. А вот ToUnicodeEx какраз и в курсе.