Zetta-Ømnis Soluções Tecnológicas
Desenvolvendo hoje a tecnologia do amanhã
Visite Nosso Patrocinador
Você está aqui:
DO NOT UNDERSTAND PORTUGUESE? CLICK ON THE FLAG TO CHANGE THE LANGUAGE!

Inno Setup (Parte 10): Página personalizada III

Imagem meramente ilustrativa

Se você tem acompanhado este tutorial até aqui, você já deve estar familiarizado tanto com a criação, como a modificação de páginas do instalador. Para páginas adicionais o caminho mais simples é usar o Inno Setup Form Designer (ISFD) como gerador de código. Para a alteração de páginas já existentes ele também pode ser usado sem problema algum, no entanto, a fim de fixar melhor o tópico das páginas personalizadas, desta vez vou focar na codificação pura, sem o auxilo do ISFD. Você verá que não é nenhum bicho-de-sete-cabeças trabalhar diretamente no código para a alteração de páginas preexistentes. Particularmente, em muitos casos, eu prefiro trabalhar desse modo pois se tem um controle maior do que está sendo feito.

Teaser!

Ficou curioso para saber como será o resultado final deste artigo? Não precisa arrancar os cabelos! Abaixo está uma imagem da tela após realizarmos nossa intervenção:

A tela original mostra apenas um ComboBox que lista os tipos de instalação disponíveis e por este motivo eu, inicialmente, incluí na descrição do tipo da instalação um pequeno texto entre parênteses para indicar do que se trata. Você já deve ter visto esta tela ao executar o instalador que estamos construindo:

Como se pode observar, esta forma de descrever o tipo da instalação é bem limitada. Se seu instalador tiver mais tipos de instalação com várias ações sendo realizadas por cada um deles é bem mais interessantes ter um campo específico que mostra uma descrição mais detalhada do que cada tipo de instalação faz.


Colocando a mão na massa

A alteração que vamos fazer não é muito complexa mas ela envolve codificação pura e apesar de eu não gostar, tenho que admitir que muitos de vocês não estão acostumados com este tipo de programação.

Se você algum dia já instanciou componentes em runtime não terá problema algum, mas se você é iniciante ou não tem necessidade de, no dia-a-dia, instanciar componentes manualmente vai ter uma certa dificuldade mesmo, contudo não se desespere, pois como eu disse, esta alteração não é complexa. Sem mais blá blá blá, vamos direto ao ponto.

Para começar abra o script no Inno Script Studio, clique no item Inno Setup Script, no canto superior esquerdo da tela, vá até a seção [Types] e altere as descrições dos 3 primeiros tipos de instalação tal como na figura abaixo:

Nós não vamos mais precisar dar maiores detalhes de cada tipo de instalação, pois isso vai ser feito no painel que vamos construir, por isso nós precisamos alterar a descrição dos 3 primeiros tipos de instalação. As descrições dos tipos de instalação aparecem no combobox da tela de seleção de componentes.

Agora vá até a seção [CustomMessages] e, no seu final, digite 3 novos itens tal como na imagem a seguir:

Como não dá pra ver todas as 3 linhas completamente, transcrevi abaixo seu conteúdo:

CompletaDescription=Instala o programa o programa principal juntamente com o PostgreSQL e sua documentação. Use este tipo de instalação preferencialmente para realizar uma nova instalação a partir do zero
MinimaEXEDescription=Instala apenas o programa principal. Use este tipo de instalação preferencialmente para atualizar apenas o programa principal
MinimaPGDescription=Instala apaenas o PostgreSQL. Use este tipo de instalação para reinstalar apenas o PostgreSQL. ATENÇÃO, este tipo de instalação é potecialmente perigoso. Faça um backup da pasta de dados do PostgreSQL antes de continuar

Considere estas 3 custom messages como se fossem 3 variáveis do tipo String, as quais serão posteriormente acessadas via código no Pascal Script. De agora em diante vou chamar estas custom messages simplesmente de variáveis, para facilitar a escrita do artigo. Estas variáveis, caso não tenha ficado claro, contém os textos que serão exibidos quando cada um dos tipos de instalação for selecionado no combobox da tela de seleção de componentes da instalação.


