From Axaptapedia
Criar formulário em runtime pode ser muito útil em várias circunstâncias. Qualquer tipo de controle pode ser adicionado: groups, string edits, buttons etc.

O DAX usa esta técnica para adicionar dinamicamente ‘Action buttons’ em formulários quando é necessário. O código para adicionar esses controles para essas funções é chamado no método new() do SysSetupFormRun.

Introdução
O processo basico para adicionar controles e interceptar seus eventos em tempo de execusão:

use form.addControl(ControlType, ControlName) para adicionar o controle
chame form.controlMethodOverload(true) para ativar sobrescrevendo os controles do evento

Se você está tratando apenas com botões, então é possivel setar o MenuItemType e MenuItemName no botão quando ele é criado. Desta forma, você pode chamar um relatório diretamente, uma classe ou outro form, e você não precisa escrever nenhum código adicional para tratar o evento click do botão.

O básico
O mais simples exemplo usa o método init() do formulário para adicionar os controles, e criar métodos para interceptar o eventos dos controles. Guarde bem os nomes dos controles usados durante a chamada .addControl(). No exemplo abaixo, o nome do controle é ‘DynamicStringControl’ e ‘DynamicButtonControl’.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public void init()
{
  FormStringControl formStringControl;
  FormButtonControl formButtonControl;
  FormGroupControl formGroupControl;
  ;
 
  // Adicionando um grupo
  formGroupControl = this.form().addControl(FormControlType::Group, "MyGroup");
  formGroupControl.caption("It's my group!");
 
  // Adicionando uma string ao grupo
  formStringControl = formGroupControl.addControl(
  FormControlType::String, "DynamicStringControl");
  formStringControl.label("Dynamic string control");
 
  //Adicionando outra string ao grupo usando o mesmo nome.
  //Usará o mesmo método de evento como no primeiro "DynamicStringControl"
  formStringControl = formGroupControl.addControl
                    (FormControlType::String,"DynamicStringControl");
  formStringControl.label("Dynamic string control2");
  formButtonControl = this.form().addControl
                    (FormControlType::Button, "DynamicButtonControl");
  formButtonControl.text("Dynamic button");
  this.controlMethodOverload(true);
 
  super();
}

Você pode então escrever um método event handler para o controle no nível mais alto (element) do seu formulário.

1
2
3
4
5
6
7
8
9
10
11
12
13
void dynamicButtonControl_Clicked()
{
  ;
  info ("Dynamic button clicked!");
}
 
boolean dynamicStringControl_Modified()
{
  FormStringControl control = element.controlCallingMethod();
  ;
  info (strFmt("Modified dynamic control %1 to %2", int2str(control.id()), control.text()));
  return true;
}

Atente para que a primeira parte do nome do método (antes do underscore) é exatamente igual ao nome do controle usado no método init().

Adicionando um botão de item de menu
O exemplo seguinte adiciona um botão de item de menu em um formulário, o qual abrirá o formulário SalesTable. Note que nós agora devemos usar um FormFunctionButtonControl, ao invés de um FormButtonControl.

O botão exibirá o label correto do item de menu.

1
2
3
4
5
6
7
8
9
10
public void init()
{
  FormFunctionButtonControl formFunctionButtonControl;
  ;
  formFunctionButtonControl = this.form().addControl
  (FormControlType::MenuFunctionButton, "SalesTableButton");
  formFunctionButtonControl.menuItemType(MenuItemType::Display);
  formFunctionButtonControl.menuItemName(MenuItemDisplayStr(SalesTable));
  super();
}

O mesmo principio pode ser usado para chamar outros tipos de itens de menu. Isto é muito usado se um botão deve executar processamento intensivo em uma base de dados, o qual beneficiaria de ser encapsulado em uma classe de servidor.

Veja o método () na classe KMActionMenuButtonAuto para ter um exemplo de um código mais complexo.