Тема: AHK: Панель быстрого доступа в WinXP как в Win7
Написал скрипт, который позволяет назначить до 12 сочетаний клавиш через графическое меню (Ctrl+F7) для переключения между окнами приложений + Анализатор логов Key Catcher (Ctrl+F2). Страничка помощи вызывается Ctrl+F1.
Можно сделать аналогичную (почти как) панель с использованием сочетаний Win+`,1,2,,,,-,= и Ctrl+`,1,2,...,-,=, то есть переключаться между окнами как в Windows 7.
Весь код не помещается, отрезал верхнюю часть и некоторые комментарии.
; Проверка на наличие файла настроек скрипта (Путь к файлу настроек в ahk_script_settings) - quickpanel.ini
IfNotExist, %A_ScriptDir%\templates\ahkscriptsettings.txt
MsgBox, % "Нет файла шаблона для файла настроек" %A_ScriptDir% "\templates\ahkscriptsettings.txt"
else
IfNotExist, %ahk_script_settings% ; Если файла нет, то он будет создан из шаблона
{
; Считаем шаблон в память
FileRead, template_in_memory, *m1024 %A_ScriptDir%\templates\ahkscriptsettings.txt
IF(ErrorLevel)
MsgBox, % "Не могу загрузить шаблон " A_ScriptDir "\templates\ahkscriptsettings.txt"
valueN_array1:=marker ; пока в массиве только 1 элемент
; Заменим значения в шаблоне на значения из массива valueN_array (Значения представлены в шаблоне в виде $%!value1!%$, $%!value2!%$, ...)
valueN_Count=1
Loop, %valueN_Count%
{
valueN=$`%!value%A_Index%!`%$
valueN_paste:=valueN_array%A_Index%
StringReplace, template_in_memory, template_in_memory, %valueN%, %valueN_paste%, All
}
fileappend, %template_in_memory%, %ahk_script_settings% ; Создадим файл настроек скрипта
}
; Forming Window Title Array in Memory (Соответствие имени .exe файла приложения названию окна этого приложения)
WTArray_Count = 0
Loop, Read, %a_scriptdir%\windowtitles.txt
{
WTArray_Count+=1
WindowTitleArray%WTArray_Count% := A_LoopReadLine
}
; Извлечение тегов-запросов на добавленные авгенерируемые теги (теги добавляются в скрипт A_ScriptFullPath) из quickpanel.ini
; Запрос будет в виде строки [секция|tag_id|tag_data]. Запросы идут один за другим, разделенные знаком "|"
ahk_parsing_file:=ahk_script_settings
tag_data:=quickpanel_params_count ; Для секции quickpanel_settings в каждом теге-запросе содержится по 5 параметров для каждого
; добавленного тега
If((tag_count:=tag_modify("get", "quickpanel_settings", "template", tag_id_list, , tag_data))<0)
MsgBox, Ошибка при извлечении тегов-запросов из файла %ahk_script_settings% Переменная tag_data = %tag_data%
ahk_parsing_file:=A_ScriptFullPath ; Вернем на место
If(tag_count>quickpanel_max_lines)
MsgBox, Превышено максимально допустимое число тегов-запросов (max=%quickpanel_max_lines%) tag_count = %tag_count%
else
Loop, %tag_count%
{ ; Из tag_data нам нужны следующие параметры:
; 4-ый - Клавиша/HotKey
; 5-ый - WindowTitle
; 7-й - Путь к программе
StringGetPos, position_2, tag_data,|,L1
StringGetPos, position_3, tag_data,|,L2
StringGetPos, position_4, tag_data,|,L3
StringGetPos, position_5, tag_data,|,L4
StringGetPos, position_6, tag_data,|,L5
StringGetPos, position_7, tag_data,|,L6
StringGetPos, position_8, tag_data,|,L7
StringGetPos, position_id, tag_id_list,|,L%A_Index%
temp:=A_Index-1
StringGetPos, position_id_previous, tag_id_list,|,L%temp%
If(ErrorLevel==1)
position_id_previous=-1
; MsgBox % position_id_previous ; debug
StringMid, str_right_part, tag_id_list, position_id_previous+2, position_id-position_id_previous-1
StringMid, str_temp, tag_data, position_2+2, position_3-position_2-1
str_temp .= "/"str_right_part
; MsgBox, % str_right_part ; debug
GuiControl, 3:,fileplaceapp%A_Index%id,%str_temp%
StringMid, str_temp, tag_data, position_4+2, position_5-position_4-1
GuiControl, 3:,fileplaceapp%A_Index%fk,%str_temp%
; MsgBox, % "TEST 777 = " fileplaceapp%A_Index%fk ; debug
StringMid, str_temp, tag_data, position_5+2, position_6-position_5-1
GuiControl, 3:,fileplaceapp%A_Index%t,%str_temp%
StringMid, str_temp, tag_data, position_7+3, position_8-position_7-3 ; потому что нужно удалить кавычку слева/справа
GuiControl, 3:,fileplaceapp%A_Index%v,%str_temp%
; MsgBox, % "TEST 777 = " fileplaceapp%A_Index%v " str_temp = " str_temp ; debug
; quickpanel_params_count+5 ; смотри функцию tag_modify() - там 5 определяет структуру тега-запроса
; Нужно убрать левую часть из tag_data
StringTrimLeft, tag_data, tag_data, position_8+1
}
; Данные о сгенерированных тегах хранятся в файле настроек скрипта "имя скрипта.ini" (ex. quickpanel.ini)
ahk_parsing_file:=ahk_script_settings
tag_data:=quickpanel_params_count ; Для секции quickpanel_settings в каждом теге-запросе содержится по 5 параметров для каждого
If(tag_modify("get", "quickpanel_settings", "status", tag_id_list, 0, tag_data)<0)
MsgBox, Ошибка при получении статуса секции файла %A_ScriptFullPath% Секция hot_keys
ahk_parsing_file:=A_ScriptFullPath ; Вернем на место
If((id_count:=tag_modify("get", "hot_keys", "status", 0, 0, 0))<0)
MsgBox, Ошибка при получении статуса секции файла %A_ScriptFullPath% Секция hot_keys
ahk_generate_trigger=1
; by default ahk_generate_trigger=0 QuickPanel_Changes="0|0|0|0|0|0|0|0|0|0|0|0|"
Loop, %quickpanel_max_lines%
QuickPanel_Changes%A_Index%=0
Loop, %tag_count%
QuickPanel_Changes%A_Index%=1
QuickPanel_Changes:=""
Loop, %quickpanel_max_lines%
QuickPanel_Changes .= QuickPanel_Changes%A_Index% "|"
; MsgBox, % "QuickPanel_Changes =" QuickPanel_Changes " tag_count = " tag_count " id_count = " id_count ; debug
; MsgBox, % tag_id_list debug
If(tag_count>0 and id_count==0) ; Секция пуста, а теги-запросы есть
{
ahk_generate(ahk_generate_trigger, QuickPanel_Changes,1, tag_id_list) ; Recovery_bit=1 , то есть нужно восстановить теги
Reload ; Перегрузка
}
; MsgBox, OK ; debug
; Set timers (wait the timer's value then trigger an action)
SetTimer, UpdateMemStatus, 300000 ; every 5 minutes
; SetTimer, DebugFileMove, 10000 ; every 10 sec
return ; really need it here! т.к. До этого места выполняются все действия, которые описаны выше, при каждой загрузке/перегрузке скрипта
; Кнопка "Save", сохранение изменений в файле скрипта (Окно Settings в Experimental Functionality)
generateahk:
; Запомним значения переменных до изменения пользователем
ahk_generate_trigger=0
Loop, %quickpanel_max_lines%
QuickPanel_Changes%A_Index%=0
Gui, 3:Submit, NoHide ; Сохранение изменений в окне Settings (CTRL+F7) в привязанные к элементам окна переменные
; Найдем измененные значения, чтобы определить какие теги нам нужно править
; QuickPanel_Changes%A_Index% - массив, где отмечены какие строчки должны быть добавлены в качестве тегов
Loop, %quickpanel_max_lines%
{
QuickPanel_Changes%A_Index%=0 ; нет изменений
; Клавиша/HotKey
GuiControlGet, str_temp, 3:,fileplaceapp%A_Index%fk
str_clean_spaces_tabs(str_temp)
if(before_change%A_Index%fk!=str_temp)
{
; MsgBox, % "YEAP |" before_change%A_Index%fk "|" ; debug
If(before_change%A_Index%fk!="")
{
GuiControlGet, tag_id, 3:,fileplaceapp%A_Index%id
StringGetPos, position, tag_id,/
StringLeft, tag_id_left, tag_id, position
StringTrimLeft, tag_id_right, tag_id, position+1
; MsgBox % "tag_id_left = "tag_id_left " tag_id_right = " tag_id_right ; debug
; MsgBox, % "1:" tag_id_left
If(tag_modify("delete", "hot_keys", "template",tag_id_left,0,0)<0)
{
MsgBox, Ошибка при удалении тега tag_id = %tag_id%
continue ; Пробуем следующую строчку из 12
}
ahk_parsing_file:=ahk_script_settings
; Удаление запроса на автогенерируемые теги в quickpanel.ini (Путь к файлу в ahk_script_settings)
If(tag_modify("delete", "quickpanel_settings", "template",tag_id_right,0,0)<0)
{
MsgBox, Критическая ошибка при удалении тега-запроса в файле %ahk_script_settings%. tag_get_id = %tag_get_id%
ahk_parsing_file:=A_ScriptFullPath ; вернем на место
break ; если не можем удалить теги-запросы, то функциональность скрипта нарушена
}
ahk_parsing_file:=A_ScriptFullPath ; вернем на место
}
GuiControl, 3:,fileplaceapp%A_Index%fk,%str_temp% ; Сохраним скорректированное значение (без табуляции и пробелов)
QuickPanel_Changes%A_Index%=1 ; Есть изменения
ahk_generate_trigger=1
continue ; тег и тег-запрос удален, не имеет смысла продолжать сравнивать по другим изменениям
}
; Путь
GuiControlGet, str_temp, 3:,fileplaceapp%A_Index%v
str_clean_spaces_tabs(str_temp)
if(before_change%A_Index%v!=str_temp)
{
; MsgBox, Changed detected ; debug
If(before_change%A_Index%v!="")
{
GuiControlGet, tag_id, 3:,fileplaceapp%A_Index%id
StringGetPos, position, tag_id,/
StringLeft, tag_id_left, tag_id, position
StringTrimLeft, tag_id_right, tag_id, position+1
; MsgBox % "tag_id_left = "tag_id_left " tag_id_right = " tag_id_right ; debug
; MsgBox, % "2:" tag_id_left
If(tag_modify("delete", "hot_keys", "template",tag_id_left,0,0)<0)
{
MsgBox, Ошибка при удалении тега tag_id = %tag_id%
continue ; Пробуем следующую строчку из 12
}
ahk_parsing_file:=ahk_script_settings
; Удаление запроса на автогенерируемые теги в quickpanel.ini (Путь в ahk_script_settings)
If(tag_modify("delete", "quickpanel_settings", "template",tag_id_right,0,0)<0)
{
MsgBox, Критическая ошибка при удалении тега-запроса в файле %ahk_script_settings%. tag_get_id = %tag_get_id%
ahk_parsing_file:=A_ScriptFullPath ; вернем на место
break ; если не можем удалить теги-запросы, то функциональность скрипта нарушена
}
ahk_parsing_file:=A_ScriptFullPath ; вернем на место
}
GuiControl, 3:,fileplaceapp%A_Index%v,%str_temp% ; Сохраним скорректированное значение (без табуляции и пробелов)
QuickPanel_Changes%A_Index%=1 ; Есть изменения
ahk_generate_trigger=1
continue ; тег и тег-запрос удален, не имеет смысла продолжать сравнивать по другим изменениям
}
; WindowTitle
GuiControlGet, str_temp, 3:,fileplaceapp%A_Index%t
str_clean_spaces_tabs(str_temp)
if(before_change%A_Index%t!=str_temp)
{
; MsgBox, Changed detected ; debug
If(before_change%A_Index%t!="")
{
GuiControlGet, tag_id, 3:,fileplaceapp%A_Index%id
StringGetPos, position, tag_id,/
StringLeft, tag_id_left, tag_id, position
StringTrimLeft, tag_id_right, tag_id, position+1
; MsgBox, % "3:" tag_id_left
; MsgBox % "tag_id_left = "tag_id_left " tag_id_right = " tag_id_right ; debug
If(tag_modify("delete", "hot_keys", "template",tag_id_left,0,0)<0)
{
MsgBox, Ошибка при удалении тега tag_id = %tag_id%
continue ; Пробуем следующую строчку из 12
}
ahk_parsing_file:=ahk_script_settings
; Удаление запроса на автогенерируемые теги в quickpanel.ini (Путь хранится в ahk_script_settings)
If(tag_modify("delete", "quickpanel_settings", "template",tag_id_right,0,0)<0)
{
MsgBox, Критическая ошибка при удалении тега-запроса в файле %ahk_script_settings%. tag_get_id = %tag_get_id%
ahk_parsing_file:=A_ScriptFullPath ; вернем на место
break ; если не можем удалить теги-запросы, то функциональность скрипта нарушена
}
ahk_parsing_file:=A_ScriptFullPath ; вернем на место
}
GuiControl, 3:,fileplaceapp%A_Index%t,%str_temp% ; Сохраним скорректированное значение (без табуляции и пробелов)
QuickPanel_Changes%A_Index%=1 ; Есть изменения
ahk_generate_trigger=1
continue ; тег и тег-запрос удален, не имеет смысла продолжать сравнивать по другим изменениям
}
}
; Заглушка: Проверка на уникальность каждого HotKey, чтобы не совпадали
Sleep, 100
; Check left, right fields for correct pathes, window titles
; Generate AHK quickpanel's hot keys from quickpanelsample.txt
; use variables like $%!description!%$ in sample to fill in
; by default ahk_generate_trigger=0 QuickPanel_Changes="0|0|0|0|0|0|0|0|0|0|0|0|"
QuickPanel_Changes:=""
Loop, %quickpanel_max_lines%
QuickPanel_Changes .= QuickPanel_Changes%A_Index% "|"
; MsgBox, % "generateahk " QuickPanel_Changes ; debug
ahk_generate(ahk_generate_trigger, QuickPanel_Changes,0,"0|0|0|0|0|0|0|0|0|0|0|0|") ; Сгенерируем изменения в скрипте
Reload ; reload this instance of script to changes take place
return
; Кнопка "Titles", БД подсказок (Соответствие имени .exe файла приложения названию окна этого приложения) (Окно Settings в Experimental Functionality)
windowtitledatabase:
Gui, 5:Destroy
Gui, 5:Add, Text,, Window Titles Data Base
Gui, 5:Add, Text,,
temp:=".exe -> "
Loop %WTArray_Count%
{
StringReplace, str, WindowTitleArray%A_Index%,:,%temp%
Gui, 5:Add, Text,, % A_Index " " str
}
Gui, 5:Show, w400 h350, Create Quick Panel - Title's List
return
; ## Open file dialog
openfileapp:
FileSelectFile, newpath
; Try to autofill right field
If (newpath != "")
{
GuiControl,3:, %A_GuiControl%v, %newpath% ; In left text field will display the path to your application
; In right text field will display the possible window title of your application
StringGetPos, position_number, newpath,\,r1 ; Looking for "\" symbol's position at the end of the string
StringTrimLeft, str, newpath, position_number+1 ; cutting off the path, in str will be only the name of app
StringTrimRight, newpath, str, 4 ; cut off ".exe"
position_number:=-1
Loop %WTArray_Count% ; Looking for possible titles in WT DataBase (WT - Window Titles)
{
StringGetPos, position_number, WindowTitleArray%A_Index%,%newpath%
If(position_number!= -1)
{
StringGetPos, position_number, WindowTitleArray%A_Index%,: ; Looking for ":" symbol's position
StringTrimLeft, str, WindowTitleArray%A_Index%, position_number+1 ; str - Window title
GuiControl,3:, %A_GuiControl%t, %str%
}
}
}
return
; Кнопка "Cancel", выход из окна (Окно Settings в Experimental Functionality)
exitdialogahk:
Gui, Cancel
return
; ## Загрузка памяти RAM (used RAM load.ahk from library catalog) web-link http://www.autohotkey.com/board/topic/35785-find-system-memory-ram/
UpdateMemStatus:
memload:=MemGetStats()
if(memload>90)
TrayTip, quickpanel Warning Message, RAM load = %memload%`%`nЕсли загрузка памяти достигнет 100`% будут дикие тормоза`, система встанет в лаге и выпадет в BSOD`, так как нет файла подкачки.`nНемедленно выгрузите приложения`, занимающие много памяти!, 2
return
MemGetStats()
{
; See:
; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/memorystatus_str.asp
VarSetCapacity(memorystatus, 4+4+4+4+4+4+4+4)
success := DllCall("kernel32.dll\GlobalMemoryStatus", "uint", &memorystatus)
stats := ReadInteger(&memorystatus,4,4, false) ; Memory Load (Percentage of memory in use)
return stats
}
ReadInteger( p_address, p_offset, p_size, p_hex=true )
{
value = 0
old_FormatInteger := a_FormatInteger
if ( p_hex )
SetFormat, integer, hex
else
SetFormat, integer, dec
loop, %p_size%
value := value+( *( ( p_address+p_offset )+( a_Index-1 ) ) << ( 8* ( a_Index-1 ) ) )
SetFormat, integer, %old_FormatInteger%
return, value
}
; ##
str_clean_spaces_tabs(ByRef str_temp) ; Удалим знаки табуляции везде и пробелы в конце/начале строки
{
StringReplace, str_temp, str_temp,%A_Tab%,, All ; Удалим знаки табуляции
; Убираем пробелы в начале строки
position_L=0
While position_L==0
{
StringGetPos, position_L, str_temp,%A_Space%,L
if(ErrorLevel==1) ; Не нашли ни одного пробела в строке
break
if (position_L ==0)
StringTrimLeft, str_temp, str_temp, 1
}
; Убираем пробелы в конце строки
position_R=0
While position_R==0
{
StringGetPos, position_R, str_temp,%A_Space%,R
if(ErrorLevel==1) ; Не нашли ни одного пробела в строке
break
if (position_R == StrLen(str_temp)-1)
StringTrimRight, str_temp, str_temp, 1
}
return 0
}
;####$$$$!!!! Generated section !!!!$$$$#### Don't touch it! # Start
;<hot_keys marker="^-_5@)+Hj*sDp{a2mark" id_count="1" id_next="45" hash="0">
;<template id="44" template="quickpanelsample.txt" hash="0">
; - App1 ; Description
#2:: ; HotKey
IfWinExist, - App1 ; Window Title
{
IfWinActive, - App1 ; Window Title
WinMinimize
else
WinActivate
return
}
else
Run "C:\Users\Алексей\Downloads\greyforum_quickpanel\readme.txt" ; Program path
return
;</template>
;</hot_keys>
;####$$$$!!!! Generated section !!!!$$$$#### Don't touch it! # End
^F7:: ; Окно Settings в Experimental Functionality
Gui, 3:Show, x45 y142 h737 w1100, Create Quick Panel
; WinActivate, Create Quick Panel
; Sleep, 200
; PostMessage 0x50, 0, %en%,, A ; switch keyboard layout to English (send command to current window)
Loop, %quickpanel_max_lines%
{
GuiControlGet, before_change%A_Index%fk, 3:,fileplaceapp%A_Index%fk
str_clean_spaces_tabs(before_change%A_Index%fk)
If(before_change%A_Index%fk=="Type HotKey")
before_change%A_Index%fk:=""
GuiControlGet, before_change%A_Index%v, 3:,fileplaceapp%A_Index%v
str_clean_spaces_tabs(before_change%A_Index%v)
GuiControlGet, before_change%A_Index%t, 3:,fileplaceapp%A_Index%t
str_clean_spaces_tabs(before_change%A_Index%t)
}
return
^!r::Reload ; Assign Ctrl-Alt-R as a hotkey to restart the script
; Pressing Win+X once will suspend hot keys of the script. Pressing it again will unsuspend.
#x::
Suspend ; suspend/unsuspend AHK script IMPORTANT: must be first string after "#a::", so "#a::" will not be suspended
if (A_IsSuspended==0)
{
Gui, Destroy
Gui, font, s55 cGreen, Verdana ; font size
Gui, Color, Red
Gui +LastFound ; Make the GUI window the last found window for use by the line below.
WinSet, TransColor, Red
Gui -Caption
Gui, Add, Text,, ON
Gui, Show
Sleep, 500
Gui, Destroy
return
}
else
{
Gui, Destroy
Gui, font, s55 cRed, Verdana ; font size
Gui, Color, Green
Gui +LastFound ; Make the GUI window the last found window for use by the line below.
WinSet, TransColor, Green
Gui -Caption
Gui, Add, Text,, OFF
Gui, Show
Sleep, 500
Gui, Destroy
return
}
; ------------- Посчитаем количество нажатий различных комбинаций клавиш по логам
; логи хранятся A_ScriptDir\Key Catcher\log.txt
^F2:: ; При каждом нажатии Ctrl+F2 комбинации (другими словами, переоткрытии окна) будет пересчитываться статистика
DateTime_Trigger = 0 ; Ловим начало снятия лога во времени 0-еще не нашли, 1-уже нашли
HotKeys_Count = 0 ; Число элементов массива "Сочетания клавиш"
HotKeysStats_Count = 0 ; Число элементов массива "Число нажатий клавиш"
Loop, Read, %log_path%
{
temp := A_LoopReadLine
; Исключим из логов позиции курсора мыши и прокрутку
StringGetPos, position_number, temp,click,r1 ; курсор
temp_ErrorLevel:=ErrorLevel
StringGetPos, position_number, temp,scroll,r1 ; прокрутка (колесико мыши)
if(ErrorLevel==1&&temp_ErrorLevel==1)
{
if (DateTime_Trigger==0) ; Время начала периода сбора логов - datetime_start
{
; Пример вида строки лога: "temp = 31/01/2014 11:55:22 - {Win + 2}"
StringLeft, datetime_start, temp, 19 ; Берем 19 символов слева из строки (это дата и время нажатия клавиши)
DateTime_Trigger=1
}
;Log_Count+=1
datetime_end:=temp ; сохраним возможное время окончания сбора логов (после цикла почистим его и преобразуем)
StringGetPos, position_number, temp,{,r1 ; найдем "{", чтобы отрезать левую часть строки (секция с временем нажатия)
StringTrimLeft, temp, temp, position_number+1 ; вырежем время нажатия клавиши
StringTrimRight, temp, temp, 1 ; удаляем "}" в конце строки
; Заполняем массив всех возможных сочетаний клавиш, но без повторов
if (HotKeys_Count>0)
{
i=1
While (i<=HotKeys_Count)&&(HotKeys%i%!=temp) ; Если такое сочетание клавиш уже было, то i<=HotKeys_Count, нет, то >
i+=1
if (i>HotKeys_Count)
{
HotKeys_Count+=1
HotKeys%HotKeys_Count% := temp
HotKeysStats_Count+=1
HotKeysStats%HotKeysStats_Count% = 1 ; Одно вхождение
}
else
{
HotKeysStats%i% += 1 ; Нашли еще одно вхождение в логе уже найденного сочетания клавиш из массива HotKeys
}
}
else ; На случай первого элемента массива
{
HotKeys_Count+=1
HotKeys%HotKeys_Count% := temp
HotKeysStats_Count+=1
HotKeysStats%HotKeysStats_Count% = 1 ; Одно вхождение
}
}
}
; Пример вида строки лога: "temp = 31/01/2014 11:55:22 - {Win + 2}"
StringLeft, datetime_end, datetime_end, 19 ; Берем 19 символов слева из строки (это дата и время нажатия клавиши)
; Теперь в datetime_start, datetime_end хранится период снятия лога
temp:= % datetime_start " - " datetime_end
GuiControl,2:, vDateTime,%temp% ; Отобразим в окне период снятия логов
Gui, 2:Show, w700 h700, AutoHotKey - Key Pressed Statistics ; Элементы окна подготовлены в начале скрипта
return
; Смотрим результаты вычисления статистики нажатия клавиш
HotKey_display:
Gui, 2:Submit, NoHide
LV_Delete() ; Почистим предыдущий список клавиш
Loop %HotKeys_Count%
{
temp := HotKeys%A_Index% ; Горячая клавиша
temp2 := HotKeysStats%A_Index% ; Сколько раз ее нажали (за период ведения лога)
temp_err2=1 ; В окне статистики есть 2 поля vKey, они позволяют сузить круг поиска клавиш
if (vKey2!="") ; Если второе поле не пустое
{
StringGetPos, position_number, temp,% vKey2,r1 ; Проверим есть ли данное поле в названии сочетания клавиши
temp_err2:= ErrorLevel
}
StringGetPos, position_number, temp,% vKey1,r1 ; есть ли первое поле
if (temp2>vMin && (ErrorLevel==0 || temp_err2==0))
LV_Add("",temp,temp2) ; Заполняем построчно список клавиш
}
LV_ModifyCol() ; Auto-size each column to fit its contents.
LV_ModifyCol(2, "Integer") ; For sorting purposes, indicate that column 2 is an integer.
Gui, 2:Show, w700 h700, AutoHotKey - Key Pressed Statistics
return
; -------------
; ## Help page
; display current hot keys help
^F1::
MsgBox, 0, Help page (Hot Keys & Timers),
(
Ctrl + F1 - This help
Ctrl + F4 - Experimental Functionality Help
Ctrl-Alt-R - Reload this AHK script
Win + X - Pause/Unpause hot keys
_______________________
Ctrl + F2 - Hot Keys Log Statistics
Ctrl + F7 - Quick Panel Settings
_______________________
Timers:
Check RAM load (warning trigger >90`%) - every 5 minutes
Script location: %A_ScriptFullPath%
Created by Li, 22.05.2014, modified 5.08.2014
), 3600
return
; #Include %A_ScriptDir%\ahk_library.ahk ; Подключаем библиотеку с описанием функций для Quick Panel (tag_modify(), IfPathIsBad())
; Добавление/удаление/изменение тегов в секциях, получение данных о тегах (Универсальная функция)
tag_modify(tag_action, section_name, tag_name, ByRef tag_id=0, tag_hash=0, ByRef tag_data="TEST")
; добавление/удаление нового тега в заданную секцию, tag_name также определяет структуру тела самого тега
{ ; По tag_name также автоматически может быть выбрано и имя секции (определенные теги, могут быть только в определенных секциях)
global marker ; берем глобальное значение marker
global ahk_parsing_file ; Какой файл будем парсить
global ahk_script_settings ; Путь к файлу настроек скрипта (quickpanel.ini)
return_value=0
; MsgBox, DEBUG ; debug
if (tag_action=="add"||tag_action=="delete"||tag_action=="get")
{
if !FileExist(ahk_parsing_file)
{
MsgBox % "Нет файла для парсинга " ahk_parsing_file " Error code = 1"
return -1
}
if (section_name==tag_name)
{
MsgBox % "Имя тега не может совпадать с именем секции section_name = " section_name " tag_name = " tag_name " Error Code = 5"
return -5
}
; Часть текста AHK скрипта до секции будет в массиве FirstPart%FirstPart_Count%
; Заголовок секции будет в строке Section_head
; Тело секции из файла AHK скрипта в массив Section_body%Section_Count%, чтобы потом изменить
; Часть текста AHK скрипта после секции будет в массиве ThirdPart%ThirdPart_Count%
Search_Count=0
section_found=0 ; 0 - секцию не нашли, 1 - секция найдена
section_close_tag_found=0 ; 0 - закрывающий тег не нашли, 1 - закрывающий тег найден
Section_head="" ; Первая строка секции <section_name ...
section_open_tag:=% ";<" section_name " marker=""" marker """ " ; Открывающий тег
section_close_tag:=% ";</" section_name ">" ; Так выглядит закрывающий тег
Section_Count=0 ; Количество строк в секции
ThirdPart_Count=0
test_ahk:="" ; в эту переменную наберем все то, что мы хотим записать в файл (64 Мб макс размер ее, но можно увеличить, но можно увеличить с помощью #MaxMem Megabytes (от 1 до 4095 Мб))
Loop, Read, %ahk_parsing_file% ; test.ahk
{
; Ищем вхождение marker в файл AHK скрипта и проверяем, если в той же строке имя тега
if(section_found==0)
{
Search_Count+=1
position_section_name=0
position_section_name:=InStr(A_LoopReadLine,section_open_tag)
if(position_section_name>0) ; Нашли заголовок секции
{
Section_head:=A_LoopReadLine ; Сохраним строку начала секции <section_name ...
section_found=1
}
else ; Запомним очередную строчку перед началом секции
test_ahk .= A_LoopReadLine "`n"
}
else
{
; И так Search_Count - номер строки в файле, где есть marker и tag_name
; position_marker - номер символа (начиная с 1), где находится значение marker в этой строке
; position_tag_name - номер символа (начиная с 1), где находится tag_name в этой строке
; Проверим действительно ли это секция
; Запомним все строки до закрывающего тега </tag_name>
if(section_close_tag_found==0)
{
if(A_LoopReadLine==section_close_tag)
{
section_close_tag_found=1
}
else
{
Section_Count+=1
Section_body%Section_Count%:=A_LoopReadLine
}
}
else
{ ; Запомним очередную строчку за закрывающим тегом
ThirdPart_Count+=1
ThirdPart%ThirdPart_Count%:=A_LoopReadLine
}
}
}
;MsgBox % "Search_Count= " Search_Count ", position_marker= " position_marker ", marker= " marker ; debug
if (position_marker==0)
{
MsgBox % "Не могу найти marker = " marker " Error Code = 2"
return -2
}
if (position_section_name==0)
{
MsgBox % "Не могу найти section_name = " section_name " Error Code = 3"
return -3
}
if (section_close_tag_found==0)
{
MsgBox % "Не могу найти закрывающий тег для section_name = " section_name " Error Code = 4"
return -4
}
; Теперь имеем:
; Section_head - заголовок секции <section_name ...
; Section_body%Section_Count% - массив строк тела секции, закрывающий тег нам не нужен
; Заглушка - Проверка целостности секции (на будущее реализовать проверку)
; Секция проверена, hash совпадают, теперь нам надо вставить в нее еще один тег
; #### Работа с секцией
ahk_script_changes=0 ; Не нужно делать изменения в файле AHK скрипта
tag_open_position=0
tag_close_position=0
; Вытащим значение id_count из головы секции
str_temp:=" id_count="""
StringGetPos, position, Section_head,%str_temp%,l1
If (ErrorLevel==0)
{
temp:=position+11 ; Позиция и длина самой записи [ id_count="]
StringTrimLeft, str_temp, Section_head,%temp%
}
else
{
MsgBox, % "Не могу найти id_count в Section_head = " Section_head " Error Code = 12"
return -12
}
StringGetPos, position, str_temp,",l1
If (ErrorLevel==0)
StringLeft, id_count, str_temp,%position%
else
{
MsgBox, % "Не могу найти символ "" в модифицированном Section_head = " Section_head " Error Code = 13"
return -13
}
; Вытащим значение id_next из головы секции
str_temp:=" id_next="""
StringGetPos, position, Section_head,%str_temp%,l1
If (ErrorLevel==0)
{
temp:=position+10 ; Позиция и длина самой записи [ id_next="]
StringTrimLeft, str_temp, Section_head,%temp%
}
else
{
MsgBox, % "Не могу найти id_next в Section_head = " Section_head " Error Code = 14"
return -14
}
StringGetPos, position, str_temp,",l1
If (ErrorLevel==0)
StringLeft, id_next, str_temp,%position%
else
{
MsgBox, % "Не могу найти символ "" в модифицированном Section_head = " Section_head " Error Code = 15"
return -15
}
; ### Здесь описаны действия с тегами
If IsLabel("Case-" . tag_action) ; Создаем аналог оператора CASE
Loop 1
{
Goto Case-%tag_action%
Case-add: ; Добавление тега в секцию
If IsLabel("Case-add-" . tag_name) ; Создаем вложенный CASE для tag_action="add"
Loop 1
{
Goto Case-add-%tag_name%
Case-add-TEST_TAG:
; TEST
; Добавляем данные в заголовок секции
;<current_settings marker="TEST" id_count="0" id_next="1" hash="0">
id_count+=1 ; Число тегов увеличиться на 1
id_next++
hash:="0"
Section_head:=% ";<" section_name " marker=""" marker """ id_count=""" id_count """ id_next=""" id_next """ hash=""" hash """>"
; Добавляем тег в тело секции
Section_Count+=1
tag_id:=id_next-1
template_name:="None"
tag_hash:="0"
Section_body%Section_Count%:=% ";<" tag_name " id=""" tag_id """ template=""" template_name """ hash=""" tag_hash """>"
Section_Count+=1
Section_body%Section_Count%:=% "tag_data_test:=""" tag_data """"
Section_Count+=1
Section_body%Section_Count%:=% ";</" tag_name ">"
ahk_script_changes=1
break
Case-add-template: ; Добавление тега согласно шаблону
; Данные представлены в следующем виде tag_data="file_template_name|number_of_values|value1|value2|value3|value4"
; Для примера Используется шаблон C:\i_files\i_scripts\templates\quickpanelsample.txt
; Тег "quickpanelsample" содержит следующие значения: Имя файла шаблона|Число параметров|Описание|Горячая клавиша|Заголовок окна|Полный путь к программе
; Вытащим имя файла шаблона (ex. quickpanelsample.txt)
StringGetPos, position, tag_data,|,l1
If (ErrorLevel==0)
StringLeft, file_template_name, tag_data, position
else
{
MsgBox, % "Не могу извлечь имя файла шаблона из tag_data = " tag_data " Error Code = 9"
return -9
}
; Вытащим число параметров для данного template
StringGetPos, position_2, tag_data,|,l2
If (ErrorLevel==0)
StringMid, valueN_array_Count, tag_data, position+2, position_2-position-1
else
{
MsgBox, % "Не могу извлечь число параметров шаблона из tag_data = " tag_data " Error Code = 10"
return -10
}
; Сформируем массив значений для шаблона (valueN_array), далее $%!value1!%$ будет соответствовать valueN_array1
position_2:=StrLen(tag_data)
Loop, %valueN_array_Count%
{
StringGetPos, position, tag_data,|,r%A_Index% ; Значения value ищем с конца строки tag_data
If (ErrorLevel==0)
{
StringMid, str_temp, tag_data, position+2, position_2-position-1
temp_index:=valueN_array_Count-A_Index+1
; MsgBox, temp_index = %temp_index% +++ str_temp = %str_temp% ; debug
valueN_array%temp_index%:=str_temp
position_2:=position
}
else
{
MsgBox, % "Не могу извлечь " A_Index " параметр из tag_data = " tag_data " Error Code = 11"
return -11
}
}
; Считаем шаблон в память
FileRead, template_in_memory, *m1024 %A_ScriptDir%\templates\%file_template_name%
IF(ErrorLevel)
{
MsgBox, % "Не могу загрузить шаблон " A_ScriptDir "\templates\" file_template_name " Error Code = 19"
return -19
}
; Заменим значения в шаблоне на значения из массива valueN_array
Loop, %valueN_array_Count%
{
valueN=$`%!value%A_Index%!`%$
valueN_paste:=valueN_array%A_Index%
StringReplace, template_in_memory, template_in_memory, %valueN%, %valueN_paste%, All
}
; Теперь код согласно шаблону file_template_name сформирован
; Добавляем тег в тело секции
; MsgBox % template_in_memory
id_count+=1 ; Число тегов увеличиться на 1
hash:="0"
If(tag_id=="NEW") ; если новый тег добавляется, то формируем его ID, если восстанавливаем, то берем старый ID из tag_id
{
id_next++
tag_id:=id_next-1
}
Section_head:=% ";<" section_name " marker=""" marker """ id_count=""" id_count """ id_next=""" id_next """ hash=""" hash """>"
template_name:=file_template_name ; Используемый шаблон
tag_hash:="0"
Section_Count++
Section_body%Section_Count%:=% ";<" tag_name " id=""" tag_id """ template=""" template_name """ hash=""" tag_hash """>"
Section_Count++
Section_body%Section_Count%:=template_in_memory ; тело тега
Section_Count++
Section_body%Section_Count%:=% ";</" tag_name ">"
ahk_script_changes=1 ; Триггер на внесение изменений в файл
template_in_memory= ; Освободим память
break
} else {
MsgBox % "Не умею добавлять такой тег tag_name = " tag_name " Error Code = 6"
return -6
}
break
Case-delete: ; Удаление тега tag_name с tag_id из секции
;MsgBox Зашли в удаление; debug
id_count-=1 ; Число тегов уменьшится на 1
hash:="0"
Section_head:=% ";<" section_name " marker=""" marker """ id_count=""" id_count """ id_next=""" id_next """ hash=""" hash """>"
; Ищем тег для удаления
tag_open_tag:=% ";<" tag_name " id=""" tag_id """ " ; Открывающий тег
tag_close_tag:=% ";</" tag_name ">"
tag_found=0
tag_open_position=0
tag_close_position=0
Loop %Section_Count%
{
if (tag_found==0)
{
tag_found:=InStr( Section_body%A_Index% ,tag_open_tag)
if(tag_found>0) ; Нашли заголовок секции
{
Tag_head:= Section_body%A_Index% ; Сохраним строку начала тега <tag_name ...
tag_open_position = %A_Index%
}
}
else
if (Section_body%A_Index%==tag_close_tag)
{
tag_close_position = %A_Index%
break
}
}
if(tag_open_position>0&&tag_close_position>0)
{
ahk_script_changes=1
;MsgBox % "tag_open_position = " tag_open_position "tag_close_position = " tag_close_position "Section_Count = " Section_Count ; debug
}
else
{
MsgBox % "Не нашел открывающий и закрывающий тег для tag_name = " tag_name " Error Code = 8"
return -8
}
break
Case-get: ; Извлечение данных из уже сгенерированных тегов
If IsLabel("Case-get-" . tag_name) ; Создаем вложенный CASE для tag_action="get"
Loop 1
{
Goto Case-get-%tag_name%
Case-get-template:
; Извлечение запросов на авгенерируемые теги из quickpanel.ini (Переменная ahk_script_settings)
; Содержание секции без открывающего и закрывающего тега находится в массиве Section_body%Section_Count%
; В tag_data подразумевается, что находится число строк с параметрами тега. Тег-запрос выглядит следующим образом:
;<template id="2" template="quickpanelsettings.txt" hash="0">
; section=hot_keys
; tag_id=1
; tag_data
; - App1
; ^F11
; - App1
; - App1
; "C:\Program Files (x86)\Notepad++\functionList.xml"
;</template>
; Итого имеем: 5 строк с параметрами и 5 строк структуры (открывающий и закрывающий теги - 2 строки и 3 строки данные
; о местонахождении добавленного тега). Число строк с параметрами отличается в зависимости от типа тегов
; Замечание: В каждой секции могут быть только однотипные теги-запросы (мб в будущем реализую для разных типов)
; Данное замечание не относится к тегам (только к тегам-запросам)
; Проверим совпадает ли общее число тегов в секции (id_count) с фактическим числом строк в секции (всего теги содержат
; одинаковое количество строк
tag_length_params:=tag_data
tag_length:=5+tag_length_params
If(id_count*tag_length!=Section_Count)
{
MsgBox % "Реальное число тегов в секции не соответствует общему числу тегов в секции id_count = " id_count " Error Code = 17"
return -17
}
return_value:= id_count ; возвращаем общее число тегов-запросов
tag_data:="" ; В tag_data будут возвращаться параметры запросов добавленных тегов
tag_id:="" ; В tag_id будет возвращен список id тегов-запросов
Loop, %id_count%
{
; Берем id тега-запроса между первой и второй кавычкой (в дальнейшем переписать, чтобы брать точно из id="23" )
i:=1+(A_Index-1)*tag_length
str_temp:=Section_body%i%
StringGetPos, position_2, str_temp,`",L1
StringGetPos, position_3, str_temp,`",L2
StringMid, str_temp, str_temp, position_2+2, position_3-position_2-1
tag_id .= str_temp "|"
i:=2+(A_Index-1)*tag_length
str_temp:=Section_body%i%
StringTrimLeft, str_temp, str_temp, 10 ; Убираем начало строки "; section="
tag_data .= str_temp "|"
i:=3+(A_Index-1)*tag_length
str_temp:=Section_body%i%
StringTrimLeft, str_temp, str_temp, 9 ; Убираем начало строки "; tag_id="
tag_data .= str_temp "|"
B_Index:=A_Index
Loop, %tag_length_params%
{
i:=5+A_Index-1+(B_Index-1)*tag_length
str_temp:=Section_body%i%
StringTrimLeft, str_temp, str_temp, 2 ; Убираем начало строки "; "
tag_data .= str_temp "|"
}
}
; Теперь в tag_data один за другим находятся запросы на добавленные теги
; MsgBox, DEBUG get template Имеем tag_data = %tag_data% ; debug
break
Case-get-status:
return_value:= id_count ; возвращаем общее число сгенерированных тегов (Для проверки на пустоту секции)
If(ahk_parsing_file==ahk_script_settings) ; Парсим файл настроек скрипта
{ ; в tag_id будет возвращен список id тегов для восстановления
tag_length_params:=tag_data
tag_length:=5+tag_length_params
If(id_count*tag_length!=Section_Count)
{
MsgBox % "Реальное число тегов в секции не соответствует общему числу тегов в секции id_count = " id_count " Error Code = 17"
return -17
}
tag_id:="" ; В tag_id будет возвращен список id тегов (для случая восстановления, нужны id тегов)
Loop, %id_count%
{
i:=3+(A_Index-1)*tag_length
str_temp:=Section_body%i%
StringTrimLeft, str_temp, str_temp, 9 ; Убираем начало строки "; tag_id="
tag_id .= str_temp "|"
}
}
break
} else {
MsgBox % "Не умею извлекать данные для такого тега tag_name = " tag_name " Error Code = 16"
return -16
}
break
} else {
MsgBox % "Не умею делать действие tag_action = " tag_action " Error Code = 7"
return -7
}
; #### Конец работы с секцией
; Теперь нам нужно рассчитать новый hash для секции и добавить его в строку Section_head
; Заглушка - Проверка целостности секции (на будущее реализовать проверку)
; Часть текста AHK скрипта до секции будет в массиве FirstPart%FirstPart_Count%
; Заголовок секции будет в строке Section_head
; Тело секции из файла AHK скрипта в массив Section_body%Section_Count%, чтобы потом изменить
; Часть текста AHK скрипта после секции будет в массиве ThirdPart%ThirdPart_Count%
;time=%a_dd%/%a_mm%/%a_yyyy% %a_hour%:%a_min%:%a_sec%
;MsgBox Пишем в файл ; debug
; #### Запишем проведеные изменения в файл
if (ahk_script_changes>0)
{ ; Текст до начала секции уже находится в test_ahk
test_ahk .= Section_head "`n" ; заголовок секции
Loop %Section_Count% ; тело секции
{
if (A_Index < tag_open_position || tag_close_position < A_Index) ; Для операции удаления тега из секции
{ ; Просто не пишем в файл те части секции, которые нужно удалить
temp_string:= Section_body%A_Index%
test_ahk .= temp_string "`n"
}
}
temp_string:=% ";</" section_name ">" ; добавим закрывающий тег секции
test_ahk .= temp_string "`n"
Loop %ThirdPart_Count% ; текст после секции
{
temp_string:= ThirdPart%A_Index%
test_ahk .= temp_string "`n"
}
; Проверка, чтобы не было временного файла с нужным нам именем
IfExist, %A_ScriptDir%\temp.ahk
FileDelete, %A_ScriptDir%\temp.ahk
; Записываем все изменения
; Запись идет в файл именно одной переменной, так как каждую строчку массива сохранять в файл занимает гораздо дольше по времени
fileappend, %test_ahk%, %A_ScriptDir%\temp.ahk
If(ErrorLevel!=0)
MsgBox Error fileappend
filemove, %A_ScriptDir%\temp.ahk, %ahk_parsing_file%, 1
If(ErrorLevel!=0)
MsgBox % "Error filemove() ahk_parsing_file = " ahk_parsing_file
; emptymem()
test_ahk= ; Очистка памяти
; MsgBox Файл Готов ; debug
}
; #### Файл записан
return %return_value%
}
else
{
MsgBox % "Не умею выполнять такое действие tag_action = " tag_action " Error Code = 18"
return -18
}
}
; Запись сгенерированных тегов в файл скрипта (quickpanel.ahk) и тегов-запросов в файл настроек скрипта (quickpanel.ini)
ahk_generate(ahk_generate_trigger=0, QuickPanel_Changes="0|0|0|0|0|0|0|0|0|0|0|0|", Recovery_bit=0, tag_id_list="0|0|0|0|0|0|0|0|0|0|0|0|")
{
global
; Проверка на открытие файла скрипта (Путь к файлу скрипта в A_ScriptFullPath) - quickpanel.ahk
quickpanelahkscript:= FileOpen(A_ScriptFullPath,"rw") ; open AHK script file
if !IsObject(quickpanelahkscript)
{
MsgBox Can't open AHK script "%A_ScriptFullPath%".
return
}
quickpanelahkscript.Close() ; Close AHK script file
; Проверка на открытие файла настроек скрипта (Путь к файлу настроек в ahk_script_settings) - quickpanel.ini
quickpanelahkscript:= FileOpen(ahk_script_settings,"rw") ; open AHK script file
if !IsObject(quickpanelahkscript)
{
MsgBox Can't open settings for AHK script "%ahk_script_settings%".
return
}
quickpanelahkscript.Close() ; Close AHK script file
; Примеры tag_modify()
; tag_modify("add", "TEST", "TEST_TAG", , , "TEST TEST TEST")
; tag_modify("delete", "TEST", "TEST_TAG",1,0,0)
; tag_modify("add", "TEST", "template", , , "quickpanelsample.txt|5|TEST|^6|- Opera|- Opera|""c:\Opera.exe""")
; tag_modify("delete", "TEST", "template",6,0,0)
; Связность:
; Клавиша/HotKey - value2 - fileplaceapp%A_Index%fk
; Путь к программе/Path - value5 - fileplaceapp%A_Index%v
; Заголовок окна/Windows Title - value3,value4,value1 - fileplaceapp%A_Index%t
; !!! Каждый сгенерированный тег дублируется соответствующей записью о нем в файле настроек скрипта quickpanel.ini
; (Путь к файлу в ahk_script_settings) !!!
Loop, %quickpanel_max_lines%
{
position:=(A_Index-1)*2+1
StringMid, QuickPanel_Changes%A_Index%, QuickPanel_Changes, position, 1
}
; MsgBox, % "ahk_generate_trigger = " ahk_generate_trigger " QuickPanel_Changes1 = " QuickPanel_Changes1 " QuickPanel_Changes2 = " QuickPanel_Changes2 " quickpanel_max_lines = " quickpanel_max_lines ; debug
If(ahk_generate_trigger==1)
{
Loop, %quickpanel_max_lines% ; максимум можно 12 горячих клавиш назначить
{
If(QuickPanel_Changes%A_Index%==1) ; Если в данной строке есть изменения, то тег и тег-запрос выше были удалены, либо
{ ; их не было изначально, то есть нам нужно добавить тег и тег-запрос
GuiControlGet, str_path, 3:,fileplaceapp%A_Index%v ; Путь к программе
str_clean_spaces_tabs(str_path) ; Удалим знаки табуляции везде и пробелы в конце/начале строки
If(!IfPathIsBad(str_path, error_code, error_description))
{ ; Путь действителен, добавим тег по шаблону quickpanelsample.txt
str_path="%str_path%"
GuiControlGet, str_windowtitle, 3:,fileplaceapp%A_Index%t ; Window Title
str_description:=str_windowtitle ; На данный момент описание берется из Windows Title
GuiControlGet, str_hotkey, 3:,fileplaceapp%A_Index%fk
tag_data_right:=str_description "|" str_hotkey "|" str_windowtitle "|" str_windowtitle "|" str_path
tag_data:="quickpanelsample.txt|5|" tag_data_right
If(Recovery_bit=="0")
tag_id:="NEW"
else
{
; Восстановление: здесь в tag_id мы должны получить id тега для его восстановления, список id нам передан в tag_id_list
StringGetPos, position_id, tag_id_list,|,L%A_Index%
temp:=A_Index-1
StringGetPos, position_id_previous, tag_id_list,|,L%temp%
If(ErrorLevel==1)
position_id_previous=-1
StringMid, tag_id, tag_id_list, position_id_previous+2, position_id-position_id_previous-1
; MsgBox % "tag_id = " tag_id
}
If(tag_modify("add", "hot_keys", "template", tag_id, , tag_data)<0)
{
MsgBox, Ошибка при добавлении тега tag_data = %tag_data%
continue ; Пробуем следующую строчку из 12
}
; MsgBox, tag_id = %tag_id% tag_data = %tag_data% ; debug
If(Recovery_bit=="0") ; При восстановлении тегов в секции, не нужно добавлять ничего в файл настроек скрипта, так как восстановление
{ ; идет из этого файла
; Запишем запрос на добавление тега в настройки quickpanel.ini (ahk_script_settings) по тому же принципу автогенерируемых секций
; Запрос будет в виде строки str_tag = [секция|tag_id|tag_data]
ahk_parsing_file:=ahk_script_settings
; Запись запросов на автогенерируемые теги в quickpanel.ini (ahk_script_settings)
tag_data:="quickpanelsettings.txt|7|hot_keys|" tag_id "|" tag_data_right
; MsgBox, XXX tag_data = %tag_data% ; debug
If(tag_modify("add", "quickpanel_settings", "template", "NEW", , tag_data)<0)
{
MsgBox, Ошибка при добавлении тега tag_data = %tag_data% в файл %ahk_script_settings%. Попробуем откатить изменения...
ahk_parsing_file:=A_ScriptFullPath ; вернем на место
If(tag_modify("delete", "hot_keys", "template", tag_id,0,0)<0) ; Придется удалить только что добавленный тег, так как настройки
{ ; для него не сохранились в файле quickpanel.ini (ahk_script_settings)
MsgBox, Critical Error! Не удалось удалить только что сгенерированный тег. Обратитесь к разработчику tag_id = %tag_id% section = hot_keys
}
}
ahk_parsing_file:=A_ScriptFullPath ; вернем на место
}
}
}
}
} ; if
}
; Проверка на пустоту, ошибки в строке пути к файлу/папке
; >=2 error codes
IfPathIsBad(str_temp, ByRef error_code, ByRef error_description)
{
error_code=0
error_description:=""
if(str_temp=="")
return true
StringGetPos, position, str_temp,<,L
if(ErrorLevel!=1) ; Нашли символ "<", тобиш вместо пути к файлу имеем тег
{
error_code=2
error_description:="Не найден путь к файлу. Нужно сделать так: строка с тегом <tag_name>, ниже строка с путем к файлу/папке, закрывающий тег не нужен"
return true
}
return false ; true
}
Суть функциональности скрипта заключается в встраивании в свой код (секция hot_keys) кусков кода согласно шаблону:
; $%!value1!%$ ; Description
$%!value2!%$:: ; HotKey
IfWinExist, $%!value3!%$ ; Window Title
{
IfWinActive, $%!value4!%$ ; Window Title
WinMinimize
else
WinActivate
return
}
else
Run $%!value5!%$ ; Program path
returnСкрипт модифицирует свой код и перегружается, чтобы изменения вступили в силу. Пока готов только один шаблон (quickpanel функциональность), но можно использовать произвольный шаблон (в коде используется понятие тег и тег-запрос, сам тег - шаблон, с уже подставленными значениями переменных, тег-запрос - шаблон, с подставленными переменными, но для файла настроек скрипта "имя скрипта.ini", служит для удобного считывания данных о тегах и на случай восстановления при обновлении/затирании самого скрипта), подготовленный следующим образом:
1. Шаблон разместить в папке templates\Имя шаблона.txt
2. То, что нужно заменить в шаблоне, обозначить в виде переменных $%!valueNN!%$, где NN номер переменной.
3. Создать если нужно новую секцию по аналогии с секцией hot_keys, либо размещать в самой hot_keys. Предусмотреть дублирование данных и создать новую секцию в файле настроек скрипта "имя скрипта.ini"
4. С помощью функций ahk_generate(), tag_modify() организовать редактирование скрипта. Примеры использования функций есть в коде скрипта.
5. Создать, если нужно, графическое окошко, для работы с переменными шаблона, смотреть ^F7, метку generateahk для примера.
Удобные сочетания: #`,#q,#w,#s,^`,^1,^-,^=,#a,#x (Свободны, по крайней мере в Windows 7)
Распаковать в любую папку, например C:\AHK.
Для автоматического запуска в Планировщике Задач настроить запуск двух скриптов:
C:\AHK\Autohotkey.exe C:\AHK\greyforum_quickpanel.ahk
C:\AHK\Key Catcher\Key Catcher 1.00.3b modified.exe
Триггер: при разблокировке ПК, при входе такого-то пользователя
Не запускать, если уже запущен.
В архиве находится скрипт, шаблоны к нему, скрипт логирования, AHK Unicode 32 bit 1.1.15.0.
Совместим с версией AHK Unicode 32 bit 1.1.15.0 (С другими не тестировался)
Поддерживается в ОС: WinXP 32bit, WinVista 64 (сочетания ^!r, #x не работают, нужно их заменить), Win7 32bit&64bit
Скрипт логирования слегка переделан из Key Catcher автор Daniel Green Copyright 2010-2011
Отдельное спасибо Malcev за функцию FileRead(), что позволило мне оптимизировать код и слегка расширить функциональность шаблона.

