Я свободно признаю, что это размышление вслух для меня, но первое, что бросилось в глаза, это:
procedure TMenu1.OnEvent (c: Char);
var
Next: TExtendedUIManager;
begin
if c = '2' then begin
Next := TSubMenu1.Create;
Self.Start(Next);
Next.Free;
end;
end;
Такое ощущение, что конечным условием такого рода программирования будут огромные деревья решений if c = '2' then ... else if c = '3' then ... else
и так далее. Это действительно утомительно писать и поддерживать; если это возможно, входной символ отображения массива с функцией для выполнения часто гораздо проще поддерживать.
[['2', foo_create],
['3', foo_delete],
['4', foo_ship],
['d', foo_destroy_all],
['`', foo_return_to_previous_menu]]
Когда появляется новый символ, вы должны найти соответствующую функцию в таблице и выполнить ее. Как только вы закончите, вернитесь к ожиданию.
Вы можете дополнительно расширить этот массив, чтобы отслеживать требуемые аргументы и значения, возвращаемые каждой функцией. Когда вы выполняете функцию, сохраняйте ее возвращаемое значение в глобальной переменной и отслеживайте, какие типы были возвращены. (Возможно, система типов Delphi достаточно сложна, чтобы ее можно было тривиально и даже не стоит упоминать.) Когда вы выполняете новую функцию, проверьте, подходит ли тип «текущего» возвращаемого результата для передачи в нужную функцию. (Вы можете даже выделить пункты меню серым цветом, если типы указаны неправильно, чтобы указать пользователю, что эта комбинация не будет работать.)
/* key function arg ret types */
[['2', foo_create, NULL, FOO],
['3', foo_delete, FOO, NULL],
['4', foo_ship, FOO, NULL],
['d', foo_destroy_all, NULL, NULL],
['`', foo_return_to_previous_menu, NULL, NULL]]
Надеюсь, это полезно каким-то образом. :)