Начальные сведения описаны в моем блоге Система внутренних команд на основе published методов и Система внутренних команд - THotkeyManager
А здесь собственно обсуждение и некоторая информация по использованию.
Преимущества (похвастаюсь ):
- Кроссплатформенность: никаких завязок на систему, все на основе LCL.
- Обьектность: Хоткеи подвязываются для конкретных обьектов форм или на сами формы. При этом можно назначать одинаковые хоткеи для разных обьектов на одной форме. По хоткею будет вызвана команда, ассоциированная с обьектом в фокусе, или команда ассоциированная с формой (если этот хоткей не обработан фокусированым обьектом).
- Параметры. Возможно назначение на хоткей команды с параметром.
- Возможность назначить несколько хоткеев на одну команду. Удобно, например, для привязки Del и F8 для команды cm_Delete.
Все команды из ActionList-а перенесенны в класс TActs. Экшены были оставленны для совместимости и удобства назначения команд менюшкам и кнопкам. Для всех экшенов из листа actionList главной формы, назначен один и тот же обработчик вида:
- Код: Выделить всё
procedure TfrmMain.actExecute(Sender: TObject);
var cmd:string;
begin
cmd:=(Sender as TAction).Name;
cmd:='cm_'+copy(cmd,4,length(cmd)-3);
Actions.Execute(cmd);
end;
Actions - переменная типа TActs обьявленная в uGlobs.
Вызов команд возможен по имени:
- Код: Выделить всё
Actions.Execute(cmd)
- Код: Выделить всё
Actions.Execute(cmd,param)
или прямым вызовом:
- Код: Выделить всё
Actions.cm_DirHotList;//без параметра
- Код: Выделить всё
Actions.cm_DirHotList('some param');//с параметром
Категории команд в TActs:
- Код: Выделить всё
function GetCategoriesList(var List:TStrings):integer;
function GetCommandsByCategory(Category:string; var List:TStrings):integer;
Категории получаем обрабатывая имя метода.
Стандартный вид команды-метода:
- Код: Выделить всё
procedure cm_SomeFunction (param:string; var Result:integer);
procedure cm_SomeProcedure(param:string);
procedure cm_Category1_SomeProcedure(param:string);
procedure cm_Category2_SomeProcedure(param:string);
Методы без указания категории (например cm_SomeProcedure) считаются входящими в категорию Main
Эти категории отображаются в настройках на форме опций и позволяют назначать хоткеи для нужных контролов ориентируясь на название категории.
Хоткей-система представленна классом THotKeyManager (переменная HotMan в модуле uGlobs).
Два основных элемента - это списки
- Код: Выделить всё
FHotList:TStringList;
FFormsList:TStringList;
FFormsList - содержит список имен форм и класс TObjInfoClass в обьекте, для каждой формы.
- Код: Выделить всё
TObjInfoClass=class
AKeyDownProc :TKeyEvent;
AObject :TWinControl;
AChilds:TStringList; //list of form's registered controls. For controls this is nil.
destructor Destroy; override;
end;
FHotList - трех-уровневая структура списков вида:
хоткеи ->Список форм ->Список контролов -> THotkeyInfoClass
Например:
-----------------------
- Код: Выделить всё
FHotList:
| Хоткей1 -> Список форм
|Форма1 -> Список контролов ->
| Контрол1 -> THotkeyInfoClass
| Контрол2 -> THotkeyInfoClass
|Форма2 -> Список контролов ->
| Контрол1 -> THotkeyInfoClass
| Контрол2 -> THotkeyInfoClass
| Контрол3 -> THotkeyInfoClass
| Хоткей2 -> Список форм
|Форма3 -> Список контролов ->
| Контрол1 -> THotkeyInfoClass
| Контрол2 -> THotkeyInfoClass
| Контрол3 -> THotkeyInfoClass
| Контрол4-> THotkeyInfoClass
- Код: Выделить всё
THotkeyInfoClass=class
AShortCut,
ACommand,
AParams,
AObjectName,
AObjectFormName :string;
end;
Код обработки этого добра получился жутковатый, но оно того стоит.
Для регистрации менеджера хоткеев, в OnCreate формы нужно вызвать метод
- Код: Выделить всё
procedure RegisterHotkeyManager(AObject:TWinControl);
и соответственно в OnDestroy:
- Код: Выделить всё
procedure UnRegisterHotkeyManager(AObject: TWinControl);
Добавление хоткеев:
- Код: Выделить всё
function AddHotKey(AHotKey,ACommand,AParams:string; AObject:TWinControl):integer;
function AddHotKey(AHotKey,ACommand,AParams,AObjectName,AObjectFormName:string):integer;
Например в OnCreate формы:
- Код: Выделить всё
HotMan.AddHotkey('WinKey+A','cm_About',Self)
или
- Код: Выделить всё
HotMan.AddHotkey('WinKey+A','cm_About','frmMain','frmMain')
или
- Код: Выделить всё
HotMan.AddHotkey('WinKey+A','cm_About',edtCmdLine)
или
- Код: Выделить всё
HotMan.AddHotkey('WinKey+A','cm_About','edtCmdLine','frmMain')
Удаление хоткея - аналогично:
- Код: Выделить всё
function DeleteHotKey(AHotKey,AObjectName,AObjectFormName:string):boolean;
function DeleteHotKey(AHotKey:string; AObject:TWinControl):boolean;
Например:
- Код: Выделить всё
HotMan.DeleteHotkey('WinKey+A',Self)
Теперь о грустном - реализация интерфейса, для выборочной ассоциации хоткеев к контролам, практически нереальна. Только частично - заранее предусмотрев разделы, например, для раздела CmdLine, проводить привязку хоткеев к edtCmdLine, для раздела, Lister проводить привязку хоткеев к форме просмотрщика.
Полноценная выборочная привязка возможна ручной правкой конфига или из кода.