A modificação a ser realizada na página de seleção de componentes do instalador possui 3 componentes, por isso será necessário declarar 3 variáveis, uma para cada um destes componentes. Desça no script até achar a seção [Code] e logo no começo dessa sessão, onde são declaradas as variáveis, declare as variáveis, tal como visto a seguir:

SetupTypeDescriptionPanel é um TPanel que vai servir como contêiner para SetupTypeDescriptionLabel (TLabel). Eu optei por usar um TPanel pois eu quis ter uma área delimitada por bordas e se eu usasse apenas um TLabel eu não conseguiria este efeito. A variável OriginalComboboxTypesOnChangeHandler servirá para guardar o manipulador do evento OnChange original do combobox que lista os tipos de instalação na página de seleção de componentes. Posteriormente nós precisaremos alterar o comportamento do evento OnChange deste combobox, mantendo seu comportamento original mas adicionando codificação extra para mudar o texto do label SetupTypeDescriptionLabel. Não se preocupe muito. Você vai entender melhor no desenrolar do artigo.

Daqui pra frente veremos somente codificação em pascal e o primeiro código que quero explicar é o responsável por alterar a descrição do tipo de instalação. Ao selecionar um tipo de instalação no combobox existente na tela de seleção de componentes, a descrição correspondente precisa ser exibida em SetupTypeDescriptionLabel e esse comportamento é conseguido codificando-se um novo manipulador para o evento OnChange desse combobox. A nova codificação é vista a seguir:

procedure NewComboBoxTypesOnChangeHandler(Sender: TObject);
begin
  OriginalComboboxTypesOnChangeHandler(Sender);

  if UpperCase(WizardSetupType(False)) = UpperCase('personalizada') then
    SetupTypeDescriptionPanel.Visible := False
  else
  begin
    SetupTypeDescriptionLabel.Caption := CustomMessage(WizardSetupType(False) + 'Description');
    SetupTypeDescriptionPanel.Visible := True;
  end;
end;

Coloque este código no script em qualquer lugar após a declaração das variáveis. Na linha 3 nós executamos o manipulador original do evento OnChange, o qual vai realizar ações predefinidas, mantendo o comportamento original do combobox quando se dá a seleção de novos itens. As linhas 5 a 11 exibem ou ocultam o painel de descrição (SetupTypeDescriptionPanel) e alteram o caption do label de descrição (SetupTypeDescriptionLabel).

A função WizardSetupType retorna o nome ou a descrição do tipo de instalação atualmente selecionado pelo usuário. Nas partes iniciais deste tutorial eu falei a respeito de tipos de instalação. Quando criamos um tipo de instalação nós damos a este tipo um nome, que é seu identificador único (cada tipo de instalação tem um nome diferente).


Na linha 5, a função WizardSetupType é executada com um parâmetro False que faz com que ela retorne o nome do tipo de instalação atualmente selecionado pelo usuário. Nosso script atualmente tem 4 tipos de instalação, cujos nomes são CompletaMinimaEXEMinimaPGPersonalizada. Quando selecionamos o tipo de instalação Personalizada, automaticamente é exibido um TreeView que mostra todos os componentes selecionáveis, de forma que possamos selecionar exatamente o que quisermos. Este comportamento é padrão do Inno Setup e acontece porque o manipulador original está sendo executado (na linha 3 acima). Quando selecionamos o tipo de instalação Personalizada, portanto, precisamos ocultar o nosso painel de descrição e é exatamente isso que está sendo feito nas linhas 5 e 6.

