Создание приложений сродни приготовлению еды: требуются свежие ингредиенты (требования заказчика), качественное оборудование (среда разработки) и сноровка. Некоторые проекты можно подавать через пару часов, но есть такие, приготовление которых занимает недели, месяцы и даже годы.
Одна из сложностей, которая при этом возникает – потеря актуальной информации о коде или визуальных формах. И это становится проблемой, если количество форм переваливает за сотню. Конечно, при наличии хорошей проектной документации с этим легко справиться, однако на практике хотелось бы иметь инструмент, который бы помогал определять имя формы приложения прямо во время его выполнения. Для реализации такой функциональности пригодится система горячих клавиш.
Но для начала потребуется небольшая доработка: возможность выполнения произвольной процедуры. Напомню, что в текущей версии этой системы доступны два варианта: нажатие кнопки и выбор пункта меню.
Нужная функциональность должна быть добавлена в процедуру Hotkey_OnKeyDownST(). Чтобы это стало возможным, при анализе названия будем использовать соглашение о наименовании объектов. Первые три символа будут сообщать нам, какую категорию действий нужно выбрать.
const
T_BUTTON = 'btn'; // кнопка
T_MENU_ITEM = 'mni'; // элемент меню
procedure Hotkey_OnKeyDownST(Sender: TObject; var Key: Word; ShiftState: TShiftState);
// обработка горячих клавиш - по стандарту Delphi
var
tmpForm: TForm;
tmpButton: TdbButton;
tmpName: string;
tmpComponent: TComponent;
i: integer;
tmpLength:integer;
begin
tmpForm := TForm(Sender);
tmpName := '';
tmpLength := Length(HotKey_Code) - 1;
for i := 0 to tmpLength do
begin
// найдено совпадение
if (Key = HotKey_Code[i]) and (ShiftState = HotKey_ShiftState[i]) then
begin
tmpName := HotKey_Command[i];
case GetClassName(tmpName) of // в префиксе указания, что нужно нажать/выполнить
T_BUTTON: begin // ищем кнопку
FindC(tmpForm, tmpName, tmpComponent, False);
if tmpComponent <> nil then
begin
if tmpComponent is TdbButton then
begin
TdbButton(tmpComponent).Click;
Key := 0;
end
else if tmpComponent is TMenuItem then
begin
TMenuItem(tmpComponent).Click;
Key := 0;
end
end;
end;
T_MENU_ITEM: begin // ищем пункт меню
FindC(tmpForm, tmpName, tmpComponent, False);
if tmpComponent <> nil then
begin
if tmpComponent is TMenuItem then
TMenuItem(tmpComponent).Click
end;
end;
else begin // выполняем процедуру по имени
ExecProc(tmpName,tmpForm.Name);
end;
end; // case
break;
end;
end;
end;
Code language: Delphi (delphi)
В My Visual Datavase нельзя преобразовать строку в вызов процедуры, но можно присвоить обработчик события OnClick и нажать кнопку, вызвав метод Click. Главное условие – входные параметры процедуры должны соответствовать входным параметрам обработчика нажатия кнопки. А на случай, если понадобиться что-то передать в качестве параметра, используем свойство кнопки TagString в качестве камеры хранения.
procedure ExecProc( AProcName:string; AParamStr:string='' );
// выполнение процедуры
// AProcName - имя выполняемой процедуры
// AParamStr - строковый параметр, который можно передать в кнопку (процедуру)
var
tmpButton :TdbButton;
begin
try
FindC(MainForm,'btnExecProc',tmpButton, False);
if tmpButton = nil then
tmpButton := TdbButton.Create(MainForm);
tmpButton.Name := 'btnExecProc';
tmpButton.OnClick := AProcName; // имя выполняемой процедуры
tmpButton.TagString := AParamStr; // передаём параметр
tmpButton.Click; // BClick;
except
RaiseException('ExecProc('''+AProcName+''') - '+ExceptionMessage);
end;
end;
Code language: Delphi (delphi)
Техническая информация о форме будет пока будет включать название формы. Но в дальнейшем, зная название, можно получить больше информации о самой форме и компонентах, которые на ней находятся:
procedure FormSysInfo( sender:TObject; ACancel:boolean );
// системная информация об активной форме
var
tmpFormName: string;
tmpForm:TForm;
begin
tmpFormName := TdbButton(Sender).TagString;
ShowMessage( tmpFormName );
end;
Code language: JavaScript (javascript)
Небольшая доработка потребовалась и для процедуры Hotkey_Init(). Вместо фиксированного размера массивов теперь применяется динамическое увеличение их размера при добавлении каждой новой комбинации.
var
HotKey_Code: array of byte; // виртуальный код
HotKey_ShiftState: array of TShiftState; // флаги нажатия
HotKey_Command: array of string; // выполняемая команда: название кнопки, пункта меню или процедуры
procedure Hotkey_Init(Sender: TObject);
// подключение к форме
// Sender - форма, для которой подключается система горячих клавиш
var
i: integer;
//
procedure AddHotKey(ACode: byte; AShiftState: TShiftState; ACommend: string);
var
tmpLength:integer;
begin
inc(i);
// увеличить размер массивов
tmpLength := Length(HotKey_Code)+1;
SetLength(HotKey_Code, tmpLength);
SetLength(HotKey_ShiftState, tmpLength);
SetLength(HotKey_Command, tmpLength);
HotKey_Code[i] := ACode;
HotKey_ShiftState[i] := AShiftState;
HotKey_Command[i] := ACommend;
end;
begin
try
if not(Sender is TForm) then
begin
RaiseException('Hotkey_Init() - параметр не является формой');
exit;
end;
//
TForm(Sender).KeyPreview := True;
TForm(Sender).OnKeyDown := 'Hotkey_OnKeyDownSt';
//
// настройка горячих клавиш
AddHotKey(VK_F1, 0, 'btnHelp'); // показать помощь
AddHotKey(VK_F2, 0, 'btnNew'); // добавить запись
AddHotKey(VK_F4, 0, 'btnEdit'); // редактировать запись
AddHotKey(VK_F8, 0, 'btnDelete'); // удалить запись
AddHotKey(VK_F11, 0, 'mniAboutEx'); // показать окно "О программе"
AddHotKey(VK_F12, 0, 'FormSysInfo'); // системная информация о форме
except
RaiseException(ExceptionMessage);
end;
//
end;
Code language: Delphi (delphi)
Опосредованная инициализация горячих клавиш через инициализацию помощи – Help_Init()
procedure MainForm_OnShow(Sender: TObject; Action: string);
// отображение главной формы
var
tmpForm: TForm;
tmpStartTime: TTime;
tmpSleepTime: integer;
begin
//
tmpForm := Splash_Create;
tmpForm.Show;
Application.ProcessMessages;
tmpStartTime := Time();
//
// тут должна быть всяческая инициализация, которая может занять продолжительное время
App_InitSystemVar; // инициализация системных переменных
DTF_Init(frmMain.tgrStyle);
// после инициации системных переменных; нужно указать любую реальную таблицу, чтобы с неё тянуть цвета для стиля
Resource_Init();
Resource_CreateMenu(frmMain);
Images_Init; // инициализация подcистемы загрузки картинок
// unicode_Init;
Style_Init; // активация стиля
// Style_CreateMenu(frmMain); // добавить стили в меню
StyleView_AddToMenu(frmMain); // добавить в меню вызов менеджера стилей
UserApp_InitForm; // создать формы
UserApp_InitVar; // настроить переменные
// инициализация, которая идет после настройки переменных
// CE_Init(MainForm); // главное меню находится на главной форме, но отображается там, где нужно
Hotkey_Init(MainForm); // подключить горячие клавиши
Help_Init( APP_FORM_ALL, SPLASH_FORM_NAME ); // подключить горячие клавиши на все формы - включить систему помощи
UserApp_InitBase; // инициализация базы данных
//
// гарантированная задержка, но не более указанной в APP_SPLASH_DELAY
tmpSleepTime := SPLASH_DELAY_MIN - Trunc((Time() - tmpStartTime) * 24 * 60 * 60 * 1000);
if tmpSleepTime > 0 then
Sleep(tmpSleepTime);
tmpForm.Close;
tmpForm.Free;
//
// отобразить в заголовке главной формы название и версию программы
frmMain.Caption := R('APP_NAME', APP_NAME) + ' ' + License_GetVersion;
Form_RestorePosSize(frmMain);
Form_AddColWidthMenuAll();
end;
Code language: JavaScript (javascript)
Результат
Нажимаем F12 и получаем сообщение с название формы – облегченная версия Component Explorer.
![](https://k245.ru/wp-content/uploads/2024/05/informatsiya-o-forme.jpg)
Есть ограничения использования ExecProc(). Особенность обработки скриптов не допускает рекурсивного вызова обработчиков в сочетании с модальными окнами. В нашем случае это означает, что если для вызова какой-либо формы в модальном режиме была использована горячая клавиша, то пока данная форма не закроется, воспользоваться этой подсистемой ещё раз не получится.