Instructor wrote:Не 0, потому что "A nonzero timer identifier".
Ой, проглядел.
Instructor wrote:Не 1-9, потому что резерв для hMainWnd (вдруг появятся).
В самом AkelPad'е и в любых других скриптах?
Новый уникальный идентификатор никак не запросить?
Может, лучше new Date().getTime() в качестве относительно уникального идентификатора использовать?
Posted: Fri Mar 07, 2014 10:48 am
by FeyFre
Infocatcher, если говорить по хорошему, то в указанном примере не можно использовать hMainWnd как базу для таймера скрипта.
Это, так сказать, правило собственной безопасности: не пользуйтесь неконтролируемыми окнами для создания собственных таймеров, ибо вы никогда не знаете что:
а) выбранный вами идентификатор сейчас не задействован;
б) выбранный вами идентификатор не будет задействован в зависимости от не контролируемых вами обстоятельств(пользователь кнопку нажал;
в) выбранный вами идентификатор не будет задействован в будущих версиях(автор окна решил сделать там бегущую строку).
г) может появится такой же хитрый сторонний товарищъ(в кол-ве >1 не исключено) который тоже захочет попользоваться таймером(вон нас сколько скриптописателей нарисовалось, и после поданного Инструктором примера таймерами могут начать пользоваться все кому не лень даже есть это не очень нужно).
По пунктах:
а) ваш обработчик может быть вызван до того как вы готовы, либо после(до инициализации либо после разрушения окружения, что может вызвать падения) и в общем случае с не корректным интервалом. Также манипуляция таймером по вашем усмотрению может быть совсем неожиданной с исходной точки зрения и уже не ваш код может перестать функционировать так как нужно(упадет, чето сделает не так, либо перестанет работать).
б) собственно то же что и пункт а)
в) (на случай) потребуется анализ и исправления при выходе каждой очередной версии. Это работа неопределенного объема но зато известной степени геморности(возведенной в степень кол-ва конкурентов).
г) ну сами понимаете.
Даже в нашем случае, когда многоуважаемый Инструктор зарезервировал на "вдруг появятся" 9 таймеров, и будучи и хозяином окна и скрипта, всё-равно по хорошему не должен был использовать hMainWnd. Ибо со временем "вдруг понадобится" может вырасти и до 16, 50, 100, 5000 штук. Примем ко вниманию пункт г)
Выхода существует два:
1) Хост предоставляет сервис таймеров(собственно сомнительное решение)
2) Создавайте своё окно и делайте что надо на нем
Posted: Fri Mar 07, 2014 10:53 am
by FeyFre
Infocatcher, попробовать можно, но я в простыне изложил(да и Date().getTime() 8-байтный товарищъ, а UINT у нас 4 даже на x86_64)
var oSys = AkelPad.SystemFunction();
var hInstDLL = AkelPad.GetInstanceDll();
var sClass = "AkelPad::Scripts::" + WScript.ScriptName + "::" + hInstDLL;
var hMainWnd = AkelPad.GetMainWnd();
var hMenu = CreateMainMenu();
var hEdit;
var hButton;
var hFocus;
AkelPad.WindowRegisterClass(sClass);
oSys.Call("User32::CreateWindowExW",
0, //dwExStyle
sClass, //lpClassName
"Menu", //lpWindowName
0x90CA0000, //dwStyle=WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX
300, //x
200, //y
260, //nWidth
160, //nHeight
hMainWnd, //hWndParent
hMenu, //hMenu
hInstDLL, //hInstance
DialogCallback); //Script function callback. To use it class must be registered by WindowRegisterClass.
AkelPad.WindowGetMessage();
AkelPad.WindowUnregisterClass(sClass);
function DialogCallback(hWnd, uMsg, wParam, lParam)
{
if (uMsg == 1) //WM_CREATE
{
hEdit =
oSys.Call("User32::CreateWindowExW",
0x0200, //dwExStyle
"EDIT", //lpClassName
"Text", //lpWindowName
0x50010080, //dwStyle
10, //x
70, //y
130, //nWidth
21, //nHeight
hWnd, //hWndParent
1001, //ID
hInstDLL, //hInstance
0); //lpParam
hButton =
oSys.Call("User32::CreateWindowExW",
0, //dwExStyle
"BUTTON", //lpClassName
"Exit", //lpWindowName
0x50010000, //dwStyle
160, //x
70, //y
80, //nWidth
23, //nHeight
hWnd, //hWndParent
1002, //ID
hInstDLL, //hInstance
0); //lpParam
hFocus = hEdit;
}
else if ((uMsg == 6 /*WM_ACTIVATE*/) && (wParam == 0 /*WA_INACTIVE*/))
hFocus = oSys.Call("User32::GetFocus");
else if (uMsg == 7 /*WM_SETFOCUS*/)
oSys.Call("User32::SetFocus", hFocus);
else if (uMsg == 256 /*WM_KEYDOWN*/)
{
if (wParam == 27 /*VK_ESCAPE*/)
oSys.Call("User32::PostMessageW", hWnd, 16 /*WM_CLOSE*/, 0, 0);
}
else if (uMsg == 273 /*WM_COMMAND*/)
{
var nLowParam = LoWord(wParam);
var nHiwParam = HiWord(wParam);
//button
if (lParam)
{
if (nLowParam == 1002)
oSys.Call("User32::PostMessageW", hWnd, 16 /*WM_CLOSE*/, 0, 0);
}
//menu
else if (! nHiwParam)
oSys.Call("User32::SetWindowTextW", hEdit, "Menu ID: " + nLowParam);
}
else if (uMsg == 16 /*WM_CLOSE*/)
oSys.Call("User32::DestroyWindow", hWnd); //Destroy dialog
else if (uMsg == 2 /*WM_DESTROY*/)
oSys.Call("User32::PostQuitMessage", 0); //Exit message loop
return 0;
}
function LoWord(nDwNum)
{
return nDwNum & 0xFFFF;
}
function HiWord(nDwNum)
{
return (nDwNum >> 16) & 0xFFFF;
}
function CreateMainMenu()
{
var MF_STRING = 0x0000;
var MF_POPUP = 0x0010;
var hMenu = oSys.Call("User32::CreateMenu");
var hMenu1 = oSys.Call("User32::CreatePopupMenu");
var hMenu2 = oSys.Call("User32::CreatePopupMenu");
oSys.Call("User32::AppendMenuW", hMenu, MF_POPUP, hMenu1, "&Find");
oSys.Call("User32::AppendMenuW", hMenu, MF_POPUP, hMenu2, "&Go to");
oSys.Call("User32::AppendMenuW", hMenu1, MF_STRING, 5101, "Find &1");
oSys.Call("User32::AppendMenuW", hMenu1, MF_STRING, 5102, "Find &2");
oSys.Call("User32::AppendMenuW", hMenu2, MF_STRING, 5201, "Go to &1");
oSys.Call("User32::AppendMenuW", hMenu2, MF_STRING, 5202, "Go to &2");
return hMenu;
}
1. F10 key activates the menu. How to activate the menu by pressing Alt (or another key eg. F1)?
2. The menu can also be activated by pressing Alt+F or Alt+G. However, in this case, the menu pops up twice. What to do, to menu appeared only once?
On WinXP also does not work, WindowsList.js as well.
In AkelPad 4.8.6 with Scripts plugin v13.1 everything works correctly.
It seems to me that this is the error in RegisterCallback() in new version of the plugin.
Instructor
Now doesn't work the callback in function ChooseFont() - scripts ChooseFont_function.js, FontDialogMonospace.js, FileInfo.js, Translator.js.