Quando o tipo de instalação selecionado não é Personalizada, o bloco else (linhas 8 a 11) será executado. Neste bloco de instruções o painel SetupTypeDescriptionPanel é exibido e o caption do label SetupTypeDescriptionLabel é configurado com o valor de uma das 3 variáveis que definimos anteriormente na seção [CustomMessages] que são CompletaDescriptionMinimaEXEDescriptionMinimaPGDescription. Caso você não tenha percebido, os nomes das 3 variáveis é composto pelo nome do tipo de instalação, seguido da palavra "Description". Como a função WizardSetupType retorna o nome do tipo de instalação, ao fazermos WizardSetupType(False) + 'Description'  (linha 9), nós obtemos o nome de uma das 3 variáveis!

De posse do nome da variável que contém a descrição do tipo de instalação atualmente selecionado, precisamos apenas obter seu valor e é aí onde entra a função CustomMessage, a qual simplesmente retorna o valor da variável indicada em seu parâmetro (linha 9)! Isso conclui a parte da codificação que garante o dinamismo da tela, exibindo, ocultando ou modificando coisas mediante seleções em um combobox.

O próximo passo é a criação de um procedure para criar os componentes na tela de seleção de componentes do instalador. O código que torna isso possível pode ser visto abaixo:

procedure SetupTypeDescriptionPanelCreate;
var
  Page: TWizardPage;
begin
  Page := PageFromId(wpSelectComponents);
    
  SetupTypeDescriptionPanel := TPanel.Create(Page);
  with SetupTypeDescriptionPanel do
  begin
    Parent := Page.Surface;
    Left := Page.Surface.Controls[1].Left;
    Top := Page.Surface.Controls[1].Top;
    Width := Page.Surface.Controls[1].Width + 1;
    Height := Page.Surface.Controls[1].Height + 1;
    BevelInner := bvRaised;
    BevelOuter := bvLowered;
    TabOrder := 0;
    Visible := False;
    Color := clInfoBk;
    ParentBackground := False;
  end;

  SetupTypeDescriptionLabel := TLabel.Create(Page);
  with SetupTypeDescriptionLabel do
  begin
    Parent := SetupTypeDescriptionPanel;
    AutoSize := False;
    Left := ScaleX(6);
    Top := ScaleY(6);
    Width := Parent.Width - 2 * Left;
    Height := Parent.Height - 2 * Top;
    Alignment := taCenter;
    WordWrap := True;
  end;

  OriginalComboboxTypesOnChangeHandler := TComboBox(Page.Surface.Controls[2]).OnChange;
  TComboBox(Page.Surface.Controls[2]).OnChange := @NewComboBoxTypesOnChangeHandler;

  // Força a execução do evento onChange para configurar tudo corretamente
  NewComboBoxTypesOnChangeHandler(TComboBox(Page.Surface.Controls[2]));
end;

Não se assuste com essa quantidade de código, apesar de ser fácil de entender, eu vou explicar quase linha a linha. Para começar, a variável declarada na linha 3 serve para colocarmos a referência a página do instalador que iremos alterar. A função PageFromId, como se pode observar, e como seu nome sugere, retorna a página do instalador correspondente a constante passada em seu parâmetro. Na linha 5 utilizamos a função PageFromId com a constante wpSelectComponents, a qual representa a página de seleção de componentes da instalação, logo, ao fazer PageFromId(wpSelectComponents) a função retornará a referência a página de seleção de componentes, que é a página onde iremos colocar nossos componentes.


As linhas 7 a 21 criam e configuram o TPanel "SetupTypeDescriptionPanel" que vai conter o label com a descrição do tipo de instalação. A criação deste TPanel usa como Owner a página obtida na linha 5, como pode ser visto na linha 7 em SetupTypeDescriptionPanel := TPanel.Create(Page), isso é necessário, porque ao configurar um Owner para componente TPanel, será este Owner o responsável por destruir este TPanel. Ainda dentro deste bloco de linhas que cria o nosso TPanel, vale ressaltar que a propriedade Parent está sendo configurada como Page.Surface (Linha 10) e não simplesmente Page, porque Page é do tipo TWizardPage, que é um TComponent e portanto, não visual. A propriedade Surface de TWizardPage é um descendente de TCustomControl e portanto é visual, isto é, pode ser visto de fato e ser usado como pai de nosso TPanel, o qual vai aparecer dentro dele. É sempre dentro de Surface onde se encontram todos os componentes visíveis nas páginas em tempo de execução do instalador.

