O artigo trará uma abordagem prática dos temas programação orientada a objetos, generics, herança x composição, refactoring, interface com o usuário e API do Windows. Esses temas serão combinados de modo a produzir uma Deskbar que pode conter ícones para programas.
Em que situação o tema é útil
O conteúdo apresentado neste artigo servirá para criar sistemas com visual mais atraente para os usuários, mais práticos de se usar e dando um acabamento mais “profissional” ao formulário principal do software. O tema é útil sempre que houver a necessidade de se inovar na apresentação ou comportamento do software. Criação de imagens ou ícones “arrastáveis” para outros programas do computador ou para menus e formulários do sistema. Também será apresentado como utilizar e agregar componentes existentes para se mesclar funções de um componente em outro sem reinventar a roda.
Criando uma deskbar
Deskbars, também conhecidas como sidebars, toolbars e outras expressões que remetem à ideia de barra de ferramentas em sua área de trabalho, são ferramentas muito úteis para dar um visual agradável ao desktop do computador e manter certas funções sempre à mão, à distância de um clique. Uma ferramenta dessas deve conter atalhos para outras ferramentas e agregar algumas das funções mais usadas no PC como notificação de e-mails e relógio, listas de afazeres, leitores de RSS entre outras opções. Mas para ser produtiva a deskbar não deve atrapalhar o usuário ou se “intrometer” em suas tarefas quando isso não for necessário.
Existem no mercado vários programas para atuar como barra de ferramentas da área de trabalho. No Windows XP era possível colocar atalhos em uma pasta e “arrastar” esta pasta contendo somente atalhos para um canto do desktop, que ela se tornava automaticamente uma barra de ferramentas. Era possível configurar essa barra para se auto-ocultar e para exibir ícones pequenos e sem descrição, tornando a área de trabalho bem limpa, pois era possível se livrar de todos aqueles atalhos na área de trabalho.
No Windows 7 há aqueles gadgets da área de trabalho que podem conter um relógio, leitores de RSS e outras (in)utilidades. No entanto não é possível colocar atalhos para programas nesta barra.
Outro produto digno de nota é o google desktop, que além de trazer várias funcionalidades para a desktop ainda conta com as buscas do google e com uma eficiente indexação e busca de e-mails e arquivos em seu próprio computador. Esta também não permite criação de atalhos para programas, mas possui uma função interessante onde é possível digitar o nome de um programa, e o mesmo será aberto, caso seja encontrado.
Há os programas que criam apenas barras de atalhos bonitas para tentar imitar o estilo das barras de ferramentas do Mac, como a RK Launcher e a Object Dock. Esses aplicativos podem parecer simples, mas há uma lógica bem elaborada em seu comportamento e na sua apresentação. Por exemplo o recurso de ocultar-se automaticamente faz com que a barra desapareça em uma lateral qualquer da tela para reaparecer apenas quando o mouse toca essa lateral. Uma desvantagem desse comportamento é que a barra pode ser ativada “sem querer” caso seja necessário levar o mouse para um ponto extremo da tela, como o botão fechar de uma janela maximizada ou para virar a “câmera” em um jogo encostando o cursor no limite da tela para “enxergar” do outro lado.
Se a barra estiver na direita ela pode ser ativada sem querer ao se clicar no botão fechar de um programa. Na parte inferior ela será ativada sempre que for necessário clicar no menu iniciar ou em uma janela minimizada. Na esquerda atrapalha sempre que se for usar os ícones da esquerda, como a lixeira, e na parte superior ela pode atrapalhar ao se navegar na internet ou acessar menus de janelas maximizadas.
Parece uma coisa simples, e que pode ser configurada, mas ninguém pensa nisso. Usabilidade também significa ter o comportamento que vai incomodar menos por padrão, sem a necessidade de se configurar nada. E principalmente para quem trabalha com o computador o dia inteiro, usabilidade significa produtividade. A produtividade é diferente para cada tipo de trabalho. Enquanto uma “notificação de e-mail” pode tornar um vendedor ou comprador supereficiente em responder seus e-mails e se comunicar ou negociar com clientes e fornecedores, a mesma notificação de e-mail pode atrapalhar um programador ou designer quando este estiver precisando de concentração.
Particularmente eu acho interessante o comportamento de ao se aproximar o mouse exibir apenas uma área bem fina da barra de ferramentas, e esta só abrir mediante um clique. Acho que esse comportamento não prejudica a usabilidade e não atrapalha no uso de um browser, por exemplo.
Vale ressaltar que algumas dessas barras usam recursos gráficos como transparências e animações que as tornam pesadas e inviáveis para uso em netbooks, por exemplo.
Alguns conhecimentos teóricos serão apresentados neste artigo que podem ser úteis no desenvolvimento de outras aplicações. São eles:
Agregação à Não é só com herança que se estende as funcionalidades de uma classe. Se uma classe tiver internamente em seu corpo campos que são objetos de outras classes, ela pode incorporar as funções destes. Por exemplo, um ícone é uma figura com um texto embaixo, então pode-se pensar que um ícone pode ser “montado” com um TImage que tem um TLabel na parte inferior.
Agregação é uma relação todo-parte um pouco mais fraca do que a composição. Por exemplo no caso do ícone montado, a partir de um TImage e de um TLabel tem-se uma agregação pois tanto TImage como TLabel fazem sentido separados e podem coexistir separadamente.
Composição é um tipo de associação mais rígida. Quando se tem uma composição os membros desta não fazem sentido separadamente e não podem existir fora do todo. O comportamento do todo é muito diferente do comportamento das partes, e as partes são destruídas caso o todo seja destruído.
Bons exemplos de agregação e composição se encontram na culinária. Por exemplo uma omelete é uma agregação de ovos, queijo, presunto e outros ingredientes que você goste. No caso da omelete os componentes mantêm suas características, o queijo, o presunto etc. são bem perceptíveis e fazem sentido existindo fora da omelete. Já um bolo é um caso de composição, pois o bolo apresenta características e comportamento muito diferentes dos ingredientes isolados, farinha, ovos, açúcar e fermento. Os ingredientes do bolo não fazem muito sentido separados, por exemplo, ninguém come ovos com fermento. Em agregação o todo pode fazer sentido sem as partes, em composição não pode. Essa é a diferença entre agregação e composição.
Generics à Generics facilitam muito a criação de listas tipadas dinâmicas. Como uma barra de ferramentas lateral pode ter várias listas de coisas (widgets, ícones etc.) listas genéricas podem ser usadas para atingir esse objetivo.
API do Windows à Arrastar um ícone ou arquivo para dentro de uma aplicação só é possível mediante o uso da API. Primeiro deve-se informar que determinada janela (ou panel, ou handle) pode receber arquivos arrastados. Depois é preciso dizer ao sistema o que fazer com os arquivos arrastados.
Ícones e menus na system tray à É importante para “travar” a barra ou fechá-la.
ClientDataset desconectado à A lista de “ícones”, por exemplo, será gravada em um arquivo XML do ClientDataset sem o uso de providers ou bancos de dados.
Noções Gráficas à Conversões de ícone para bitmap, transparências, aparência.
Registro do Windows à A barra deve iniciar junto com o Windows, mas não deve ser um serviço pois serviços iniciam antes do login, e rodam mesmo se nenhum usuário se logar. No caso de uma barra de atalhos, ela é um programa essencialmente visual, por isso precisa iniciar apenas depois do login, para trazer apenas os atalhos do usuário logado.
Componentes Jedi à Baixe e instale o pacote de componentes JEDI, pois o componente JvBackGround será usado. Ele serve para colocar uma imagem como background de um formulário evitando flicking. Além disso esse componente tem propriedades interessantes como definir uma cor transparente e usar stretch, que significa esticar a imagem preenchendo todo o tamanho do formulário.
A Figura 1 mostra como será a classe TIconeComando sem os métodos e propriedades, apenas o rascunho de sua interface. Uma lista de ícones é uma agregação de vários ícones, depende da classe TLabel pois tem um label interno e possuirá uma ligação com um menu popup para ações como excluir. Um TIconeComando é descendente do TImage.
Figura 1. Diagrama de classes
Criando a “casca”
O primeiro passo é criar o comportamento. Uma barra de ferramentas deve ser um formulário “fino” que deve se acoplar a uma das laterais do seu desktop. O ideal é que o lado seja configurável, mas por questões de simplicidade este artigo assume que a barra ficará sempre do lado direito.
Ao iniciar, a barra não pode ter qualquer tipo de borda, muito menos botões de minimizar, maximizar ou fechar. Por isso é bom colocar BorderStyle := bsNone na inicialização.
Uma fina fatia do formulário deve ser sempre visível. Essa fatia deve ser larga o suficiente para disparar o evento OnMouseEnter quando o ponteiro do mouse passar por ela.
Passando o ponteiro por ela deve “crescer” vindo pouca coisa mais para a direita. Tirando o mouse dela, ela deve voltar à posição inicial. Todo esse comportamento cogitado até agora pode ser controlado manipulando-se apenas a propriedade left do formulário. Por exemplo, se o formulário tem 500 pixels de largura e a propriedade left for “TamanhoDaJanela – 20” isso significa que os 20 pixels da esquerda serão visíveis e os outros 480 estarão “para fora da tela”. O tamanho da tela é possível de se obter com Screen.Width.
Para isso um formulário como o da Figura 2 foi criado. Ele possui um ClientDataset, um TrayIcon, dois popup menus (um para o TrayIcon e outro será visto mais adiante) e um SpeedButton.
Figura 2. Formulário inicial
No create do formulário é executado o método Inicializa que tem por responsabilidade setar o tamanho e posição iniciais do formulário e deixar uma fina fatia visível à direita. Caso o leitor se interesse por configurar a posição onde a barra de ferramentas ficará então, caso a barra fique à esquerda, a lógica desse método deve ser invertida fazendo com que a parte visível seja um pequeno pedaço da direita do formulário, mostrado à esquerda da tela.
Outra responsabilidade deste método é inicializar o ClientDataset, criando o arquivo CDS caso o mesmo não exista. O arquivo CDS deve ser diferente para cada usuário do sistema, por isso cada usuário terá uma pasta com seu próprio arquivo CDS. A Listagem 1 mostra como criar o arquivo CDS para cada usuário. O método NomeUsuario é um método estático, público e global que funciona como wrapper para o método GetUserName da API do Windows e retorna o nome do usuário logado no momento. No código fonte disponível pode-se ver o método completo.
Listagem 1. Inicialização do formulario
procedure TfrmSideBar.Inicializa;
var
NomeArquivo: string;
DiretorioArquivo: string;
begin
DiretorioArquivo := ExtractFilePath( ParamStr(0) )+'\'+ NomeUsuario+'\';
NomeArquivo := DiretorioArquivo + 'icones.cds';
if not DirectoryExists(DiretorioArquivo) then
ForceDirectories(DiretorioArquivo);
cdsIconesInicia.FileName := NomeArquivo;
if not FileExists(NomeArquivo) then
cdsIconesInicia.CreateDataSet;
cdsIconesInicia.Open;
Left := PosicaoInicial;
Top := 0;
Height := Screen.Height;
FAberta := false;
FTravado := false;
end;
function TfrmSideBar.PosicaoInicial: integer;
begin
Result := Screen.Width -10;
end;
...