Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Все языки: Статьи, заготовки в FAQ > Форма на основе контрола-контейнера


Автор: Fr0sT 24.08.17, 12:49
Форма на основе контрола-контейнера

Очень часто бывает, что возможностей стандартных диалогов не хватает, но и отдельный файл формы заводить под пару нестандартных контролов неохота. Формировать динамически - большая морока. Можно юзать Winapi диалоги, но с ними свои нюансы, да и удобство обработки событий несравнимо с VCL. Мне пришла в голову идея, как просто накидывать интерфейс диалогов без необходимости заводить файл формы - достаточно кинуть на главную форму контрол-контейнер (panel, pagecontrol, groupbox), сделать его невидимым и создать интерфейс на нём. После чего с помощью нижеприведенной функции сгенерировать форму с контролами, скопированными с этого контейнера.

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    function FormFromControl(Container: TWinControl): TForm;
    var
      CtrlClass: TControlClass;
      Ctrl: TControl;
      ms: TMemoryStream;
      i: Integer;
    begin
      Result := TForm.Create(nil);
      Result.ClientHeight := Container.Height;
      Result.ClientWidth := Container.Width;
     
      ms := TMemoryStream.Create;
     
      for i := 0 to Container.ControlCount - 1 do
      begin
        CtrlClass := TControlClass(Container.Controls[i].ClassType);
        // Enable component to be read
        RegisterClass(CtrlClass);
        // Clone component via stream
        ms.WriteComponent(Container.Controls[i]);
        ms.Position := 0;
        Ctrl := CtrlClass.Create(Result); // To assign Parent before restoring from stream
        Ctrl.Parent := Result;
        ms.ReadComponent(Ctrl);
        ms.Position := 0;
      end;
     
      FreeAndNil(ms);
    end;
     
    // Пример
    procedure TForm1.btnClick(Sender: TObject);
    begin
      with FormFromControl(PageControl1.Pages[0]) do
      begin
        BorderStyle := bsDialog;
        Caption := 'Dialog from PageControl';
        Position := poScreenCenter;
        // assign handlers...
        ShowModal;
        Free;
      end;
    end;


Для большого количества диалогов можно сделать так:
1 - завести отдельную форму
2 - на нее PageControl, для удобства переключения между диалогами в дизайн-тайм
3 - на каждый TabSheet PageControl-а - Panel или GroupBox, для задания габаритов диалога
4 - указывать эти Panel или GroupBox в качестве параметров FormFromControl

Автор: leo 25.08.17, 06:47
Цитата Fr0sT @
Для большого количества диалогов можно сделать так:
1 - завести отдельную форму
2 - на нее PageControl, для удобства переключения между диалогами в дизайн-тайм
...

А какой тогда смысл создавать новую форму и копировать на нее контролы, если можно использовать существующую, просто установив активную страницу PageControl-а и скрыв ярлычки остальных страниц? Не устраивает рамка (и визульный стиль)? Можно древний TNotebook времен Win 3.1 использовать ;)

Автор: Fr0sT 25.08.17, 07:53
leo, сценарий использования такой - есть форма с интерфейсом, возможно даже главная, и некоторые действия юзера запускают диалоги. Естественно, для этого нужны отдельные окна (вариант с попап-рамкой а-ля диалоги на веб-страницах тоже подходит, но это муторно).

Автор: jangogo 23.09.17, 17:59
А нет решений попроще?

Автор: Fr0sT 25.09.17, 07:20
Проще - по форме на каждый диалог.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)