As linhas 11 a 14 configuram a posição e o tamanho de nosso TPanel, usando como base o controle pre-existente de índice 1 de Surface (Page.Surface.Controls[1]). Este controle foi obtido experimentalmente e é nada mais, nada menos que o TreeView de seleção de componentes, o qual só aparece quando escolhemos o tipo de instalação "Personalizada". Em outras palavras, o nosso TPanel vai estar posicionado exatamente em cima do TreeView, e terá basicamente o mesmo tamanho que esse, mas isso não vai alterar o comportamento da tela, porque quando o TreeView é exibido, o nosso TPanel será ocultado (e vice-versa), graças ao nosso manipulador do evento OnChange visto anteriormente (NewComboBoxTypesOnChangeHandler).

As linhas 23 a 34, criam e configuram o TLabel "SetupTypeDescriptionLabel" que vai conter a descrição do tipo de instalação. A criação deste TLabel usa como Owner a página obtida na linha 5, como pode ser visto na linha 23 em SetupTypeDescriptionLabel := TLabel.Create(Page). Ainda dentro deste bloco de linhas que cria o nosso TLabel, vale ressaltar que a propriedade Parent está sendo configurada como SetupTypeDescriptionPanel (Linha 26), o que é bastante natural, já que nosso TLabel deve ser colocado dentro do nosso TPanel. O restante das linhas deste bloco configuram a posição e o tamanho deste TLabel de forma que ele fique centralizado dentro do nosso TPanel e fastado de suas bordas por 6 pixels.

As linhas 36 e 37, respectivamente, salva o manipulador original do evento OnChange do combobox de seleção de tipo de instalação e configura o novo manipulador deste evento como sendo o nosso procedure personalizado NewComboBoxTypesOnChangeHandler. Note que a atribuição de um novo manipulador para um evento é feita usando-se o operador @ (arroba) antes do nome do manipulador, isso porque os manipuladores de eventos são atribuídos por referência (ponteiro).

linha 40 força a execução de nosso manipulador NewComboBoxTypesOnChangeHandler de forma que nosso TPanel possa ser inicializado (ocultado ou exibido) corretamente.

A última alteração necessária para concluir esta página personalizada consiste na execução do procedure SetupTypeDescriptionPanelCreate e isso é feito no mesmo local onde todas as nossas páginas personalizadas foram criadas até o momento: o procedure InitializeWizard.

Após realizar esta última alteração compile e execute o instalador até que ele chegue na tela de seleção de componentes, onde você poderá mudar o valor do combobox de tipos de instalação para testar o comportamento que acabou de ser implementado.

Como esta página personalizada envolveu muitas partes com código puro, eu recomendo que você abra o exemplo anexado a este artigo para estudá-lo melhor e fazer seus próprios testes!


  Arquivos anexados  
Arquivo Descrição Tamanho Modificado em
Access this URL (https://sourceforge.net/projects/addicted2delphi/files/inno.rar) inno.rar Arquivos necessários para criação do instalador e do programa de exemplo (que será instalado). Este arquivo será atualizado à medida que o tutorial for sendo feito e ao final conterá a solução completa 0.1 KB 02/10/2018 às 23:31
Acesso Rápido
Não digite mais que o necessário...



Escaneie este QRCode em dispositivos móveis para acessar a página atual rapidamente nestes dispositivos
Conteúdo Verificado!
#BULLSHITFREE #CLICKBAITFREE
#MONEYLESS
Este site é amigo do desenvolvedor do mundo real
Gostou do conteúdo?
Se você gostou do conteúdo que está lendo, você pode ajudar a manter este site no ar doando qualquer quantia. Use os botões abaixo para realizar sua doação.
 
É rápido, fácil e indolor :)
 

Estatísticas em tempo real

Visite Nosso Patrocinador