25 de agosto de 2009

Acrescentando suporte a Scripts em aplicações Delphi - parte 2

Dando continuidade ao post anterior sobre o MS Script Control, vou mostrar aqui um exemplo básico do uso do componente, montando uma aplicação onde o usuário poderá informar uma expressão qualquer em VBScript numa caixa de texto. Pressionar um botão na tela fará com que o programa avalie essa expressão, lançando numa outra caixa de texto o resultado obtido. Estou considerando que a expressão é numérica mas essa é uma questão de desenho da aplicação; se for necessário, pode-se usar qualquer dos outros tipos de dado da linguagem de script - no caso, VBScript.

Considerando que você já tem o fonte com as interfaces do Script Control, o primeiro passo é criar e configurar uma instância do componente. Coloquei esse código no evento OnCreate do Form:
_ScriptControl := TScriptControl.Create (Self);

_ScriptControl.SitehWnd := Handle;
_ScriptControl.Language := 'VBScript';
_ScriptControl.Timeout := -1;
_ScriptControl.AllowUI := true;
_ScriptControl.UseSafeSubset := false;
_ScriptControl.OnError := OnScriptError;
De acordo com o post anterior, este código configura o componente para que ele use 'VBScript'. Também permite interação via interface gráfica usando o próprio Handle do meu Form. O Timeout foi ajustado com valor -1, significando que o componente não gerará eventos relativos à expiraração de tempo enquanto executa um script demorado. Não falei da propriedade UseSafeSubset: ela determina se o componente deve restringir ou não os comandos aceitos de forma que somente os considerados seguros possam ser executados. Ajustei-a aqui para false, garantindo que todo o conjunto de funções do VBScript estará disponível. Ajuste o valor dela para true se segurança for uma preocupação pois assim o componente não permitirá a execução de comandos que possam burlar as permissões de acesso.

O evento OnError é configurado para executar a função OnScriptError sempre que houver um erro durante a execução de scripts - mesmo erros de sintaxe são reportados por este método:
procedure TfTesteScript.OnScriptError(Sender : TObject);
var lMsg : String;
lControl : TScriptControl;
begin
lControl := Sender As TScriptControl;
lMsg := lControl.Error.Source + #13#10;
lMsg := lMsg + 'Erro ' + IntToStr (lControl.Error.Number) + #13#10;
lMsg := lMsg + lControl.Error.Description + #13#10;
lMsg := lMsg + 'Linha ' + IntToStr (lControl.Error.Line);
lMsg := lMsg + ' ,Coluna ' + IntToStr (lControl.Error.Column) + #13#10;
MostraErro (lMsg);
end;
O código reproduzido acima mostra que há uma propriedade do Script Control chamado Error que descreve toda a condição do erro que ocorreu, incluindo a linha e coluna dentro do código, um número de erro e uma descrição do erro. A documentação do objeto Error pode ser encontrada aqui.

Para concluir o exemplo, faltou mostrar como é feita a avaliação da expressão. O código é a resposta ao evento de clique no botão de avaliação:
procedure TfTesteScript.btAvaliarClick(Sender: TObject);
var res : Variant;
begin
try
res := _ScriptControl.Eval(edExpressao.Text);
if VarType (res) <> varEmpty then
edResult.Text := FloatToStrF(res, ffFixed, 15, 4);
except
edResult.Text := '## erro ##';
end;
end;
Veja que o processo é bastante simples: basta chamar o método Eval do Script Control passando como parâmetro a expressão digitada pelo usuário. O valor retornado é um Variant mas como o valor que estou esperando na expressão é de ponto flutuante, posso fazer a conversão de float para string sem problema. Em todo caso, todo o trecho é protegido por um par Try/Except.

Neste exemplo, as expressões que podem ser avaliadas são fixas, isto é, não consigo informar na expressão uma variável que eu tenho criado e alimentado no meu programa. Apenas constantes, funções e operações matemáticas são válidas. Há uma lista aqui com as funções definidas no VBScript e que podem ser utilizadas na caixa com o texto para avaliação de expressões.

No próximo post, mostro como incluir métodos e funções para executar scripts mais complexos. Em outra oportunidade, mostro também como permitir que o script interaja mais efetivamente com o programa através da adição de objetos do programa ao engine de script.

Para baixar o programa de exemplo - incluindo código e executável - clique aqui. O programa foi feito com Delphi 2005 mas deve funcionar com pouca ou nenhuma alteração em outras versões.

Nenhum comentário :

Postar um comentário

OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.

Observação: somente um membro deste blog pode postar um comentário.