12 de março de 2010

Criando um editor de HTML com o TWebBrowser - parte I

Como eu disse em outro post, o componente TWebBrowser existente no Delphi e no C++ Builder pode ser usado para exibir páginas HTML num programa seu mas também tem recursos para se transformar num editor de HTML no estilo WYSWYG. Isto significa que o usuário final de seu programa pode editar visualmente um conteúdo que esteja disponível em formato HTML mesmo sem conhecer essa linguagem. Ou seja, durante a edição do texto, o usuário enxergará o documento com a mesma aparência que quando ele é exibido pelo browser.

Colocar o componente TWebBrowser em modo de edição é relativamente fácil, bastando modificar o valor de uma propriedade. No entanto, o fonte que é distribuido junto com o IDE não trás todos os tipos de dados, de modo que algumas funcionalidades ficam escondidas. Para podermos usar esses tipos, teremos que importar a Type Library que os contêm, chamada Microsoft HTML Object Library. Há um post aqui explicando como realizar a importação de uma type library no Delphi.

Agora que temos todos os tipos necessários, podemos usar a propriedade Document do WebBrowser para iniciar o modo de edição. O Document implementa um série de interfaces para trabalhar com o editor e o conteúdo HTML propriamente dito. A interface que mais utilizaremos é a IHTMLDocument2, que representa a estrutura DOM do documento HMTL, permitindo que se obtenha informações sobre os elementos HTML e os textos contidos no documento.

Uma das propriedades dessa interface é a designMode, cuja função é determinar se o documento em exibição pode ou não ser editado. Então, para iniciar o modo de edição basta atribuir o valor 'on' para a propriedade:
Uses MSHTML_TLB;

procedure TForm1.Editar;
var lDoc : IHtmlDocument2;
begin
FBrowser.Navigate('about:blank');
lDoc := FBrowser.Document as IHtmlDocument2;
lDoc.designMode := 'on';
end;
No código acima, a unit MSHTML_TLB na cláusula Uses disponibiliza para nosso fonte a type libray importada no começo. Antes de ativar o modo de edição, é obrigatório que haja um documento ativo no WebBrowser. Por isso, uma página HTML em branco é carregada através da navegação para o endereço 'about:blank'. Por fim, é feito um cast com o Document para obter acesso às propriedades da interface IHtmlDocument2 e poder iniciar o modo de edição.

Ao executar esse código, já temos um editor HTML básico que usa valores padronizados para fonte, formatações e cores. Se quisermos alterar esse valores, podemos carregar uma página HTML mais robusta, com alguma formatação pré criada. Veja os outros posts sobre o WebBrowser para ver como fazer essa carga.

Algumas das propriedades podem ser modificadas diretamente na interface IHtmlDocument2, como por exemplo a cor de fundo da página :
{ ... }
lDoc.designMode := 'on';
lDoc.bgColor := 'yellow';
end;
Veja que a cor informada deve ser compatível com o HTML. Isso implica que se um TColor no Delphi for atribuído, a cor será interpretada incorretamente.

Com relação aos comandos aceitos por esse editor, é seguido o padrão do Windows. Por exemplo, use CTRL-C e CTRL-V para operações copiar/colar, CTRL-Z para desfazer a última operação, etc.

Para deixar esse editor um pouco mais flexível, é interessante oferecer ao usuário meios intuitivos de se adicionar formatações HTML, tais como negrito, cores, tipos de fonte, etc. Ou ainda, permitir a criação de listas, tabelas e hiperlinks, adição de imagens, vídeos e outros objetos. Apesar do Document representar a estrutura do HTML, adicionar uma tag é um pouco mais complexo do que seria se tentássemos simplesmente acrescentar um novo nó à estrutura DOM - como num XML. Isso se dá porque é permitido aplicar formatações que abranjam mais de uma tag. Um bom exemplo é aplicar negrito a uma seleção que envolva mais de um parágrafo ou linhas numa tabela.

A chave para implementar esse tipo de recurso é a propriedade Selection do IHtmlDocument2. De acordo com a documentação no MSDN, o Selection representa um texto selecionado, o ponto atual para inserção de novo conteúdo no documento ou ainda um elemento no HTML onde se pode realizar alguma ação específica. O Selection possui um método chamado createRange que é capaz de recuperar a seleção atual de uma forma que permite aplicar corretamente qualquer formatação, mesmo que o texto selecionado englobe mais de uma tag. Veja como funciona para negrito:
procedure TForm1.btBoldClick(Sender: TObject);
var lSel: IHTMLSelectionObject;
lRange : OleVariant;
lDoc : IHtmlDocument2;
begin
lDoc := FBrowser.Document as IHtmlDocument2;
lSel := lDoc.selection;
lRange := lSel.createRange;
lRange.execCommand('BOLD', False, True);
end;
O objeto criado com createRange é do tipo TextRange (se a seleção contiver apenas texto) ou controlRange (se contiver múltiplos elementos selecionados). Em ambos os casos, há um método que permite aplicar comandos na seleção - o execCommand. Mesmo podendo estar em tipos diferentes, o método possui os mesmos parâmetros; isso nos permite usar um OleVariant para executar o método - o Delphi determinará em tempo de execução qual o método certo a ser chamado, usando uma técnica denominada late binding.

O efeito desse comando no texto selecionado é envolvê-lo internamente com a tag STRONG, resultando na exibição do texto em negrito. Caso o texto já esteja em negrito, o comando removerá essa formatação, voltando a exibir sem negrito. A lista de comandos aceitos pelo execCommand pode ser encontrada neste link do MSDN.

Volto em outro post com outros exemplos de facilitadores para a edição.

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.