iniciando no visual basic

409
Iniciando no Visual Basic Para demonstrar como é fácil começar a trabalhar com o Visual Basic e quão rapidamente você poderá aprender a criar aplicativos úteis, este capítulo o conduzirá a um verdadeiro mergulho de cabeça, fazendo-o escrever um programa simples. Indubitavelmente, a experimentação com o Visual Basic é a melhor forma de obter uma visão das ferramentas com as quais você trabalhará, e isso lhe dará um lampejo do potencial excitante do Visual Basic. Após esta pequena experiência prática, os capítulos seguintes oferecerão uma visão mais detalhada dos "comos e porquês" do Visual Basic. Iniciando o Visual Basic 1. Clique Iniciar na barra de tarefas 2. Selecionar Programas, e então Visual Basic 5.0. –ou– Clique Iniciar na barra de tarefas. Selecionar Programas. Use o Explorer do Windows para achar o arquivo executável Visual Basic (VB5.exe). 3. Clique duas vezes o ícone Visual Basic. Você também pode criar um atalho para o Visual Basic, clicar duas vezes no atalho. Quando você inicia o Visual Basic, você vê as janelas do ambiente de desenvolvimento integrado, como mostrado em Figura 1.1. Figura 1.1 O ambiente de desenvolvimento integrado do Visual Basic Explorando o Vídeo Após você iniciar o Visual Basic, um conjunto de janelas aparecerá no seu vídeo, conforme ilustrado pela Figura 1.1. Na parte superior da janela principal estão menus padronizados File e Edit, os outros menus do Visual Basic,

Upload: alessandro-finkler

Post on 26-Dec-2015

32 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Iniciando No Visual Basic

Iniciando no Visual Basic

Para demonstrar como é fácil começar a trabalhar com o Visual Basic e quão rapidamente você poderá aprender a criar aplicativos úteis, este capítulo o conduzirá a um verdadeiro mergulho de cabeça, fazendo-o escrever um programa simples. Indubitavelmente, a experimentação com o Visual Basic é a melhor forma de obter uma visão das ferramentas com as quais você trabalhará, e isso lhe dará um lampejo do potencial excitante do Visual Basic. Após esta pequena experiência prática, os capítulos seguintes oferecerão uma visão mais detalhada dos "comos e porquês" do Visual Basic.

Iniciando o Visual Basic

1. Clique Iniciar na barra de tarefas2. Selecionar Programas, e então Visual Basic 5.0.

–ou–

Clique Iniciar na barra de tarefas.

Selecionar Programas.

Use o Explorer do Windows para achar o arquivo executável Visual Basic (VB5.exe).

3. Clique duas vezes o ícone Visual Basic.

Você também pode criar um atalho para o Visual Basic, clicar duas vezes no atalho. Quando você inicia o Visual Basic, você vê as janelas do ambiente de desenvolvimento integrado, como mostrado em Figura 1.1.

Figura 1.1 O ambiente de desenvolvimento integrado do Visual Basic

Explorando o Vídeo

Após você iniciar o Visual Basic, um conjunto de janelas aparecerá no seu vídeo, conforme ilustrado pela Figura 1.1. Na parte superior da janela principal estão menus padronizados File e Edit, os outros menus do Visual Basic, bem como a barra de ferramentas. Na parte central do vídeo, encontra-se a janela de form, uma janela grande e vazia intitulada Form1. Diretamente à esquerda, vê-se a janela de palhetas chamada caixa de ferramentas. À direita da janela de form, situa-se a janela de propriedades, chamada Properties, e acima dela aparece a janela de exploração do projeto, intitulada Project. Uma pequena janela com uma representação do vídeo em miniatura também é vista. Trata-se da janela de Layout de Formulário.

Eu quase posso escutar sua reclamação: "Isso pode ser complicado". Realmente, pode ser complicado. Entretanto, a chave para gerenciamento de complexidade é a organização, e o ambiente do Visual Basic foi projetado para

Page 2: Iniciando No Visual Basic

que você se mantenha organizado. Vamos dar uma olhada em cada uma das janelas

A Janela Principal

A janela principal contém a barra de menu, com onze menus drop-down. Um dos mais importantes, especialmente enquanto você estiver aprendendo o Visual Basic, é o menu Help. A partir desse menu, você poderá acessar uma vasta documentação sobre o Visual Basic na forma de manuais (Books Online), encontrar informações sobre como contatar o serviço de suporte a produtos da Microsoft e explorar o sistema de ajuda online do Visual Basic.

Por exemplo, ao selecionar a opção Microsoft Visual Basic Help Topics do menu Help, você verá uma janela com divisões em forma de fichas de arquivo. Uma divisão apresenta o conteúdo do sistema de ajuda na forma de livros, que ao serem abertos exibem novas subdivisões ou tópicos de ajuda como seções de um livro. Ao dar um clique duplo num dos tópicos ou selecioná-lo e clicar no botão Exibir, uma janela contendo o tópico lhe será apresentada. Se preferir procurar por um tópico dentro da ordem alfabética de tópicos, escolha a divisão Índice. Caso tenha uma palavra que não corresponde a nenhum tópico presente no Índice, use a divisão Localizar.

Adicionalmente, o sistema de ajuda fornece informações associadas ao contexto. Se você precisar saber mais sobre um botão, uma caixa de diálogo, uma janela ou qualquer outro elemento enquanto estiver trabalhando com o Visual Basic, basta pressionar a tecla F1 quando o elemento em questão estiver destacado, e o sistema de ajuda exibirá imediatamente as informações pertinentes.

A janela principal ainda contém a barra de ferramentas. Os botões da barra de ferramentas mostrados na Figura 1.2 são atalhos para comandos usados mais freqüentemente. Por exemplo, em vez de abrir o menu File e selecionar a opção Open Project, você pode simplesmente dar um clique no botão Abrir Projeto.

Figura 1.2 A barra de ferramentas do Visual Basic.

 

A Janela de Explorador do Projeto

A janela de Explorador do Projeto contém uma árvore de pastas com todos os arquivos necessários para executar o programa Visual Basic que você está criando. Ainda que você não tenha começado, já aparece uma entrada na janela de Explorador do Projeto, como foi visto na Figura 1.1. Esta primeira entrada é a pasta Forms com o arquivo Form1.frm; o rótulo do arquivo (Form1) indica que ele se encontra associado à janela de form, chamada Form1. Se você salvar o form em disco, sem alterar seu nome, o Visual Basic usará o nome de arquivo default: Form1.frm. Um aplicativo pode conter vários forms, sendo cada um deles armazenado em um arquivo separado. (O

Page 3: Iniciando No Visual Basic

armazenamento em arquivos distintos torna possível o compartilhamento de um form com vários aplicativos.)

A janela de Explorador do Projeto também contém três botões: View Code, View Object e Toggle Folders. Por default, o Visual Basic exibe na janela de form o form correspondente à entrada que for selecionada na janela de Explorador de Projeto. Essa visão lhe permite projetar a interação que o seu aplicativo terá com o usuário final - a parte do aplicativo que o usuário vê e com a qual interage. Se você der um clique no botão View Code da janela de Explorador do Projeto, o código para o arquivo selecionado será exibido em uma janela diferente. O código refere-se às instruções em linguagem de programação.

O processo de programação é chamado de codificação. Quando você cria um programa em Visual Basic, o seu trabalho se divide entre o projeto do Form, que eventualmente será visto pelo usuário, e a codificação, que controlará as operações do programa. Para mover-se da janela de código para a janela de form, basta dar um clique sobre o form, ou então acionar o botão View Form da janela de Explorador do Projeto.

A Janela de Form e a Caixa de Ferramentas

Um form é uma área de exibição que corresponde à janela que você verá quando o seu aplicativo estiver sendo processado. Quando você inicia um novo projeto, o Visual Basic cria um form vazio com o titulo Form1. Enquanto você desenvolve seu aplicativo, o form serve como uma prancheta, sobre a qual são desenhadas as várias partes do aplicativo. Os componentes do aplicativo que você coloca no form são chamados objetos ou controles,  tais como caixas de imagens, botões de opções e barras de deslocamento. (O Visual Basic considera o próprio form como um objeto.)

Figura 1.3 A caixa de ferramentas do Visual Basic.

Os controles são criados a partir da palheta caixa de ferramentas, que é apresentada na Figura 1.3. Cada controle é representado por uma ferramenta ou ícone da caixa de ferramentas. A maioria dos controles vistos na Figura 1.3 é intrínseca ao Visual Basic. Entretanto, essa caixa de ferramentas pode ser estendida de forma a incluir ferramentas adicionais. Clicando no submenu Components do menu Project, lhe será apresentada uma janela com muitos outros controles que podem ser adicionados à caixa de ferramentas. Basta marcá-los como selecionados e dar um Ok para que eles apareçam na caixa de ferramentas.

Você constrói a aparência de seu programa escolhendo controles da caixa de ferramentas e colocando-os sobre um form. Enquanto você está desenvolvendo um aplicativo, o Visual Basic opera de forma diferente de quando o aplicativo está sendo processado. Durante a fase de desenvolvimento, o Visual Basic provê ferramentas para auxiliá-lo a criar objetos de exibição e escrever seu programa. Você interage com os objetos colocados em um form, alterando seu tamanho, sua posição e outros atributos.

Page 4: Iniciando No Visual Basic

Porém, durante a fase de desenvolvimento, os objetos estarão sempre inativos e o código de seu programa não será executado - por exemplo, caso um objeto barra de deslocamento seja colocado em um form, você poderá alterar o seu tamanho e sua posição, mas ele não poderá ser usado para deslocar coisa alguma.

Ao iniciar a fase de processamento ou execução, o Visual Basic remove as ferramentas de desenvolvimento. O layout da janela é fixado, os objetos na tela podem então ser ativados e o usuário pode interagir com a exibição, como foi planejado no aplicativo. Nesse momento, o aplicativo ganha espaço e o Visual Basic executa as instruções de seu programa. (Na barra de titulo da janela principal, o Visual Basic identifica quando você está em fase de desenvolvimento ou de execução.)

A Janela de Propriedades

As propriedades do Visual Basic são mecanismos formais para descrição dos

atributos de um objeto. No mundo real, você pode perguntar: "Qual a cor daquele carro ?". Em Visual Basic, essa pergunta deveria ser: "Qual o valor da propriedade cor daquele carro ?" Naturalmente, a resposta em ambos os casos poderia ser "azul". Marca é outra propriedade típica de carros. Valores esperados, ou configurações, para a propriedade marca poderiam incluir Ford, Volkswagen e GM.

Cada objeto do Visual Basic tem propriedades específicas, cuja configuração controla a aparência e o comportamento do objeto no aplicativo. Algumas propriedades são restritas a um conjunto prefixado de valores. Por exemplo, a propriedade Visible (visível) de um objeto apenas pode assumir o valor True ou False (verdadeiro ou falso). Outras propriedades, como Caption (título) de uma janela de form, podem assumir qualquer valor. É importante notar que não é necessário informar o valor para todas as propriedades de todos os objetos; os valores atribuídos automaticamente para muitas propriedades, via de regra, são perfeitamente aceitáveis.

Ainda que muitas propriedades possam ser alteradas, tanto em tempo de desenvolvimento quanto em tempo de execução, a janela de propriedades, mostrada na Figura 1.4, estará ativa apenas na fase de desenvolvimento. Você pode ativar a janela de propriedades de várias formas: dando um clique nela, pressionado F4 ou, ainda, dando um clique no botão Janela de Propriedades na barra de ferramentas.

Figura 1.4 A janela de propriedades.

A caixa de lista drop-down no topo da janela de propriedades é chamada de caixa de objetos. Ela exibe o nome de todos os objetos contidos em um aplicativo, bem como o tipo de cada objeto. Inicialmente, a caixa de objeto contém apenas informações a respeito do objeto form, porém, à medida que você adiciona outros controles ao form, o Visual Basic incorpora esses objetos à lista drop-down da caixa de objetos.

Page 5: Iniciando No Visual Basic

Abaixo da caixa de objetos, você encontrará a lista de propriedades. A lista de propriedades permite percorrer todas as propriedades do objeto mostrado na caixa de objetos e ver os valores de cada propriedade. Dividida em duas colunas, uma para o nome da propriedade (esquerda) e outra para os valores das propriedades (direita), a lista de propriedades é onde você modificará as características dos objetos. Para modificar uma propriedade, você deve digitar o novo valor na área à direita do nome da propriedade na lista de propriedades ou escolher a nova configuração a partir de uma lista drop-down contendo as possíveis configurações para a propriedade em questão.

Para demonstrar como usar essas várias janelas do Visual Basic para criar um aplicativo, vamos desenvolver seu primeiro projeto.

Criando a Interação com o Usuário

Como primeiro projeto, vamos criar um programa que simplesmente meça o tempo decorrido, semelhante ao que faz um cronômetro. Um cronômetro tem um botão onde se dá um clique para iniciar a contagem do tempo, outro botão que permite parar essa contagem e um mostrador no qual se vê o tempo decorrido. Você pode usar esse modelo básico para seu programa. Em Visual Basic, um form servirá como o mostrador do relógio e para o posicionamento dos botões de início e parada. Para iniciar o desenvolvimento de seu aplicativo, você terá de examinar e modificar algumas das propriedades do form.

Configurando as Propriedades do Form

Quando o aplicativo estiver sendo processado, o form será apresentado em uma janela padronizada para aplicativos. Se você desejar que essa janela se pareça com aquelas apresentadas por outros aplicativos escritos para Windows, certos atributos devem ser semelhantes. Por exemplo, um atributo comum a todos os aplicativos Windows é o nome do aplicativo aparecer como um título na barra de título do form. Em Visual Basic, a maioria desses atributos é controlada por meio das propriedades dos objetos.

Para começar a configurar as propriedades do form, selecione-o como objeto atual, dando um clique em qualquer lugar da janela intitulada Form1. Agora, olhe para a janela de propriedades, onde Form1 é exibido na caixa de objetos. Para alterar o título do form, dê um clique na propriedade Caption na lista de propriedades. Digite Cronômetro como novo título. À medida que você digita, o novo título é exibido na barra de título da janela de form.

Quando uma propriedade somente puder assumir determinados valores, no local de entrada de valores aparece uma caixa de lista drop-down e não um campo para entrada de dados. Por exemplo, percorra a lista de propriedades e selecione a propriedade Visible. A seta para baixo, colocada no lado direito do campo de valores, agora se torna habilitada, indicando que as configurações para a propriedade Visible estarão restritas às que serão exibidas na lista drop-down. Se você der um clique no botão de seta para baixo, uma lista aparecerá abaixo para mostrar as configurações True e False, conforme mostrado

Page 6: Iniciando No Visual Basic

na Figura 1.5. Assegure-se de que a propriedade Visible seja configurada como True.

Figura 1.5 Configurando a propriedade Visible do Form.

Outra propriedade relacionada com a aparência do form é BorderStyle (estilo da borda), que controla quando o usuário pode ou não redimensionar a janela de exibição durante a execução do aplicativo. Uma vez que o aplicativo Cronômetro deverá ter aparência fixa, a sua janela não poderá ser redimensionada. Selecione a propriedade BorderStyle da lista de propriedades e então configure-a para 3 - Fixed Dialog, selecionando-a a partir da lista drop-down à direita da propriedade. (Esta opção indica que a janela terá uma borda não-redimensionável, sem botões para minimização ou maximização.)

A Propriedade Name

Todo objeto Visual Basic tem uma propriedade chamada Name (nome). Ao configurar essa propriedade, você dá ao objeto uma identidade por meio da qual é possível referenciá-lo dentro do programa. Na janela de form, você pode acessar um objeto dando um clique nele. Na porção de código do programa, é preciso referenciar-se ao objeto por meio do nome que for dado a ele mediante a propriedade Name. (Note que as propriedades Name e Caption são diferentes. O nome de um objeto é sua identificação para efeito das instruções do programa; o título (Caption) é aquilo que o usuário vê na tela - um texto identificador que é exibido na janela do aplicativo.)

Na lista de propriedades, selecione a propriedade Name. Seu valor default, mostrado na lista de propriedades, é Form1. Edite a propriedade Name do seu form, digitando o texto MeuForm no campo de valor.

Nota: Quando você altera o nome de um form, o Visual Basic reflete essa modificação na lista de arquivos exibidos na janela de Explorador do Projeto. Lembre-se de que a definição de cada form é armazenada em um arquivo separado. Quando o aplicativo é salvo, você pode escolher o nome de arquivo que deseja para seu form, porém o Visual Basic sugerirá um nome de arquivo baseado no nome do form.

Adicionando Objetos de Exibição

Retornemos ao projeto do form para criar os botões que iniciarão e pararão o cronômetro:

1. Dê um clique na ferramenta Botão de Comando na caixa de ferramentas e movimente o ponteiro do mouse para a janela de form em branco. O cursor irá transformar-se numa cruz, indicando que você se encontra em modo de tracejamento.

2. Posicione o cursor no canto superior esquerdo do form.

3. Pressione o botão do mouse e arraste o cursor para baixo e para a direita.

Page 7: Iniciando No Visual Basic

4. Solte o botão do mouse

Quando você soltar o botão do mouse, o Visual Basic criará o objeto botão de comando na área delineada pela operação de arrasto. O seu botão de comando deverá ser semelhante ao mostrado na Figura 1.6.

Após a criação do botão de comando, a ferramenta Ponteiro irá tornar-se novamente a ferramenta ativa da caixa de ferramentas. Quando a ferramenta Ponteiro está ativa, você pode editar o form, deslocando objetos e redimensionando-os. Para deslocar um objeto, basta arrastá-lo para a nova posição. Para redimensionar um objeto, arraste uma de suas alças (mostradas na Figura 1.6) para expandi-lo ou encolhê-lo. Caso as alças não estejam visíveis, dê um clique sobre o objeto, para selecioná-lo.

Agora, crie um segundo botão de comando, desta vez usando um atalho. Dê um clique duplo sobre a ferramenta Botão de Comando na caixa de ferramentas. O Visual Basic criará um botão de dimensões padronizadas, colocando-o no centro do form. Após isso, posicione-o e altere suas dimensões, de forma que ambos os botões de comando apareçam do lado esquerdo da tela, um abaixo do outro, e tenham o mesmo tamanho.

Figura 1.6 O botão de comando recém-criado.

Esses dois botões, agora rotulados automaticamente como Command1 e Command2, servirão como botões de início e parada para o aplicativo Cronômetro. Por questões de clareza, você deveria assinalar seus títulos (Caption) coerentemente. Para assinalar essa propriedade dos botões, siga o mesmo processo que foi adotado para assinalar as propriedades do form:

1. Dê um clique no botão de comando superior para selecioná-lo.

2. Selecione a propriedade Caption da lista de propriedades na janela de propriedades.

3. No campo de valor, altere a propriedade para Iniciar.

4. Dê um clique no botão de comando inferior e altere a sua propriedade Caption para Parar.

Ainda que tenha alterado apenas a propriedade Caption, você deveria modificar os nomes dos botões (a propriedade Name), para poder referenciá-los mais facilmente no código de seu programa. (Lembre-se de que a propriedade Caption e Name não representam a mesma coisa. A alteração de uma não afeta a outra.) Dê um clique no botão superior e selecione sua propriedade Name. Na campo de valor da propriedade, altere o nome Command1, assinalado automaticamente, para Btnlniciar. A seguir, dê um clique no botão inferior e altere a sua propriedade Name para BtnParar.

Escolhendo Nomes

Page 8: Iniciando No Visual Basic

Não é imprescindível renomear os botões no aplicativo Cronômetro que se está criando, porém você poderá achar que fazer referência a BtnIniciar em seu aplicativo é mais claro do que referenciar a Command1. T.S. Eliot dizia: "É muito difícil dar nome a Gatos"; o mesmo também é verdadeiro para objetos em programas. Você pode concluir que nomes abreviados são mais fáceis de usar, ou pode achar conveniente deixar que o sistema forneça os nomes. No entanto, quando você retornar ao programa seis meses depois de criá-lo, certamente será muito difícil determinar o que exatamente o programa faz, se não tiver atribuído nomes que contenham algum significado.

Você deveria tentar aplicar na designação de nomes uma convenção que permitisse especificar tanto o contexto quanto a descrição. Os nomes BtnIniciar e BtnParar, por exemplo, têm um prefixo de três letras que identifica o tipo de objeto no programa. Em português, freqüentemente usamos frases para estabelecimento do contexto, por exemplo, em vez de simplesmente fazer menção a "Deputado João", eu poderia referir-me usando a frase "meu gato, Deputado João", para evitar prováveis conflitos entre meu gato e algum representante de nossa classe política. Em Visual Basic, entretanto, não é possível usar a referência "O botão chamado Iniciar", assim é muito útil abreviar o contexto (Btn) e o nome (Iniciar) em um identificador simples (Btnlniciar).

Completando o Visual do Aplicativo

Agora que você já posicionou os controles do usuário para o aplicativo Cronômetro na tela, é necessário exibir os resultados produzidos quando o programa estiver sendo processado. Vamos adicionar algumas caixas de texto ao form:

1. Dê um clique duplo na ferramenta Caixa de Texto na caixa de ferramentas para criar uma caixa de texto. Ela aparecerá no centro do form.

2. Desloque a caixa de texto para a área superior do form, à direita dos botões de comando.

3. Usando o mesmo método, crie mais duas caixas de texto, dispondo as três caixas conforme mostrado a seguir:

4. Use o mouse para selecionar o conjunto dos controles e posicioná-los no centro do form. Para isso clique numa área do form próxima ao canto inferior direito de Text3 e, mantendo o botão pressionado, arraste o mouse até que o retângulo tracejado de seleção envolva todos os controles. Solte o botão do mouse. Clique sobre qualquer um dos controles e arraste-os para a posição desejada antes de soltar o botão.

É necessário nomear esses novos objetos. Dê um clique em cada caixa de texto e modifique a propriedade Name, usando o nome TxtInicial para a caixa de texto superior, TxtFinal para a caixa de texto intermediária e TxtDecorrido para a caixa de texto inferior.

Page 9: Iniciando No Visual Basic

É preciso também remover os textos defaults que aparecem dentro das caixas de texto. Para cada caixa de texto, selecione a propriedade Text: da lista de propriedades e apague todos os caracteres do campo de valor da propriedade. Isso fará com que o valor da propriedade Text seja assinalado para "vazio" (uma cadeia de caracteres de comprimento zero).

Todos os elementos necessários para a parte de seu aplicativo com a qual o usuário interagirá já estão em seu lugar. De fato, você pode "rodar" o aplicativo como ele se encontra no momento. Escolha a opção Start do menu Run, dê um clique no botão Iniciar da barra de ferramentas ou pressione a tecla F5. A palheta caixa de ferramentas desaparece, como também a versão de desenvolvimento do form, e a janela Cronômetro é exibida, como mostrado na Figura 1.8. Você pode deslocá-la através do vídeo, e ainda pode dar um clique nos botões Iniciar e Parar. (Evidentemente, nada acontecerá, pois você ainda não escreveu em Visual Basic as instruções que calcularão o tempo decorrido.) Escolha a opção End do menu Run do Visual Basic ou dê um clique no botão Encerrar contido na barra de ferramentas para deixar o ambiente de processamento e retornar ao ambiente de projeto do Visual Basic.

Figura 1.7 A janela do aplicativo Cronômetro em tempo de execução.

Escrevendo o Código

Codificar - escrever as instruções de linguagem que controlarão a operação do programa - é o coração da programação. Agora que você já completou a parte de interação do seu aplicativo, é preciso fazer o programa funcionar. Uma vez que você estará escrevendo comandos na linguagem Visual Basic, é razoável imaginar que esses comandos estarão controlando o computador, ainda que indiretamente. Para entender essa noção, considere um avião a jato.

Quando o piloto do jato deseja voar mais alto, ele puxa a alavanca de controle. O resultado dessa ação é uma alteração na posição dos flaps do avião, e o jato começa a subir. Em jatos modernos, não há qualquer conexão física entre a alavanca e os flaps. Quando o piloto puxa a alavanca, um sensor mede o quanto ela foi deslocada e envia um sinal para o dispositivo hidráulico que controla a posição dos flaps. Entretanto, do ponto de vista do piloto, é a alavanca que controla o avião.

Não é primordial para o piloto saber que o deslocamento de um centímetro na alavanca corresponde a uma elevação de cinco ou dez graus dos flaps. É suficiente que ele saiba como o avião responde à alteração.

Da mesma forma que o piloto de um jato, você está no controle de seu computador, e o Visual Basic é o seu painel de instrumentos. A seção a seguir tem por objetivo lhe dar uma visão da cabine de seu sistema - isto é, com o que ele se parece para um programador Visual Basic. Naturalmente, fora dessa cabine de controle, muita coisa estará acontecendo, porém por alguns instantes concentrar-nos-emos numa discussão geral, deixando a abordagem dos detalhes relevantes sobre o sistema subjacente para os próximos capítulos.

Page 10: Iniciando No Visual Basic

Procedimentos de Eventos

Você já estudou propriedades de objetos e como elas podem ser modificadas para afetar um objeto. Similarmente, cada objeto pode ser associado a uma coleção de procedimentos que são executados em instantes específicos. Um procedimento é um grupo de instruções na linguagem Visual Basic. As instruções contidas no procedimento serão executadas quando o procedimento for executado. Todo código executável que você escreve será encapsulado em um ou outro tipo de procedimento.

Cada procedimento associado a um objeto está ligado a um determinado evento ou ação, portanto é chamado de procedimento de evento. Eventos incluem ações como dar um clique, um evento disparado quando o usuário pressiona o botão do mouse, e redimensionar, um evento que ocorre quando o usuário altera a dimensão de uma janela de form. Eventos podem ocorrer apenas em tempo de execução, e não durante a fase de desenvolvimento. Para todo e qualquer objeto, há uma certo número de eventos que podem ser disparados; esses eventos são descritos no Capítulo 5.

Retornemos ao nosso aplicativo Cronômetro. Dê um clique duplo no botão Iniciar no form. O Visual Basic abrirá uma janela de código, semelhante à mostrada na Figura 1. 8. A janela de código contém o título MeuForm.frm, que indica a relação entre o código e o form. O código que você introduzir nessa janela será armazenado no mesmo arquivo que contém os objetos de exibição do form.

Figura 1.8 A janela de código para o aplicativo Cronômetro.

A caixa Object, na região superior esquerda da janela de código, exibe o nome do objeto selecionado: Btnlniciar. A caixa de procedimento, ao lado da caixa Object, mostra qual procedimento está sendo editado. Como você ainda não selecionou um dos procedimentos associados ao objeto Btnlniciar, o Visual Basic selecionou automaticamente o procedimento Click. O procedimento mostrado na janela de código é o que será executado quando o usuário der um clique no botão Iniciar durante a fase de execução do aplicativo. Embora você ainda não tenha escrito qualquer código, já aparecem duas instruções na região de texto da janela de código:

Private Sub Btnlniciar_Click ()

End Sub

Quando o botão de comando foi criado, o Visual Basic criou automaticamente um conjunto de procedimentos de eventos para o objeto. Como você já deve ter imaginado, esses procedimentos criados automaticamente nada fazem; eles contêm apenas uma declaração do procedimento (primeira linha) e a instrução marcando o final do procedimento (End Sub).

Declarações de Procedimento

Page 11: Iniciando No Visual Basic

Na declaração do procedimento, a palavra Sub identifica o início do procedimento. A seguir, vem o nome do procedimento neste caso, BtnIniciar_Click. Após isso, encontra-se uma lista de parâmetros, os quais completam a definição. (Apesar de não serem usados no procedimento, os parênteses são obrigatórios; discutiremos a sua função no Capítulo 4). A palavra Private significa que o procedimento só existe para o código pertencente ao arquivo do Form. Outras partes do programa não podem fazer referência a este procedimento.

O nome de um procedimento serve para caracterizá-lo como um procedimento de evento. Nem todos os procedimentos são procedimentos de eventos. Você pode criar um procedimento em Visual Basic, dando um nome qualquer, tal como lâmpada ou almofada. Entretanto, o nome de um procedimento de evento deve concordar com as seguintes regras:

A primeira parte do nome deve ser igual ao nome de um objeto que tenha sido criado no form. (Ou precisa ser a palavra Form, quando o objeto em questão for o próprio form.)

A última parte do nome deve ser o nome de um evento. As duas partes devem estar ligadas por um caractere de sublinhado

( _ ).

O objeto associado ao procedimento BtnIniciar_Click é o botão de comando Iniciar (Btnlniciar), e o evento é o Click. Quando o programa estiver sendo processado, acontecerá mais ou menos o seguinte: o aplicativo estará em algum lugar do vídeo aguardando que algo aconteça. Enquanto isso, aparece a usuária Marta, com seu mouse. Ela movimenta o ponteiro do mouse sobre a imagem na tela e dá um clique. O Windows cutuca o aplicativo e lhe diz: "Ei, faça alguma coisa!". Quando o Visual Basic determinar que o clique foi produzido sobre o botão chamado BtnIniciar, ele procurará o procedimento BtnIniciar_Click e executará as instruções contidas naquele procedimento. Como programador, seu trabalho é decidir o que aquelas instruções deverão fazer.

Para verificar como isso funciona, digite a instrução Debug.Print "Alô, marinheiro" na linha em branco que há entre as instruções Sub e End. A  janela de código deverá ser semelhante a:

Private Sub BtnIniciar_Click ()

Debug.Print "Alô, marinheiro"

End Sub

A instrução Debug.Print faz com que o Visual Basic escreva o texto em uma janela especial chamada de janela Immediate. Pressione F5 para deixar o ambiente de desenvolvimento e iniciar a execução do aplicativo (da forma que ele se encontra). Quando você der um clique sobre o botão Iniciar, as palavras Alô, marinheiro serão escritas na janela Immediate.

Page 12: Iniciando No Visual Basic

Agora, escolha a opção End do menu Run do Visual Basic. O Visual Basic parará a execução do aplicativo e retornará ao ambiente de desenvolvimento, onde você pode continuar o projeto de seu aplicativo. (Antes de abandonar a janela de código, lembre-se de eliminar a instrução Debug.Print do procedimento BtnIniciar_Click.)

Dica: Note que palavras como Private, Sub, Debug, Print e End aparecem na tela da janela de código, com cores diferentes do restante do código. O Visual Basic destaca partes diferentes do código com várias cores para facilitar a localização de componentes individuais. Você pode controlar as cores que serão usadas, escolhendo sua opção em Editor Format da caixa de diálogo exibida pelo comando Options do menu Tools. Nela você pode assinalar as cores para texto e para fundo de palavras-chave, identificadores, comentários e inúmeros outros elementos decódigo.

Declarações de Variável

Quando o usuário der um clique no botão Iniciar no aplicativo Cronômetro, o programa precisará indicar que horas são. (O tempo de início.) Então, quando o usuário der um clique no botão Parar, o programa deve subtrair o tempo de início do tempo de término, para calcular o tempo decorrido. Naturalmente, você terá de escrever as linhas de código para que o programa possa fazer isso.

O Visual Basic usa uma função chamada Now, para fornecer a hora atual. Uma função é um tipo especial de procedimento que retorna um valor. (As funções do Visual Basic estão intimamente relacionadas com o conceito de funções matemáticas. As funções Visual Basic chamadas Sin, Cos e Tan, por exemplo, retornam o valor do seno, co-seno e tangente de um ângulo.) Quando o usuário der um clique no botão Iniciar, o seu programa deve chamar a função Now, que retornará um valor hora atual (de início). O programa deverá então memorizar esse valor até que ele possa ser subtraído do tempo final, quando o usuário der um clique no botão Parar. Para guardar um valor em um programa de computador, você deve reservar um local para ele na memória do computador. Pode-se fazer isso com declarações de variável.

O Visual Basic Supervisiona Você

Se durante a digitação de instruções na janela de código ocorrer algum erro, o Visual Basic poderá notificá-lo colocando o erro em destaque e exibindo uma caixa de diálogo com informações. Essa supervisão, chamada verificação automática de sintaxe, é efetuada toda vez que a tecla Enter é pressionada. O Visual Basic, naturalmente, não pode detectar todos os tipos de erro que se podem cometer, mas ele faz uma verificação de erros de sintaxe, isto é, enganos cometidos sobre a forma que a linguagem Visual Basic é usada, tais como palavra-chave ausente, palavras fora de ordem dentro de uma instrução, pontuação incorreta e assim por diante. Por exemplo, se você digitar TxtFinal..Text em vez de TxtFinal.Text, o Visual Basic informar-lhe-á sobre o engano ou erro. É possível desativar a verificação automática de sintaxe: escolha a opção

Page 13: Iniciando No Visual Basic

Options do menu Tools e desmarque a opção Auto Syntax Checking na caixa de diálogo de opções.

Na janela de código, dê um clique sobre o botão de seta para baixo, ao lado da caixa Object, para que seja exibida uma lista com todos os objetos criados no form. A partir dessa lista, selecione a entrada (General), que é a categoria na qual se incluem todos os procedimentos não-associados a um objeto em particular. Então, o Visual Basic altera automaticamente o titulo da caixa de procedimentos para Declarations. (Chamaremos essa parte do código de programa de seção de declarações gerais de seu código.) Agora, introduza as seguintes linhas na área de texto da janela de código:

Dim TempoInicial as Variant

Dim TempoFinal as Variant

Dim TempoDecorrido as Variant

Esses comandos avisam ao Visual Basic que você deseja reservar a área de memória para os valores de tempo Inicial, Final e Decorrido, nas variáveis chamadas TempoInicial, TempoFinal e TempoDecorrido. Variáveis são, em essência, nomes para porções reservadas da memória do computador. (Mais detalhes sobre isso nos Capítulos 2 e 3.) A instrução Dim diz ao Visual Basic para reservar memória e como designar essa área de memória. A instrução Dim é uma declaração, pois indica ao Visual Basic como o programa deve ser configurado.

Cada uma das três instruções mostradas acima declara uma variável simples e todas têm este formato:

Dim nome As Variant

Dim e As são palavras-chave, palavras reservadas que têm significado especial para o Visual Basic. As instruções diferem apenas pelo nome único que deve ser dado para cada variável. A palavra-chave Variant instrui o Visual Basic para reservar memória suficiente para qualquer tipo de valor. (Você poderia usar palavras-chave diferentes para fazer uma declaração mais específica. Por exemplo, ao usar Integer em vez de Variant, o Visual Basic seria instruído a reservar somente a memória suficiente para armazenar um valor inteiro.)

Instruções Executáveis

Agora que você reservou memória para salvar valores correspondentes a instantes do tempo, pode escrever o código executável do programa. Ao contrário de uma declaração, que estabelece uma configuração para o programa, uma instrução executável provoca alguma coisa quando é executada. Por exemplo, a instrução Debug.Print que foi usada anteriormente é uma instrução executável.

Terminologia

Page 14: Iniciando No Visual Basic

Se a palavra Dim lhe parece sem significado e você acha que Declare seria mais apropriado, tem razão. Dim, entretanto, é a abreviatura para Dimension, proveniente das primeiras versões da linguagem Basic, datadas da década de 1960. Por questões de compatibilidade, as novas versões de linguagens de programação mantêm características das versões anteriores.

Selecione o objeto BtnIniciar na caixa Object da janela de código. Edite o procedimento BtnIniciar_Click, introduzindo estas instruções entre as linhas Private Sub BtnIniciar_Click () e End Sub:

TempoInicial = Now

TxtInicial.Text = Format(TempoInicial, "hh:mm:ss")

TxtFinal.Text = ""

TxtDecorrido.Text = ""

Quando o programa estiver sendo processado e o usuário der um clique no botão Iniciar, essas instruções serão executadas. A primeira linha de código usa a função Now para recuperar a hora atual e salvá-la na posição de memória chamada TempoInicial. A próxima linha exibe a hora atual na caixa de texto superior (TxtInicial), configurando a propriedade Text desse objeto. Além disto, ela formata a hora inicial em horas, minutos e segundos, com a função Format do Visual Basic. As duas linhas seguintes apagam o conteúdo das outras duas caixas de texto (TxtFinal e TxtDecorrido), assinalando suas propriedades Text para uma string vazia.

Agora, complete o programa, selecionando o objeto BtnParar na caixa

Object da janela de código. Edite o seu procedimento de evento Click, como

mostrado abaixo:

Private Sub BtnParar_Click ( )

TempoFinal = Now

TempoDecorrido = TempoFinal - TempoInicial

TxtFinal.Text = Format(TempoFinal, "hh:mm:ss")

TxtDecorrido.Text = Format(TempoDecorrido, "hh:mm:ss")

End Sub

Esse procedimento será executado quando o usuário der um clique no botão Parar. Primeiro, a função Now retorna a hora atual, que é salva na variável TempoFinal. A próxima linha calcula o tempo decorrido, subtraindo o valor salvo em TempoInicial de TempoFinal. Então, o tempo final e o tempo

Page 15: Iniciando No Visual Basic

decorrido são escritos na tela, por meio de sua assinalação às propriedades Text dos objetos TxtFinal e TxtDecorrido. Da mesma forma que no procedimento BtnIniciar Click, a função Format converte os valores de horas para um formato que exiba horas, minutos e segundos.

Processando o Programa

Para iniciar o aplicativo, basta pressionar a tecla F5. Para usar o "cronômetro", dê um clique no botão Iniciar, esperando alguns segundos, e então dê um clique no botão Parar. Você deverá observar algo semelhante ao resultado mostrado na Figura 1.9.

Você pode dar outro clique no botão Iniciar para reiniciar a contagem do tempo. Para fechar o aplicativo Cronômetro, dê um clique no botão Encerrar da barra de ferramentas, pressione a tecla Alt-F4,ou clique na caixa de encerramento no canto alto direito do formulário ou escolha a opção Close do menu Control (este é o menu que aparece quando você dá um clique

na caixa do canto superior esquerdo de uma janela, por vezes denominado menu de sistema).

Figura 1. 9 Processando o aplicativo Cronômetro.

Revisando o Projeto

No inicio, os detalhes de programação são tão envolventes que é comum esquecermos do ponto de vista do usuário final. Vamos olhar novamente o esquema de interação do Cronômetro: dois botões, três caixas de texto. Bastante simples. Entretanto, é preciso levar em consideração uma pessoa que não conheça o objetivo do programa. Os termos Iniciar e Parar são auto-explicativos, mas que tipo de interpretação se pode fazer das três caixas de texto em branco? Sem dúvida, uma das melhorias que você pode fazer é colocar um rótulo nessas caixas, de forma que fique mais claro o tipo de informação que elas fornecem.

O ícone da ferramenta Rótulo na caixa de ferramentas se parece com uma letra A maiúscula. Usando a ferramenta Rótulo, trace um objeto de rótulo próximo da caixa de texto superior na janela de form. Você poderá ter de redimensionar o form ou deslocar as caixas de texto para a direita, para criar espaço para os rótulos. Como já vimos, você pode deslocar as três caixas de texto como um grupo, se selecioná-las com o retângulo de seleção produzido quando se arrasta o mouse com o botão esquerdo pressionado. Uma outra forma de selecioná-las em grupo é dar um clique sobre uma e , mantendo a tecla Ctrl pressionada, dar um clique sobre as outras duas caixas de texto. Essa forma de seleção em grupo é conveniente quando há outros controles na área que o retângulo de seleção cobriria e que não desejamos ver selecionados.

Agora, dê um clique sobre o novo objeto de rótulo, selecione a propriedade Caption do rótulo na lista de propriedades e digite Hora Inicial para o valor da

Page 16: Iniciando No Visual Basic

propriedade. Em seguida, crie mais dois objetos de rótulo, próximos às outras duas caixas de texto, e configure a propriedade Caption da primeira para Hora Final: e da segunda para Tempo Decorrido:, como mostrado naFigura 1.10.

Figura 1.10 Adicionando rótulos às caixas de texto.

Alguma outra melhoria a considerar? Pressione F5 para processar o aplicativo novamente e então dê um clique no botão Parar, antes de dar um clique no botão Iniciar. O aplicativo deveria reagir de maneira razoável a esse erro do usuário, mas, em vez disso, ocorreu um resultado inesperado: a hora final e o tempo decorrido são exibidos sem a hora inicial. Você terá de deixar o aplicativo e retornar ao ambiente de desenvolvimento para resolver esse problema.

Em função da estrutura atual, a forma mais simples de resolver esse problema é desabilitar o uso do botão Parar, enquanto o usuário não der um clique no botão Iniciar. Na janela do form, dê um clique no botão Parar para selecioná-lo e então selecione a propriedade Enabled (habilitado) da lista de propriedades. Clique na seta para baixo que exibe as opções de valores para esta propriedade e escolha a opção False. Dessa forma, o botão estará desabilitado quando o programa iniciar a sua execução.

Abra a janela de código e edite o procedimento BtnIniciar_Click como mostrado abaixo (incluindo as duas linhas que aparecem destacadas). Você pode usar as teclas de direção para se movimentar até o ponto de inserção na janela de código, ou então simplesmente dar um clique com o mouse para assinalar o novo ponto de inserção.

Private Sub BtnIniciar_Click ( )

TempoInicial = Now

TxtInicial.Text = Format(TempoInicial, "hh:mm:ss")

TxtFinal.Text = ""

TxtDecorrido.Text = ""

BtnParar.Enabled = True

BtnIniciar.Enabled = False

End Sub

A nova codificação, reabilita o botão Parar quando o usuário dá um clique no botão Iniciar. A seguir, é desabilitado o botão Iniciar. Com isso, elimina-se outro erro potencial: dar um clique no botão Iniciar repetidamente.

Para completar essas modificações, você precisa editar o procedimento BtnParar_Click adicionando as duas linhas mostradas abaixo:

Page 17: Iniciando No Visual Basic

Private Sub BtnParar_Click( )

TempoFinal = Now

TempoDecorrido = TempoFinal - Tempolnicial

TxtFinal.Text = Format(TempoFinal, "hh:mm:ss")

TxtDecorrido.Text = Format(TempoDecorrido, "hh:mm:ss")

BtnParar.Enabled = False

BtnIniciar.Enabled = True

End Sub

A Figura 1.11 mostra a versão final da interação do aplicativo. Nessa ilustração, o usuário deu um clique no botão Iniciar e o cronômetro está rodando.

Figura1.11 A versão final do aplicativo Cronômetro.

Existem ainda inúmeras formas de melhorar o aplicativo. Por exemplo, lembrando que alguns cronômetros possuem um único botão, seria possível modificar o programa de forma a conter apenas um botão cuja propriedade Caption fosse alterada de Iniciar para Parar (ou vice-versa) cada vez que um clique fosse dado nele. Provavelmente, você próprio pode imaginar outras melhorias.

Salvando o Seu Programa

Você tem mais uma preocupação de ordem prática: salvar o seu programa. Abra o menu File e escolha a opção Save Project ou dê um clique no botão Salvamento de Projeto na barra de ferramentas. Na caixa de diálogo Salve File As, mostrada na Figura 1.12, o Visual Basic pede o nome do arquivo e o diretório no qual o form e os procedimentos associados deverão ser salvos, sugerindo MEUFORM.FRM (o nome do form mais o sufixo FRM) como nome de arquivo default para o aplicativo Cronômetro. Após fornecer as informações necessárias, dê um clique em OK.

Figura 1.12 A caixa de diálogo Save File As.

A seguir, o Visual Basic exibirá a caixa de diálogo Save Project As, mostrada na Figura 1.13, que lhe permite salvar o arquivo do projeto. O arquivo do projeto contém os nomes de todos os arquivos forms e algumas informações adicionais sobre o projeto. (O aplicativo Cronômetro tem apenas um arquivo form.) O Visual Basic sugerirá o nome de arquivo default PROJECT 1. VBP para o arquivo de projeto do aplicativo. Por ora, salve o aplicativo Cronômetro com o nome CRONOM.VBP. (Retornaremos a esse projeto em um capítulo posterior.)

Page 18: Iniciando No Visual Basic

Figura 1.13 A caixa de diálogo Save Project As.

Para carregar e processar o seu aplicativo mais tarde, você precisará em primeiro lugar carregar o Visual Basic. (Para criar uma versão do aplicativo que possa ser processada independentemente do Visual Basic, você deverá compilar o programa, como será feito num capítulo à frente.) Em seguida, escolha a opção Open Project do menu File do Visual Basic, ou então dê um clique no botão Abertura de Projeto na barra de ferramentas. A caixa de diálogo Open Project exibe uma lista com todos os arquivos de projeto (todos os arquivos com extensão VBP). Abra o arquivo CRONOM.VBP dando um clique duplo no nome do arquivo da lista, ou selecionando-o e dando um clique no botão Abrir. Pressione F5 para processar o aplicativo, ou se você desejar fazer alguma modificação adicional, abra a janela do form ou de código, dando um clique no botão apropriado na janela do Explorador do Projeto.

Page 19: Iniciando No Visual Basic

Fundamentos de Programação para Visual Basic

Com certeza, você deve estar familiarizado com a terminologia usada na indústria de computadores: bits, bytes, RAM, ROM, CPU e assim por diante. No entanto, se você tem apenas uma idéia geral do significado desses termos, não deixe de ler as próximas seções. Compreender o que está acontecendo dentro do computador é uma parte importante do aprendizado de programação. Naturalmente, você pode apenas aprender as regras e fazer um trabalho razoável, porém alguns conhecimentos adicionais poderão levá-lo a se sentir mais produtivo e confortável com relação aos computadores.

Computadores e Dados

Computadores são ferramentas para tratamento de informações, da mesma forma que martelos e serrotes servem ao tratamento de madeira. Enquanto madeira é medida em polegadas ou centímetros, uma informação é medida em bits. Um bit é a unidade fundamental que mede a quantidade de informação que pode ser transferida de um lugar para outro. É o bloco atômico de construção do universo de informações. A resposta a uma questão, por exemplo, requer pelo menos um bit de informação - quando não há bit não há resposta. No papel, um bit é convencionalmente representado pelo número 0 ou 1. Em um computador digital, um bit é representado pelo existência ou não de uma corrente elétrica.

Quando você tem 20 centímetros de madeira, sabe que está lidando com

uma quantidade de material palpável. Porém, o que significa ter 3 bits de informação? Como Humpty Dumpty disse em "Alice no País do Maravilhas", significa "o que eu desejar que signifique". Como será mostrado pela Figura 2.1, três bits de informação poderiam representar respostas para três perguntas: "É maior do que a caixa de pão? É uma cor brilhante? Pode cantar?" (não, sim, não); uma série de voltas para a esquerda ou para a direita (direita, esquerda, direita); ou outros exemplos.

O significado da informação representada por bits depende do contexto. Para entender isso, imagine que um amigo se aproxime de você na rua e diga: "Quarenta e dois". A sua primeira reação provavelmente seria de espanto. Entretanto, se após a saudação você tivesse feito uma pergunta do tipo "Qual a sua idade?" ou "Quantas

Page 20: Iniciando No Visual Basic

vezes?", a resposta teria um significado mais ou menos evidente. A sua pergunta fornece um contexto para entendimento da resposta. Outras vezes, apesar de não haver uma pergunta, há algum fato ocorrido num passado bem recente que permite a inferência do contexto. Por exemplo, se você se encontrasse com um amigo que no dia anterior foi com você ao cinema ver um filme de terror, uma frase do tipo "Belas bruxas" teria o contexto "filme" facilmente inferido.

Figura 2.1 Bits representando informações.

Em um computador, alguns contextos são inferidos com mais freqüência do que outros. Um contexto muito comum é o numérico. Uma vez que bits são escritos como 0s e 1s, um grupo deles quase sempre representa um número binário (um valor do sistema binário, isto é, base 2).

Representando Valores Numéricos

O sistema numérico decimal (base 10) usa dez símbolos diferentes: 0, 1, 2, 3, 4, 5, 6, 7, 8 e 9 para representar os números. (Tenha em mente que esses dígitos são apenas símbolos; os romanos, por exemplo, usavam o símbolo V para representar o número 5 e X para representar o número 10) Para se representar um número maior do que 9 (digamos 14) no sistema numérico decimal, há uma combinação de dois símbolos, sendo que a posição de cada um tem um significado especial. A progressão de valores representada pelas posições, como mostrado naFigura 2.2, corresponde a potências crescentes de 10. Um número decimal que contenha vários algarismos é uma soma de potências de 10. O número 14, por exemplo, representa a soma de 1 dezena (10 1) e 4 unidades (10 0); o número 243, por usa vez, é a soma de 2 centenas (10 2), 4 dezenas (10 1) e 3 unidades (10 0), e assim por diante.

Figura 2.2 Valores posicionais no sistema de numeração decimal.

Esse método geral de representação numérica também pode ser usado com outras bases além da decimal. Por exemplo, o sistema numérico na base 7 usa sete dígitos, 0, 1, 2, 3, 4, 5 e 6, sendo que o valor de cada posição aumenta em potências de 7, como é mostrado na Figura 2.3. (Quando um número é seguido por um subscrito, isto significa que o número indica a base; números sem subscritos, a menos que haja indicação em contrário, são subentendidos como sendo de base 10.)

Figura 2.3 Valores posicionais no sistema numérico de base 7.

Page 21: Iniciando No Visual Basic

Certamente, agora, você conhece as regras do jogo. O sistema binário usa dois dígitos (0 e 1), e cada posição representa um incremento de valor posicional de potências de 2. (Veja a Figura 2.4.) O sistema binário é apenas um dos mecanismos que serão adotados para permitir a representação de números em computadores. Naturalmente, você consegue realizar operações aritméticas em qualquer sistema numérico com a mesma facilidade que no sistema de base 10; ao utilizar números binários, os computadores apenas podem fazer somas, subtrações, multiplicações e divisões.

Figura 2.4 Valores posicionais no sistema numérico de base 2 (binário).

Representando Caracteres

Na maioria dos casos, não é suficiente representar apenas informações numéricas.

Como é que você pode ultrapassar o contexto de simples números? Uma das formas seria aplicar uma codificação padronizada. No código Morse Internacional, usado para envio de sinais telegráficos, determinadas seqüências de sons representam letras do alfabeto; três pontos em sucessão rápida representam a letra S; três pontos seguidos por um traço, a letra V; e assim por diante. De forma muito semelhante, os dígitos 0 e 1 são combinados para criar um código para computadores.

O padrão ASCII (American Standard Code for Information Interchange - Código Padrão Americano para Troca de Informações) especifica as regras de combinação de 0s e 1s para formar um código para computadores. O ASCII usa valores numéricos para definir o conjunto de caracteres da língua inglesa, incluindo letras maiúsculas e minúsculas, algarismos, sinais de pontuação e outros símbolos. A versão estendida do ASCII adotada pela grande maioria dos sistemas de computadores usa 8 bits para representar cada letra, número, sinal de pontuação e outros símbolos comuns à linguagem escrita. A Figura 2.5, mostra alguns exemplos do código ASCII.

Figura 2.5 Padrão ASCII para a representação de alguns caracteres

Entretanto, é importante lembrar que a simples visualização de um conjunto de bits não revelará qual o contexto associado. Por exemplo, a seqüência 01000001 representa a letra A em código ASCII, mas também pode ser interpretada como a representação binária do número decimal 65. Como se vê, a interpretação da informação

Page 22: Iniciando No Visual Basic

contida num conjunto de bits depende do contexto. Algumas vezes, você pode tirar vantagem do fato de um valor poder ser usado tanto para a representação de números inteiros quanto para letras. Por exemplo, o fato de cada caractere possuir um valor numérico significa que você pode testar quando um caractere é maiúsculo, verificando se o seu valor numérico é maior ou igual a 65 (ASCII "A") e menor ou igual a 90 (ASCII "Z").

Usando Bits, Bytes e Palavras

O uso de bits para representar informações permite ao sistema de computação armazenar ou "memorizar" as informações. Entretanto, organizar a memória dos computadores tomando-se como base o bit é inconveniente, pois apenas um bit não representa muita informação. Por exemplo, com o código estendido do ASCII são necessários 8 bits para representar um simples caractere.

De fato, o comprimento de um caracter é usado como unidade padrão de medida. Essa unidade padrão de medida contendo 8 bits é chamada de byte. Para fazer referência a grandes quantidades de dados, os prefixos do sistema métrico kilo, mega e giga são adicionados ao termo byte. Em virtude da preferência dos cientistas de computação pelas potências de 2, um kilobyte (Kbyte) representa 1.024 (2 ^ 10) bytes, enquanto um Megabyte representa 1.048.576 (2 ^ 20) bytes. Após isso vem o gigabyte (2 ^ 30), o terabyte (2 ^ 40) e o pentabyte (2 ^ 50). Você não precisa ficar extremamente preocupado com o que vem depois.

Porém, um byte. não é apropriado para a representação da maioria dos valores numéricos. O padrão de 8 bits pode apenas representar os números decimais de 0 a 255. Portanto, para tornar mais eficientes as operações aritméticas, a maioria dos computadores trabalha com dados em blocos maiores do que um byte. O número de bits que um computador "prefere" usar é chamado de tamanho de palavra do computador e não é padronizado. Muitos computadores de grande porte e micros modernos têm um comprimento de palavra de 32 bits, o que permite a acomodação de números da ordem de bilhões. (Ainda que o hardware seja otimizado para usar esse comprimento de palavra, os computadores não se limitam ao tratamento de valores que possam ser representados em 32 bits.)

Armazenando Informação no Computador

A Figura 2.6 mostra um diagrama de blocos simplificado de um computador. No que se refere ao diagrama, você pode pensar em

Page 23: Iniciando No Visual Basic

memória como a caixa onde os bits são armazenados quando o computador está processando. No momento, restringiremos nossa discussão à memória eletrônica chamada RAM (Random Access Memory - Memória de Acesso Aleatório).

Figura 2.6 Um diagrama de blocos de um sistema de computação.

Você pode imaginar a RAM como sendo uma longa fila de caixas, cada qual grande o suficiente para conter 1 byte de dados e ser identificada por um número. Por exemplo, alguém poderia dizer, "Dê-me o byte de dados da caixa 27441" ou "Coloque a letra g na caixa 13". Esse número identificador da localização da memória é chamado de endereço da memória.

O Visual Basic, como os demais compiladores, permite o uso de nomes em lugar de números para referências a locais de memória. (O computador está habilitado a usar endereços numéricos, porém é mais confortável para os usuários trabalhar com nomes simbólicos de variáveis.) Ainda que o Visual Basic possa associar um nome a uma seqüência de bytes, cada variável do Visual Basic corresponde a uma localização de memória. Mais adiante você aprenderá mais sobre como o Visual Basic armazena e representa os diferentes tipos de dados.

Instruções de Computador

Vejamos, agora, o que o computador faz com os dados que ele contém. Dentro do computador, um ou dois chips atuam como unidade central de processamento. A CPU trata os dados na memória de acordo com um conjunto de instruções chamado de programa. Para que o computador possa executar as instruções, o programa precisa estar na RAM. Instruções, da mesma forma que os dados, precisam ser representadas por seqüências de bits.

As instruções orientam o computador para executar ações específicas simples, tais como adicionar, subtrair, comparar ou copiar bits de um endereço de memória para outro. Outras instruções enviam informações para dispositivos externos à CPU, tais como impressora, disco ou vídeo. Por exemplo, uma certa seqüência de bits poderia representar a instrução "Some 1 ao número na memória 732" ou "Envie a letra M para o dispositivo de saída 3". As seqüências de bits que controlam o processador variam de CPU para CPU. (E por isso que programas escritos para um IBM PC não rodarão em um Macintosh da Apple e vice-versa.) A lista completa de instruções de

Page 24: Iniciando No Visual Basic

controle de um certo processador é chamada de conjunto de instruções.

É possível escrever programas, submetendo diretamente as seqüências de bits que constituem cada instrução. Esse método, conhecido como programação em linguagem de máquina, raramente é usado. Algo mais comum é encontrar pessoas programando em linguagem Assembly, na qual cada seqüência especial de caracteres, tais como ADD ou TEST, corresponde a uma instrução em linguagem de máquina. Um programa chamado assemblador transforma as seqüências de caracteres escritas pelo programador em linguagem de máquina, conforme mostrado pela Figura 2.7. Muito embora a programação em linguagem Assembly, seja menos dolorosa (e menos sujeita a erros) do que a programação em linguagem de máquina, o programa continuará tendo de especificar a instrução que o processador terá de executar. Comandar o processador para efetuar uma simples captura de uma tecla pode demandar quase uma centena de instruções. Em conseqüência disso, até mesmo os programas mais simples podem requerer algumas milhares de instruções, podendo chegar a milhões de instruções no caso de programas mais complexos.

Figura 2.7 Um assemblador trabalhando.

Compiladores e Interpretadores

Programas especiais chamados de compiladores podem ajudá-lo a evitar o nível excessivo de detalhes da programação em linguagem Assembly. Um compilador permite ao programador escrever comandos mais produtivos que em Assembly ou em linguagem de máquina; um comando Visual Basic, por exemplo, geralmente é transformado em muitas instruções de linguagem de máquina. O programador escreve comandos na linguagem-fonte do compilador, que, por sua vez, transforma-a em linguagem de máquina. Linguagens-fonte comuns atualmente incluem C, Pascal e Visual Basic. A Figura 2.8 ilustra como trabalha um compilador.

Para simplificar, um compilador ou um assemblador lê um arquivo de instruções escritas pelo programador e produz como saída um arquivo em código de máquina. O programa em código de máquina é então executado para produzir o resultado que se esperava ao escrever o programa. Nos sistemas operacionais MS-DOS e Windows, um arquivo com extensão EXE ou COM contém código de máquina e pode ser carregado diretamente na memória para ser executado.

Page 25: Iniciando No Visual Basic

Figura 2.8 - Compilando linguagem-fonte em linguagem de máquina.

Interpretadores, de forma similar aos compiladores, também transformam instruções escritas em código-fonte. Entretanto, um interpretador transforma cada linha de código-fonte e então executa imediatamente o código de máquina resultante. O interpretador então volta ao código-fonte e transforma a próxima linha. A Figura 2.9 apresenta as principais diferenças entre compiladores e interpretadores. Outro meio de compreender a diferença entre compiladores e interpretadores é imaginar como a tradução de um livro difere da tradução simultânea fornecida pelos intérpretes da ONU. O trabalho de tradução de um livro assemelha-se ao processo de um compilador. Um tradutor recebe uma edição do livro russo Guerra e Paz, e após alguns anos de árduo trabalho, produz um novo livro com o mesmo texto em javanês. O intérprete russo-javanês na ONU, entretanto, trabalha com cada palavra falada imediatamente, da mesma forma que o interpretador do computador.

Figura 2.9 Compilando e interpretando.

Compilador ou interpretador, cada qual tem suas vantagens. Os compiladores fazem o seu trabalho uma única vez e o resultado é um arquivo executável que pode ser processado quantas vezes for preciso. Interpretadores lhe dão retorno mais rápido, podendo ajudá-lo na detecção de erros. O Visual Basic contém tanto um interpretador quanto um compilador.

Você logo estará em contato com o interpretador do Visual Basic. Quando você escolher a opção Start do menu Run, o Visual Basic interpretará o código escrito e começará a executá-lo. Você aprenderá como suspender a execução de seu programa enquanto ele está sendo processado e então submeter comandos diretamente para o interpretador, para identificar e localizar possíveis erros de sua codificação. Quando o interpretador está fazendo o seu trabalho, tanto o programa Visual Basic quanto o seu aplicativo devem estar na memória ao mesmo tempo.

Você também pode optar por compilar os seus aplicativos. Um aplicativo compilado pode ser processado em qualquer sistema de computação que esteja rodando o Windows; ele não dependerá do programa Visual Basic para poder ser processado.

Compilando o Programa Cronômetro

Page 26: Iniciando No Visual Basic

Vamos tentar compilar o programa escrito por você no Capitulo 1. Caso não esteja trabalhando com o Visual Basic no momento, inicie a sua execução. Carregue o projeto Cronom, selecionando a opção Open Project do menu File. Abra o arquivo Cronom.vbp, que é o arquivo de projeto para o programa Cronômetro. Para compilar o aplicativo, selecione a opção Make EXE a partir do menu File. Na caixa de diálogo Make EXE File, mostrada na Figura 2.10, altere o título do aplicativo para Cronom. Informe o diretório de sua escolha, digite Cronom.exe como nome do arquivo e dê um clique no botão OK, para fechar a caixa de diálogo. Após isso, o Visual Basic transformará o código-fonte de seu programa em linguagem de máquina, gravando-o no arquivo Cronom.exe.

Agora, tente executar a versão compilada do programa Cronom sem o Visual Basic. Saia do Visual Basic, selecionando a opção Exit do menu File. No menu Iniciar do Windows, selecione a opção Executar. Na caixa de texto linha de comando da caixa de diálogo Executar, digite o caminho de acesso do programa Cronom - por exemplo, \VB\Cronômetro\Cronom.exe - e dê um clique em OK. O aplicativo será carregado na memória e executado.

Figura 2.10 A caixa de diálogo Make EXE File usada para compilar programas.

Você pode dar cópias da versão EXE de seu programa para seus amigos ou companheiros de trabalho, os quais poderão processá-lo, mesmo que o Visual Basic não esteja instalado em seus computadores. Entretanto, eles precisarão de um arquivo adicional chamado MSVBVM60.DLL (que foi gravado no diretório System do Windows quando você instalou o Visual Basic.) Qualquer um que for processar um aplicativo compilado pelo Visual Basic precisa de uma cópia desse arquivo. (Uma vez que a Microsoft garante explicitamente que esse arquivo pode ser distribuído, você não estará violando sua licença de uso do Visual Basic se der uma cópia do MSVBVM60.DLL juntamente com o programa compilado.)

MSVBVM60.DLL contém um conjunto de rotinas que o seu programa necessita. O Visual Basic não transforma cada comando diretamente em linguagem de máquina. Alguns conjuntos de instruções, tal como a rotina para controlar a data e a hora atual do sistema, são necessários com tanta freqüência que o Visual Basic mantém disponível apenas uma única cópia no arquivo MSVBVM60.DLL. Quando o seu programa requisita a hora atual, a rotina contida no arquivo MSVBVM60.DLL é executada. Uma vez que esse arquivo ainda contém rotinas para tratamento de elementos básicos, tais como janelas e menus, até

Page 27: Iniciando No Visual Basic

mesmo os programas mais simples necessitarão dos recursos contidos em MSVBVM60.DLL.

À medida que você desenvolver aplicativos mais sofisticados, terá de incluir arquivos adicionais do tipo DLL que fazem parte do Visual Basic. O Visual Basic pode ajudá-lo a criar um disco de instalação ou setup (semelhante aos que acompanham os aplicativos profissionais) que inclui todos os componentes necessários.

Page 28: Iniciando No Visual Basic

Constantes e Variáveis no Visual Basic

Anteriormente vimos o problema da interpretação contextual das informações contidas em bits, isto é, saber quando se trata de números, caracteres ou algo completamente diferente. O Visual Basic ajuda-o a resolver essa questão, permitindo que seja especificado o tipo de informação a ser armazenada.

Especificando Tipos de Dados do Visual Basic

Como você já viu, os bits 01000001 podem representar a letra A, se o contexto for o código ASCII, ou o valor 65, quando o contexto for o sistema numérico decimal. Você poderia resolver essa ambigüidade, desenvolvendo codificações especiais de bits para cada tipo de informação, porém, felizmente você não precisará envolver-se com essa questão, pois o Visual Basic define um conjunto padronizado para representações de dados chamado de tipos de dados. A Figura 3.1 lista os nomes e características dos vários tipos de dados suportados pelo Visual Basic.

Figura 3.1 Tipos de dados do Visual Basic.

O tipo byte é útil para conter dados binários. Seus valores são numéricos e podem variar de 0 a 255 sem sinal. Ocupam oito bits na memória.

O tipo boolean é um tipo numérico especial, pois pode conter apenas dois valores: 0 (False) ou -1 (True). Na memória, ocupam 16 bits (2 bytes).

Os tipos Integer e Long são inteiros simples de 16 e 32 bits, representados por valores binários, semelhantes aos que foram discutidos no Capitulo 2. Ambos os tipos devem ser usados apenas para representar números que não contenham parte fracionária. O tipo Integer requer apenas 16 bits de memória, porém possui uma faixa de valores mais restrita do que o tipo Long (Voltaremos a falar sobre a faixa de valores mais adiante.)

O tipo string é uma seqüência de caracteres, cada uma das quais representada pelo esquema ASCII. A seqüência que não contém qualquer caractere é chamada de string vazia. As strings podem ser de tamanho fixo ou variável.

Page 29: Iniciando No Visual Basic

Strings de tamanho fixo podem possuir de 1 a aproximadamente 65.400 caracteres, enquanto as strings de tamanho variável podem chegar a aproximadamente 2 bilhões de caracteres. Vale lembrar que as strings em Visual Basic ocupam 2 bytes de memória por caractere e as strings de tamanho variável possuem 10 bytes iniciais de informação sobre a string.

O tipo de dado currency foi especialmente projetado para representar valores monetários. Um valor monetário tem sempre quatro casas decimais após a vírgula - isto é, você pode armazenar um valor como 11,1625, mas não um valor como 21,00003. (Este último valor seria arredondado para 21,0000)

Os tipos de dados single e double permitem-lhe expressar números de ponto flutuante. Números de ponto flutuante (também chamados de números reais ou apenas reais) representam valores que possuem partes fracionárias. O nome ponto flutuante provém de ponto decimal flutuante, que pode aparecer em qualquer posição, como em 0,000001, 356,555 ou, ainda, 10000,0; ao contrário do tipo currency, que é um exemplo de tipo de dado com ponto decimal fixo.

Decimal é um tipo de dados para números gigantescos. Ocupa 14 bytes de memória e pode representar valores no intervalo +/-79.228.162.514.264.337.593.543.950.335 sem a vírgula; ou valores no intervalo +/-7,9228162514264337593543950335 com 28 posições à direita da vírgula; o menor número diferente de zero pode ser +/-0,0000000000000000000000000001

O tipo de dados Date é usado para representar datas que variam de 1 de janeiro de 100 até 31 de dezembro de 9999 e a hora de 0:00:00 a 23:59:59. Ocupam 64 bits (8 bytes) de memória.

O tipo de dados Object ocupa 4 bytes na memória e é usado para guardar referências a objetos. Falaremos mais sobre este tipo de dados quando tratarmos do uso de objetos no Visual Basic.

Finalmente, o Visual Basic inclui o tipo variant, uma espécie de tipo de dado mutável que pode assumir qualquer um dos tipos de dados já apresentados. O tipo variant na realidade contém duas partes de informação: um valor, que poderá ser qualquer um dos tipos mencionados, e um código indicando o tipo de dado que está sendo representado. (Por exemplo, currency ou string.)

Faixa de Valores

Page 30: Iniciando No Visual Basic

Uma das características mais importante dos tipos de dados é a sua faixa de valores, que limita os valores que o tipo de dado pode armazenar. Esses limites se baseiam na quantidade de bits que será usada para armazenar os valores. Por exemplo, considere a Figura 3.2, que ilustra o que acontece quando você tenta contar de 0 a 9 usando um número binário de 3 bits. Com 3 bits, você pode apenas definir oito valores. Em conseqüência disso, alguma informação será perdida, um problema conhecido como estouro de campo, pois a quantidade de bits necessários para armazenar a informação é maior do que a quantidade de bits disponíveis.

Figura 3.2 Perda de informação em função de estouro.

Como um programador, você deve decidir qual tipo de dado usar para um certo valor. Se você estiver escrevendo programas simples, esta questão pode muito bem ser evitada usando sempre o tipo de dado variant, que pode representar qualquer valor. Entretanto, quando se tratar de programas mais complexos, você provavelmente estará preocupado em escolher o tipo de dado mais adequado, por questões de espaço em memória e velocidade de execução. (O tipo de dado variant é menos eficiente do que os outros, pois, antes de tratar o dado propriamente dito, o Visual Basic tem de verificar de que forma ele deverá ser tratado.)

Uma Cartilha sobre Ponto Flutuante

Quando você trabalhar com números de ponto flutuante, perceberá que a precisão é quase tão importante quanto a sua faixa de valores. Números de ponto flutuante têm uma faixa de valores que define o maior e menor valor que eles podem representar e uma precisão que estabelece a quantidade de algarismos significativos que o valor pode conter.

O Visual Basic armazena números de ponto flutuante em uma versão binária da notação científica, onde os valores são expressos pelo produto de dois números: uma fração e um expoente. Em notação científica, por exemplo, você pode representar a distância entre o Sol e a Terra por 5,84 x 10 ^ 12 polegadas.

A parte fracionária do tipo single é um valor binário que expressa um pouco mais do que 6 dígitos decimais de precisão. O expoente permite que sejam representados valores que vão desde números muito pequenos (10 ^ -45) até números muito grandes (10 ^ 38). O tipo double, por sua vez, permite a representação de valores com uma

Page 31: Iniciando No Visual Basic

faixa de variação ainda maior (de 10 ^ -324 a 10 ^ 308), com aproximadamente 13 dígitos decimais de precisão.

Se a idéia de um número contendo apenas 13 dígitos de precisão lhe parece estranha, considere o seguinte: o número 0,00000000017 parece bem preciso. Repare que ele contém apenas dois dígitos de precisão. Isso fica mais fácil de visualizar quando se adota a notação científica: 1,7 x 10 ^ -10. A parte fracionária é apenas 1,7; o resto da informação (o expoente) lhe indica onde colocar a vírgula decimal. Como outro exemplo, considere o valor 5,84 x 10 ^ 12 polegadas. Embora ele esteja representando um número de 13 dígitos, a sua precisão é de apenas 3 dígitos. Ainda que essa medida possa apresentar um erro de alguns milhares de polegadas, isso não é importante, pois em comparação a um número da ordem de trilhões de polegadas esse desvio é desprezível.

A distinção entre precisão e faixa de valores é sutil, porém importante. Suponhamos que você seja contratado pela Imensamente Grande MegaCorp para escrever um programa que controle a contabilidade da corporação. Essa empresa fatura todos os anos centenas de bilhões de dólares. Você pode concluir que o tipo single seja perfeitamente adequado para o tratamento de valores, afinal ele pode representar valores até 10 ^ 38, quando centenas de bilhões de dólares significa algo parecido com 10 ^ 11. Entretanto, quando se fala em contabilidade, é necessária extrema exatidão de valores, e o tipo single não tem a precisão desejável para tal. Por exemplo, se o balanço fosse iniciado com um saldo de $121.734.240.722, seriam necessários 12 dígitos de precisão para representá-lo, pois cada um dos 12 dígitos nesse valor é significativo. Repare então que, apesar de o tipo single poder armazenar valores bem maiores do que esse, se esse valor fosse armazenado nesse tipo, ocorreria um estouro de campo, pois esse tipo permite até 6 dígitos de precisão, isto é, seria armazenado um valor de 1,217342 x 10 ^ 11, ou seja, 121.734.200.000. Em seu primeiro dia no emprego, você já teria provocado o desaparecimento de 40.722!

Nota: O tipo de dado currency do Visual Basic é perfeito para tratamento monetário. Ele providencia até 18 dígitos de precisão e sempre mantém 4 desses dígitos como posições decimais. Uma variável do tipo double também admite a mesma quantidade de dígitos significativos, porém o tipo currency tem ponto decimal fixo e não está sujeito a arredondamentos.

Naturalmente, isso não quer dizer que o tipo single deva ser desprezado. Se, por exemplo, você estiver trabalhando com equações

Page 32: Iniciando No Visual Basic

físicas e medindo a quantidade de átomos em 31 gramas de silício (aproximadamente 6,02 x 10 ^ 23), um número real servirá aos seus propósitos - a menos que você planeje calcular a quantidade exata de átomos.

Criando Variáveis e Constantes

Deixando de lado o tipo de dado a ser armazenado, o próprio armazenamento não tem qualquer sentido quando não se pode referenciar as informações armazenadas, isto é, se não for possível recuperar essas informações. O Visual Basic permite-lhe nomear localizações de memória de forma a acessar as informações lá armazenadas. Uma posição de memória nomeada é chamada de variável. A instrução Dim, que informa o Visual Basic a respeito de sua intenção de reservar uma área de memória, tem o seguinte formato:

Dim variável [As Tipo]

Quando você usa essa instrução, precisa colocar a palavra-chave Dim e seguí-Ia com o nome da variável que deseja usar. A frase mostrada entre colchetes é opcional; se você usá-la, precisa colocar a palavra-chave As e, em seguida, especificar o tipo, sem incluir os próprios colchetes. (Será visto mais sobre notação em outro capítulo.) Por exemplo, a instrução a seguir avisa ao Visual Basic para reservar memória suficiente para um dado do tipo currency (8 bytes) e usar como referência a essa localização de memória o nome SaldoDaConta:

Dim SaldoDaConta As Currency

Usando o nome da variável, você poderá posteriormente instruir o Visual Basic para armazenar novas informações nessa localização, recuperá-las, modificá-las e assim por diante. Caso a cláusula As seja omitida, o Visual Basic assumirá que a variável é do tipo Variant.

Você pode imaginar as variáveis como sendo caixas. A instrução Dim cria uma nova caixa de um certo tamanho e lhe atribui um nome, como ilustrado na Figura 3.3. Quando você usa o nome de uma variável em um programa, o Visual Basic lhe fornece o conteúdo atual da caixa (o valor atualmente lá armazenado).

Figura 3.3 Reservando memória com declarações de variáveis.

Quando uma área de memória é reservada para uma variável numérica, o Visual Basic assinala a essa variável o valor inicial 0

Page 33: Iniciando No Visual Basic

(zero). Entretanto, não é boa idéia confiar nessa inicialização automática. Se você desejar que uma variável assuma um certo valor, é melhor atribuir esse valor à variável em seu programa. A atribuição explícita de valores às variáveis torna o seu programa mais fácil de entender, evitando pressuposições dúbias. Além disso, você deve lembrar-se de que a inicialização automática é uma característica particular do Visual Basic. Se você converter seu programa para outro ambiente de programação, o novo sistema pode não suportar a inicialização automática, e seu programa não funcionará mais.

Às vezes, você pode ter de usar valores que não se alterem - o valor de pi, o número de Avogadro, o número de centímetros em uma polegada. Ainda que seja possível usar esses valores numéricos diretamente na instrução em que são necessários, é mais simples usar um nome como PI, do que repetir o número 3,1415926 toda vez.

Para fixar tais valores, o Visual Basic permite que você declare constantes, ou seja, localizações de memória cujo conteúdo não se modifica (ao contrário do conteúdo de variáveis). Se você tentar modificar uma constante, o Visual Basic gerará uma mensagem de erro. A instrução Const declara um valor constante e tem a seguinte forma:

Const nome  [As tipo]= expressão

Não é necessário declarar o tipo de uma constante, pois o Visual Basic determina-o automaticamente usando a verificação do valor da expressão. Se você escrever Const RESPOSTA = 42, o Visual Basic usará o tipo Integer; se você introduzir Const NOMEINICIAL = "Paulo", ele criará uma constante do tipo string. (Normalmente, costuma-se usar letras maiúsculas para criação de nomes de constantes.)

Com freqüência, pode haver alguma ambigüidade quanto ao tipo de constante que o Visual Basic deveria criar. Por exemplo, o valor 3,01 poderia ser single, double ou currency. Por default, o Visual Basic selecionará o tipo que demandar menor espaço de memória para seu armazenamento. No entanto, você pode forçá-lo a assumir um certo tipo, colocando As tipo após o nome da constante ou um caractere de declaração de tipo. Os caracteres para declaração de tipo estão listados na Figura 3.4.

Figura 3.4 Caracteres para declaração de tipos do Visual Basic.

Assim, a declaração Const ONE& = 1 reserva 4 bytes de memória para uma constante do tipo long, e a declaração Const ONE# = 1

Page 34: Iniciando No Visual Basic

reserva 8 bytes e armazena o valor em uma representação de ponto flutuante. Em qualquer um dos casos, você deveria usar o nome ONE (sem o caractere de declaração de tipo) em seu programa para se referir a esse valor. Você deveria adquirir o hábito de definir constantes para valores padrões; essa prática tornará seus programas mais inteligíveis.

Dica: Ocasionalmente, você poderá ter de definir uma constante muito grande - um valor como o número de Avogadro, por exemplo, que, como você deve se lembrar, é 6.02 x 10 ^ 23. Felizmente, não é necessário digitar algo como 602000000000000000000000. O Visual Basic permite que você introduza uma constante simples, especificando apenas a parte fracionária do número (mantissa), seguida pela letra E, e em seguida o expoente (6.02E23 no exemplo). Para constantes do tipo double, use a letra D no lugar da letra E (6.02D23).

Regras para Nomes

Para nomear variáveis e constantes em Visual Basic, você deve seguir alguma regras:

O primeiro caractere deve ser uma letra. Os caracteres seguintes podem ser apenas letras, dígitos ou o

caractere de sublinhado ( _ ). O nome pode conter no máximo 40 caracteres. Palavras-chave que contenham significado especial para o

Visual Basic tais como Sub, Now e End, não podem ser usadas como nomes. (Se você tem dúvida a respeito de alguma palavra, pressione a tecla F1 para exibir o sistema de ajuda e então procure o tópico Reserved words.)

Estas instruções usam nomes ilegais:

Dim 1Tempo As Long ' Inicia com um número

Const PRINT = 2 ' Print é uma palavra-chave

Dim Isto*aqui As Currency 'Asterisco não é aceito

Comentários

Um apóstrofo (') inicia o comentário do programador em Visual Basic. O apóstrofo ou caractere de comentário permite-lhe inserir observações sobre seu programa em qualquer lugar da codificação. Uma vez que o Visual Basic ignora todos os caracteres à direita de um

Page 35: Iniciando No Visual Basic

apóstrofo, o texto que se segue deveria conter apenas informação ou descrição que seja útil a alguém que esteja lendo o programa. Quando um apóstrofo é o primeiro caractere de uma linha, a linha inteira é considerada como comentário. Observe que, se o seu comentário precisar de mais de uma linha, você deve preceder cada linha com um apóstrofo.

Eis como o procedimento de evento BtnIniciar - Click do aplicativo Cronômetro,

desenvolvido no Capitulo 1, ficaria se fossem adicionados comentários:

Figura 3.5

As instruções a seguir são declarações válidas para o Visual Basic:

Dim NomedeVariáveIMuitoLonto As Integer

Dim RX7 As String

Const CENT_POR_INCH = 2,54

O Visual Basic não diferencia letras maiúsculas de minúsculas usadas em nomes de variáveis; CONTADOR, CONTador e Contador são idênticos. Quando você define o nome de uma variável, o Visual Basic providencia para que todas as referências feitas à variável em questão sigam a mesma utilização de letras maiúsculas e minúsculas adotada na declaração. Os programas tornam-se mais legíveis quando se usam letras maiúsculas e minúsculas alternadamente, por exemplo, iniciando o nome com maiúscula e deixando as outras letras em minúscula. Para constantes, é interessante que todas as letras sejam maiúsculas.

Criando Tipos Definidos pelo Usuário

Os tipos de dados mencionados até agora, ditos inerentes ao Visual Basic, normalmente atendem a todos os requisitos para informações, que podem facilmente ser desdobradas em componentes individuais, tais como textos, números e assim por diante. No entanto, apenas esses tipos de dados podem revelar-se insuficientes para tratamento de informações que deveriam permanecer agrupadas. Vejamos um exemplo específico.

Suponha que seu passatempo seja a criação de animais raros e que você tenha adquirido duas doninhas de topete da Floresta da Baviera

Page 36: Iniciando No Visual Basic

chamadas Siegmund e Sieglinda. Ansioso por testar as suas novas aptidões de programação, você decide manter dados descritivos sobre seus animais no computador, incluindo informações como cor, peso, tamanho e data de nascimento deles, bem como cor e tamanho de seus topetes. Você pode começar escrevendo declarações como estas:

Dim Siegmund_Cor as String

Dim Siegrnund_Peso As Integer

Dim Siegmund_Tamanho As Integer

Dim Siegmund_Data_nascimento As Double

Dim Siegmund_Compr_topete As Integer

Dim Siegmund_Cor_topete As String

Após haver feito isto para Siegmund, há a Sieglinda:

Dim Sieglinda_Cor as String

Dim Sieglinda_Peso As Integer

Dim Sieglinda_Tamanho As Integer

Dim Sieglinda_Data_nascimento As Double

Dim Sieglinda_Compr_topete As Integer

Dim Sieglinda_Cor_topete As String

Sem dúvida, teria sido mais simples se fosse possível declarar as informações relevantes uma única vez. O Visual Basic oferece uma solução ideal: criar seus próprios tipos de dados.

Um tipo de dado definido pelo usuário é um agrupamento de tipos de dados inerentes ao Visual Basic: integers, strings, doubles e assim por diante. A palavra-chave Type indica o início de uma declaração de tipo feita pelo usuário, como mostrado abaixo:

Type DoninhaTFB

Cor As String

Page 37: Iniciando No Visual Basic

Peso As Integer

Tamanho As Integer

Data_nascimento As Double

Compr_topete As Integer

Cor_topete As String

End Type

A declaração de tipo agrupa todas as informações que você acredita ser importantes sobre seus novos amiguinhos. Observe que você ainda não reservou qualquer área de memória para os dados, simplesmente descreveu para o Visual Basic a estrutura ou layout dos dados. Você pode imaginar essa declaração como sendo a planta de uma área de memória. Após a definição do novo tipo, é possível criar as variáveis como usualmente:

Dim Siegmund As DoninhaTFB

Dim Sieglinda As DoninhaTFB

Essas duas instruções criam as variáveis Siegmund e Sieglinda - isto é, reserva-se uma área de memória com um nome associado a ela. Cada variável contém todos os componentes de dados que foram definidos. Na maioria das linguagens de programação, as variáveis que podem conter múltiplos componentes são chamadas de registros, e cada componente separado é chamado de elemento dentro do registro. Quando você usa a variável Siegmund, está-se referindo a todos os dados (cor, tamanho, peso etc.) simultaneamente. Quando é necessário fazer referência a um componente individual, você pode usar o nome da variável seguido por um ponto (.) e pelo nome do componente. Assim, Siegmund.Peso é um componente de dados integer que armazena o peso do macho, enquanto Sieglinda.Cor é uma string de texto que descreve a cor da fêmea.

Vantagens Práticas

Os tipos definidos pelo usuário facilitam a leitura e a atualização de seu programa. Considere o exemplo das doninhas. A primeira forma envolveria 12 instruções Dim, cada uma definindo um atributo para cada doninha. Neste primeiro caso, é preciso ler todas as 12 instruções para poder determinar quais atributos do Siegmund e da Sieglinda estão sendo declarados. Ainda assim, não está claro se

Page 38: Iniciando No Visual Basic

existem ou não outros atributos declarados em algum outro ponto do programa e muito menos se pode afirmar que Siegmund e Sieglinda sejam itens de dados relacionados.

Contrastando com essa confusão, observe a clareza que há na declaração de tipo feita pelo usuário. Os atributos contidos na instrução Type claramente pertencem a DoninhaTFB. Num piscar de olhos, pode-se dizer que as variáveis Siegmund e Sieglinda são do mesmo tipo e quais as informações específicas que ambas contêm. Além disso, se você desejar modificar o seu programa mais tarde, acrescentando, por exemplo, a cor dos olhos ao conjunto de informações sobre os animais, bastará alterar a instrução Type. Isso fará com que todas as variáveis passem a conter esse novo elemento de dados. Finalmente, se as doninhas. tiverem um relacionamento amoroso e lhe presentearem com um nova doninha. você poderá incluir uma variável nova para o pequeno Siegfried no programa, com uma instrução bem simples do tipo Dim Siegfried As DoninhaTFB.

Déjà Vu

O modo como se acessam os campos de tipos definidos pelo usuário se parece com o que você usou para configurar as propriedades da caixa de texto no aplicativo Cronômetro (Capítulo 1). No programa Cronômetro, você usou a instrução TxtDecorrido.Text = Format(TempoDecorrido, "hh:mm:ss") para configurar a propriedade Text do objeto de exibição TxtDecorrido.

Observe a similaridade entre a referência a TxtDecorrido.Text (que tem o formato Objeto. Propriedade) na instrução mostrada e a referência a componentes de variáveis, tais como Siegmund.Cor (que tem o formato Variável. Elemento). Como as variáveis, os objetos também são representados em memória; quando modifica uma propriedade, você está alterando um dos componentes daquele objeto.

Determinando o Escopo

Vamos tentar um experimento:

1. Inicie o Visual Basic e selecione a opção New Project: do menu File para criar um novo projeto.

2. Crie dois botões de comando no form, um abaixo do outro. Você pode dar um clique duplo na ferramenta Botão de Comando na caixa

Page 39: Iniciando No Visual Basic

de ferramentas, ou selecionar a ferramenta e desenhar os botões no form.

3. Selecione o primeiro botão de comando (Command1) e a seguir selecione a propriedade Caption da lista de propriedades na janela de propriedades. Configure o Caption desse botão para AssinalarEMostrar, digitando esse novo título no campo de valor da propriedade. Então, selecione o segundo botão de comando e configure o seu título (Caption) para Mostrar, como apresentado a seguir:

Figura 3.6

4. Dê um clique duplo no botão AssinalarEMostar para exibir a janela de código. Na janela de código, defina o procedimento Click da seguinte forma:

Private Sub Command1_Click ()

Dim SeuNome As String

SeuNome = lnputBox("Qual é o seu nome ?")

MsgBox "O seu nome é " & SeuNome

End Sub

Examinemos esse conjunto de instruções. A primeira linha é a declaração do procedimento. A segunda reserva memória para uma variável string chamada SeuNome. A terceira linha chama a função InputBox, uma função interna do Visual Basic que exibe uma caixa de diálogo na tela. O usuário digita um texto na caixa de diálogo e a função InputBox retorna o texto digitado. Esse texto é armazenado na variável SeuNome. A quarta linha usa o procedimento interno MsgBox para exibir urna caixa de diálogo contendo o texto "O seu nome é" seguido pelo conteúdo da variável SeuNome. O operador (&) concatena ou "Junta" duas strings; por exemplo, a expressão "Al" & "ô companheiro" é equivalente a "Alô companheiro". Finalmente, a última linha marca o final do procedimento.

5. Selecione agora o botão Command2 a partir da caixa Object na janela de código e insira o seguinte código para o procedimento Click:

Private Sub Command2_Click ()

Dim SeuNome As String

Page 40: Iniciando No Visual Basic

MsgBox "Alô " & SeuNome

End Sub

Esse procedimento apenas exibirá a palavra Alô e o conteúdo de SeuNome. Você pode usar o procedimento MsgBox e o operador de concatenação (&), como foi feito no procedimento anterior.

6. Feche a janela de código e pressione F5 para executar este aplicativo.

7. Dê um clique no botão AssinalarEMostrar. Digite um nome na caixa de diálogo e pressione Enter ou dê um clique no botão OK. Se, por exemplo, você tiver digitado Mariana, o resultado será semelhante ao seguinte:

Figura 3.7

8. Dê um clique no botão OK para fechar a caixa de diálogo. Em seguida, dê um clique no botão Mostrar. A caixa de diálogo exibirá apenas a palavra Alô.

Por que o Visual Basic não preservou o conteúdo da variável SeuNome? Por que será que esse aplicativo se comporta de forma diferente do Cronômetro no Capitulo 1? Há uma explicação bem simples: o aplicativo Cronômetro continha apenas uma instrução Dim, e ela não estava dentro de um procedimento. Tentemos novamente, usando o esquema adotado com sucesso no aplicativo Cronômetro:

1 . Pressione Alt-F4 para deixar o aplicativo.

2. Dê um clique duplo no botão AssinalarEMostrar na janela de form, para mover-se para a janela de código, e remova a instrução Dim do procedimento Click.

3. Remova também a instrução Dim contida no procedimento Click do botão Mostrar.

4. Selecione (General) a partir da caixa Object da janela de código. Nesta seção de declarações gerais, digite a instrução Dim SeuNome As String.

5. Feche a janela de código e processe o seu aplicativo novamente.

Desta vez, o botão Mostrar funcionará da maneira esperada. Isso serviu para você constatar os efeitos do escopo de uma variável.

Page 41: Iniciando No Visual Basic

Variáveis Locais e em Nível de Módulo

O escopo de uma variável determina quais procedimentos terão acesso à variável. Na primeira vez que você processou o exemplo precedente, haviam sido criadas duas cópias da variável SeuNome, cada qual acessível apenas dentro de um procedimento. Elas são chamadas de variáveis locais. Na segunda vez, você declarou uma única variável na seção de declarações gerais do form, tornando-a uma variável em nível de módulo. Variáveis declaradas dessa forma são acessíveis a todos os procedimentos contidos no form, (O termo módulo. neste contexto, refere-se essencialmente a arquivo; lembre-se de que o código de todos os procedimentos associados a um form, ou a objetos contidos nesse form, são gravados num único arquivo.) Essa diferença entre as duas versões do programa encontra-se ilustrada na Figura 3.8.

Restringir o escopo de variáveis é útil, pois permite-lhe reutilizar os nomes de variáveis. Por exemplo, ao somar alguns números em um procedimento, você poderia armazenar o resultado em uma variável local chamada Soma. Se, mais tarde, for necessário escrever nesse mesmo programa um outro procedimento semelhante que também efetue uma soma, você poderia usar o nome Soma novamente, sem afetar o resultado do procedimento anterior. Escopo local permite que cada procedimento seja uma unidade autocontida - isto é, modificações em outras porções do programa não interferem na operação de um procedimento em particular.

Figura 3.8 Variáveis locais versus variáveis em nível de módulo

Variáveis Globais

As variáveis em nível de módulo são acessíveis apenas pelos procedimentos definidos dentro do módulo. Caso venha a ser criado um programa com múltiplos forms, você terá de arranjar algum modo para poder compartilhar as informações entre os vários forms, Para atender a esse requisito, o Visual Basic provê um terceiro nível de escopo, as variáveis públicas. Variáveis públicas são declaradas em módulos de código e de classes. São acessíveis a partir de qualquer parte de um programa. (Discutiremos os módulos de código na próxima seção.) A Figura 3.9ilustra os três níveis de escopo de variáveis.

Figura 3.9 Variáveis locais, em nível de módulo e públicas.

Page 42: Iniciando No Visual Basic

Para criar variáveis públicas, deve-se usar a palavra-chave Public em lugar de Dim. A sintaxe, afora isto, é idêntica à da instrução Dim.

Public variável [As tipo]

As regras de escopo aplicam-se igualmente para o tratamento de constantes. Às constantes declaradas com a instrução Const é associado o escopo local ou em nível de módulo dependendo de sua colocação em um procedimento ou em um módulo Para criar constantes públicas, deve-se colocar a sua declaração na seção de declarações gerais de um módulo e usar a palavra-chave Public para iniciar a instrução, como mostrado a seguir:

Public Const VELOCIDADELUZ! = 300000

Public Const PRIMEIROIMPERADOR = "D. Pedro I"

O ponto de exclamação na constante VelocidadeLuz avisa ao Visual Basic para armazenar a constante como um número real de precisão simples (Single). Lembre-se, entretanto, de que constantes publicas não podem ser declaradas dentro de procedimentos de um form.

Módulos de Código

Como você viu, a definição de um form e a codificação associada a ele, procedimentos e seção de declarações gerais, são armazenadas em um único arquivo com o sufixo FRM. É possível criar aplicativos que contenham múltiplos forms e, consequentemente, múltiplos arquivos de forms É possível também haver arquivos de aplicativos que contenham apenas codificações. Esses módulos de código, cujos arquivos têm o sufixo BAS, são criados quando você seleciona a opção Add Module do menu Project do Visual Basic.

Módulos de código separados, a princípio, são úteis para armazenar códigos a serem compartilhados e para ajudar a organizar o seu programa. Declarações públicas em um módulo de código podem ser compartilhadas por todas as instruções do programa. Quando você estiver construindo programas maiores e mais complexos, talvez seja útil agrupar a codificação relacionada a certo aspecto do programa num módulo separado.

Declarações Default

É possível declarar uma variável local sem usar a instrução Dim: basta usar o nome da variável quando necessário. Pode-se usar um dos caracteres (%, &, !, # ou $) para especificar o tipo de dado da variável;

Page 43: Iniciando No Visual Basic

do contrário, o Visual Basic assinalará o tipo variant como default. A título de exemplo, abra um novo projeto e coloque um único botão de comando no Form. Defina o procedimento de evento Click para esse botão de comando, como mostrado a seguir:

Sub Command1_Click ()

Resposta$ = lnputBox("Você me ama ?")

If Resposta$ = "Sim" Then

MsgBox "Ele me ama"

Else

MsgBox "Ele não me ama"

End If

End Sub

Esse fragmento de código não contém uma declaração explícita para a variável Resposta$. No entanto, o sinal $ indica que ela é uma variável do tipo string. Por default, o Visual Basic cria essa variável com escopo local.

Ainda que as declarações default possam ser consideradas convenientes, é recomendável evitá-las. Em vez disso, procure declarar explicitamente toda e qualquer variável que o seu programa for usar. O uso de declarações default pode gerar erros em seus programas. Assim, no exemplo anterior, você poderia declarar uma variável em nível de módulo chamada Resposta como parte de uma modificação posterior. Quando o procedimento viesse a ser executado, o Visual Basic: assumiria que a variável Resposta contida no procedimento Command1_Click faz referência à variável em nível de módulo pois não há uma declaração explícita. Consequentemente, após esse procedimento ser executado, o conteúdo armazenado na variável em nível de módulo seria sobreposto.

Declarações default sempre dão origem a variáveis locais. Variáveis em nível de módulo ou públicas têm de ser declaradas usando-se a instrução Dim, Private ou a instrução Public na seção de declarações gerais da janela de código. A instrução Dim usada dentro de um procedimento cria uma variável local.

Page 44: Iniciando No Visual Basic

O Visual Basic pode ajudá-lo a evitar declarações default. Selecione a opção Options do menu Tools. Na caixa de diálogo, marque a opção Require Variable Declarations, conforme mostrado na Figura 3.10.

Figura 3.10 A caixa de diálogo Options.

Assim, toda vez que você criar um novo arquivo, o Visual Basic incluirá a instrução Option Explicit à seção de declarações gerais de seu código. (Você também pode introduzir essa instrução diretamente na seção de declarações gerais.) Com isso, quando você tentar executar um programa que contenha variáveis não declaradas, o Visual Basic colocará o nome dessas variáveis em destaque, exibindo a mensagem Variable not defined.

Outras Opções de Ambiente

A caixa de diálogo Options ainda permite-lhe modificar outras configurações. Tab Width (comprimento de parada para a tecla Tab), normalmente configurada para 4, pode ser modificada, alterando as posições de tabulação da janela de código. Repare, no entanto, que o Visual Basic não insere no seu código o caracter correspondente à tecla TAB. Em vez disso, são colocados tantos espaços em branco quantos forem necessários para atingir a próxima posição de tabulação.

A opção Auto Syntax Checking (verificação sintática automática), quando marcada, habilita a verificação de cada linha de código à medida que você a introduz. (Quando a tecla Enter é pressionada.)

Na ficha Environment, configure a opção When a Program Starts para Save Changes (salva o projeto antes de executar). O Visual Basic automaticamente salvará a versão atual de seus arquivos de forms e de projeto antes de processar o seu aplicativo. Isso assegura que você não perderá qualquer trabalho realizado, no caso de uma queda do sistema. Você pode preferir deixar essa opção desabilitada enquanto estiver fazendo algumas modificações que não deseja salvar.

Outras opções na caixa de diálogo Options - em Editor Format - permitem-lhe configurar as cores de exibição de texto nas janelas de código. Por meio da configuração dessas cores, é possível reconhecer rapidamente comentários, variáveis, palavras-chave e assim por diante, diferenciando dessa forma as várias partes de seu programa.

Page 45: Iniciando No Visual Basic

Instruções, Expressões e Procedimentos no Visual Basic

Este capítulo concentrar-se-á nas instruções simples do Visual Basic. Uma instrução na linguagem Visual Basic é a exposição de um comando completo para o computador, o equivalente a uma frase em português. Dentro das instruções você pode criar expressões combinando valores e operadores. Este capítulo descreve os diferentes tipos de operadores e como usá-los. Fornece também uma explicação mais detalhada sobre procedimentos que você encontrou anteriormente, quando construiu seu primeiro aplicativo.

Instruções de Assinalamento

A instrução mais simples e provavelmente mais comum em programas é a instrução de assinalamento. Ela consiste em um nome de variável seguido pelo operador de assinalamento (=) e por algum tipo de expressão. Em sua forma mais simples, uma expressão contém apenas uma constante; ela pode no entanto conter uma referência a uma variável, ou a variáveis e constantes, sobre a qual certas operações são executadas. Todas as instruções a seguir são instruções de assinalamento válidas:

Tempoinicial = Now

Explorador.Nome = "Capitão Mascarenhas"

ContadordeBits = ContadordeBytes * 8

Energia = Massa * VelocidadeLuz ^ 2

Líquido = Proventos - Descontos

Uma instrução de assinalamento armazena informação. O valor da expressão, que aparece à direita do operador de assinalamento, é calculado e o resultado armazenado na variável à esquerda do operador. O tipo de dado da variável deve ser apropriado para armazenar o resultado da expressão. Por exemplo, uma constante ou expressão do tipo string não pode ser armazenada em uma variável integer ou double. Se os tipos de dados estiverem relacionados, mas não forem iguais - por exemplo, você pode desejar armazenar um valor inteiro em uma variável de ponto flutuante -, o Visual Basic converterá o resultado da expressão para o tipo da variável. Porém, se você armazenar o resultado de uma expressão em uma variável do

Page 46: Iniciando No Visual Basic

tipo variant, o tipo da expressão será mantido. Variáveis do tipo variant mantêm tanto o tipo quanto o valor.

Infelizmente, o operador de assinalamento é idêntico ao símbolo matemático usado para representar igualdades (o sinal de igual que une as duas partes de uma equação, como em x ² + 1 = 0). Igualdade no sentido matemático expressa uma condição que é verdadeira. Nas instruções de assinalamento do Visual Basic, o símbolo = é um comando que transfere o resultado da expressão que se segue para a variável que o precede. O sinal de igual em Visual Basic representa uma ação que o sistema deve executar, em vez de estabelecer um fato. A equação 2 + 1 = 1 + 2 não é uma instrução válida em Visual Basic, pois falta uma variável do lado esquerdo do sinal de igual. Caso tente-se introduzir essa linha como uma instrução completa, o Visual Basic gerará uma mensagem de erro.

Todas as instruções que você criou no aplicativo Cronômetro são instruções de assinalamento. Em algumas instruções, como BtnParar.Enabled = True, foram assinalados valores constantes simples. Em outras, tal como TempoDecorrido = TempoFinal - TempoInicial, você usou uma expressão. Em instruções como TxtInicial.Text = Format(TempoInicial, "hh:mm:ss"), você invocou uma função interna. O restante deste capitulo explora a capacidade do Visual Basic nessas áreas.

Expressões e Operadores

Como foi dito, uma expressão pode ser tão simples quanto uma constante, no entanto, usualmente as expressões representam cálculos a serem executados. Via de regra, um operador indica o tipo de operação a ser feita. Certamente, você já deve estar familiarizado com os operadores aritméticos, como o sinal de mais (+), que indica uma soma. A expressão 2 + 1 avisa ao Visual Basic para somar os valores 2 e 1. O 2 e o 1 são os operandos da operação de soma. Além dos operadores aritméticos, o Visual Basic provê um operador de concatenação de strings, operadores de comparação, operadores lógicos e o operador AddressOf, que permite referenciar o endereço de um procedimento na memória (serão discutidos mais adiante neste mesmo capítulo).

Por si só, as expressões não são instruções válidas, pois não estão completas. Introduzir, por exemplo, apenas 2 + 1 no seu programa provocará um erro. Se considerarmos uma instrução na linguagem Visual Basic uma frase, uma expressão deve ser considerada uma

Page 47: Iniciando No Visual Basic

frase. E possível usar expressões em todo e qualquer lugar onde se possa colocar uma constante.

É muito difícil definir uma expressão. As melhores definições são sempre referências à própria expressão. Uma definição parcial poderia incluir estas regras:

Um valor constante é uma expressão. A combinação de uma expressão seguida por um operador e

uma outra expressão também é uma expressão.

Conforme essas regras, 3 é uma expressão, tanto quanto 1; além disso, 3 + 1 também é uma expressão. De onde se deduz que 3 * 3 + 1 é uma expressão, como o é 3 * 3 + 1 + 1. Você pode imaginar até onde isso pode continuar: expressões podem ser arbitrariamente complexas.

Tipos de Expressões

O tipo de uma expressão é determinado a partir do tipo de seus operandos. Para um valor constante, o tipo da expressão é o mesmo que o da constante. Para uma expressão que contenha uma operação, o Visual Basic usa o tipo dos dois operandos para determinar o tipo do resultado. Naturalmente, quando você soma dois números inteiros, o resultado é inteiro. Se você soma dois valores de dupla precisão, o resultado será do tipo double (real). Se você misturar tipos diferentes - por exemplo, multiplicar um inteiro por um single, como na expressão 2 * 7,5 -, o Visual Basic geralmente transformará o resultado no tipo que puder acomodar a maior faixa de valores. Neste caso, o resultado seria do tipo single. Para prevenir possíveis ambigüidades, é melhor não usar tipos diferentes em uma expressão.

O uso de caracteres de declaração de tipo para constantes numéricas poderá ajudá-lo a minimizar a quantidade de tipos diferentes de uma expressão. Esses caracteres farão com que a constante seja tratada de acordo com o tipo especificado. Por exemplo, 100 normalmente seria um inteiro. Mas 100! é do tipo single e 100@, do tipo currency. (Os caracteres usados pelo Visual Basic para declaração de tipos encontram-se listados na Figura 3.4 do Capítulo 3.)

Nota: O Visual Basic não permite o uso de caracteres de declaração de tipo para truncar constantes reais em valores inteiros. Por exemplo, você não pode usar 3,14% como se fosse o inteiro 3 (ainda que quisesse). No entanto, se você desejar converter variáveis de ponto flutuante para inteiros, o Visual Basic provê funções de conversão

Page 48: Iniciando No Visual Basic

específicas que se encontram documentadas no arquivo de ajuda do Visual Basic.

As expressões não precisam restringir-se a operadores e constantes. Por exemplo, a expressão 17733,50 + (ReceitasAjustadas - 32450) * 23 / 100 inclui uma variável e um conjunto de parênteses, operadores e constantes.

Quando as expressões são mais complexas do que dois operandos e um operador, é possível haver duas ou mais formas distintas de avaliá-las. Por exemplo, a avaliação da expressão 2 + 6 / 2 pode, em primeiro lugar, fazer com que seja feita a soma de 2 com 6 e então dividir o resultado por 2, obtendo 4 como resultado final, ou dividir 6 por 2 e, ao resultado, somar 2, obtendo-se 5 como resultado final. Os parênteses são usados para eliminar esse tipo de ambigüidade. As subexpressões contidas entre parênteses são sempre avaliadas em primeiro lugar. A expressão 2 + (6 / 2) indica claramente que a operação de divisão deve ser efetuada em primeiro lugar. Expressões muito complexas podem requerer o uso de vários conjuntos de parênteses. As expressões mais internas ou contendo maior nível de aninhamento são avaliadas em primeiro lugar.

Na falta dos parênteses direcionadores, o Visual Basic aplica um conjunto de regras, chamado precedência de operadores, para determinar quais operações devem ser executadas em primeiro lugar. Por exemplo, em virtude de a divisão e a multiplicação terem precedência maior que a soma e a subtração, o Visual Basic avaliaria a expressão 2 + 6 / 2 como 2 + (6 / 2). A próxima seção deste capítulo descreve os operadores disponíveis em Visual Basic, agrupados de acordo com a função e seguidos pela tabela de precedência, que ilustra como os operadores se relacionam entre si.

 

Operadores Aritméticos

Os operadores mais familiares são os responsáveis por operações aritméticas simples. A Figura 4.1 lista os operadores aritméticos oferecidos pelo Visual Basic.

Nas operações de adição, subtração e multiplicação, os resultados são números do mesmo tipo que os operandos. (Combinação de tipos foi descrita na Seção precedente.) Via de regra, o uso de números inteiros ou números de ponto fixo é mais eficiente do que o uso de

Page 49: Iniciando No Visual Basic

números de ponto flutuante. Porém, a menos que a avaliação envolva muitos cálculos complexos, a diferença não será notada.

Figura 4.1 Operadores aritméticos.

Exponenciação

O operador de exponenciação permite-lhe calcular potências e raízes. Em matemática, a exponenciação é indicada por números sobrescritos. Por exemplo, o valor 28 e 2 elevado à oitava potência, que seria computado pelo Visual Basic pela expressão 2 ^ 8. A raiz quadrada de 2, que é 2 elevado à potência 1/2, poderia ser computado em Visual Basic pela expressão 2 ^ (1 / 2) ou por 2 ^ 0,5. A Figura 4.2 apresenta outros exemplos de exponenciação.

Figura 4.2 Exemplos de exponenciação.

Divisão de Inteiros e de Ponto Flutuante

O operador de divisão de ponto flutuante (/) executa a divisão padrão, porém retorna o resultado num formato de ponto flutuante. Assim, a expressão 3 / 2 é avaliada como 1,5, como seria de se esperar. Contrastando com o operador de divisão de inteiros (\), que retorna um valor inteiro. Se esse operador fosse aplicado à expressão 3 \ 2, produziria 1 como resultado. Era o que faltava, você deve lamentar - uma função que retorna a resposta errada.

Depende do ponto vista. Imagine que você esteja empacotando pimenta malagueta e precise saber quantas pimentas pode colocar em um vidro de 0,5 litro. Como especialista que é na matéria, você sabe que em um vasilhame de 4 litros cabem 150 pimentas e que não se costuma colocar pedaços de pimenta. Uma vez que 0,5 litro é 8 vezes menor do que 4 litros, você sabe que deve colocar 18 pimentas no vasilhame menor, ou seja, 150 \ 8. Se for usado o operador de divisão de ponto flutuante, o resultado seria 18,75, que não pode ser aceito, pelo menos no caso das pimentas.

Como o Visual Basic pode facilmente converter valores de um tipo para outro, você pode achar que chegaria ao mesmo resultado simplesmente usando uma variável inteira para guardar o resultado, como abaixo, onde é usado o operador de divisão de ponto flutuante (/):

Dim PimentasPorVidro As Integer

PimentasPorVidro = 150 / 8

Page 50: Iniciando No Visual Basic

Na realidade, quando a instrução de assinalamento for executada, será armazenado o valor 19 na variável PimentasPorVidro e não 18, como você esperava. Ao avaliar a expressão acima, o Visual Basic obtém como resultado 18,75, porém, como esse resultado deve ser armazenado em uma variável inteira, o Visual Basic promove o arredondamento, do número de ponto flutuante para o próximo inteiro, que é 19. Quando você usar o operador de divisão de inteiros, qualquer parte fracionária existente será truncado em vez de ser arredondada. A Figura 4.3 mostra as diferenças entre truncagem e arredondamento.

Figura 4.3 Truncagem e arredondamento.

Resto

O operador Mod, que está intimamente ligado à divisão inteira, retorna o resto produzido pela divisão inteira do primeiro pelo segundo operando. Por exemplo, se você divide 7 por 4, o resultado é 1, com resto 3. Assim, a expressão 7 Mod 4 é avaliada como 3. Analogamente, a expressão 21 Mod 4 produz 1 como resultado. (21 divido por 4 é igual a 5 e resta 1.)

Usando o exemplo das pimentas novamente, você agora sabe que pode colocar 18 pimentas em um vidro de 0,5 litro. Se você tiver 75 pimentas para embalar, a expressão 75 \ 18 lhe informará quantos vidros poderão ser preenchidos (4), enquanto a expressão 75 Mod 18 indicará quantas pimentas sobrarão.

Precedência de Operadores Aritméticos

A Figura 4.4 indica a ordem de precedência para os operadores aritméticos. A exponenciação tem a maior precedência; as operações de adição e subtração possuem a menor precedência. Operadores colocados na mesma linha são iguais em termos de precedência.

Figura 4.4 Ordem de precedência dos operadores aritméticos.

A Figura 4.5 contém algumas expressões simples em Visual Basic e os valores que resultam quando elas são avaliadas. Se necessário, use a ordem de precedência mostrada na Figura 4.4 para entender como o Visual Basic chegou aos resultados.

Figura 4.5 Usando a ordem de precedência para avaliação de expressões.

O Operador de Concatenação de String

Page 51: Iniciando No Visual Basic

Quando os operandos em uma expressão são do tipo string, o operador (&)

concatena, ou combina, as strings. Você pode usar a concatenação para "colar" duas ou mais strings, para obter uma string maior. O resultado de uma concatenação é uma string inteiramente nova. Nenhum dos operandos originais sofre qualquer alteração. O fragmento de programa a seguir usa a concatenação para reproduzir algumas linhas do livro de Lewis Carroll:

x$ = "morcegos"

y$ = "gatos"

Debug.Print "Os " & x$ & " comem " & y$ & "?"'Os morcegos comem gatos ?

Debug.Print "Os " & y$ & " comem " + x$ & "?"'Os gatos comem morcegos ?

Nota: o operador (+) também pode ser usado para concatenação de strings, mas procure usar sempre o operador próprio para essa função.

Interagindo Diretamente com o Visual Basic

No Capítulo 1, você usou a instrução Debug.Print para escrever na janela Immediate que pode ser exibida quando o seu aplicativo está sendo processado. A janela Immediate é mais do que apenas um local útil para colocar mensagens; nessa janela você pode interagir diretamente com o interpretador.

Crie um projeto novo, selecionando a opção New Project a partir do menu File. Pressione F5 para iniciar o aplicativo. Ainda que você não tenha escrito qualquer instrução, e muito menos colocado qualquer objeto no form, o Visual Basic processará o form, em branco. Agora, selecione a opção Break do menu Run. Isso fará com que o processamento do seu aplicativo seja suspenso, independentemente do que estiver sendo processado (que, neste caso, não deve ser muita coisa). Digite a instrução Debug.Print "Alô" na janela Immediate e pressione a tecla Enter. O interpretador do Visual Basic processá-la-á imediatamente, executando a sua instrução.

Figura 4.6

Page 52: Iniciando No Visual Basic

Como a janela Immediate é o form ativo no momento que o interpretador executa o seu comando, você não precisa incluir o nome do objeto Debug ao chamar o método Print; basta usar a palavra Print. Além disso, o Visual Basic lhe permite abreviar Print como ? para obter os resultados mais rapidamente, como mostrado a seguir:

Figura 4.7

Você pode submeter expressões a serem avaliadas e fazer chamadas a funções na janela Immediate. Você também pode chamar um procedimento e executar normalmente qualquer instrução que possa ser codificada em um programa. Passar para a janela Immediate é um meio rápido e fácil de depurar (testar) uma linha de código. Após terminar, pressione a tecla F5 para continuar o processamento normal de seu aplicativo, ou então selecione End do menu Run para sair do aplicativo.

Caso seja necessário concatenar um número com uma string, você deve usar uma das funções internas do Visual Basic para converter o número em string. A mais simples dessas funções é chamada de Str$. Por exemplo, a expressão "A raiz quadrada de 2 é " + Str$(2 ^ 0,5), converte o número entre parênteses para uma string.

É preciso não se esquecer de incluir espaços em branco nas suas strings quando necessário; do contrário o Visual Basic apenas irá combiná-las, sem incluir espaços.

Operadores de Comparação

Os seis operadores de comparação são mostrados na Figura 4.8. Quando dois valores forem comparados, o resultado será um valor booleano - isto é, será True (verdadeiro) ou False (falso). ( O termo booleano provém do nome do matemático inglês George Boole.) O Visual Basic oferece as constantes internas chamadas de True e False, que representam os valores -1 e 0, respectivamente. A representação binária de 0 é um número em que todos os bits se encontram no estado 0, e a representação de -1 é um número binário em que todos os bits se encontram no estado 1, tornando o estado True oposto ao estado False

Figura 4.8 Operadores de comparação.

A Figura 4.9 explica e avalia algumas expressões típicas de comparação. Os operadores de comparação são também conhecidos como operadores relacionais, porque avaliam o relacionamento entre

Page 53: Iniciando No Visual Basic

dois operandos. Ainda que todos os operadores de comparação tenham a mesma ordem de precedência, ela é menor que a ordem de precedência de qualquer operador aritmético.

Provavelmente, você deve ter notado que o operador "igual a" usa o mesmo símbolo (=) que o operador de assinalamento. Entretanto, isso não deve causar nenhuma confusão, pois o operador de assinalamento é válido apenas em um local: imediatamente após o nome de uma variável em uma instrução de assinalamento. Em todos os outros casos, o sinal de igual estará sendo usado como operador de comparação, ou operador relacional. Por exemplo, na instrução Test = a = b, a expressão a = b será avaliada como True ou False. O resultado será então assinalado para a variável Test.

Figura 4.9 Usando operadores de comparação.

Operadores Lógicos

Os operadores lógicos às vezes são chamados de operadores booleanos, porque derivam da álgebra de lógica matemática desenvolvida por George Boole. Esses operadores possuem valores booleanos como operandos e retornam resultados

booleanos. A Figura 4.10 exibe os operadores booleanos organizados segundo sua ordem de precedência. (Todos os operadores lógicos têm ordem de precedência menor do que os operadores de comparação.)

Figura 4.10 Operadores lógicos ou booleanos em ordem de precedência.

O operador lógico mais simples é chamado de Not. Ele sempre precede um operando simples e retorna o seu oposto lógico - isto é, ele nega o operando. Por exemplo, a expressão Not False leva ao resultado True (o oposto de False); enquanto a expressão Not (4 < 3) é avaliada como True, porque a expressão (4 < 3) é falsa. O operador Not tem a maior ordem de precedência entre os operadores lógicos.

O próximo operador na ordem de precedência é And. Ele retorna True como resultado se (e somente se) ambos os operandos forem avaliados como True. Se qualquer um dos operandos for avaliado como False, ele retorna False. Esse operador corresponde ao e usado em português, como na frase "Ficarei impressionado apenas se ele for Ph.D. e (And) tiver mais de 1,90 metro de altura".

Page 54: Iniciando No Visual Basic

Expressão Resultado

False And False False

False And True False

True And False False

True And True True

O operador Or retorna o resultado True se qualquer um dos dois operandos for avaliado como True. Novamente, o significado é similar ao uso da palavra ou em português, como, por exemplo, "Eu comprarei o gato se ele custar menos de 50 dólares ou (Or) for um siamês".

Expressão Resultado

False Or False False

False Or True True

True Or False True

True Or True True

Ainda que os operadores Not, And e Or sejam os mais usados, o Visual Basic ainda oferece três outros operadores: Xor, Eqv e Imp. O operador Xor (Or exclusivo) retorna o resultado True se qualquer um dos operandos, mas não ambos simultaneamente, for avaliado como True. Em outras palavras, ele funciona como o operador Or exceto no caso em que ambos os operandos são True.

Expressão Resultado

False Xor False False

False Xor True True

True Xor False True

True Xor True False

O operador Eqv (equivalência) retorna True como resultado se os dois operandos tiverem o mesmo valor.

Page 55: Iniciando No Visual Basic

Expressão Resultado

False Eqv False True

False Eqv True False

True Eqv False False

True Eqv True True

Quando você usar o operador Imp (Implicação), o resultado será False somente se o primeiro operando for True e o segundo for False. Nos outros casos, o resultado será True. O operador Imp é o único operador booleano onde a ordem dos operandos faz diferença. A implicação é usada algumas vezes com o operador And, como ilustrado pelo famoso silogismo "Sócrates é homem e (And) todo homem é mortal, isso Implica (Imp) que Sócrates é mortal".

Expressão Resultado

False Imp False True

False Imp True True

True Imp False False

True Imp True True

É possível usar mais de um operador lógico em uma expressão. A Figura 4.11 fornece alguns exemplos; tente avaliar cada expressão e verifique se o resultado está de acordo com a ordem de precedência mostrada na Figura 4. 10.

Figura 4.11 Usando múltiplos operadores lógicos em uma expressão.

Precedência

A Figura 4.12 exibe o conjunto completo dos operadores do Visual Basic (menos o operador de concatenação de strings), segundo a ordem decrescente de precedência. Ao encontrar uma expressão complexa, você deve em primeiro lugar determinar qual é o operador que tem a maior precedência e então avaliar a subexpressão que o contém. Em seguida, determine qual o operador com a ordem de precedência imediatamente menor, avaliando a subexpressão, e assim por diante até chegar ao resultado final.

Page 56: Iniciando No Visual Basic

Figura 4.12 Operadores do Visual Basic em ordem de precedência.

Alguns operadores, como adição e subtração ou, ainda, todos os operadores de comparação, têm ordem de precedência igual. Ao encontrar operadores com precedências iguais, você deve avaliar as subexpressões da esquerda para a direita.

Considere, por exemplo, a seguinte expressão:

Temperatura >= 300 And Inflamável True

Como os operadores ( > e = ) têm o mesmo nível de precedência, o Visual Basic avaliará essa expressão da esquerda para a direita. Após avaliar as subexpressões que contêm esses operadores, o Visual Basic executará a operação And. Neste caso, se Temperatura for menor do que 300 ou Inflamável for False, o Visual Basic determinará False como resultado final.

Eis aqui um exemplo mais complexo:

Contador * 2 < 15 Or Cor = "Azul" And Contador * 2 < 21

Seguindo a tabela de precedência, o Visual Basic em primeiro lugar executará as duas operações de multiplicação e em seguida as três comparações, da esquerda para a direita. Depois, trabalhará com a operação And e, finalmente, com a operação Or.

Se isso lhe parece um bom jeito de se perder, você está certo. Mesmo que não seja necessário usar parênteses para modificar a ordem de execução das operações, é uma boa idéia colocá-los para melhorar a legibilidade das expressões que serão avaliadas. Com os parênteses, o exemplo anterior ficaria assim:

((Contador * 2) < 15) Or ((Cor = "Azul") And ((Contador * 2) < 21))

Erros Comuns

Quase todos os programadores iniciantes cometem erros relacionados a expressões. Vamos dar uma olhada em alguns dos erros cometidos com maior freqüência, para que você possa evitá-los ou pelo menos identificá-los.

Um dos erros mais comuns é o engano cometido no uso de operadores relacionais quando se deseja testar se uma variável está dentro de uma certa faixa de valores. Por exemplo, ao trabalhar com a variável Temperatura para determinar se o seu valor é maior do que

Page 57: Iniciando No Visual Basic

10 e menor do que 100 graus, você deveria fazê-lo com a expressão Temperatura > 10 And Temperatura < 100. No entanto, você poderia sentir-se tentado a usar a expressão 10 < Temperatura < 100, que apesar de parecer matematicamente correta não funcionará com o Visual Basic. Apesar de estar sintaticamente correta, essa expressão resultaria em uma resposta errada. Por quê?

Comecemos a avaliação das duas subexpressões da esquerda para a direita. (Os dois operadores têm a mesma ordem de precedência.) Como os operadores relacionais sempre retornam True ou False, que são equivalentes aos inteiros -1 e 0, o resultado da primeira subexpressão 10 < Temperatura será -1 ou 0. Em função disso, a segunda subexpressão poderá ser - 1 < 100 ou 0 < 100, que é True. Assim, a expressão 10 < Temperatura < 100 sempre retornará True como resultado final, independentemente do valor da variável Temperatura. Isso é mostrado graficamente na Figura 4.13.

Figura 4.13 Modo incorreto de testar faixa de valores.

Outro erro típico é a criação de expressões lógicas com a mesma imprecisão que freqüentemente há na língua falada. A expressão no exemplo anterior foi cuidadosamente formulada para encontrar um valor que seja "maior do que 10 graus, mas menor do que 100 graus". Porém, se estivesse conversando com um colega, você poderia ter estabelecido a questão da seguinte forma: "Eu desejo saber quando a temperatura é maior do que 10 graus ou menor do que 100 graus". Essa formulação é menos precisa (e de fato errônea), porém as pessoas são razoavelmente inteligentes para conviver com esta ambigüidade, e provavelmente o seu colega entenderia o que você realmente pretendia falar. A expressão correta correspondente a essa formulação seria Temperatura > 10 Or Temperatura < 100.

Novamente, examinando a expressão sob a ótica do Visual Basic, você pode perceber onde está o problema. Primeiro seriam avaliadas as duas expressões relacionais e depois a operação booleana Or. A subexpressão Temperatura > 10 será True para todos os números maiores do que 10; a outra subexpressão relacional, Temperatura < 100, será True para todos os valores menores do que 100. Veja, agora, o que acontece quando você junta essas duas expressões. Se a variável contiver o valor 5, a primeira subexpressão resultará False ( 5 < 10), enquanto a segunda resultará True, pois 5 é menor do que 100. A operação Or sempre terá True como resultado, pois um operando sempre será True. Analogamente, o valor 200 fará com que a primeira resulte True e a segunda, False, levando a operação Or a ser True. Para o valor 50, ambas as subexpressões resultarão True e

Page 58: Iniciando No Visual Basic

a operação Or será True também. Portanto, o uso do operador Or em vez de And fará com que a expressão que você montou resulte sempre True.

Um terceiro engano comum é confundir uma instrução de assinalamento com condições matemáticas. Esse problema pode ser ilustrado pelo seguinte fragmento de código:

A = 10

B = A / 2

A = 20

Após a execução dessas três instruções, A valerá 20 e B, 5. Se você imaginou que B deveria valer 10, caiu na armadilha. A segunda instrução não expressa uma condição que é True a todo instante; em vez disso, é uma expressão que é avaliada uma única vez, com um determinado valor para a variável A. Nesse exemplo, a instrução é processada quando a variável A tem o valor 10. Instruções que se seguem podem alterar o valor de A, porém o valor armazenado na variável B permanecerá intacto até que seja executada outra instrução de assinalamento para essa variável.

Vejamos outro erro comum. Até agora, usamos apenas os valores False e True em operações booleanas, porque é isso que você encontrará com maior freqüência. No entanto, é preciso estar atento para o fato de que os valores True e False são equivalentes aos valores -1 e 0. O Visual Basic não gerará qualquer mensagem de erro se você usar And, Or Imp ou qualquer um dos operadores lógicos com operandos inteiros, tais como 6 ou 237. O Visual Basic realmente executará a operação booleana especificada sobre cada bit dos operandos

Isso pode conduzir a erros estranhos. Por exemplo, digamos que seja necessário saber quando a variável x é igual a 5 ou 6. Você poderia tentar codificar a instrução como Debug.Print x = 5 Or 6. O Visual Basic executará a operação Or sobre os inteiros 5 e 6, um bit de cada vez, resultando 7. Então o valor de x seria comparado com 7, que não é exatamente o que você tinha em mente. Em vez disso, você deveria codificar a instrução como Debug.Print (x = 5) Or (x = 6).

Procedimentos

Page 59: Iniciando No Visual Basic

Muito embora você já tenha escrito alguns procedimentos e saiba o que são e como funcionam, será útil investir algum tempo para formalizar esse conhecimento. Esta seção aborda basicamente os procedimentos internos do Visual Basic; mais adiante enfocaremos o projeto e a criação de novos procedimentos.

Um procedimento e um conjunto de instruções que executa um determinado serviço. Você pode requisitar a execução do serviço pelo nome do procedimento que o contém. Por exemplo, no Capítulo 3, você escreveu um pequeno programa que usava o procedimento MsgBox. Quando aquela parte do seu programa era executada, o Visual Basic exibia em uma caixa de diálogo a mensagem que havia sido fornecida. Quando a caixa de diálogo era fechada, a execução de seu programa prosseguia. O Visual Basic oferece o serviço de desenhar uma caixa de diálogo ao redor de sua mensagem, criando um botão OK, inspecionando o mouse até que seja dado um clique no botão e removendo a caixa de diálogo da tela; tudo o que você tem de fazer é fornecer a mensagem a ser exibida.

Serviços oferecidos pelo Visual Basic podem ser comparados com aqueles serviços corriqueiros, executados todos os dias. Por exemplo, se você acabou de adquirir uma pintura de Van Gogh e está preocupado com uma possível falta de fundo para cobrir o cheque com o qual pagou o quadro, pode chamar o banco e solicitar uma transferência. Você fornece ao banco os números das contas e o valor a ser transferido. Após isso, o banco executará o serviço requisitado, sem qualquer intervenção de sua parte.

Em outros casos, um objeto palpável é retornado pelo provedor do serviço. Por exemplo, você pode visitar uma pizzaria local, entregar a eles o seu pedido de pizza e alguns trocados e obter uma pizza como retorno. Como você deve lembrar-se, os procedimentos do Visual Basic que retornam valores são chamados de funções. No programa de exemplo do Capitulo 3, você chamou a função InputBox, passou-lhe uma frase a ser apresentada e ela exibiu a caixa de diálogo e lhe retornou o texto introduzido na caixa de diálogo.

O Visual Basic oferece muitas funções internas úteis, algumas das quais se encontram descritas na Figura 4.14. Você pode usar o sistema de ajuda on-line do Visual Basic, para explorar em maiores detalhes essas funções internas.

Sintaxe para Procedimentos e Funções

Page 60: Iniciando No Visual Basic

Para chamar um procedimento ou função, é preciso usar o seu nome. Além disso, o Visual Basic tem regras específicas sobre a sintaxe de uma instrução - isto é, sobre como a instrução tem de ser codificada. (Ainda que as funções também possam ser chamadas de procedimentos, na abordagem que se segue, por questões de clareza, será mantida a diferenciação entre funções e procedimentos. Apenas lembrando: funções são procedimentos que retornam valores.)

Figura 4.14 Algumas funções internas do Visual Basic.

Para usar ou chamar um procedimento, deve-se escrever uma instrução Visual Basic em que o nome do procedimento seja o primeiro item. A chamada a um procedimento é uma instrução completa do Visual Basic, e o procedimento pode não requerer qualquer informação adicional. Caso necessário, os valores a serem passados para o procedimento devem ser separados por vírgulas. Os valores a serem passados são chamados de argumentos ou parâmetros do procedimento. No caso do procedimento MsgBox, você usou apenas um argumento, a string de texto a ser exibida. As instruções a seguir são exemplos de chamadas a procedimentos:

MsgBox "Alô, companheiro"

ChDir "\teste\dados"

Beep

SavePicture NoitedeEstrelas, "vincent.bmp"

A sintaxe para a chamada de funções é diferente. Como há o retorno de valor, a chamada pode ser usada em todos os lugares onde uma expressão possa ser colocada. A chamada a uma função será habitualmente encontrada dentro do contexto de alguma outra instrução, mais freqüentemente a instrução de assinalamento.

Quando uma função não requer argumentos, você pode usar o nome de função como se fosse o nome de uma variável, tal como em Tempoinicial = Now. A função Now não requer argumentos e retorna um valor temporal. O Visual Basic chama a função e assinala o valor retornado à variável Tempoinicial.

Quando uma função requer um ou mais argumentos, deve-se colocar um parêntese à esquerda antes do primeiro argumento e um parêntese à direita após o último. Os parênteses só são usados se a função estiver sendo usada numa expressão em que um valor de

Page 61: Iniciando No Visual Basic

retorno é esperado da função. Caso o valor de retorno da função não seja esperado no contexto de uso, os parênteses precisam ser omitidos e a função é chamada como um procedimento comum (A exemplo dos procedimentos, os argumentos de uma função também devem ser separados por vírgulas.) As expressões a seguir contêm chamadas válidas para funções, porém não são instruções completas do Visual Basic:

Sin(x) ^ 2 'Obtém o quadrado do seno de x

Chr$(65) Retoma o caractere ASCII correspondente a 65

Format(Now,"hh:mm") Formata a hora atual

Note que, no terceiro exemplo, a expressão contém uma chamada de função dentro de outra. O valor retornado pela função Now é passado como argumento para a função Format.

Métodos

Procedimentos e funções fazem parte de linguagens de programação há muitos anos. Mais recentemente, os projetistas das linguagens de programação orientadas a objetos introduziram um tipo especial de procedimentos e funções, chamado método. O Visual Basic inclui métodos para cada um de seus objetos, tais como forms ou botões de comando. Métodos funcionam da mesma maneira que procedimentos e funções, porém são componentes de objetos específicos, tais como propriedades e nomes de campos.

Para chamar um método, deve-se usar o nome do objeto seguido pelo nome do método (separados por um ponto ".", evidentemente), como, por exemplo, Debug.Print.

Isso é um pouco mais trabalhoso do que apenas usar o nome do procedimento, porém tem a vantagem de permitir que vários métodos tenham o mesmo nome. Em versões antigas do Visual Basic, o procedimento Print escrevia uma string de texto no terminal do usuário. Para enviar a mesma string para uma impressora, era necessário usar um procedimento diferente, LPrint. Ambos os procedimentos operavam similarmente, mas, devido a pequenas diferenças, eram necessários dois comandos distintos.

O Visual Basic não tem um procedimento Print. Em vez disso, todos os objetos para os quais você puder enviar dados que serão

Page 62: Iniciando No Visual Basic

registrados têm um método chamado Print. Para escrever o texto "Alô" em um form chamado MeuForm, você poderia criar a instrução:

MeuForm.Print "Alô"

Para enviá-lo para a impressora, que é representada em Visual Basic por um objeto especial chamado Printer, você poderia usar este código

Printer.Print "Alô"

A janela Immediate, representada por um objeto chamado Debug, também possui um método Print. Muito bem, como o Visual Basic oferece método Print para cada um desses objetos, não é necessário que haja diversos comandos com nomes diferentes. Com menos comandos para assimilar, seu aprendizado será facilitado.

Com freqüência, o Visual Basic permite-lhe omitir o nome do objeto ao usar um método. Caso isso seja feito, o Visual Basic assumirá tratar-se do form atual. Se você tivesse escrito apenas Print "Alô" nos exemplos acima, a saída seria direcionada para o form que estava ativo quando essas instruções fossem executadas. Para evitar ambigüidade, você sempre pode especificar o objeto ao qual pertence o método desejado, usando a denominação Objeto.Método.

Métodos podem funcionar como procedimentos ou como funções - isto é, eles podem apenas executar um serviço, tal como o método Print, ou podem retornar um valor. Alguns métodos - tais como Move, que altera o posicionamento de um objeto - encontram-se implementados para quase todos os tipos de objetos. Outros são mais específicos. Por exemplo, o método Print é implementado apenas para alguns objetos, tais como forms e printer. O próximo capítulo explora os objetos do Visual Basic, seus métodos e suas propriedades.

Page 63: Iniciando No Visual Basic

Usando as Ferramentas e Forms do Visual Basic

Objetos do Visual Basic

Uma das maiores vantagens da interface gráfica é que o usuário pode interagir com um conjunto padronizado de objetos, tais como janelas, botões e barras de deslocamento. Aplicativos que usam esses objetos padrões comportam-se de forma padrão, simplificando o aprendizado do aplicativo. Uma parte do trabalho do programador é selecionar o estilo de interação mais apropriado para a situação e escrever os seus programas de forma que o usuário ache-o intuitivamente.

Em um ambiente GUI (Graphical User Interface - Interface Gráfica com Usuário), o usuário interage com os objetos apresentados na tela, para dar início a eventos -abrir uma janela, dar um clique em um ícone, escolher um item de menu, e por meio disto, controlar o aplicativo. O Visual Basic transforma eventos iniciados pelo usuário em atividade programada, chamando o procedimento associado ao evento. A codificação que você insere no tal procedimento de evento implementa a resposta apropriada à interação com o objeto.

Uma Nota sobre Este Capítulo

Este capítulo descreve a maioria dos objetos que se encontram disponíveis quando você constrói aplicativos em Visual Basic, incluindo forms e os objetos criados pelas várias ferramentas contidas na caixa de ferramentas. Você já encontrou alguns destes objetos em capítulos anteriores; aqui, entretanto, terá uma visão mais aprofundada sobre algumas das propriedades que podem ser configuradas e como elas afetam os objetos, em eventos gerados quando o usuário manipula esses objetos em um aplicativo, e sobre alguns procedimentos e métodos que podem ser usados com os objetos. Também exploraremos o processo de criação e desenvolvimento de menus para seus aplicativos.

No final da maioria das seções deste capítulo, um projeto simples demonstra como você pode usar os objetos do Visual Basic que foram abordados. Os passos para a criação dos dois primeiros projetos foram colocados explícita e detalhadamente, entretanto, nos projetos subseqüentes, as recomendações serão mais genéricas - por exemplo, simplesmente avisando-o para criar um novo projeto, sem indicar de que forma fazer isso -, assumindo que você já saiba como proceder.

Page 64: Iniciando No Visual Basic

Geralmente, será decisão sua salvar ou não um aplicativo de exemplo. Na maioria dos casos, isso não é necessário. Porém, se você sabe que usará uma ferramenta específica ou objeto em um futuro próximo, poderá ser útil salvar o projeto associado, para poder posteriormente retornar a ele.

Você deve saber que as listas de propriedades, procedimentos, eventos e métodos apresentados neste capítulo não estão completas; ao contrário, o objetivo é fornecer-lhe as ferramentas suficientes para escrever programas úteis. Achamos que a apresentação da lista completa neste momento seria um tanto quanto exaustiva. Porém, caso necessite de informações adicionais, ela se encontra disponível no sistema de ajuda on-line. No CD que contém este manual, você pode encontrar uma tradução para o português da parte mais utilizada da ajuda on-line.

Observe que muitos dos objetos que serão descritos aqui têm propriedades idênticas ou suportam eventos semelhantes. Em tais casos, a descrição completa das propriedades, procedimentos, eventos, e assim por diante, não será repetida para cada objeto. Iniciaremos com a descrição dos forms; você encontrará uma descrição mais ampla nesta mesma seção.

Uma Nota sobre Sintaxe

A maioria das descrições de procedimentos e métodos inclui a sintaxe das instruções Visual Basic envolvidas. Nesta sintaxe das instruções, itens mostrados em itálico indicam que o tipo de informação deve ser fornecido; por exemplo, onde for visto o termo variável, deverá ser introduzido o nome de uma variável. Itens tipo romano (texto) indicam palavras-chave ou caracteres que devem ser colocados na forma em que estão sendo apresentados. Itens colocados entre colchetes ([ ]) são opcionais, isto é, a instrução será válida mesmo que os itens sejam omitidos. Itens entre chaves ({ }) que estejam separados por barra vertical ( | ) indicam uma escolha; você deve selecionar um dos itens dentro das chaves. Se um conjunto de colchetes ou chaves for seguido por reticências ( ... ), a seqüência dentro do conjunto de colchetes ou chaves pode ser repetida. Eis um exemplo:

O nome é [muito] {grande | pequeno} [e { espessa | tímida | verde }] ...

Segundo a notação sintática apresentada, você pode usar este exemplo para construir todas as frases abaixo:

A fábrica é muito grande.

Page 65: Iniciando No Visual Basic

O submarino é pequeno e verde.

A janela é muito pequena e espessa e tímida e verde.

Como se pode ver, sintaxe correta não produz necessariamente instruções com significado; você verá que é muito fácil escrever programas sintaticamente corretos, mas que não funcionam. Cuidaremos desse problema no Capítulo 7.

Forms

Como você aprendeu no Capítulo 1, forms são pranchetas onde o aplicativo é criado visualmente. Cada form corresponde a uma janela, quando o aplicativo estiver sendo processado.

Propriedades

Muitas propriedades podem afetar a aparência e o comportamento de um form quando ele é exibido; aqui, serão apresentadas apenas as propriedades usadas com maior freqüência. A menos que seja feita alguma observação em contrário, as propriedades podem ser configuradas por meio da janela de propriedades (Properties) enquanto você está desenvolvendo o seu aplicativo, ou então por meio de instruções executadas durante o processamento do programa.

AutoRedraw A propriedade AutoRedraw (discutida em detalhe quando falarmos de gráficos) controla como as imagens da tela são recriadas. Quando você volta ao form do Visual Basic, após trabalhar em outra janela que tenha sido sobreposta, o Visual Basic gerará ou traçará novamente qualquer gráfico sobre o form se a propriedade

AutoRedraw estiver configurada para True. Quando essa propriedade está configurada como False, o Visual Basic deve chamar um procedimento de evento para efetuar esse trabalho.

BackColor Esta propriedade determina a cor do fundo. Ao selecionar BackColor a partir da lista de propriedades, na janela de propriedades, vê-se a configuração default &H8000000F&, uma constante hexadecimal (base 16) que define uma cor Visual Basic. O Capitulo 10 fornece maiores detalhes sobre essas configurações de cores, porém não é necessário saber muito a seu respeito para configurar a propriedade BackColor: basta dar um clique no botão de seta para baixo à direita do valor padrão na janela de propriedades e o Visual Basic exibirá as opções de cores, como mostrado aqui:

Page 66: Iniciando No Visual Basic

Figura 5.1

Escolha a cor a partir da palheta, dando um clique no quadrado que contiver a cor desejada, ou então dê um clique fora da área da palheta para fechá-la.

BorderStyle Você pode configurar esta propriedade para um dos seis valores predefinidos. A propriedade BorderStyle pode ser configurada apenas em tempo de desenvolvimento. As configurações não afetam o form em tempo de desenvolvimento, porém modificarão a exibição da janela em tempo de execução, como segue:

Figura 5.2

Caption Esta propriedade contém o texto da barra de título da janela de form

ControlBox Esta propriedade booleana deve ser configurada para True se você desejar uma caixa para o menu de controle a ser exibido no canto superior esquerdo da janela. Você pode alterar esta propriedade apenas em tempo de desenvolvimento. Configurar esta propriedade para True não tem efeito se a configuração de BorderStyle for 0 - None.

Enabled Todo objeto Visual Basic tem a propriedade Enabled, que pode ser configurada para True ou False, ativando-se ou desativando-se o objeto. Para forms esta propriedade é normalmente configurada como True, porém você pode passá-la para False, para evitar que eventos de teclado ou mouse sejam enviados para o form.

FontBold, FontItalic, FontStrikethru, FontUnderline Você pode configurar estas propriedades booleanas para True se desejar que o texto a ser impresso no form apareça em negrito, em itálico, tachado ou sublinhado (ou ainda com qualquer combinação destas propriedades). Apenas os caracteres impressos após a modificação destas propriedades é que serão afetados pela nova configuração.

FontName A esta propriedade é assinalado o nome da fonte que será usada para impressões no form Quando esta propriedade é modificada, o texto já escrito sobre o form permanece com a fonte anterior. Por exemplo, se você executasse a codificação a seguir, a letra C seria impressa na fonte Courier New, e todas as outras seriam impressas em Times New Roman:

FontName = "Times New Roman"

Page 67: Iniciando No Visual Basic

Print "AB"

 

FontName = "Courier New"

Print "C"

FontName = "Times New Roman"

Print "DE"

FontSize Esta propriedade permite-lhe especificar o tamanho (em pontos) para o texto a ser impresso no form (Ponto é a unidade padrão tipográfica para mensuração de tamanho de tipos; 1 ponto equivale a 1/72 polegadas.) Como as anteriores, a modificação desta propriedade afeta apenas os textos que forem impressos após a mudança.

ForeColor Esta propriedade define a cor do texto ou gráfico. Você pode configurar esta propriedade com a palheta de cores, da mesma forma que a usou para configurar a propriedade BackColor. (Maiores detalhes no Capítulo 11.) Todas as instruções Print escrevem texto usando esta cor.

Height, Width Estas propriedades determinam a altura e o comprimento de um form, medidos na unidade chamada twips, ou seja, 1/20 de um ponto. (Um twip é equivalente a 1/1440 polegadas.)

Icon Você pode configurar esta propriedade para o nome de um arquivo contendo um ícone. Esse ícone representará o form, quando ele for minimizado. Para configurar esta propriedade em tempo de desenvolvimento, selecione-a a partir da lista de propriedades na janela de propriedades e então dê um clique no botão de reticências, que aparece ao lado da caixa de configurações para esta propriedade ao selecioná-la. Na caixa de diálogo resultante, escolha o arquivo de ícone. Se desejar configurar esta propriedade em tempo de execução, você deverá usar a função LoadPicture, ou assinalar o valor da propriedade Icon de algum outro form,

MaxButton, MinButton Você deve assinalar estas propriedades para True se desejar que os botões de minimização e maximização sejam exibidos no canto superior direito da janela. Estas duas propriedades serão ignoradas se a propriedade BorderStyle for configurada para 0 - None. Observe que esses botões não desaparecem do form, em tempo de desenvolvimento, mesmo que as propriedades MaxButton e

Page 68: Iniciando No Visual Basic

MinButton tenham sido configuradas para False; o efeito dessa configuração é visível apenas em tempo de execução.

Name Esta propriedade define o nome do form, no código do programa. Não pode ser modificada em tempo de execução.

Picture Você pode configurar esta propriedade para indicar a imagem do tipo bitmap que sempre será exibida na janela. Para configurar esta propriedade em tempo de desenvolvimento, selecione-a a partir da lista de propriedades e dê um clique no botão de reticências que aparece à direita da caixa de configurações na janela de propriedades. Na caixa de diálogo resultante, escolha o arquivo contendo a imagem que você deseja exibir. Para alterar esta propriedade em tempo de execução, você deve usar a função LoadPicture.

Top, Left Estas propriedades controlam o posicionamento da janela em relação ao vídeo, definindo as coordenadas do ponto superior esquerdo da janela, calculadas em twips.

Visible A definição desta propriedade booleana indica quando a janela form, é ou não visível. Configurá-la para False faz com que o form, torne-se "invisível".

WindowState Esta propriedade determina quando a janela está exibida em seu estado normal (valor 0), minimizada como um Ícone (valor 1) ou em um estado maximizado (valor 2).

StartUpPosition Com esta propriedade você define a posição inicial do formulário na tela quando do seu carregamento. Pode ser configurada tanto em tempo de desenvolvimento quanto em execução. As seguintes constantes representam os valores válidos para a propriedade:

Figura 5.3

Eventos

Click (dar um clique), DlbClick (dar um clique duplo) e Load (carga) são os eventos mais comuns para um form processar. (O evento Keypress - pressionamento de tecla - e o processo de arrastar e soltar (drag-and-drop) serão apresentados nos Capítulos 6 e 7.)

Click Quando o usuário dá um clique no form, o Visual Basic chama o procedimento form_Click. Caso o clique seja dado em um objeto que se encontra no form, o evento Click não será passado para o form mesmo que o objeto em questão não processe o evento.

Page 69: Iniciando No Visual Basic

DblClick Este evento é recebido quando o usuário dá dois cliques em rápida sucessão no mesmo ponto do form, Este processo na realidade dispara dois eventos: o evento Click para o primeiro clique do mouse e o evento DbIClick para o segundo clique.

Load Este evento ocorre automaticamente sempre que o form, for carregado. Por exemplo, quando o aplicativo é iniciado.

Procedimentos e Métodos

Os métodos mais interessantes de um form, são gráficos. Por serem um tanto complexos, foi reservado um capítulo especial para eles (Capítulo 11). Neste momento, daremos uma pequena introdução a alguns métodos (e a uma função) para despertar o seu interesse.

Cls Este método provoca a limpeza de todos os textos e gráficos de um form. A sintaxe completa é a seguinte:

[formName].Cls

LoadPicture Você pode usar esta função para configurar a propriedade Picture de um form. Eis a sua sintaxe:

LoadPicture([fileName])

fileName deve ser uma expressão de string que identifique um arquivo contendo um ícone, um bitmap do Windows ou um metarquivo do Windows. (Esses nomes de arquivos têm sufixos bem característicos: ICO, BMP e WMF, respectivamente.)

Caso não seja especificado um nome de arquivo, load picture retornará uma imagem em branco.

Print Este método escreve texto em um form. Use a sintaxe:

[formName].print [[expressão][{;|,}]]...

Cada expressão é seguida por ponto e vírgula ou por vírgula. Se for usado (;) a saída da próxima expressão segue imediatamente o último caractere escrito. Se for usado (,), a posição de saída no form será tabulada para a próxima coluna. (Colunas são definidas a cada 14 caracteres.) Caso a expressão final na instrução Print não termine com (;) ou(,), a posição do próximo caractere a ser escrito no form será configurada para o início da próxima linha. Eis aqui alguns exemplos de uso do método Print na janela Immediate:

Page 70: Iniciando No Visual Basic

Figura 5.4

Por mais estranho que possa parecer, o método Print na realidade é um método gráfico; você encontrará maiores informações a respeito no Capítulo 12.

O Aplicativo Sorriso

Agora, tente construir este projeto simples, que demonstra algumas configurações de propriedades, métodos e procedimentos associados a forms.

Inicie o aplicativo Paint no Windows 95, desenhe uma imagem simples e salve-a em seu disco fixo. Eis um exemplo, usando um famoso ícone cultural dos anos 70, que chamaremos de Sorriso.bmp.

Figura 5.5

Retorne ao Visual Basic e crie um novo projeto com a opção New Project do menu File

Na janela de propriedades, selecione a propriedade Picture da lista de propriedades e dê um clique no botão de reticências à direita do campo de configurações. A caixa de diálogo Load Picture aparece:

Figura 5.6

Use a caixa de diálogo para localizar o arquivo gráfico criado pelo Paint e dê um clique no botão Abrir. A versão do form agora está parecida com:

Figura 5.7

Abra a janela de código para Form1, clicando no botão View Code na janela do Explorador de Projeto ou com um clique duplo no form.

Selecione Form na caixa Object no topo da janela de código e então selecione Click na caixa de procedimentos. Introduza o código necessário para criar o procedimento Form_Click, como mostrado abaixo:

Private Sub Form_Click ()

Form1.Print "Tenha um ";

Form1.FontBold = True

Page 71: Iniciando No Visual Basic

Form1.Print "bom";

Form1.FontBold = False

Form1.Print " dia"

End Sub

Selecione o procedimento DlbClick na caixa de procedimentos. Introduza a linha de código para criar o procedimento Form_DbIClick, como mostrado a seguir:

Sub Form_DbIClick()

Form1.Cls

End Sub

Execute agora o aplicativo, escolhendo a opção Start do menu Run, dando um clique no botão Start da barra de ferramentas ou pressionando F5. Dê cliques em vários pontos do form O aplicativo deveria comportar-se como mostrado aqui:

Figura 5.8

8. Enquanto o aplicativo estiver sendo processado, tente dar um clique duplo no form Isso fará com que seu programa execute o procedimento Form_DbIClick. Se você examinar atentamente, verá que o procedimento Form_Click é executado antes que o procedimento Form_DbIClick limpe o form Além disso, repare que o método Cls limpa apenas as informações que foram adicionadas ao form e não a imagem de fundo.

O código escrito para esse exemplo é muito específico. Por exemplo, tanto o método Print quanto a propriedade FontBold fazem referência explícita ao form Form1, Em certas ocasiões, essa especificidade pode causar problemas. Para ilustrar, deixe o aplicativo (pressionando Alt-F4 ou dando um clique no botão End da barra de ferramentas) e retorne ao modo de desenvolvimento. Agora, altere a propriedade Name do form para Sorriso. Em seguida, tente executar o programa novamente. O Visual Basic exibirá a mensagem de erro mostrada na Figura 5.9.

O Visual Basic está reclamando que não conhece o objeto chamado de Form1, Realmente, o seu programa não contém tal objeto; o único form agora se chama Sorriso.

Page 72: Iniciando No Visual Basic

Figura 5.9 A mensagem de erro objeto não definido

A modificação dos nomes dos forms pode demandar um tempo considerável, principalmente quando se tornar necessário incorporar pedaços de um programa em outro. O Visual Basic oferece um mecanismo que permite evitar esse tipo de problema. Métodos e propriedades, tais como variáveis, também têm escopo. Caso o nome de propriedades ou métodos sejam usados sem referência explícita ao objeto o que pertencem, o Visual Basic usará o contexto da execução presente para determinar qual o objeto envolvido. Se você eliminar todas as referência ao Form1, o código do aplicativo Sorriso ficará assim:

Sub Form_Click ()

Print "Tenha um ";

FontBold = True

Print "bom";

FontBold = False

Print " dia"

End Sub

Sub Form_DbIClick ()

CIS

End Sub

Uma vez que os procedimentos Form_Click e Form_DbIClick sempre são executados levando-se em consideração o contexto do form (independentemente do nome do Form), os métodos Print e CIs e a propriedade FontBold devem estar dentro do escopo do form atual. Assim, o código que você cria será mais genérico.

(Além disso, haverá menos digitação a ser feita.)

Caixas de Imagem e Imagens

Os controles de caixa de imagem e imagens permitem-lhe colocar informações gráficas em posições especificas do form As ferramentas Caixa de Imagem e Imagens da caixa de ferramentas são mostradas

Page 73: Iniciando No Visual Basic

nas Figuras 5.10 e 5.11. A caixa de imagem é o controle mais flexível, portanto seu uso demanda mais memória e tempo de processamento. As caixas de imagem são mais indicadas para o tratamento de ambientes dinâmicos - por exemplo, quando você está traçando gráficos diretamente sobre o vídeo, enquanto o programa está executando ou deslocando um ícone pela tela para gerar o efeito de animação. (Métodos gráficos, que lhe permitem traçar linhas e imprimir textos, encontram-se descritos no Capítulo 11.) Quando se tratar de situações estáticas, é mais recomendável o uso de objetos de imagens - isto é, quando ícones ou imagens bitmap que você criou e colocou sobre a tela não são modificados.

Figura 5.10 A ferramenta Caixa de Imagem.

Figura 5.11 A ferramenta Imagem.

Propriedades

Os controles de caixa de imagem e imagem têm as propriedades Enabled, Height, Left, Name, Picture, Top, Visible e Width. A maioria dessas propriedades comporta-se exatamente como descrito na seção precedente sobre forms exceto pelo fato de as coordenadas para as propriedades Height, Left, Top e Width serem medidas com relação à localização do objeto dentro do form e não em termos de sua posição absoluta na tela. (Isso é válido para todos os controles criados a partir da caixa de ferramentas.) A propriedade Picture pode ser configurada para exibir uma imagem bitmap ou um ícone. Em tempo de desenvolvimento, use a janela de propriedades e a caixa de diálogo Load Picture (como será usada no projeto simples que se segue); em tempo de execução, é necessário usar a função LoadPicture.

Caixas de imagem, que apresentam comportamento semelhante a pequenos forms colocados dentro do form principal, possuem algumas propriedades a mais que o controle de imagem: AutoRedraw, FontBold, FontItalic, FontName, FontSize, FontUnderline. Essas propriedades comportam-se do mesmo modo que para o form. Controles de imagens têm uma propriedade que as caixas de imagem não têm: a propriedade Stretch. Por default, essa propriedade é configurada para False, fazendo com que o controle de imagens se redimensione para acomodar a imagem que ele contém. Quando a propriedade Stretch for True, o redimensionamento é feito sobre a imagem, de forma a caber dentro do controle.

Os controles caixas de imagem e imagens ainda diferem em um aspecto. A exibição de um form. é composta por três camadas,

Page 74: Iniciando No Visual Basic

conforme ilustrado pela Figura 5.12. Toda e qualquer informação exibida diretamente sobre o form. (por exemplo, mediante impressão ou desenho com métodos gráficos) será colocada na camada inferior. Informações geradas a partir dos três controles gráficos (imagens, forma e controle de linhas) aparecem na camada intermediária e todos os outros objetos são exibidos na camada superior. Em função disso, texto impresso no form. poderá ser sobreposto por uma caixa de imagem.

Figura 5.12 As camadas de exibição de um form.

Eventos

A exemplo dos forms os controles caixas de imagem e imagens também podem receber os eventos mais simples que ocorrem com maior freqüência: Click e DbIClick.

Métodos e Procedimentos

A função LoadPicture pode ser chamada para configurar a propriedade Picture de uma caixa de imagem ou do controle de imagens. Caixas de imagens suportam tanto os métodos CIs e Print quanto os métodos gráficos descritos no Capítulo 11.

A Palheta de Símbolos

Este projeto simples faz com que você use uma série de imagens para criar uma palheta de ícones semelhante à caixa de ferramentas do Visual Basic. Este programa deveria funcionar da mesma forma, seja com caixas de imagem, seja com controles de imagens; lembre-se, no entanto, de que as caixas de imagens são menos eficientes para o tratamento de situações estáticas.

Crie um novo projeto em Visual Basic, com a opção New Project do menu File.

Configure as propriedades do form. conforme mostrado a seguir. (A notação [vazio] indica que a configuração dever ser uma string vazia.)

Propriedade Configuração

BorderStyle 1 - Fixed Single

Caption [vazio]

MaxButton False

Page 75: Iniciando No Visual Basic

MinButton False

Name Simbolos

Dê um clique na ferramenta Imagem da caixa de ferramentas e arraste o ponteiro do mouse no form para criar um pequeno controle de imagem no canto superior esquerdo do form:

Figura 5.13

Crie mais três controles de imagem do mesmo tamanho, dispondo-os dois a dois. Para realizar essa tarefa com mais facilidade, selecione o primeiro controle imagem criado e dê um clique no botão de Copiar na barra de ferramentas; clique então no botão de Colar; responda não à caixa de diálogo que perguntará se você quer criar uma matriz de controles; uma cópia do controle será colada sobre o primeiro; para movimentar com precisão o novo controle, mantenha a tecla Ctrl pressionada e use as teclas de seta para movimentá-lo na direção desejada. Com o mouse redimensione o contorno da janela do form para acomodar apenas os quatro controles de imagem. Agora, o seu form deve estar parecido com:

Figura 5.14

Dê um clique no controle de imagem superior esquerdo do form (Image1) para selecioná-lo. Na janela de propriedades, selecione a propriedade Picture para Image1, a partir da lista de propriedades. A seguir, dê um clique no botão de reticências, à direita da propriedade selecionada, para abrir a caixa de diálogo Load Picture (mostrada anteriormente). Na caixa de diálogo, configure o tipo de arquivo para exibir arquivos de ícones (com extensão ICO). Você poderá encontrar os quatro arquivos de ícone que usaremos neste projeto na pasta ...\PacoteVB\Icones\Misc\ no primeiro cd deste produto. Selecione o arquivo CLUB.ICO e clique em abrir na caixa de diálogo LoadPicture. Ao escolher esse arquivo, o ícone que ele contém aparecerá no controle de imagem selecionado:

Figura 5.15

Dê um clique duplo na imagem e defina o seguinte procedimento na janela de código:

Private Sub lmage1_Click ()

Debug.Print "Selecionado Paus"

Page 76: Iniciando No Visual Basic

End Sub

Repita esse mesmo processo para os outros três controles de imagem, carregando os arquivos DIAMOND.ICO, HEART.ICO e SPADE.ICO e definindo os três procedimentos Click como mostrado a seguir:

Private Sub Image2_Click ()

Debug.Print "Selecionado Ouro"

End Sub

Private Sub Image3_Click ()

Debug.Print "Selecionado Copas"

End Sub

Private Sub Image4_Click ()

Debug.Print "Selecionado Espada"

End Sub

8. Para separar visualmente os ícones, você pode colocar bordas ao seu redor. Dê um clique na imagem no canto superior esquerdo para selecioná-la e então, mantendo a tecla Ctrl pressionada, dê um clique nas outras três imagens para selecionar as quatro ao mesmo tempo. Selecione a propriedade BorderStyle na lista de propriedades da janela de propriedades e configure-a para 1 - Fixed Single.

Quando você executar o aplicativo (pressionando F5), o seu form será a palheta "Símbolos". Dando cliques em alguns dos ícones, você deverá ver um resultado semelhante ao mostrado naFigura 5.16.

Figura 5.16 Usando a palheta de símbolos.

Ao incluir uma codificação semelhante em um aplicativo maior, você pode criar uma palheta de ícones apropriada ao programa. A caixa de ferramentas do Visual Basic, que é usada em tempo de desenvolvimento, é um exemplo desse tipo de palheta.

Dica: Se você tem o Visual C++ instalado no seu sistema, pode utilizar-se do editor de ícones que o acompanha. Entre no Visual C++ e escolha a opção New do menu File. Entre as opções apresentadas

Page 77: Iniciando No Visual Basic

na janela New escolha a ficha File. Será exibida uma relação de tipos de arquivos dentre os quais está a opção "Icon File". Ao selecionar esta opção, será aberto o editor de ícones para que você crie um novo ícone para a sua aplicação. Para informar-se sobre como utilizá-lo procure mais informações no help do próprio Visual C++.

Rótulos

Um rótulo oferece uma área na qual você pode apresentar informação textual que não poderá ser editada pelo usuário. O conteúdo é configurado pela propriedade Caption do rótulo. Você não pode imprimir ou desenhar um rótulo. Os rótulos devem ser criados com a ferramenta Rótulo da caixa de ferramentas do Visual Basic, mostrada na Figura 5.17.

Figura 5.17 A ferramenta Rótulo.

Propriedades

Os rótulos têm as propriedades FontBold, FontItalic, FontName, FontSize, FontUnderline, Height, Left, Name, Top, Visible e Width, que operam de forma padrão. Algumas propriedades adicionais são apresentadas a seguir:

Alignment Esta propriedade determina o alinhamento do texto (propriedade Caption) em relação ao rótulo. Por default, a propriedade Alignment é configurada para 0, o que provoca alinhamento à esquerda. Você pode ainda configurar o alinhamento para 1 -Right Justify (justificado à direita) ou 2 - Center (centralizado).

AutoSize Se esta propriedade for True, o rótulo é automaticamente redimensionado para conter o texto especificado pela propriedade Caption. Se for False, o rótulo manterá o tamanho definido em tempo de desenvolvimento; nesse caso, se o texto for muito longo, ele será truncado.

BorderStyle Esta propriedade pode ser 0 (default) para o rótulo não conter borda ou 1 para ter borda simples.

Caption A propriedade Caption contém o texto a ser exibido no campo de rótulo ou numa área da tela.

Enabled Esta propriedade é normalmente configurada como True. Porém, você pode passá-la para False, para dar um tom acinzentado ao texto, desabilitando qualquer evento associado ao mouse

Page 78: Iniciando No Visual Basic

Eventos

Os objetos do tipo rótulo recebem os eventos Click e DlbClick da mesma forma que caixas de imagem, controles de imagem e forms.

Procedimentos e Métodos

Objetos de rótulos são adequados para exibir pequenos blocos de texto. Uma vez que os textos que serão exibidos são definidos simplesmente pela configuração da propriedade Caption, nenhum dos métodos associados com rótulos é de grande utilidade ou necessário para programadores iniciantes.

Modificando o Aplicativo Cronômetro

Façamos mais uma modificação no programa Cronômetro criado no Capítulo 1. Nesse programa, você usou caixas de texto para exibir a saída do aplicativo. Como você deve lembrar-se, caixas de texto podem ser modificadas pelo usuário. Para ilustrar isso, carregue e execute o aplicativo. Depois de parar o cronômetro, selecione o texto na caixa Hora Inicial e digite xyz - muito estranho, não? Evidentemente, é um tanto difícil saber por que o usuário desejaria fazer isso, no entanto, é comum programadores gastarem longas noites solitárias imaginando por que os usuários fazem o que fazem. Seja como for, para evitar esse tipo de problema no seu aplicativo, uma solução é usar rótulos em vez de caixas de texto.

Termine a execução do aplicativo e retorne ao modo de desenvolvimento. Elimine as três caixas de texto, dando um clique em cada uma para selecioná-las, e então pressione a tecla DeI ou escolha a opção Delete do menu Edit. No lugar das caixas de texto, desenhe três rótulos.

Configure a propriedade BorderStyle de cada rótulo para 1 - Fixed Single, para criar uma linha de borda simples. Remova qualquer texto que apareça no área de valor para a propriedade Caption, deixando essa propriedade configurada como uma string vazia para cada um dos rótulos.

Configure a propriedade Name do rótulo superior para IblInicial. Em seguida, configure a propriedade Name do rótulo intermediário para IbIFinal e a propriedade Name do rótulo inferior para IblDecorrido.

Nota: A abreviatura lbl provém da palavra Label, que em inglês significa rótulo

Page 79: Iniciando No Visual Basic

Você deve ainda modificar a codificação para os botões Iniciar e Parar. A versão anterior do programa exibia seus resultados, assinalando a propriedade Text das caixas de texto. No entanto, no caso dos rótulos, é necessário usar a propriedade Caption em vez da propriedade Text. E, naturalmente, você substituiu as caixas de texto por rótulos. É preciso que você edite os procedimentos Click dos dois botões, para que todas as referências à propriedade Text das caixas de texto sejam corrigidas. O seu novo código deveria parecer-se com:

Private Sub btnlniciar_Click ()

TempoInicial = Now

IblInicial.Caption Format(TempoInicial, "hh:mm:ss")

IbIFinal.Caption = ""

lblDecorrido.Caption = ""

btnParar.Enabled = True

btnIniciar.Enabled = False

End Sub

Private Sub btnParar_Click ()

TempoFinal = Now

TempoDecorrido = TempoFinal - TempoInicial

IbIFinal.Caption = Format(TempoFinal, "hh:mm:ss")

lblDecorrido.Caption = Format(TempoDecorrido, "hh:mm:ss")

btnParar.Enabled = False

btnIniciar.Enabled = True

End Sub

Execute o aplicativo novamente para testar as suas modificações. A aparência deveria ser exatamente igual à de quando você executou o aplicativo no Capítulo 1, porém agora não é mais possível selecionar e modificar o texto exibido na tela.

Page 80: Iniciando No Visual Basic

Caixas de Texto

Até agora, você trabalhou com caixas de texto, usando a ferramenta Caixa de Texto mostrada na Figura 5.18. A sua simples colocação no form cria uma área na tela na qual o usuário pode introduzir texto.

Figura 5.18 A ferramenta Caixa de Texto.

Propriedades

As caixas de texto têm as propriedades padrões BorderStyle, Enabled, FontBold, FontItalic, FontName, FontSize, FontUnderline, Height, Left, Name, Top, Visible e Width, e as seguintes propriedades:

Locked Você pode rolar o texto e selecioná-lo, mas não pode editá-lo. O programa ainda pode modificar o texto atribuindo valores à propriedade Text.

MaxLength Esta propriedade normalmente é configurada para 0 (por default), indicando que a caixa de texto deverá aceitar tantos caracteres quantos o usuário digitar. Caso esta propriedade seja configurada para um valor diferente de zero, o Visual Basic restringirá a entrada do usuário ao número de caracteres especificado.

MultLine Na maioria das vezes, você desejará configurar esta propriedade de forma que o usuário introduza apenas uma linha de texto. Caso esta propriedade seja configurada para True, o usuário poderá pressionar a tecla Enter, fazendo com que o texto continue na próxima linha.

PasswordChar Esta propriedade controla quando a caixa de texto é um campo de senha. Ao introduzir um texto num campo de senha, os caracteres mostrados são diferentes dos caracteres digitados. Por default, esta propriedade é configurada para uma string vazia, indicando que o usuário verá os caracteres que introduziu. Caso a propriedade seja configurada para um caractere, tal como asterisco (*), será exibido um asterisco a cada caractere introduzido pelo usuário. Observe que o conteúdo real da caixa de texto é configurado para o texto digitado pelo usuário; apenas a exibição é afetada.

ScrollBars Você pode configurar esta propriedade para 0 (sem barras de deslocamento na caixa de texto), 1 (apenas barra de deslocamento horizontal), 2 (barra de deslocamento vertical) e 3 (barras de deslocamento horizontal e vertical).

Page 81: Iniciando No Visual Basic

SelLength Esta propriedade indica a quantidade de caracteres atualmente selecionados. O seu valor se modifica à medida que o usuário seleciona texto na caixa de texto. Você também pode alterar o texto selecionado via programa, configurando essa propriedade para um valor inteiro. Se SelLength for 0, não há nenhum caractere selecionado. Essa propriedade, junto com SeIStart e SeIText, apenas pode ser acessada em tempo de execução. (Não pode ser configurada em tempo de desenvolvimento.)

SeIStart O valor armazenado nesta propriedade indica-lhe a posição do texto onde se inicia a seleção atual. O valor 0 indica que a seleção (ou ponto de inserção) inicia-se antes do primeiro caractere, o valor 1 indica que a seleção começa antes do segundo caractere, e assim por diante. O valor desta propriedade pode ser alterado com instruções de assinalamento.

SeIText Nesta propriedade é armazenada a string de texto atualmente selecionada. Se não houver qualquer seleção, esta propriedade contém uma string vazia. Caso venha a alterar o conteúdo desta propriedade, você fará com que o texto selecionado anteriormente seja substituído pelo novo texto. Por exemplo, se uma caixa de texto contiver a linha "Francamente, meu claro, eu não me importo com isto" e for selecionada a palavra "claro", você pode corrigir a frase, executando a instrução Text1.SeIText = "caro". Observe que isso também modificará o valor da propriedade SelLength. Por outro lado, como a seleção inicia-se na mesma posição, a propriedade SelStart não será alterada.

Text O programa lê esta propriedade para ver o que o usuário digitou. O programa também pode alterar a propriedade Text para modificar o texto que está sendo exibido.

Eventos

Caixas de texto podem monitorar cada tecla pressionada pelo usuário. Veremos mais a respeito de eventos de teclado no Capítulo 6.

Change Este evento será sinalizado quando a propriedade Text de uma caixa de texto vier a ser modificada, seja pelo usuário, seja pelo próprio programa, que pode assinalar um novo valor para a propriedade Text. Observe que, quando o usuário digitar a palavra Alô, este evento será disparado três vezes, uma para cada letra digitada.

Page 82: Iniciando No Visual Basic

LostFocus Este evento é sinalizado quando o usuário pressiona a tecla Tab para se mover para outro lugar, ou usa o mouse para selecionar algum outro objeto no form. Se você quiser examinar o conteúdo da propriedade Text, normalmente será mais eficiente fazê-lo como parte do procedimento de evento LostFocus. O procedimento de evento Change, como se viu, é acionado a cada letra digitada.

Procedimentos e Métodos

O método mais útil associado às caixas de texto é SetFocus, que coloca o cursor em uma caixa de texto específica. Quando você cria um form. com múltiplas caixas de texto, pode usar este método para direcionar a atenção do usuário para a caixa de texto mais importante. A sintaxe é simples:

[object.]SetFocus

 

  Novidades do Visual Basic 6.0

 

O Aplicativo NotasEdit

Até agora, você usou caixas de texto para textos simples de uma única linha; vejamos agora como as caixas de texto se comportam com linhas múltiplas, implementando um pequeno bloco de notas que permita cortar, colar e fazer edições simples.

Inicie abrindo um novo projeto. Configure as propriedades Caption e Name do form. para NotasEdit. Crie uma caixa de texto no form. e configure as suas propriedades como segue:

Propriedade Configuração

MultLine True

Name TxtBox

ScrollBars 3 - Both

Text [vazio]

Após isso, o seu form. NotasEdit deverá parecer-se com:

Page 83: Iniciando No Visual Basic

Figura 5.19

A caixa de texto trabalhará com o texto introduzido e fará edição sem que seja necessário escrever alguma instrução. Quando você processar o aplicativo, poderá introduzir texto, editá-lo, cortá-lo, copiá-lo e colá-lo com essas teclas de atalho padronizadas pelo Windows: Ctrl-X, Ctrl-C e Ctrl-V.

Para tornar esse aplicativo mais profissional, você poderá fazer com que a caixa de texto ocupe inteiramente a janela do form. Para tanto, edite o procedimento ReSize do form. como abaixo:

Private Sub Form_ReSize()

TxtBox.Top = 0

TxtBox.Left = 0

TxtBox.Width = ScaleWidth

TxtBox.Height = ScaleHeight

End Sub

Esse procedimento será executado toda vez que o form for redimensionado, inclusive na primeira vez em que for exibido. Configurando as propriedades Top e Left da caixa de texto para 0, você assegura que o seu canto superior esquerdo seja colocado no topo do form. como mostrado na Figura 5.20. As propriedades Width e Height da caixa de texto foram configuradas para ficar de acordo com as propriedades ScaleWidth e ScaleHeight do form. (as dimensões totais da área de exibição do form. Observe que você poderia ter escrito essas duas linhas como: TxtBox.Width = NotasEdit.ScaleWidth e TxtBox.Height = NotasEdit.ScaleHeight. Porém, como as instruções sempre serão executadas no contexto do form. não é necessário fazer referência ao nome do form. Além disso, se o nome do form viesse a ser modificado posteriormente, seria preciso alterar a codificação.

Figura 5.20 Processando o aplicativo NotasEdit redimensionado.

Botões de Comando, Caixas de Checagem e Botões de Opção

Estes três objetos do Visual Basic, sob o ponto de vista dos programadores, são muito semelhantes. No entanto, para o usuário final, eles diferem visualmente, prestando-se a propósitos distintos.

Page 84: Iniciando No Visual Basic

Botões de comando normalmente disparam uma ação (isto é, um comando a ser executado) quando recebem um clique, enquanto caixas de checagem e botões de opções indicam estados e permitem ao usuário alterar o estado. O usuário dá cliques nas caixas de checagem para selecionar ou cancelar um certo recurso; quando um sinal aparece na caixa de checagem, a característica é selecionada, ou é habilitada. Cada caixa de checagem opera independentemente. Ao contrário, os botões de opção aparecem em conjunto e permitem ao usuário escolher uma opção do conjunto. Quando um botão de opção de um conjunto é acionado, todos os outros são desabilitados. (Botões de opção são algumas vezes chamados de botões de rádio.)

As ferramentas da caixa de ferramentas usadas para criar esses três tipos de objetos do Visual Basic são mostradas nas Figuras 5.21, 5.22 e 5.23.

Figura 5.21 A ferramenta Botão de Comando.

Figura 5.22 A ferramenta Caixa de Checagem.

Figura 5.23 A ferramenta Botão de Opção.

Propriedades

Botões de comando, caixas de checagem e botões de opção, dentre outros, possuem as propriedades: Caption, Enabled, FontBold, FontItalic, FontName, FontSize, FontUnderline, Height, Left, Top, Visible e Width. Adicionalmente, você poderá achar útil as seguintes propriedades:

Cancel Esta propriedade é suportada apenas por botões de comando. Quando a propriedade Cancel de um botão de comando é definida para True, o pressionamento da tecla Esc passa a ter o mesmo efeito de dar um clique no botão (como o botão Cancel em uma caixa de diálogo). Apenas um botão de comando em um form pode ter sua propriedade Cancel definida para True.

Default Esta propriedade é suportada apenas por botões de comando. Quando esta propriedade é definida para True, o pressionamento da tecla Enter passa a ter o mesmo efeito de dar um clique no botão OK (como o botão OK em uma caixa de diálogo). Apenas um dos botões de comando de um form pode ter a sua propriedade Default definida para True.

Page 85: Iniciando No Visual Basic

Value Esta propriedade indica o estado de uma caixa de checagem ou botão de opção. A propriedade Value de um botão de opção pode ser True ou False. Quando definida para True, o botão está acionado, isto é, o centro do botão se encontra em destaque. A propriedade Value de uma caixa de checagem pode ser assinalada para 0, 1 ou 2. O valor 0 indica que a caixa de checagem não está assinalada; 1 indica que a caixa está assinalada e 2, que a caixa está "desabilitada".

Eventos

Ainda que haja uma forte tendência em usar o procedimento de evento Click apenas para botões de comando, todos os três tipos de objetos recebem o evento Click. Os botões de opção e as caixas de checagem automaticamente exibem o seu estado quando é dado um clique sobre eles; geralmente, não é necessária nenhuma codificação.

Procedimentos e Métodos

Você não pode imprimir ou desenhar sobre botões de comando, caixas de verificação ou botões de opção. Nenhum dos métodos apresentados até agora são aplicáveis a esses três tipos de objetos.

O Aplicativo Jogo

Este projeto contém a aparência de um videogame. Inicie criando um projeto novo. Crie três botões de comando, quatro botões de opção e duas caixas de verificação, dispondo-os da seguinte forma:

Figura 5.24

Configure as propriedades desses objetos como mostrado na Figura 5.25. Após isso, o seu form deverá parecer-se com o mostrado na Figura 5.26.

Figura 5.25 Configuração de propriedades para o aplicativo Jogo.

Figura 5.26 A interface do Jogo.

Finalmente, edite o procedimento Click para os botões Command2 e Command3, incluindo este código:

Private Sub Command2_Click ( )

MsgBox "Fim de Jogo"

End Sub

Page 86: Iniciando No Visual Basic

Private Sub Command3_Click ( )

End

End Sub

Processe o programa algumas vezes para ver como ele se comporta. Tente pressionar as teclas Enter e Esc para ver que comandos eles executam.

Se quiser exibir o estado dos botões de opção e das caixas de checagem na janela Immediate, você pode alterar o procedimento Click do Command2 como mostrado aqui:

Private Sub Command2_Click ( )

Debug.Print Option1.Value

Debug.Print Option2.Value

Debug.Print Option3.Value

Debug.Print Option4.Value

Debug.Print Check1.Value

Debug.Print Check2.Value

End Sub

Molduras

Molduras existem para permitir a criação de agrupamentos de objetos. No caso de botões de opção, as molduras também afetam o seu comportamento, como o projeto de exemplo demonstrará. Para outros objetos, as molduras podem ser usadas como uma separação visual ou como uma característica genérica de habilitação/desabilitação. Para colocar uma moldura em um form, use a ferramenta Moldura da caixa de ferramentas do Visual Basic, mostrada na Figura 5.27.

Figura 5.27 A ferramenta Moldura.

Propriedades

A propriedade Name de uma moldura é usada para identificá-la nas instruções de seu programa, e a propriedade Caption define o texto

Page 87: Iniciando No Visual Basic

que é visível, como parte da moldura. Molduras têm ainda as propriedades Enabled, FontBold, Fontltalic, FontName, FontSize, FontUnderline, Height, Left, Top, Visible e Width.

A propriedade Enabled, já abordada anteriormente, comporta-se de forma um pouco diferente para as molduras. Essa propriedade normalmente é assinalada para True; quando é assinalada para False, o texto de titulo da moldura fica acinzentado e todos os objetos dentro da moldura são desabilitados, incluindo caixas de texto, controles de botões e outros objetos.

Eventos

As molduras não respondem a eventos de mouse ou de entrada de dados feitos pelo usuário.

Procedimentos e Métodos

Você não pode imprimir ou desenhar sobre molduras, nem pode associá-las a gráficos.

Modificando o Aplicativo Jogo

Como as molduras não são intrinsecamente interessantes, em vez de criar um exemplo específico, vamos adaptar o projeto Jogo usado anteriormente.

Na janela de form do aplicativo, remova os botões de opção chamados 3 Jogadores e 4 Jogadores. Em seu lugar, desenhe uma moldura.:

Coloque dois novos botões de opção dentro da moldura. Observe que você deve traçá-los dentro da moldura; assim sendo, não pode dar um clique duplo na ferramenta Botão de Opção para criar os botões e depois arrastá-los para dentro da moldura.

Configure a propriedade Caption da moldura para Modo.

Configure a propriedade Value do botão Option3 para True.

Configure a propriedade Caption do botão Option3 para Iniciantes, e a propriedade Caption do botão Option4 para Experientes.

O resultado deverá parecer-se com o mostrado na Figura 5.28. Quando você processar o aplicativo, note que os botões de opção

Page 88: Iniciando No Visual Basic

dentro da moldura operam independentemente dos que estão fora dela.

Figura 5.28 A interface remodelada do Jogo.

Caixas de Lista

As caixas de lista permitem que você dê ao usuário uma escolha de opções. A caixa de lista exibe as opções disponíveis, e o usuário seleciona um item ou entrada da lista, dando um clique nele. O Visual Basic adicionará a barra de deslocamento à caixa de lista, se a quantidade de entradas que serão exibidas não couber na caixa de lista. Para que uma caixa de lista possa trabalhar corretamente, é preciso que contenha pelo menos três linhas. Para adicionar uma caixa de lista a um form deve-se usar a ferramenta Caixa de Lista da caixa de ferramentas, mostrada na Figura 5.29. (Caixas de lista drop-down, como a que aparece na caixa de objetos da janela de propriedades quando se pressiona o botão de seta para baixo, são variações de caixas combinadas e serão discutidas na próxima seção.)

Figura 5.29 A ferramenta Caixa de Lista.

O conteúdo de uma caixa de lista pode ser definido em tempo de desenvolvimento usando-se a propriedade List. Em tempo de execução é preciso usar o método AddItem para introduzir os itens na lista. Normalmente, é mais prático inicializar uma caixa de lista no procedimento de evento Load do form que a contém.

Propriedades

As propriedades usuais suportadas pelas caixas de lista são: Enabled, FontBold, FontItalic, FontName, FontSize, FontUnderline, Height, Left, Top, Visible e Width. Algumas propriedades especiais das caixas de lista são as seguintes:

Columns Quando esta propriedade é configurada para 0 (default), todos os itens são exibidos em uma única coluna. Caso esta propriedade seja configurada para um valor maior ou igual a 1, os itens da lista serão dispostos em múltiplas colunas; o valor desta propriedade indica quantas colunas serão visíveis ao mesmo tempo. A barra de deslocamento horizontal será adicionada à lista, quando necessário.

Page 89: Iniciando No Visual Basic

List Esta propriedade contém uma matriz com todos os itens armazenados na lista. (Matrizes serão discutidas no Capítulo 6.) Pode-se acessar os itens individuais de uma caixa de lista com a sintaxe:

objeto.List(índice)

ListCount A propriedade ListCount, que não pode ser modificada diretamente, contém a quantidade de itens da caixa de lista.

ListIndex A configuração desta propriedade indica o índice do último item selecionado. O valor de índice para o primeiro item da caixa de lista é 0, o valor de índice para o próximo item é 1, e assim por diante. Caso não haja nenhum item selecionado, Listlndex contém o valor -1. Caso o valor desta propriedade seja modificado por uma instrução do programa, o mecanismo de destaque da lista mudará para refletir a nova seleção. Para ter acesso ao texto do item selecionado, deve-se usar a propriedade Text.

MultiSelect Esta propriedade controla quantos itens podem ser selecionados na caixa de lista. Caso esta propriedade seja configura da para 0 -None, o usuário poderá selecionar apenas um item de cada vez. (Em outras palavras, não é permitida seleção múltipla.) Se for carregado o valor 1 - Simple, o usuário poderá selecionar mais de um item. Quando MultiSelect for configurada para 2 - Extended, o usuário poderá selecionar uma faixa de itens, dando um clique no primeiro item e, com a tecla Shift pressionada, selecionando o último item da faixa. O usuário também pode manter a tecla CtrI pressionada e dar um clique para selecionar ou anular a seleção de cada item individualmente. Observe que, ainda que haja múltiplos itens selecionados, as propriedades ListIndex e Text referem-se apenas à seleção mais recente. Você deve examinar cada elemento da propriedade Selected para determinar quais itens foram selecionados.

Selected A propriedade Selected é uma matriz que contém um elemento para cada item da caixa de lista. O elemento correspondente a um item é configurado para True, para indicar que o item está selecionado. Para verificar o estado de um determinado item, é preciso usar a seguinte sintaxe:

objeto.Selected(índice)

Sorted Se você deseja que o Visual Basic mantenha os itens classificados em ordem alfabética, deve configurar esta propriedade para True. Quando esta propriedade for False, os itens serão exibidos na ordem em que foram adicionados à lista.

Page 90: Iniciando No Visual Basic

Text Esta propriedade, que não pode ser modificada diretamente, contém o texto do último item selecionado.

Eventos

As caixas de lista recebem os eventos Click e DblClick. Normalmente, você deve evitar a codificação do procedimento Click, pois o usuário pode selecionar um item e então desistir de sua seleção. Em vez disso, seu programa deve ler a propriedade Text quando o usuário der um clique em um botão de comando ou quando ocorrer o evento DblClick.

Procedimentos e Métodos

Os métodos usados com maior freqüência para as caixas de lista incluem: AddItem, Clear e RemoveItem. Esses três métodos permitem que você modifique o conteúdo de uma caixa de lista em tempo de execução.

AddItem Este método permite-lhe inserir uma linha de texto (um item) em uma caixa de lista. Você especifica o texto a ser incluído e, opcionalmente, o índice do item a inserir. Se você não especificar um índice, o Visual Basic incluirá o item após todos os itens já existentes. Caso a propriedade Sorted esteja configurada para True, não especifique um valor para índice; o Visual Basic incluirá o item em ordem alfabética. Aqui está a sintaxe para o método AddItem:

objeto.AddItem text[, índice]

Clear Este método remove todos os itens de uma caixa de lista. A sua sintaxe é bem simples:

objeto.Clear

RemoveItem O método RemoveItem permite que você remova um item de uma caixa de lista. Você deve especificar o índice do item a ser removido, usando a seguinte sintaxe:

objeto. RemoveItem índice

O Aplicativo Queijo

O objetivo deste aplicativo simples é transferir itens entre duas caixas de lista. Os itens de uma caixa de lista estarão classificados em ordem alfabética; enquanto os itens da outra aparecerão na ordem em que forem selecionados.

Page 91: Iniciando No Visual Basic

Inicie criando um novo projeto. Desenhe no form duas caixas de lista, como mostrado na Figura 5.30, e configure a propriedade Sorted da lista à direita (List2) para True. O restante da codificação necessária para o aplicativo é mostrado na Figura 5.31. O procedimento Form_Load inicializa a caixa de lista. Os procedimentos List1_DblClick e List2_DblClick são basicamente idênticos, exceto pelo fato de fazerem a transferência de itens de lista em direções opostas.

Figura 5.30 O projeto do form do aplicativo Queijo.

Figura 5.31 A codificação para o aplicativo, Queijo.

Quando for dado um clique duplo em um item de uma das caixas de lista, ele será incluído na outra caixa, sendo removido da caixa onde estava. A caixa de lista (List2) continua a classificar os seus itens alfabeticamente.

Caixas Combinadas

Caixas combinadas são criadas com a ferramenta Caixa Combinada contida na caixa de ferramentas, mostrada na Figura 5.32. A caixa combinada recebe esse nome porque ela combina uma caixa de texto com uma caixa de lista, formando um único controle. Entretanto, ao contrário de uma caixa de lista, ela não suporta múltiplas colunas. Você pode optar por um dos três tipos de comportamento para uma caixa combinada por meio de sua propriedade Style.

Figura 5.32 A ferramenta Caixa Combinada.

Propriedades

Adicionalmente às propriedades usuais, as caixas combinadas têm duas propriedades interessantes: Style e Text.

Style Esta propriedade determina o tipo de caixa combinada e como ela se comporta, podendo assumir os valores 0, 1 e 2.

Quando a propriedade é 2, a caixa combinada transforma-se em uma caixa de lista drop-down. Inicialmente, é visível apenas um item; porém, quando o usuário dá um clique no botão seta para baixo que aparece ao lado da caixa, é exibida a caixa de lista contendo os itens, permitindo ao usuário selecionar um deles. A caixa Object na janela de propriedades do Visual Basic é um exemplo familiar. (Nesse caso, não é permitido ao usuário a digitação de qualquer texto na caixa de texto.)

Page 92: Iniciando No Visual Basic

O valor 1 dá origem ao que chamamos de caixa combinada simples; uma área de edição na qual o usuário pode introduzir texto com uma caixa de lista padrão abaixo de si. A lista não é retirada, permanecendo sempre em exibição. O usuário pode selecionar um item da caixa de lista ou então digitar um texto na área de edição.

Para dimensionar o tamanho da área da caixa de lista associada, selecione a caixa combinada, clique com o mouse sobre uma alça de redimensionamento inferior e arraste-a para baixo até atingir o tamanho desejado.

A configuração dessa propriedade para 0 cria uma caixa combinada drop-down exibida quando o botão seta para baixo é pressionado, permitindo a seleção de um item. Porém é possível ao usuário introduzir texto na caixa de texto.

Text Esta propriedade pode conter o texto de um item selecionado a partir da lista, ou o próprio texto digitado pelo usuário.

Eventos

A forma como uma caixa combinada responde aos eventos depende de seu estilo de operação - isto é, de como a propriedade Style está configurada. Por exemplo, o evento DblClick é recebido apenas quando a propriedade está configurada para 1 (caixa combinada simples). Nos outros dois estilos, apenas o evento Click é recebido. Os dois estilos que permitem a introdução de texto recebem o evento Change à medida que o usuário está digitando o texto na área de edição da caixa combinada. Via de regra, você desejará que o seu programa leia a propriedade Text da caixa combinada após o usuário completar a seleção.

Procedimentos e Métodos

Os métodos AddItem, Clear e RemoveItem, descritos para caixas de lista, também estão implementados para caixas combinadas e são usados da mesma forma.

O Aplicativo Vôo

Este projeto de exemplo inclui os três estilos de caixas combinadas lado a lado; assim você pode fazer algumas experiências com eles. O aplicativo simula uma caixa de diálogo que pergunta ao usuário sobre suas preferências quanto ao próximo vôo.

Page 93: Iniciando No Visual Basic

Crie um novo projeto. Coloque três rótulos e dois botões de comando no form e configure a propriedade Caption de cada objeto como mostrado abaixo:

 Figura 5.33

Configure para True a propriedade Default do botão OK e a propriedade Cancel do botão Cancel.

Abaixo do rótulo Destino, desenhe uma caixa combinada, configure a sua propriedade Style para 1 e sua propriedade Name para cboDestino. Torne-a grande o suficiente para permitir a exibição de quatro ou cinco linhas de texto na parte da caixa de lista.

Nota: a sigla "cbo", que usamos aqui como prefixo nos nomes das caixas combinadas, vem de ComboBox – caixa combinada, em inglês.

Crie outra caixa combinada abaixo do rótulo Assento configurando as propriedades Style para 2 e Name para cboAssento.

Crie mais uma caixa combinada, agora abaixo do rótulo Refeição. Configure as propriedades da caixa Name para cboRefeição e Style para 0.

Configure as propriedades Text de cboDestino e cboRefeição para "". O seu Form deverá estar parecido com:

Figura 5.34

Figura 5.35 A codificação para o aplicativo Vôo.

Agora, será preciso escrever dois procedimentos, um para relatar os resultados da escolha das ações do usuário quando for dado um clique no botão OK e outro para inicializar as caixas combinadas. Esses procedimentos são apresentados na Figura 5.35.

Quando você executar o aplicativo, observe quais caixas combinadas lhe permitem digitar um texto. Repare também que o aspecto de cada tipo de caixa combinada, conforme mostrado naFigura 5.36, indica como proceder.

Figura 5.36 Processando o aplicativo Vôo.

Barras de Deslocamento Horizontal e Vertical

Page 94: Iniciando No Visual Basic

As barras de deslocamento horizontal e vertical (mostradas na Figura 5.37.) comportam-se da mesma forma, mudando apenas a direção. Esses objetos simples mostram a posição do elevador na barra de deslocamento; você tem controle sobre os limites da barra de deslocamento e sobre os incrementos pelos quais o elevador pode ser avançado. Por exemplo, se você estiver usando uma barra de deslocamento para representar o acelerador de um automóvel, ela poderia variar de 0 a 100, com incrementos de 5. Um controle de volume poderia variar de 0 a 10, com incrementos de 1.

Figura 5.37 Barras de deslocamento horizontal e vertical.

Para criar esses objetos, use a ferramenta Barra de Deslocamento Horizontal ou a ferramenta Barra de Deslocamento da caixa de ferramentas do Visual Basic.

Propriedades

As propriedades padrões suportadas por barras de deslocamento incluem Enabled, Height, Left, Name, Top, Visible e Width. As propriedades especiais tanto para barras de deslocamento vertical quanto horizontal incluem LargeChange, Max, Min, SmalIChange e Value.

LargeChange A configuração desta propriedade representa o incremento adicionado ou subtraído do número contido na propriedade Value quando o usuário dá cliques na área da barra de deslocamento, entre o elevador e as setas de deslocamento.

Max Esta propriedade pode ser configurada para um número entre -32.767 e +32.767. Quando o elevador está na extrema direita (barra horizontal) ou na posição inferior (barra vertical), a propriedade Value é configurada para o valor armazenado na propriedade Max.

Min Esta propriedade pode ser configurada para um número entre -32.767 e +32.767. Quando o elevador está na extrema esquerda ou na posição superior, a propriedade Value é configurada para o valor armazenado na propriedade Min.

SmallChange A configuração desta propriedade representa o incremento adicionado ou subtraído do número contido na propriedade Value quando o usuário dá um clique em uma das setas de direção localizadas nos extremos da barra de deslocamento.

Page 95: Iniciando No Visual Basic

Value Esta propriedade contém o número representando a posição atual do elevador dentro da barra de deslocamento. Se alguma instrução de um programa vier a alterar esta propriedade, o Visual Basic moverá o elevador para a posição correspondente. Definir para esta propriedade valores que estejam fora dos limites estabelecidos pelas propriedades Max e Min produz uma mensagem de erro.

Eventos

Os eventos primários associados a barras de deslocamento são Scroll e Change. O evento Scroll é repetidamente disparado enquanto o elevador estiver sendo arrastado dentro da caixa de deslocamento. O evento Change é sinalizado após a posição do elevador ter sido modificada. Use o evento Scroll para rastrear as modificações dinâmicas na barra de deslocamento e o evento Change para obter o valor final da barra de deslocamento.

Procedimentos e Métodos

Nenhum dos procedimentos e métodos discutidos anteriormente são aplicáveis às barras de deslocamento.

O Aplicativo Barra de Deslocamento

O objetivo deste aplicativo é fornecer-lhe apenas uma visão de como as barras de deslocamento trabalham.

Crie um novo projeto. No form vazio, coloque um rótulo e uma barra de deslocamento horizontal, como mostrado aqui:

Figura 5.38

Configure a propriedade BorderStyle do rótulo para 1 - Fixed Single, e a propriedade Caption para uma string vazia. Configure as propriedades da barra de deslocamento horizontal como segue:

 

Propriedade Configuração

LargeChange 10

Max 100

Min 0

Page 96: Iniciando No Visual Basic

SmallChange 2

Dê um clique duplo na barra de deslocamento, fazendo com que a janela de código seja apresentada. Introduza este procedimento para tratamento do evento Change:

Private Sub_Hscroll1_Change ( )

Label1.Caption = Str$(HScroll1.Value)

End Sub

Como a propriedade Caption aceita apenas textos para sua configuração, você deve converter o valor HScroll.Value para uma string usando Str$.

Introduza o seguinte procedimento para tratar o evento Scroll:

 

Private Sub Hscroll1_Scroll ( )

Label1.Caption = "Movendo para " & Str$(HScroll1.Value)

End Sub

Inicie agora o processamento do aplicativo. Quando você dá um clique na área cinza da barra de deslocamento, o valor exibido no rótulo se modifica de 10 em 10. Quando você dá um clique sobre as setas de deslocamento, nas extremidades da barra, o valor se modifica de 2 em 2.

Arrastando o elevador com seu mouse, é possível ajustar o valor em incrementos diferentes de 2 ou 10. Por exemplo, o valor exibido na Figura 5.25, poderia ser alcançado dando-se cliques sobre as setas de deslocamento ou arrastando-se o elevador. Observe que o procedimento para o evento Scroll atualiza a propriedade Caption do rótulo à medida que o elevador é arrastado. Selecione a opção Break do menu Run ou dê um clique no botão Interromper da barra de ferramentas e introduza a instrução Hscroll1.Value = 17 na janela Immediate. Observe que a posição do elevador da caixa de deslocamento se modifica quando o valor é alterado. Agora, submeta a instrução Hscroll1.Max = 500. A posição do elevador se modifica novamente, de forma a manter a posição relativa às configurações das propriedades Min e Max.

Page 97: Iniciando No Visual Basic

Figura 5.39 Processando o aplicativo Barra de Deslocamento.

 

Temporizadores

Temporizadores, criados com a ferramenta Temporizador mostrada na Figura 5.40, são objetos que podem disparar eventos em intervalos regulares de tempo. Você programa um temporizador configurando sua propriedade Interval para a quantidade de milissegundos que deve decorrer entre os eventos a serem disparados.

Figura 5.40 A ferramenta Temporizador.

Um temporizador está limitado pela configuração do hardware de seu sistema. A maioria dos computadores pessoais é capaz de gerar até 18 eventos por segundo, isto é, com um intervalo de tempo entre os eventos de aproximadamente 56/1000 segundos. Em termos práticos, esse limite significa que valores menores do que 56 não terão utilidade - em outras palavras, valores de intervalos intermediários, entre os múltiplos de 56, provavelmente produzirão o mesmo resultado. Essa limitação, no entanto, não significa que você possa se descuidar dos seus cálculos afinal de contas, os futuros hardwares provavelmente terão um melhor suporte para os temporizadores. Em suma, deve-se entender essa limitação como um aviso para não se buscar extrema precisão quando se tratar de temporizadores.

Adicionalmente, alguns dos eventos disparados por temporizadores podem simplesmente perder-se no meio da confusão. Suponha, por exemplo, que o seu programa esteja preparado para receber eventos de um temporizador a cada segundo. Porém, uma parte de seu programa que envolve cálculos complexos pode demandar até 10 segundos. Quando esses cálculos acabam, você poderia esperar que os 10 eventos disparados pelo temporizador fossem empilhados, como ocorre em uma lenta fila de supermercado. No entanto, isso não acontece. Apenas um evento será sinalizado. Sempre que ocorre um evento de temporização, o sistema verifica se o evento de temporização anterior ainda se encontra pendente. Em caso positivo, nenhuma evento será gerado.

Sem dúvida, devido a essas restrições, você deve estar se questionando sobre a real utilidade dos temporizadores. Na realidade, ainda que não tenham extrema precisão, eles podem ser muito úteis. Você pode imaginar os temporizadores como "pontapés no traseiro" de seu aplicativo. Com efeito, um temporizador pode, em intervalos de

Page 98: Iniciando No Visual Basic

tempo regulares, "cutucar" o seu programa dizendo "Ei, está na hora de verificar algumas coisas".

Propriedades

As propriedades Name e Enabled são padrões para temporizadores. A propriedade mais importante dos objetos temporizadores é a Interval. Essa propriedade contém o número de milissegundos entre os eventos de temporização, variando em uma faixa de 0 a 65.535, gerando eventos numa velocidade que varia teoricamente de 1000 eventos por segundo a quase 1 evento por minuto. O valor 0 equivale a desativar o temporizador. Caso seja necessário gerar n eventos por segundo, use a fórmula 1000 / n para achar o valor a ser armazenado nessa propriedade. Por exemplo, para gerar eventos a cada meio segundo (dois eventos por segundo), o cálculo 1000 / 2 indica o valor 500 para a propriedade Interval.

Eventos

O evento Timer é gerado em intervalos regulares quando o temporizador está ativado.

Procedimentos e Métodos

Não há procedimentos ou métodos que operem com objetos temporizadores.

O Aplicativo Metrônomo

Este projeto - que cria um metrônomo usando um temporizador e uma barra de deslocamento - demonstra o que acontece quando você tenta usar um objeto temporizador como um controle de tempo extremamente preciso. Os metrônomos operam tipicamente numa faixa que vai de 40 batimentos por minuto (para músicas muito lentas) a 200 batimentos por minuto (para músicas muito rápidas). A configuração de 40 batimentos por minuto corresponde a 2/3 de batimento por segundo, ou seja, 1 batimento a cada 1500 milissegundos. Na outra extremidade, 200 batimentos por minuto significam 3 1/3 batimentos por segundo, ou 1 batimento a cada 300 milissegundos. Assim, os valores 300 e 1500 podem ser usados em seu aplicativo como limites máximo e mínimo para uma barra de deslocamento. (Note que, quanto maior o valor, menor a quantidade de batimentos; portanto, 1500 é o valor mínimo e não o máximo.)

Page 99: Iniciando No Visual Basic

Crie um novo projeto e inclua uma barra de deslocamento horizontal no form. Depois, crie um objeto temporizador, dando um clique duplo na ferramenta Temporizador contida na caixa de ferramentas. Não é preciso desenhar ou redimensionar um objeto temporizador, ele aparece no form. em tempo de desenvolvimento; em tempo de execução, porém, será invisível.

Coloque um rótulo abaixo da extremidade esquerda da barra de deslocamento e configure a sua propriedade Caption para Lento. Abaixo da extremidade direita, crie outro rótulo, configurando a sua propriedade Caption para Rápido. Veja a seguir como deverá ficar o seu aplicativo.

 Figura 5.41

Configure a propriedade Interval do temporizador para 1000.

Configure as propriedades da barra de deslocamento horizontal como se segue:

 Propriedade Configuração

LargeChange 10

Max 300

Min 1500

SmallChange 25

Value 1000

Será preciso incluir duas linhas de código para esse aplicativo, uma no procedimento Change da barra de deslocamento e outra no procedimento Timer do objeto temporizador. O procedimento Change mantém o objeto temporizador em sincronia com a barra de deslocamento, enquanto o procedimento Timer gerará o tique do metrônomo. (Ou, neste caso, um beep):

Private Sub HScroll1_Change ( )

Timer1.Interval = HScroll1.Value

End Sub

Sub Timer1_Timer ( )

Page 100: Iniciando No Visual Basic

Beep

End Sub

Quando você iniciar o aplicativo, o metrônomo baterá 1 vez por segundo. O deslocamento do elevador modificará a velocidade de batimento. Tente deslocar a janela do aplicativo ao longo da tela ou processe outro aplicativo em segundo plano. Enquanto nada estiver acontecendo, o temporizador será bastante preciso, porém você pode ver como alguns eventos de temporização são perdidos quando o sistema desvia sua atenção para outra tarefa.

Linhas e Formas

Para melhorar a aparência dos forms de seus aplicativos, você pode incluir linhas simples e gráficos de formas sólidas, usando as ferramentas Linha e Forma da caixa de ferramentas, mostradas nas Figuras 5.42 e 5.43. Os objetos criados com essas ferramentas aparecem na mesma camada que os objetos de imagem.

Figura 5.42 A ferramenta Linha.

Figura 5.43 A ferramenta Forma.

Os controles de linhas e formas (tanto quanto os controles de imagem) são úteis principalmente para implementar visões de segundo plano para os seus forms A ferramenta Linha cria segmentos de linha reta simples. Você pode modificar tamanho, cor e padrões de linhas, alterando suas propriedades. A ferramenta Forma cria sempre um retângulo na tela, porém, modificando a configuração das propriedades dos objetos forma, você pode criar círculos, ovais e retângulos arredondados. Além disso, você pode configurar cores e o padrão de preenchimento das formas.

Propriedades

Ambos os objetos têm as propriedades Name e Visible usuais. Objetos do tipo Forma possuem ainda as propriedades padrões Height, Left, Top e Width. Objetos Linha têm as propriedades posicionais X1, Y1 e X2, Y2, que são as coordenadas das duas extremidades da linha. Outras propriedades determinam como esses objetos aparecem na tela.

BorderColor Esta propriedade determina a cor de contorno (ou no caso de objetos Linha, a cor da linha). Você configura a propriedade BorderColor escolhendo uma cor de uma palheta, da mesma forma

Page 101: Iniciando No Visual Basic

que é usada para configurar as propriedades BackColor e ForeColor de um form.

BorderStyle A propriedade BorderStyle controla como a linha ou o contorno da forma é traçada. Você pode aplicar uma das sete configurações:

0 - Transparent (Transparente)

1 - Solid (Sólida)

2 - Dash (Traço)

3 - Dot (Ponto)

4 - Dash-Dot (Traço-Ponto)

5 - Dash-Dot-Dot (Traço-Ponto-Ponto)

6 - Inside Solid (Sólido Interno)

BorderWidth Esta propriedade permite-lhe especificar a largura de uma linha ou do contorno da forma. Se você configurar BorderWidth para um valor diferente de 1, não poderá usar configurações pontilhadas ou tracejadas de BorderStyle.

Objetos forma têm ainda as propriedades FillColor e FilIStyle:

FilIColor Análoga à propriedade BorderColor, FilIColor permite-lhe definir a cor interior de uma forma. Você configura esta propriedade do mesmo jeito que a propriedade BorderColor, com o auxílio de uma palheta.

FillStyle A configuração da propriedade FilIStyle determina o padrão interno de um objeto Forma.

0 - Solid (Sólido)

1 - Transparent (Transparente)

2 - Horizontal Line (Linha Horizontal)

3 - Vertical Line (Linha Vertical)

4 - Upward Diagonal (Diagonal Ascendente)

Page 102: Iniciando No Visual Basic

5 - Downward Diagonal (Diagonal Descendente)

6 - Cross (Cruz)

7 - Diagonal Cross (Diagonal em Cruz)

Eventos

Objetos Linha e Forma não recebem evento algum.

Procedimentos e Métodos

Nenhum dos métodos apresentados neste capítulo se aplicam a linhas e formas.

O Projeto Camada

Este projeto de exemplo não é um aplicativo completo; ele simplesmente leva você a fazer algumas experiências com objetos de exibição, para familiarizá-lo com as ferramentas.

Crie um novo projeto. Coloque no form uma caixa de imagem, um botão de comando, uma forma, uma linha e um controle de imagem, nesta ordem. Distribua-os no form como mostrado aqui:

Figura 5.44

Selecione a propriedade Picture do objeto Picture1 na janela de propriedades. Dê um clique no botão de reticências, à direita do valor da propriedade, para exibir a caixa de diálogo Load Picture. Na caixa de diálogo, configure o tipo de arquivo para exibir os arquivos com sufixo ICO. No diretório \PacoteVB\Icones\Misc\ no primeiro cd deste produto, você encontrará o arquivo de ícones HEART.ICO. Escolha esse arquivo para carregar o ícone na caixa de imagem. De forma semelhante, configure a propriedade Picture de Image1 para carregar o ícone DIAMOND.ICO no controle de imagem.

Configure a propriedade FilIStyle de Shape1 para 0 - Solid e a propriedade FilIColor para azul. (Dê um clique no botão de seta para baixo à direita da propriedade e selecione a cor azul na palheta.) Configure a propriedade BorderWidth de Line1 para 4. O form deverá parecer-se com:

Figura 5.45

Page 103: Iniciando No Visual Basic

Movimente o objeto forma para o centro do form e depois mova os outros objetos sobre a forma de modo que se sobreponham, como mostrado aqui:

 Figura 5.46

Observe que, em cada camada da exibição, o objeto criado mais recentemente aparece sobre os objetos criados anteriormente. (A caixa de imagem e o botão de comando se encontram na camada superior; a forma, a linha e a imagem encontram-se na camada intermediária.)

A ordem segundo a qual certos objetos se sobrepõem a outros é chamada de Z-Order, e pode ser alterada. Dê um clique sobre o objeto Line1 para selecioná-lo e escolha a opção Bring to Front (trazer para frente) do menu Format\Order do Visual Basic. A linha, que já apareceu sobre a forma, agora se sobrepõe também à imagem. No entanto, note que, quando você move a linha ao longo da tela, ela não se sobreporá à caixa de imagem ou ao botão de comando. As opções Bring to Front e Send to Back (Mandar para trás) trabalham apenas dentro de uma camada; objetos da camada intermediária sempre serão sobrepostos por objetos da camada superior. Você pode aplicar essas duas opções a todos os controles (objetos), e com isso controlar a Z-Order. Experimente usar essas opções após selecionar o botão de comando.

Caixas de Lista de Unidades, Caixas de Lista de Diretórios e Caixas de Lista de Arquivos.

As três ferramentas da caixa de ferramentas do Visual Basic mostradas nas Figuras 5.47, 5.48 e 5.49 lhe permitem construir caixas de diálogo personalizadas para fazer a interação com o sistema de arquivos. Cada controle do sistema de arquivos gerencia um componente isolado do sistema: a caixa de lista de unidades aparece como uma caixa de lista drop-down, contendo os nomes de todas as unidades de disco do sistema; a caixa de lista de diretórios exibe todos os subdiretórios do diretório atual; e a caixa de lista de arquivos exibe alguns ou todos os arquivos gravados no diretório atual.

Na maioria das vezes, você não usará a caixa de lista de unidades ou a caixa de lista de diretórios individualmente. Ao contrário, quando o usuário está selecionando um arquivo a ser aberto ou salvo, você terá de oferecer acesso a todos os componentes do sistema de arquivos simultaneamente. Nesses casos, você poderá usar o controle diálogos comuns, que acondiciona as funções File Open e File Save As.

Page 104: Iniciando No Visual Basic

Porém, ocasionalmente, você poderá precisar de uma caixa de diálogo com mais componentes do que os fornecidos pelas caixas de diálogo padrões para File Open e File Save As. Por exemplo, o Word for Windows da Microsoft tem botões adicionais para Salvar Versão e Opções na caixa de diálogo Salvar Como.

Nesses casos, você poderá usar as ferramentas Caixa de Lista de Unidades, Caixa de Lista de Diretórios e Caixa de Lista de Arquivos. (Veja um exemplo no Capítulo 10.)

Figura 5.47 A ferramenta Caixa de Lista de Unidades.

Figura 5.48 A ferramenta Caixa de Lista de Diretórios.

Figura 5.49 A ferramenta Caixa de Lista de Arquivos.

Propriedades

Os três controles do sistema de arquivos têm muitas das propriedades usuais: Enabled, FontBold, Fontltalic, FontName, FontSize, Height, Left, Name, Top, Visible e Width. Adicionalmente, as seguintes propriedades são importantes:

Drive Esta propriedade, que se aplica apenas a caixas de lista de unidades, contém o nome da unidade atualmente selecionada.

FileName Apenas as caixas de lista de arquivos têm esta propriedade, que contém o nome do arquivo atualmente selecionado na caixa de lista de arquivos.

List, ListIndex Estas propriedades são suportadas somente pelas caixas de lista de arquivos e são idênticas às propriedades List e ListIndex das caixas de listas.

Path Nas caixas de lista de arquivos e de diretórios, esta propriedade contém o caminho hierárquico atual. Esta propriedade não se aplica a caixas de lista de unidades.

Pattern Esta propriedade das caixas de lista de arquivos contém uma string que determina quais arquivos serão exibidos. Ela suporta o uso dos caracteres * e ? para especificação dos nomes de arquivos. Por exemplo, configurar esta propriedade para *.DAT faria com que fossem exibidos todos os arquivos que tivessem a extensão DAT.

Eventos

Page 105: Iniciando No Visual Basic

Apenas as caixas de lista de arquivos e de diretórios respondem ao evento Click. O evento DbIClick é recebido apenas pelas caixas de lista de arquivos. Além disso, mais dois eventos são importantes para os controles do sistema de arquivos:

Change Este evento é reconhecido somente pelas caixas de lista de unidades e de diretórios. Ele é disparado quando o usuário ou o programa modifica a seleção na caixa de lista.

PaIthChange Este evento aplica-se apenas às caixas de lista de arquivos. Ele ocorre quando o caminho hierárquico é modificado, devido a um clique duplo em uma pasta de diretório ou porque o programa alterou alguma das propriedades Path ou FileName. Este evento permite ao seu programa atualizar o conteúdo da caixa de lista de diretórios de forma a exibir os subdiretórios do novo caminho hierárquico.

Procedimentos e Métodos

Nenhum dos procedimentos ou métodos discutidos até agora é aplicável aos controles do sistema de arquivos.

Outras Ferramentas do Visual Basic

A caixa de ferramentas do Visual Basic também inclui algumas outras ferramentas, que serão descritas brevemente aqui. Essas ferramentas e os objetos criados com elas, por exigirem um esforço considerável de programação e algumas técnicas avançadas, serão abordados posteriormente.

Grades

A ferramenta Grade representada na Figura 5.32 permite-lhe criar um controle de grade. Uma grade é um bloco de células bidimensional, muito parecido com as linhas e colunas de uma planilha. Você pode usar um controle de grade para implementar funções semelhantes a planilhas em Visual Basic. O Visual Basic é distribuído com os controles de grade DbGrid e MSFlexGrid. O segundo é mais moderno e rico em possibilidades de uso. O ícone da figura 5.50 refere-se ao controle MSFlexGrid. Para que um projeto use uma dessas duas grades, deve-se selecionar no menu Project o comando Components e selecionar ,entre os componentes listados , o item Microsoft Data Bound Grid Control 5.0, para o controle DBGrid ou Microsoft FlexGrid Control 5.0, para o controle MSFlexGrid.

Page 106: Iniciando No Visual Basic

Após o OK e sair da janela o controle escolhido aparecerá na caixa de ferramentas do projeto.

Figura 5.50 A ferramenta Grade.

O controle MSFlexGrid exibe e opera em dados na forma de tabelas. Ele lhe permite flexibilidade total para classificar, mergear e formatar tabelas contendo strings e imagens. Quando ligada ao controle Dados, exibe dados apenas para leitura.

Você pode adicionar texto, uma imagem ou ambos em uma célula da grade. As propriedades Row (linha) e Col (coluna) são usadas para indicar a célula atual da grade. Você pode especificar a célula atual em código, ou o usuário pode modificá-la em tempo de execução usando o mouse ou as teclas de seta. A propriedade Text refere-se ao conteúdo da célula atual.

Se o texto da célula é muito longo para ser exibido na célula, e a propriedade WordWrap está configurada como True, o texto é quebrado para a próxima linha dentro da mesma célula. Para ver o texto quebrado dentro da célula, você pode precisar aumentar a largura da coluna da célula (propriedade ColWidth) ou a altura da linha (propriedade RowHeight).

Use as propriedades Cols e Rows para determinar o número de colunas e linhas da grade.

Para adicionar uma linha na grade use o método AddItem e, para removê-la, use o método RemoveItem. A sintaxe do método AddItem é:

objeto.AddItem (item As String, índice)

Onde:

Objeto é um controle MSFlexGrid.

Item (requerido) é uma string exibida na nova linha. Para adicionar múltiplas strings (numa grade de múltiplas colunas), separe o texto de cada célula com caracteres de tabulação (vbTab).

Índice (opcional) é um inteiro longo representando a posição dentro da grade onde será inserida a nova linha. Se o índice for omitido, a linha será posta no final de todas. A primeira linha possui o índice 0.

Para remover linhas use o método RemoveItem. Sua sintaxe é:

Page 107: Iniciando No Visual Basic

objeto.RemoveItem índice

Onde:

Objeto é um controle MSFlexGrid.

Índice é a posição da linha dentro da grade.

Dados

A ferramenta Dados, mostrada na Figura 5.51, permite-lhe criar um controle de dados por meio do qual você implementa um acesso a dados específicos em um banco de dados. Um controle de dados tem algumas propriedades especiais que definem a conexão entre o aplicativo Visual Basic e o banco de dados que você planeja acessar. Entretanto, antes de usar a ferramenta Dados em Visual Basic, será necessário habilitar o compartilhamento de arquivos. Veja como usar esta ferramenta no final do Capítulo 14.

Figura 5.51 A ferramenta Dados.

OLE

A tecnologia OLE (Object Linking and Embedding - Aninhamento e Ligação de Objetos) da Microsoft permite-lhe criar um objeto num aplicativo que contenha dados de outro aplicativo não-relacionado. Por exemplo, o diagrama de um programa gráfico ou um desenho detalhado de um programa CAD (Computer-Aided Design -Projeto Auxiliado por Computador) poderia vir a ser colocado em seu programa Visual Basic. Entretanto, em vez de inserir uma cópia do gráfico ou do desenho no seu programa Visual Basic, o OLE manterá uma conexão com o aplicativo original, de forma que qualquer modificação feita sobre o desenho ou gráfico seja refletida imediatamente em seu programa Visual Basic.

A ferramenta OLE da caixa de ferramentas do Visual Basic, mostrada na Figura 5.52, permite-lhe implementar em seu programa Visual Basic habilidades para estabelecer ligação e aninhamento entre objetos.

 Figura 5.52 A ferramenta OLE.

Caixas de Dialogo Comuns

Para padronizar a interface com os usuários, para as operações comuns a todos os aplicativos baseados em Windows, a Microsoft

Page 108: Iniciando No Visual Basic

criou um conjunto de caixas de diálogo. O Visual Basic oferece acesso a essas funções por meio da ferramenta Diálogos Comuns. O uso dessa ferramenta assegurará que seus aplicativos estejam dentro do padrão estabelecido para as operações suportadas.

A exemplo da ferramenta Temporizador, a ferramenta Diálogos Comuns, mostrada na Figura 5.53, estará invisível em tempo de execução. Entretanto, quando você colocar o seu ícone em um de seus forms será possível chamar qualquer uma das cinco funções padrões suportadas pela ferramenta. Cada função padrão está associada a uma caixa de diálogo. As caixas de diálogo comuns padrões do Windows são: Open, Save As, Color, Font: e Printer (Abrir, Salvar Como, Cor, Fonte e Impressora). Além disso, a ferramenta Diálogos Comuns pode invocar o sistema de ajuda on-line do Windows. É preciso que seja feita uma inclusão desta ferramenta em seu projeto selecionando-a na caixa de diálogo Components. Clique em Components no menu Project e selecione Microsoft Common Dialog Control. A ferramenta então aparecerá na sua caixa de ferramentas após o OK.

Figura 5.53 A ferramenta Diálogos Comuns.

A execução de uma certa função é iniciada quando você se utiliza de um dos métodos do controle de diálogos comuns que exibem caixas de diálogo. As instruções de seu programa Visual Basic ficarão suspensas até que o usuário não precise mais da caixa de diálogo. Você pode então examinar as propriedades do controle para determinar o que aconteceu. Não há eventos associados a controles de diálogos comuns. Você especifica sua operação, configurando os valores das propriedades e então chamando um dos métodos abaixo:

 

Método Caixa de Diálogo Exibida

ShowOpen Abrir

ShowSave Salvar Como

ShowColor Cores

ShowFont Fontes

ShowPrinter Imprimir

ShowHelp Invoca o Help

 

Page 109: Iniciando No Visual Basic

Além dos métodos acima, a propriedade CancelError é usada por todas as funções de diálogos comuns. O estado default de CancelError é False. Quando configurada para True, o Visual Basic sinalizará um erro se o usuário escolher o botão Cancel na caixa de diálogo. Se você tem intenção de configurar essa propriedade como True, precisa usar os recursos para tratamento de erros do Visual Basic, descritos no Capítulo 9.

Os parágrafos a seguir descrevem os métodos da ferramenta Diálogos Comuns. Devido ao seu grande número, não foi fornecido um programa de exemplo completo, apenas fragmentos de programas que ilustram o uso típico do controle.

Método ShowOpen (Abrir)

A caixa de diálogo Abrir, mostrada na Figura 5.54, é chamada quando o método ShowOpen é usado. Você pode configurar as seguintes propriedades para controlar a aparência da caixa de diálogo. Observe que a caixa de diálogo na realidade não abre o arquivo, apenas permite ao usuário selecionar o nome do arquivo.

Figura 5.54 A caixa de diálogo Abrir

Propriedades relacionadas a ShowOpen

DialogTitle Esta propriedade pode ser configurada para qualquer string. A string será exibida na barra de título da caixa de diálogo. O título default é "Abrir".

FileName Esta propriedade é usada para configurar o nome inicialmente mostrado na caixa de texto FileName da caixa de diálogo. Após a caixa de diálogo ser fechada, pode-se ler esta propriedade para determinar o nome selecionado para o arquivo.

Filter A propriedade Filter pode ser configurada para restringir os nomes de arquivos que aparecem na caixa de lista de arquivos. A propriedade Filter deve conter uma string com um ou mais pares de componentes. Cada par de componentes é composto por uma descrição, seguida pelo símbolo ( | ) e por caracteres de especificação globais para nomes de arquivos. Os múltiplos pares de componentes também são separados pelo símbolo ( | ). Por exemplo, a string a seguir especifica três pares de componentes:

"Documentos (*. DOC)|*.doc|Arquivos Texto (*.TXT)|*.txt|Todos Arquivos (*.*)|*.*"

Page 110: Iniciando No Visual Basic

O primeiro filtro restringe a lista de arquivos a arquivos com a extensão DOC; o segundo, a arquivos com a extensão TXT e o último permite a seleção de qualquer extensão. Note que não há nenhum espaço antes ou depois do símbolo ( | ).

FilterIndex Esta propriedade é configurada para um inteiro indicando qual é o par de componentes que será usado como default. No exemplo acima, poderia ser 1, 2 ou 3.

Flags A propriedade Flags pode ser configurada para uma combinação de um ou mais valores que controlam as características especiais da caixa de diálogo. Os valores válidos para esta propriedade estão descritos no sistema de ajuda on-line do Visual Basic. Um exemplo é cdlOFNFileMustExist, que forçará o usuário a selecionar um arquivo existente.

Exemplo

Este fragmento de programa exibe a caixa de diálogo Abrir. Ela força o usuário a escolher um arquivo que exista e aplica um filtro padrão para arquivos de dados (*.DAT). Assume-se que o objeto diálogos comuns chama-se Dlog.

 

Figura 5.55 Exemplo de uso do método ShowOpen

 

Save As (Salvar Como)

A caixa de diálogo Save As, mostrada na Figura 5.56, é aberta com o uso do método ShowSave. As propriedades para ShowSave são idênticas às descritas anteriormente para ShowOpen, só que o valor default para a propriedade DialogTitle é Save As.

 

Figura 5.56 A caixa de diálogo Save As.

 

Propriedades relacionadas a ShowSave

Page 111: Iniciando No Visual Basic

DefaultExt Esta propriedade pode ser configurada para uma string de 1 a 3 caracteres, que será usada como extensão default caso o usuário especifique um nome de arquivo sem extensão.

Exemplo

O fragmento de programa a seguir exibe a caixa de diálogo Salvar Como. Assume-se que o objeto diálogos comuns chama-se Dlog. Neste exemplo, a propriedade CancelError é configurada para True; do contrário, seria impossível determinar se foi ou não selecionado um nome de arquivo. Note que as instruções não provocam o salvamento de qualquer arquivo; simplesmente permitem ao usuário selecionar o nome para o arquivo.

Figura 5.57 Exemplo de uso do método ShowSave

 

Color (Cor)

A caixa de diálogo Color, mostrada na Figura 5.58, é exibida quando o método ShowColor é chamado. Você pode configurar as seguintes propriedades para controlar a aparência desta caixa de diálogo.

Figura 5.58 A caixa de diálogo Color.

Propriedades relacionadas a ShowColor

Color Esta propriedade é usada para configurar a cor inicial. Após o usuário dispensar a caixa de diálogo, a cor selecionada poderá ser determinada com esta propriedade.

Flags Esta propriedade deve ser configurada para cdlCCRGBInit para ler ou configurar a propriedade Color.

Exemplo

Este fragmento de programa exibe uma caixa de diálogo para a seleção de cores. Assume-se que o objeto diálogos comuns tenha o nome Dlog. A cor selecionada é usada para configurar o fundo do form atual.

Figura 5.59 Exemplo de uso do método ShowColor

Font (Fonte)

Page 112: Iniciando No Visual Basic

A caixa de diálogo Fonte, mostrada na Figura 5.60, é chamada quando se usa o método ShowFont. Você pode configurar as seguintes propriedades para controlar a aparência da caixa de diálogo.

Figura 5.60 A caixa de diálogo Font.

Propriedades relacionadas a ShowFont

Color Esta propriedade permite configurar ou ler a cor da fonte. (Ela está ativa apenas quando a propriedade Flags inclui cdlCFEffects.)

Flags Esta propriedade pode ser configurada para modificar o comportamento da caixa de diálogo. Entretanto, ela deve incluir um dos seguintes valores: cdlCFPrinterFonts, cdlCFScreenFonts ou cdlCFBoth. Eles determinam quais fontes devem ser listadas na caixa de diálogo (apenas fontes para impressora, apenas para vídeo ou ambas).

FontBold, FontItalic, FontStrikethru, FontUnderline Estas são propriedades booleanas que podem ser configuradas ou lidas para determinar o estilo de informação para a fonte. A configuração da propriedade Flags deve incluir cdlCCEffects para permitir a configuração de estilos.

FontName Esta propriedade pode ser configurada para inicializar a fonte default e pode ser lida para determinar a fonte selecionada pelo usuário.

FontSize Esta propriedade pode ser configurada ou lida e determina o tamanho da fonte em pontos.

Esta sub-rotina permite que os atributos do controle caixa de texto sejam modificados. O controle é passado como um parâmetro. Assume-se que o objeto diálogos comuns chama-se Dlog.

Figura 5.61 Exemplo de uso de ShowFont

Print (Imprimir)

A caixa de diálogo Imprimir, mostrada na Figura 5.62, é exibida quando se chama o método ShowPrinter. Você pode configurar as seguintes propriedades para controlar a aparência desta caixa de diálogo.

 

Page 113: Iniciando No Visual Basic

Figura 5.62 A caixa de diálogo Imprimir.

 

Propriedades relacionadas a ShowPrinter

Copies Esta propriedade especifica a quantidade de cópias que será impressa.

Flags Esta propriedade trata das características especiais da caixa de diálogo. Valores de constantes são combinados usando o operador lógico Or para definir características da caixa de diálogo a ser exibida. Veja o arquivo de ajuda para a descrição detalhada do efeito do uso de cada constante na configuração da propriedade Flags.

Exemplo

Este fragmento de programa exibe a caixa de diálogo para impressão. Como antes, assume-se que o objeto de diálogo chama-se Dlog. É importante notar que a chamada da caixa de diálogo não provocará o início do processo de impressão. Você deve escrever para o objeto Printer. A caixa de diálogo apenas permite ao usuário selecionar certas opções de impressão.

 

Figura 5.63 Exemplo de uso de ShowPrinter

 

ShowHelp (Ajuda)

O aplicativo Help do Windows, mostrado na Figura 5.64, é chamado quando se usa o método ShowHelp do controle de diálogos comuns. Você pode configurar as seguintes propriedades para controlar a aparência desta caixa de diálogo.

 

Figura 5.64 O aplicativo Help.

 

Propriedades relacionadas a ShowHelp

Page 114: Iniciando No Visual Basic

HelpCommand Esta propriedade especifica o tipo de ajuda que você deseja obter. Normalmente, você usará a constante cdlHelpKey, indicando ajuda para uma certa palavra-chave.

HelpFile Esta propriedade indica o nome do arquivo de texto de ajuda.

HelpKey Esta propriedade indica a palavra-chave inicial a ser usada na tela de ajuda.

 

Exemplo

Este fragmento de programa invoca o sistema de ajuda do Windows para a função MsgBox

Dlog.HelpCommand = cdlHelpKey

Dlog.HelpFile = "vb5.hlp"

Dlog.HelpKey = "MsgBox"

Dlog.ShowHelp 'Invoca a ajuda

Menus

Ainda que tenha criado diversos aplicativos até agora, você pode estar com a impressão de que nenhum deles se parece com "aplicativos reais". Por que não? Para começar, nenhum deles tem barra de menus. Entretanto, isso é contornável, pois o Visual Basic torna muito simples a criação de menus. Os menus operam de uma forma orientada a eventos, muito semelhante à maioria dos objetos que foram discutidos.

Para criar o menu para um aplicativo, você deve usar a janela do editor de menus do Visual Basic, mostrada na Figura 5.65. Crie um novo projeto e abra essa janela, escolhendo a opção Menu Editor do menu Tools ou dando um clique no botão Menu Editor contido na barra de ferramentas do Visual Basic.

Figura 5.65 A janela do editor de menu (Menu Editor) do Visual Basic.

Você constrói a barra de menus de seu aplicativo, criando uma hierarquia de itens na janela do editor de menu. Para cada item de menu, você deve definir a propriedade Caption e a propriedade Name. Na propriedade Caption, coloque o título que deverá aparecer na barra

Page 115: Iniciando No Visual Basic

de menus ou no menu drop-down (submenu). O nome (name) do item de menu identifica-o na codificação de seu programa. É obrigatório um nome, pois cada item de menu terá um procedimento Click associado a ele.

Suponha que seu computador contenha os dispositivos de hardware necessários para mostrar imagens de TV dentro de uma janela. Os menus para o aplicativo, que controla esses dispositivos poderiam ser semelhantes a um controle remoto. Veja a seguir um layout: possível para a estrutura de menus, com três níveis de hierarquia.

Arquivo

On

Off

Exit

Canal

Selecionar ...

Up

Down

Som

Mute

Preset

Soft

Moderate

Loud

Louder

Softer

Observe o sinal de reticências (...) que aparece após o item de menu Selecionar. Ele serve para indicar ao usuário que a sua seleção provocará o aparecimento de uma caixa de diálogo.

Page 116: Iniciando No Visual Basic

Vamos agora implementar os menus desse aplicativo. Entretanto, antes de ir para a janela do editor de menus, é preciso dar uma refinada na sua lista de menus.

Na maioria dos aplicativos Windows, você pode usar o teclado para escolher itens de menus, sem usar o mouse. Essas alternativas via teclado são chamadas de teclas de acesso e normalmente se baseiam no pressionamento da tecla Alt, seguido pelos caracteres que estiverem sublinhados nos menus. Por exemplo, em Visual Basic, você pode digitar Alt, F, S para selecionar a opção Save do menu File. Na janela de projeto de menus, você pode especificar a tecla de acesso para um item de menu, colocando o sinal & antes do caractere a ser sublinhado no menu do aplicativo. (Esse sinal não será exibido no menu.)

A menos que haja algum conflito, use sempre como caractere a primeira letra do título da opção. Por exemplo, em nosso aplicativo, os itens On e Off começam com a mesma letra. Dois itens de menu de mesmo nível não podem ter teclas de acesso iguais. Assim, será preciso escolher alguma outra letra para um dos itens. (Uma outra exceção é o uso da letra X, em vez de E, para a opção Exit. Já se tornou padrão usar a seqüência Alt, F, X para sair dos aplicativos.)

Veja, a seguir, como ficam os itens de menus para o aplicativo de exemplo, com os caracteres para teclas de acesso especificados:

&Arquivo

On

Of&f

E&xit

&Canal

&Selecionar ...

&Up

&Down

&Som

&Mute

Page 117: Iniciando No Visual Basic

&Preset

&Soft

&Moderate

&Loud

&Louder

&Softer

Além de um título e de uma tecla de acesso, cada item de menu precisa de um nome. Ainda que possa parecer lógico usar a mesma palavra tanto para o título quanto para o nome, acontece que muitas vezes isso é impossível. Por exemplo, Exit é uma palavra reservada em Visual Basic que pode ser usada como título, mas não como nome de objetos.

É melhor estabelecer um esquema padrão para designação, a fim de reconhecer imediatamente cada item. Nomes significativos e claros são importantes, pois cada item de menu tem um procedimento Click; quando você está codificando, é muito fácil esquecer qual item de menu está sendo tratado. Por exemplo, vamos usar o prefixo mnu para os nomes de objetos; isso identificará os objetos como itens de menus, diferenciando-os de botões de comandos ou barras de deslocamento.

Para os itens de menu no primeiro nível de hierarquia, coloque após a sigla mnu o próprio título do item: mnuArquivo, por exemplo. Para itens no segundo nível, use mnu seguido por três letras que identifiquem o item de primeiro nível, ao qual está subordinado esse segundo nível, e, finalmente, o próprio título do item de menu: mnuArqOn, por exemplo, ou mnuCanSelecionar. Da mesma forma, para itens de menu do terceiro nível, inclua duas abreviaturas para identificar os níveis superiores. Veja, a seguir, os nomes sugeridos para este aplicativo:

mnuArquivo

mnuArqOn

mnuArqOff

mnuArqExit

Page 118: Iniciando No Visual Basic

mnuCanal

mnuCanSelecionar

mnuCanUp

mnuCanDown

mnuSom

mnuSomMute

mnuSomPreset

mnuSomPreSoft

mnuSomPreModerate

mnuSomPreLoud

mnuSomLouder

mnuSomSofter

Agora, você está pronto para passar para a janela do editor de menus e criar os menus deste aplicativo.

Dê um clique na caixa de texto Caption da janela Menu Editor e digite &Arquivo. Depois, pressione a tecla TAB para mover-se para a caixa de texto Name. Digite mnuArquivo nessa caixa e pressione Enter. O título (mas não o nome) aparecerá na caixa de lista na parte inferior da janela.

Dê um clique no botão seta para a direita acima da caixa de lista. Quatro pontos aparecerão na linha abaixo de &Arquivo, indicando que os próximos itens que serão incluídos fazem parte do segundo nível da hierarquia.

Retorne à caixa de texto Caption e digite &On. Mova-se para a caixa de texto Name, digite mnuArqOn e pressione Enter. Volte para a caixa de texto Caption, digite Of&f, mova-se para a caixa de texto Name, digite mnuArqOff e pressione Enter. Use o mesmo procedimento com o título E&xit e o nome mnuArqExit. A sua janela de editor de menus deverá estar parecida com:

 

Page 119: Iniciando No Visual Basic

Figura 5.66

4. Dê um clique no botão seta para a esquerda para retornar ao primeiro nível da hierarquia. Agora, digite os títulos e nomes restantes de nossa lista. Para incluir os itens do terceiro nível de hierarquia, dê dois cliques no botão seta para a direita. Caso seja cometido algum engano ao colocar um item na hierarquia, você pode selecionar o nome do item na caixa de lista e então dar um clique nos botões setas para a direita e para a esquerda, para ajustar seu nível. Os botões setas para cima e para baixo movimentam um item de menu para um local diferente na lista.

5. Quando você completar a introdução dos itens de menu, dê um clique no botão OK.

A barra de menu agora aparece no form principal do aplicativo. Você pode ver os itens de menu dando um clique nos seus títulos que aparecem na barra. Um menu drop-down será exibido, mostrando as entradas que contém, como pode ser visto na Figura 5.67.

Se você der um clique sobre uma entrada de menu que não conduza a outros níveis hierárquicos, o Visual Basic abrirá a janela de código para o evento Click. Nessa janela, você escreve as instruções a serem processadas quando o usuário selecionar aquele item de menu. Por exemplo, dê um clique no item de menu Exit do menu Arquivo para abrir a janela de código com o procedimento de evento mnuArqExit_Click. A instrução Visual Basic para encerrar um aplicativo é End, assim o procedimento para o item Exit deverá ser:

Sub mnuArqExit_Click ( )

End

End Sub

Figura 5.67 Um form com barra de menu e menus drop-down.

Faça experiências com seu aplicativo, colocando instruções Debug.Print em vários procedimentos de menu e então processando novamente o aplicativo. À medida que selecionar diferentes itens de menu, fique de olho na janela Immediate, para verificar quais procedimentos de menu estão sendo executados.

Opções Adicionais para o Editor de Menus

Page 120: Iniciando No Visual Basic

A janela de edição de menus oferece ainda algumas opções interessantes. Por exemplo, se você colocar um hífen (-) como título, o Visual Basic coloca uma barra separadora naquele item de menu, permitindo um agrupamento visual de itens de menu relacionados. (Ainda que esse nome não seja usado no programa, é preciso assinalar um nome à entrada "hífen".)

Você também pode assinalar teclas de atalho para itens de menu. Abra a janela do editor de menus novamente e selecione E&xit. Depois, dê um clique no botão seta para baixo, ao lado da caixa ShortCut. Você pode assinalar qualquer uma das teclas contidas na lista para o item de menu Exit.

As caixas de verificação Checked, Enabled e Visible na janela de edição de menus correspondem a propriedades do item de menu selecionado na lista de itens de menu. Cada propriedade pode ser configurada para True (indicado por um X na caixa de checagem) ou False (caixa de checagem vazia). A configuração da propriedade Checked para True coloca uma marca de verificação no menu, ao lado do item de menu, indicando que ele está ativo. A propriedade Enabled é configurada para True por default; se você configurá-la para False, o item de menu fica cinza, não podendo ser selecionado a partir do menu. Caso a propriedade Visible seja configurada para False, o item de menu não aparecerá no menu.

As configurações Checked, Enabled e Visible na janela de edição de menus indicam a configuração inicial dessas propriedades. Você pode alterar essas configurações por meio de instruções com a seguinte sintaxe:

objeto.propriedade = [True I False]

A opção Window List é usada com menus de janelas MDI (Multiple Document Interface - Interface de Múltiplos Documentos). No modelo MDI, uma janela mãe do tipo MDI contém janelas filhas (propriedade MDIChild = True). Quando um menu da janela MDI possui a propriedade WindowList assinalada, haverá dentro dele uma lista de todas as janelas filhas abertas no momento. Somente um menu pode possuir esta propriedade ativa.

A opção Index tem nos menus o mesmo significado que para outros objetos: um número que o identifica em uma matriz de objetos com o mesmo nome. No próximo capítulo falaremos sobre matrizes.

Page 121: Iniciando No Visual Basic

HelpContextID é um número que serve para ligar o menu a um tópico no arquivo de help da aplicação quando se quer criar ajuda sensível ao contexto para o menu: o usuário pressiona F1 e um tópico de ajuda aparece explicando o objeto clicado.

Menus Popup

Ainda que, via de regra, os menus sejam invocados a partir da barra de menus, algumas vezes você pode querer exibir um menu a partir de um controle. Esse tipo de menu é chamado de menu popup, pois normalmente não é visível, mas aparece quando é dado um clique em algum controle. Você pode configurar qualquer menu para ser invocado como um menu popup usando o método PopupMenu.

Por exemplo, você poderia associar o menu Som mostrado na Figura 5.69 à imagem de um botão de controle de volume. Use a ferramenta Imagem para criar uma caixa de imagem na tela e depois use a ferramenta Forma para traçar um botão de controle circular dentro da caixa de imagem. (A forma será inicialmente um retângulo. Para criar um círculo, configure a propriedade Shape para 3 - Circle.) Introduza o seguinte código para o evento MouseDown da caixa de imagem.

Figura 5.68

Quando o usuário pressionar o botão do mouse dentro da área da caixa de imagem, o menu Som será invocado, como mostra a Figura 5.69.

Figura 5.69 Um menu popup.

Note que, nesse exemplo, o menu Som poderá ser acessado tanto a partir da barra de menus quanto a partir de um clique na caixa de imagem. Se você quiser que o menu seja visível apenas como popup, deverá configurar a sua propriedade Visible para False na janela de projeto de menus. A propriedade Visible de um item de menu de níveis superiores aplica-se apenas à barra de menus, sendo ignorada pelo método PopupMenu.

 

Page 122: Iniciando No Visual Basic

Controle do Programa no Visual Basic

Os pequenos programas que você escreveu são extremamente simples: executam instruções seqüenciais, realizam tarefas sem grandes desvios e, via de regra, são relativamente descomplicados. Este capítulo introduz conceitos que lhe ajudarão a ter um controle adicional sobre como um programa é executado, permitindo-lhe criar mecanismos que possam tratar de várias condições, repetidamente e com ampla variedade de dados.

Fazendo Escolhas

Os programas escritos nos capítulos anteriores eram formados exclusivamente por instruções e expressões, o equivalente a frases imperativas da língua portuguesa. Porém, ninguém, nem mesmo o mais exaltado ditador vitalício, pode passar a vida inteira apenas dando ordens. Na vida real, as pessoas precisam fazer escolhas. A ferramenta principal do Visual Basic para tratamento de escolhas é a instrução If.

 

A Instrução If

Suponhamos que você esteja ensinando a um amigo como obedecer aos sinais de tráfego. Em particular, o que deve ser feito quando se encontra um sinal de Atenção. Você pode explicar o sinal de Atenção da seguinte forma: "Reduza a velocidade para 20 Km/hora. Caso não venha ninguém, continue o seu caminho; do contrário, pare e deixe o carro passar". Em Visual Basic, essas instruções poderiam ser transformadas em:

Figura 6.1

A forma clássica da instrução If especifica uma escolha entre duas opções. Na vida real, é costume escolher-se uma alternativa, deixando de lado a outra e suas possíveis conseqüências. Como programador, é necessário seguir todas as alternativas possíveis, até suas últimas conseqüências.

Como programador, você tem de orientar o computador. Como você não sabe exatamente quais condições o programa encontrará a cada momento quando estiver em processamento, torna-se necessário

Page 123: Iniciando No Visual Basic

incluir instruções para tratamento de todos os casos. No exemplo do sinal de Atenção, você não sabe quando seu amigo encontrará ou não carros trafegando, assim forneça as instruções adequadas para as duas possibilidades. Na codificação de seu programa, aplique um mecanismo conhecido como desvio condicional, usando a instrução If.

Eis aqui a sintaxe da instrução If em Visual Basic:

If expressão booleana Then

[Instrução] ...

Else

[Instrução] ...

End If

A palavra-chave If é seguida por uma expressão booleana, que (como você se recorda do Capítulo 4) é uma expressão avaliada como Verdadeira (True) ou Falsa (False). Isso é um outro exemplo da representação do mundo em termos binários: True ou False, Desvio à esquerda ou à direita, If ou Else. Caso a expressão booleana seja True, todas as instruções que seguem a palavra Then até a palavra-chave Else serão executadas. (As reticências na descrição da sintaxe indicam que pode haver mais de uma instrução.) O programa então saltará as próximas instruções, continuando a sua execução após as palavras-chave End If. Se a expressão booleana for False, as instruções imediatamente após a palavra Then serão saltadas. Quando for encontrada a parte Else da instrução If, o programa continuará a executar as instruções. Os dois possíveis caminhos de execução são mostrados a seguir:

Figura 6.2

A instrução If é uma instrução composta - isto é, apesar de ser avaliada como um todo, ela contém várias instruções dentro de si. A maioria dos programadores costuma colocar essas instruções internas recuadas, para melhorar a sua visualização. Observe como seria difícil ler o primeiro exemplo se isso não fosse feito:

Figura 6.3

Se você examinar a definição da sintaxe da instrução If, poderá ver que a parte Else da instrução é opcional. Isso evita codificação desnecessária quando não houver instruções para serem colocadas

Page 124: Iniciando No Visual Basic

para a cláusula Else. Assim, estes dois fragmentos de programa são equivalentes:

Figura 6.4

Múltiplas Escolhas

A instrução If permite ao seu programa tratar da escolha entre duas opções. Mas como o seu programa pode tratar uma escolha entre muitas opções? Vejamos como utilizar a instrução If para tratar múltiplas escolhas.

A título de exemplo, considere o problema de identificação de cada um dos Três Patetas. Obviamente, você tem três possibilidades de escolha. Neste caso, o tipo de cabelo pode ser usado como característica de identificação. Você pode construir um teste simples, como mostrado na Figura 6.5.

Figura 6.5

O uso da instrução If para construção de uma seleção múltipla pode trazer à lembrança o jogo das Vinte Questões, onde uma pessoa pensa em alguma coisa de um tipo previamente combinado e as outras pessoas tentam adivinhar de que se trata, fazendo perguntas que recebem sempre uma resposta do tipo "Sim" ou "Não". A cada resposta, certas características vão sendo eliminadas, e o processo de adivinhação se encaminha para uma certa direção.

A codificação a ser implementada em Visual Basic para fazer o teste dos Três Patetas, da Figura 6.5, é mostrada aqui; a segunda instrução If é uma instrução aninhada integralmente contida na primeira:

lf Cabelo = "Nenhum" Then

Pateta = "Curly"

Else

lf Cabelo = "Preto" Then

Pateta = "Moe"

Else

Pateta = "Larry"

Page 125: Iniciando No Visual Basic

End If

End If

Como o aninhamento de mais de duas ou três instruções If torna-se complexo, o Visual Basic oferece uma variante para a cláusula Else, chamada ElseIf. A cláusula ElseIf combina a cláusula Else com a funcionalidade de outra instrução If. Veja a seguir uma versão da codificação precedente, refeita para usar ElseIf. Ao lado, encontra-se a sintaxe completa para as instruções If do Visual Basic.

Figura 6.6

Conforme indicado pela sintaxe da instrução, a cláusula ElseIf pode ser repetida muitas vezes, eliminando a necessidade de colocação de múltiplas instruções If aninhadas.

O Aplicativo Caça-níqueis

Para explorar um pouco mais a instrução If, vamos construir uma simulação de um caça-níqueis. Com o botão de comando fazendo o papel de uma alavanca, o programa Caça-níqueis exibirá três ícones aleatoriamente toda vez que o botão de comando for acionado. Caso os três ícones sejam iguais, o usuário vence. O programa manterá um registro das vitórias do jogador.

Voltaremos a usar aqui os ícones Copas, Paus, Ouro e Espadas, encontrados, respectivamente, nos arquivos HEART.ICO, CLUB.ICO, DIAMOND.ICO e SPADE.ICO no diretório \PacoteVB\Icones\Misc do primeiro cd deste produto. O programa pegará aleatoriamente um desses ícones para cada uma das três janelas do visor. Cada jogada custará R$ 1, 00. Se os três ícones combinarem, o jogador ganhará R$ 10, 00. Se os três forem de Ouro, o jogador ganhará R$25,00.

Pensando a Respeito

Reveja com rigor todas as condições, quando estiver programando com instruções If. É preciso ser cuidadoso para não incluir acidentalmente opções inesperadas ou, inversamente, excluir condições que deveriam ser tratadas. Não seja precipitado em assumir que o seu primeiro impulso para escrever uma cláusula Else cubra somente as alternativas possíveis.

A codificação escrita para identificar os Três Patetas, por exemplo, assume que, se Curly e Moe foram eliminados, a única possibilidade que resta é Larry. Entretanto, como sabem os

Page 126: Iniciando No Visual Basic

estudantes da arte cinematográfica, realmente há outras possibilidades, tais como Shemp ou Curly-Joe. (Para quem não está familiarizado com a arte cinematográfica, o trio Moe Howard, Larry Fine e Curly Howard protagonizou a maioria dos filmes dos Três Patetas. Entretanto, após Curly sofrer um acidente, os filmes posteriores foram feitos com outras pessoas no papel do terceiro Pateta.)

Para um exemplo semelhante desse tipo de erro, imagine o teste da cor de um elemento. Caso não seja branco ou vermelho, podemos assumir que seja azul. Isso funciona se você sabe que todos os elementos a serem testados pertencem à bandeira americana; do contrário, o seu teste poderá tornar-se inválido.

Para desenhar a interface do programa, crie um novo projeto. Inclua três controles de imagem na parte superior do form, que serão usados como o visor do caça-níqueis. Abaixo dos controles de imagem, coloque o botão de comando que servirá como alavanca da máquina. À esquerda, acrescente um campo de rótulo para exibir as vitórias do jogador; à direita, crie outro botão de comando que permitirá ao jogador sair do jogo. Finalmente, para acomodar os quatro ícones que serão usados, inclua mais quatro controles de imagem na parte inferior do form. O seu form deverá parecer-se com o mostrado na Figura 6.7.

Para configurar os quatro controles de imagem inferiores, inicie selecionando o mais à esquerda e configurando a sua propriedade Name para ImgCopas. A seguir, configure a propriedade Picture, selecionando Picture na lista de propriedades, e dê um clique no botão de reticências, ao lado da propriedade. Na caixa de diálogo Load Picture, escolha o arquivo HEART.ICO a partir do subdiretório \PacoteVB \ Icones\Misc no primeiro cd deste produto. Repita esse processo para os outros três controles de imagem, nomeando-os como lmgPaus, lmgOuros e lmgEspadas e configurando as suas propriedades Picture de forma a carregar os arquivos CLUB.ICO, DIAMOND.ICO e SPADE.ICO, nesta ordem.

Figura 6.7 O projeto inicial do form para o aplicativo Caça-nÍqueis.

Agora, configure as propriedades dos elementos de exibição, como mostrado na Figura 6.8. O seu form agora deve parecer-se com a Figura 6.9.

Figura 6.8 Configuração de propriedades para o aplicativo Caça-níquel.

Page 127: Iniciando No Visual Basic

Para iniciar a codificação do programa, dê um clique duplo no form, para

abrir a janela de código. Inclua as seguintes linhas de código na seção de declarações gerais:

Const COPAS% = 1

Const PAUS% = 2

Const OUROS% = 3

Const ESPADAS% = 4

Dim Vitórias As Currency

Os inteiros de 1 a 4 mapearão os números gerados aleatoriamente para os ícones apropriados. As declarações de constantes permitem-lhe usar os nomes COPAS, PAUS, OUROS e ESPADAS no programa, simplificando sua leitura e compreensão. A variável Vitórias, que também foi declarada neste ponto, será usada para armazenar as vitórias do jogador.

Figura 6.9 O desenho do form completo para o aplicativo Caça-níquel.

Agora, selecione Form na caixa Object da janela de código e selecione o procedimento Load na caixa de procedimentos. Inclua estas linhas de código, que serão executadas quando o form for carregado pela primeira vez (isto é, no início do programa):

Private Sub Form_Load ()

 

Randomize

Vitórias = 0

End Sub

A instrução Randomize avisa ao Visual Basic para alternar os números produzidos pelo gerador de números aleatórios; sem essa instrução, haveria uma repetição dos números gerados toda vez que o programa fosse executado. Uma vez que o jogador ainda não começou a jogar, você deve zerar a variável Vitórias

Veja a seguir o código para o botão Sair:

Page 128: Iniciando No Visual Basic

Private Sub btnSair_Click ()

End

End Sub

O procedimento para o botão Jogada é apresentado na Figura 6.10. Cada uma das variáveis locais P1, P2 e P3 armazenará o número aleatório que será usado para selecionar os ícones que aparecerão nos controles de imagem superiores (ImgVisor1, lmgVisor2 e ImgVisor3). A variável Pagar conterá o resultado de cada jogada (um giro do caça-níqueis).

Figura 6.10 O procedimento btnJogada_Click para o aplicativo Caça-níquel.

Em primeiro lugar, o programa abate R$1,00 do total de vitórias, ou seja, o custo de uma jogada. A seguir, são gerados três números aleatórios. A fórmula Int(n * Rnd + 1) usa a função interna do Visual Basic Rnd para recuperar um inteiro aleatório dentro da faixa de 1 a n.

Após isso, o programa examina o número inteiro gerado e armazenado em P1 e configura a propriedade Picture do controle ImgVisor1, para copiar a imagem de um dos ícones predefinidos na parte inferior do form. Esse processo repete-se para os outros dois visores, ImgVisor2 e lmgVisor3.

Uma vez configurado o visor do caça-níqueis, o programa verifica se ocorreu alguma combinação vencedora. Se os três número forem iguais, o jogador vence. Além disso, o programa verifica se a combinação vencedora é composta por ouros. A variável Pagar é então assinalada para 10 ou 25, de acordo com a combinação que ocorreu. Caso o jogador não tenha vencido, a variável Pagar é zerada.

Finalmente, o programa adiciona o valor contido na variável Pagar ao total acumulado do jogador e exibe o total apurado no rótulo. A função Format do Visual Basic assegura que o total seja apresentado em reais e centavos de reais.

Ao fechar a janela de código, você estará pronto para executar o aplicativo. Entretanto, antes de fazê-lo, redimensione o form para esconder os quatro ícones predefinidos, conforme mostrado na Figura 6.11. Eles continuarão a fazer parte de seu aplicativo, mas já não aparecerão na interação com o usuário.

Page 129: Iniciando No Visual Basic

Você se sente com sorte? Pressione F5 e faça algumas tentativas. Quando terminar o jogo, pode ser que você queira salvar esse aplicativo para retornar mais tarde a ele.

Figura 6.11 O form redimensionado para o aplicativo Caça-níquel.

Uma alternativa a ElseIf: Select Case

No aplicativo Caça-níquel, você fez uso da palavra ElseIf para criar testes de múltiplas possibilidades. Uma outra instrução do Visual Basic lhe serviria ao mesmo propósito e com maior riqueza de recursos e clareza. Trata-se da instrução Select Case.

A instrução Select Case é uma estrutura de tomada de decisão que obedece a sintaxe abaixo:

Select Case expressãodeteste

[Case listadeexpressões

[instruções]] ...

[Case Else

[instruçõeselse]]

End Select

Onde:

expressãodeteste é qualquer expressão a ser testada quanto ao seu valor.

listadeexpressões lista de uma ou mais expressões numa das seguintes formas de arranjo: expressão; expressão To expressão; Is operadordecomparação expressão. A palavra To especifica um intervalo de valores. Se você usa a palavra To, a expressão de menor valor deve vir antes do To. Use a palavra Is com operadores de comparação ( exceto Is e Like) para especificar um intervalo de valores. Se não for fornecida, a palavra Is é automaticamente inserida.

Instruções pode ser uma ou mais instruções executadas se o valor da expressão sendo testada conferir com o valor de alguma das expressões da lista de expressões na cláusula Case.

Page 130: Iniciando No Visual Basic

Instruçõeselse são opcionais. Representam uma ou mais instruções que serão executadas caso nenhuma das cláusulas Case contiver uma expressão cujo valor confira com o da expressão sendo testada.

Se quiser utilizar Select Case no aplicativo Caça-níquel, você pode, por exemplo, substituir os testes das variáveis P1, P2 e P3 pelo seguinte código:

Select Case P1

Case COPAS:

ImgVisor1.Picture = ImgCopas.Picture

Case PAUS:

ImgVisor1.Picture = ImgPAUS.Picture

Case OUROS:

ImgVisor1.Picture = ImgOUROS.Picture

Case ESPADAS:

ImgVisor1.Picture = ImgESPADAS.Picture

End Select

Select Case P2

Case COPAS:

ImgVisor2.Picture = ImgCopas.Picture

Case PAUS:

ImgVisor2.Picture = ImgPAUS.Picture

Case OUROS:

ImgVisor2.Picture = ImgOUROS.Picture

Case ESPADAS:

ImgVisor2.Picture = ImgESPADAS.Picture

End Select

Page 131: Iniciando No Visual Basic

Select Case P3

Case COPAS:

ImgVisor3.Picture = ImgCopas.Picture

Case PAUS:

ImgVisor3.Picture = ImgPAUS.Picture

Case OUROS:

ImgVisor3.Picture = ImgOUROS.Picture

Case ESPADAS:

ImgVisor3.Picture = ImgESPADAS.Picture

End Select

Tornando-se Repetitivo

A habilidade de escrever instruções de assinalamento, e fazer escolhas usando a instrução If teoricamente lhe dá as ferramentas necessárias para criar qualquer tipo de programa. Porém, muitas tarefas são mais fáceis em teoria do que na prática. Considere o problema de imprimir todos os números do intervalo de 1 a 1000. A solução óbvia, escrever um programa contendo 1000 instruções Print (Print 1, Print 2, Print 3 e assim por diante), seria extremamente fatigante. Felizmente, o Visual Basic oferece um meio melhor.

A instrução Do do Visual Basic pode processar repetidamente um conjunto de instruções. Eis a sintaxe mais simples para essa instrução:

Do

[instrução] ...

Loop

A palavra-chave Do marca o início de uma instrução composta, que inclui todos os comandos até a palavra-chave Loop. As instruções são executadas em ordem até que a palavra-chave Loop seja encontrada; nesse ponto, a execução começa novamente no inicio do bloco com a instrução Do.

Page 132: Iniciando No Visual Basic

O conjunto de instruções que se repete é chamado de laço. Quando um programa está executando repetidamente esse conjunto de instruções, costuma-se dizer que está em looping. O nome laço provém do diagrama circular de fluxo de programa mostrado na Figura 6.12

O laço mostrado na Figura 6.12 é um lago infinito, isto é, o Visual Basic executará a instrução composta para sempre. E claro que, normalmente, você desejará que o programa interrompa a estrutura de laço em algum ponto, passando a executar as instruções que existem após o laço. O Visual Basic permite-lhe implementar isso de várias formas.

Figura 6.12 Um diagrama de laço Do.

Você pode anexar uma cláusula While (enquanto) à instrução Do ou à instrução Loop. O exemplo de impressão dos números de 1 a 1000 é tratado mais facilmente com um laço Do While, como mostrado a seguir:

Contador = 1

Do While Contador <= 1000

Print Contador

Contador = Contador + 1

Loop

A variável Contador recebe o valor 1. Então, a instrução Do While, que é

executada "enquanto" o Contador for menor ou igual a 1000, envolve uma

instrução Print e uma instrução de assinalamento. Quando o laço se encerrar, a execução continuará com as instruções do programa que se seguem à palavra-chave Loop.

A palavra-chave While deve ser seguida por uma condição com o formato de uma expressão booleana. Caso a expressão seja False, as instruções que a seguem, até a palavra-chave Loop, serão saltadas e a execução do programa prosseguirá com as instruções que vêm após a instrução Loop. Neste exemplo, Contador é verificado no início de

Page 133: Iniciando No Visual Basic

cada laço, inclusive no primeiro. (Se Contador tivesse sido inicializado com 5000, nenhuma das instruções dentro do laço seria executada.)

Observe que, se a instrução Contador = Contador + 1 não tivesse sido incluída, a expressão booleana seria sempre True (pois Contador permaneceria com o valor 1) e o laço seria eternamente executado. A criação de laços infinitos é um erro comum, mesmo entre os programadores mais experientes. Lembre-se de que, em Visual Basic, você pode sempre pressionar Ctrl-Break para interromper um programa que está sendo executado e sair do laço infinito.

A palavra-chave While também pode ser associada à instrução Loop, obtendo-se um efeito um pouco diferente, como mostrado neste código:

Do

Password = lnputBox ("Digite a senha")

Loop While Password <> "Mussum"

A colocação da cláusula While no final do laço assegura que as instruções contidas no laço sejam executadas pelo menos uma vez, pois o teste de terminação ocorre após a palavra-chave Loop. Neste exemplo, a caixa de diálogo solicitando ao usuário a digitação da senha será exibida repetidamente, até que o usuário introduza a palavra certa.

Finalmente, para melhorar a legibilidade de seu programa, você pode usar a palavra-chave Until (até que) em vez de While. O uso de Until inverte a lógica da condição. Compare os dois exemplos anteriores, usando cada uma das alternativas.

Exemplos usando While

Contador = 1

Do While Contador <= 1000

Print Contador

Contador = Contador + 1

Loop

Do

Page 134: Iniciando No Visual Basic

Password = lnputBox("Digite a Senha")

Loop While Password <> "Mussurn"

Exemplos usando Until

Contador = 1

Do Until Contador > 1000

Print Contador

Contador = Contador + 1

Loop

Do

Password = lnputBox("Digite a Senha")

Loop Until Password = "Mussum"

Eis a sintaxe completa para a instrução Do no Visual Basic:

 

Teste no início do laço

 

Do [While | Until] expressão

[Instrução]

Loop

Teste no final do laço

Do

[Instrução]

Loop [While I Until] expressão

O Aplicativo Banco

Page 135: Iniciando No Visual Basic

Vamos usar o conhecimento recém-adquirido para escrever um programa que servirá de banco privado, contendo alguma informação diferente. Quando o usuário introduzir em uma caixa combinada os montantes de todos os cheques emitidos durante um certo período, o programa avisará ao usuário sobre o valor médio por cheque. Para encontrar essa média, o programa irá acumular todos os valores e dividi-los pela quantidade de cheques - uma tarefa perfeita para um laço Do While.

Crie um novo projeto no Visual Basic. A interface do programa requer uma caixa combinada para armazenar o valor de todos os cheques, um botão de comando para calcular a média e um rótulo para exibir a média. Desenhe um form contendo esses objetos, configurando as suas propriedades de acordo com a Figura 6.13. O seu form deverá parecer-se com o mostrado naFigura 6.14.

Figura 6.13 Configuração de propriedades para o aplicativo Banco.

Figura 6.14 Projeto do form para o aplicativo Banco.

Agora, você deve modificar ligeiramente a caixa combinada. Normalmente, uma caixa combinada oferece uma lista de opções para o usuário. Neste caso, você irá usá-la para construir uma lista de entradas do usuário. Cada vez que o usuário introduzir um valor na parte de texto da caixa combinada, o programa adicionará o valor aos itens da parte de lista. Para fazer isso, será necessário usar um procedimento de evento que foi citado no Capítulo 5, aquele baseado no evento KeyPress.

O evento KeyPress ocorre toda vez que o usuário pressiona uma tecla. Dê um clique duplo na caixa combinada e selecione KeyPress a partir da caixa de procedimentos na janela de código. A declaração desse procedimento deverá ser a seguinte:

Private Sub cboEntrada_KeyPress (KeyAscii As Integer)

End Sub

 

A variável chamada de KeyAscii é definida dentro dos parênteses. Essa variável é um parâmetro. Os parâmetros funcionam como variáveis locais, exceto pelo fato de serem inicializados pelo procedimento chamador e não pelo procedimento que contém a sua declaração. (Parâmetros em procedimentos são abordados em

Page 136: Iniciando No Visual Basic

maiores detalhes no Capitulo 7.) Por enquanto, basta saber que o evento KeyPress ocorre com uma variável predefinida chamada de KeyAscii. Quando a execução do procedimento é iniciada, o valor de KeyAscii é o código ASCII correspondente ao caractere digitado pelo usuário. Por exemplo, se o usuário pressionar a tecla A, o valor de KeyAscii será 65. A digitação de a gera o valor 97. Dar um clique na tecla 3 gera o valor 51.

A codificação do procedimento KeyPress pode modificar a variável KeyAscii. Caso isso venha a ser feito, o Visual Basic incluirá o novo caractere na caixa combinada, em vez daquele originalmente introduzido pelo usuário. Experimente essa característica. Defina o procedimento KeyPress como segue:

Private Sub cboEntrada_KeyPress (KeyAscii As Integer)

lf KeyAscii = 83 Or KeyAscii = 84 Then

KeyAscii = 42

End lf

End Sub

Pressione F5 para iniciar a execução do aplicativo e digite TESTANDO na parte de texto da caixa combinada. As letras S e T serão substituídas por asteriscos. (O código ASCII para um asterisco é 42.) Deixe o aplicativo e edite o procedimento

KeyPress novamente, como mostrado abaixo:

Private Sub cboEntrada_KeyPress (KeyAscii As Integer)

‘Se a tecla for Enter

lf KeyAscii = 13 Then

‘Inserir nova entrada

cboEntrada.AddItem cboEntrada.Text

‘Limpar a parte de texto

cboEntrada.Text = ""

‘Descartar a tecla pressionada

Page 137: Iniciando No Visual Basic

KeyAscii = 0

End lf

End Sub

Esse procedimento foi configurado para detectar o pressionamento de Enter (código ASCII13). Se a tecla pressionada pelo usuário não for Enter, o Visual Basic simplesmente inserirá o caractere digitado na parte de texto da caixa combinada. Entretanto, quando o programa detecta a tecla Enter, esse procedimento insere a parte de texto da caixa combinada como um novo item na parte de lista. Depois, apaga a entrada da parte de texto e configura KeyAscii para 0. Uma vez que 0 é o código ASCII para caracter nulo, o Visual Basic simplesmente ignorará esse caractere.

Calculando a Média

Após o usuário introduzir todos os valores, ele poderá dar um clique no botão Média para fazer com que o programa calcule o valor médio. Dê um clique duplo no botão de comando Média e introduza o seguinte código:

Figura 6.15

A instrução Dim define duas variáveis locais: Atual, para ser usada como indexador para os itens da caixa de lista ou caixa combinada; e Total, que armazena a somatória dos valores. Total é então inicializada como 0, e o indexador de itens é configurado para 0. (Os itens em uma caixa de lista ou caixa combinada são identificados por meio dos indexadores 0, 1, 2 e assim por diante.)

A instrução Do While direciona o Visual Basic para continuar o processamento enquanto o indexador for menor que a quantidade total de itens. (Não se pode esperar que o programa encontre o item 21 se apenas 7 itens tiverem sido incluídos.) A próxima instrução contém a expressão cboEntrada.List(Atual), que especifica um item da lista. Como os itens de caixas de lista e de caixas combinadas são armazenados como texto, a função Val do Visual Basic é usada para converter o texto para valor numérico. Analogamente, a função Str$ converte o valor da média calculada para uma string de texto antes do programa exibí-lo no rótulo.

Agora, você pode processar o programa Banco. Digite uma série de valores na parte de texto da caixa combinada, pressionando Enter a

Page 138: Iniciando No Visual Basic

cada valor. Quando tiver introduzido a lista completa, dê um clique no botão Média. Seus resultados devem ser semelhantes aos mostrados na Figura 6.16.

Figura 6.16 Processando o aplicativo Banco.

 

Laços Que Contam

A instrução For é uma instrução especial em Visual Basic que trata de mecanismos de laços, fazendo contagem em ordem crescente ou decrescente. Ela tem a seguinte sintaxe:

For variável = primeiroValor To últimoValor [Step Incremento]

[Instrução] ...

Next variável

A instrução For cria um laço no qual a variável contadora é inicializada com o valor de primeiroValor, sendo então incrementada toda vez que o programa executa o laço pelo valor incremento até atingir o valor últimoValor. Se a cláusula Step for omitida, será assumido incremento 1. A menos que o valor do incremento seja negativo, primeiroValor deverá ser menor do queúltimoValor. Caso seja usado incremento negativo, primeiroValor deverá ser maior do que últimoValor.

O laço For pode ser escrito por meio de uma instrução While (enquanto), porém é mais comum usar o laço For, por sua simplicidade. A sintaxe dos laços While equivalentes é mostrada aqui:

Figura 6.17

Repare que a expressão To no laço For é equivalente à comparação menor ou igual no laço While, com incremento positivo, e equivalente à comparação maior ou igual, quando o incremento é negativo. Isso significa que o valor da variável ao final da execução do laço poderá ser diferente de últimoValor. Como um exemplo, veja este laço e a saída que ele produz:

For Contador = 1 To 10 Step 4

Print Contador

Page 139: Iniciando No Visual Basic

Next Contador

Saída

1

5

9

Se desejar, você pode modificar a codificação do programa Banco para usar

o laço For. Compare as suas modificações com esta versão (que mostra as linhas

alteradas em destaque):

Figura 6.18

Ao escrever a sua versão da codificação, você configurou o valor final do laço For para cboEntrada.ListCount - 1? Essa mudança, apesar de importante, costuma ser esquecida com freqüência. Lembre-se de que o Visual Basic numera os itens de uma caixa combinada, começando pelo 0, isto é, três itens são numerados como 0, 1 e 2. A versão original do código usa um laço com uma comparação menor do que. O laço For usa menor ou igual.

Essas diferenças sutis podem conduzir a erros, fazendo com que o laço seja executado uma vez a mais ou a menos. Até mesmo os programadores mais experientes cometem esses tipos de engano; assim, preocupe-se em testar o seu programa cuidadosamente. Por exemplo, quando eu criei o programa Banco pela primeira vez, ele foi processado usando os valores 1, 2, 3 e 4. Entretanto, como sabia que a média deveria ser 2,5, eu percebi que alguma coisa estava errada. Quando um programa não produz nenhum resultado, imediatamente descobre-se que está errado. Entretanto, quando um programa gera um resultado, somos quase sempre tentados a assumir que ele esteja correto.

Espere o Inesperado

Ainda que um programa produza um resultado correto nos primeiros testes, não se pode assumir que estará sempre correto. Um exemplo disso é o programa Banco. Esse programa falhará se o usuário der um clique no botão Média sem introduzir algum valor na caixa combinada.

Page 140: Iniciando No Visual Basic

Você pode achar que ninguém faria uma coisa dessas. Porém, parte de seu trabalho como programador é entender que tudo o que pode acontecer provavelmente acontecerá. E você deve antecipar-se a tais eventos da melhor maneira possível.

No programa Banco, o laço Do While (ou o laço For, se você fez as alterações) apresenta um problema no cálculo da média. Se não houver algum item na caixa combinada, a expressão Total/cboEntrada.ListCount causará uma divisão por zero. Nesse caso, o Visual Basic oferece um tratamento de erro, exibindo uma caixa de diálogo que diz Division by zero. Isso, porém, não serve de conforto para o usuário. Além disso, alguns sistemas (tais como o MS-DOS) simplesmente encerram a execução de um programa que tente fazer uma divisão por zero. Sem dúvida é melhor que você, como um bom programador, antecipe-se a esse erro, em vez de acreditar que o sistema irá tratá-lo de alguma forma (possivelmente indesejável).

Você pode melhorar o programa Banco de várias formas. Uma é inserir o seguinte código no início do procedimento btnMédia_Click:

If cboEntrada.ListCount = 0 Then

Exit Sub

End If

Esse código fará com que o programa simplesmente ignore o clique do mouse no botão Média quando inadequado, encerrando o procedimento. Dará a impressão de que o botão Média não está respondendo, o que pode confundir o usuário. Se estiver preocupado com essa possibilidade, você pode exibir uma caixa de diálogo, como o código mostrado abaixo:

If cboEntrada.ListCount = 0 Then

MsgBox "Não há entradas para Média"

Exit Sub

End If

Usando Matrizes

No programa Banco, você usou a variável cboEntrada.List, que é uma matriz. Variáveis matriz podem conter múltiplos valores. Isso pode parecer-se um pouco com os tipos definidos pelo usuário no Capítulo

Page 141: Iniciando No Visual Basic

3, porém não é a mesma coisa. Uma variável de tipo definido pelo usuário contém um número fixo de componentes, cada um dos quais com nomes e tipos de dados diferentes. Em uma matriz, todos os elementos têm o mesmo tipo e cada elemento individual é numerado seqüencialmente. Para fazer referência a um campo de um tipo definido pelo usuário, você usa o nome da variável do tipo seguido pelo nome do campo, tal como em Siegmund.Cor. Para se referir ao elemento de uma matriz, você usa o nome da variável matriz seguido pelo número do elemento colocado entre parênteses, tal como cboEntrada.List(3). O número que especifica um elemento de uma matriz é chamado de índice. Os valores de índices são sempre inteiros. O Visual Basic armazena o valor dos elementos de matrizes em memória, por ordem do índice, começando pelo elemento 0. A Figura 6.19 compara o armazenamento de memória para variáveis simples e tipos definidos pelo usuário com o armazenamento de memória para matrizes.

Figura 6.19 Alocação de memória para variáveis simples, registros e matrizes.

 

Reservando Memória para Matrizes

O Visual Basic permite-lhe criar matrizes para armazenar qualquer tipo de dado, incluindo tipos de dados definidos pelo usuário. O programa Banco usa uma matriz de strings (cboEntrada.List) que é uma propriedade predefinida de caixa combinada. Para criar uma matriz e reservar memória para ela, deve-se usar uma declaração de variável. A exemplo das outras variáveis, as matrizes são declaradas por meio da instrução Dim. Eis a sintaxe para uma declaração padrão de matriz:

{ Dim | Private | Public } name (tamáximo) [As tipo]

O valor entre parênteses (tamáximo) é chamado de dimensão da matriz; ele indica para o Visual Basic a quantidade de memória a ser reservada para a matriz. A declaração cria uma matriz com índices que vão de 0 a tamáximo - Por exemplo, a Instrução Dim X(3) As Integer declara uma matriz com tamáximo igual a 3, criando uma matriz com quatro elementos: X(0), X(1), X(2) e X(3).

Fazendo Experiências com Matrizes

Matrizes são incrivelmente úteis, permitindo-lhe escrever programas mais genéricos e menos dependentes de tipos específicos de dados.

Page 142: Iniciando No Visual Basic

Para demonstrar, considere nossos amigos do Capítulo 3, as doninhas de topete da Floresta da Baviera.

Para avaliar sua capacidade como criador de doninhas, você decide calcular o tamanho médio das doninhas, para compará-lo com a média nacional. A expressão a ser usada para este cálculo é (Siegmund.Tamanho + Sieglinda.Tamanho + Siegfried.Tamanho ) / 3. Naturalmente, qualquer programa que incorpore essa expressão será válido apenas para doninhas especificas. Cada vez que a sua população de doninhas aumentar, será preciso modificar o programa. Você precisa de uma forma mais genérica para armazenar informações.

Em vez de armazenar as informações sobre cada doninha em uma variável separada, você pode alterar a descrição do tipo (definida anteriormente) para conter o nome da doninha. O novo tipo de dados DoninhaTFB é mostrado a seguir.

Type DoninhaTFB

Nome As String

Cor As String

Peso As Integer

Tamanho As Integer

Data_nascimento As Date

Cor_topete As String

Compr_topete As Integer

End Type

Agora, você pode armazenar todas as informações sobre as doninhas coletivamente em uma variável matriz Doninhas. Você pode declarar a variável matriz Doninhas com a instrução Dim Doninhas(20) As DoninhaTFB. Uma vez que essa matriz pode armazenar informações sobre diversas doninhas (21 para ser exato), você precisa declarar outra variável para conter a quantidade de doninhas que existe no momento: use a instrução Dim QtdDoninhas As Integer.

Depois de declarar as variáveis, você pode armazenar dados sobre doninhas, quase da mesma forma que foi usada para armazená-los

Page 143: Iniciando No Visual Basic

em variáveis separadas. As instruções que se seguem mostram como alguns desses valores podem ser inicializados:

QtdDoninhas = 3

Doninhas(0).Nome = "Siegmund"

Doninhas(0).Cor = "Marrom"

Doninhas(0).Peso = 300

Doninhas(1).Nome = "Sieglinda"

Doninhas(1).Peso = 250

Doninhas(2).Nome = "Siegfried"

Doninhas(2).Peso = 150

Agora, assumindo que todas as informações sobre as doninhas; tenham sido armazenadas, você pode escrever um programa para calcular o tamanho médio, independentemente da quantidade de doninhas que você tenha. Como seria de se esperar, a codificação se parece com a usada no programa Banco:

Dim Atual As Integer, Total As Integer, Média As Single

Total = 0

For Atual = 0 To QtdDoninhas - 1

Total = Total + Doninhas(Atual).Tamanho

Next Atual

Média = Total / QtdDoninhas

Esse código continuará a ser útil também quando a população de doninhas se modificar. O fator-chave para ser bem-sucedido em programação é examinar o problema para determinar quando pode ou não ser generalizado e então escrever um programa para resolver casos mais gerais, em vez de um programa que tenha de ser constantemente modificado à medida que as condições se alterem.

Usando Laços com Matrizes

Page 144: Iniciando No Visual Basic

Confirmando o que os programas simples deste capítulo devem ter-lhe sugerido, matrizes e laços são tão complementares quanto mão e luva. Operações como cálculo de totais, de médias, achar valores máximos e mínimos prestam-se muito bem ao processamento matricial. Todas essas operações precisam examinar a matriz completa. Outras operações, como procura, examinam apenas alguns elementos de uma matriz.

Considere a matriz das doninhas. Agora que as informações vitais estão armazenadas anonimamente, você não pode usar uma variável como Siegmund para extrair dados de uma certa doninha. Para isso, é necessário pesquisar a matriz até encontrar a doninha cujo elemento Nome seja igual a Siegmund. Por exemplo, se você quiser imprimir o peso de Siegmund, o processo mais simples seria parecido com:

Figura 6.20

Infelizmente, esse programa terá de examinar cada um dos elementos da matriz, mesmo que Siegmund seja o primeiro elemento. Esse problema não é tão sério, enquanto a população de doninhas for pequena, mas a pesquisa poderá demandar um tempo significativo se você tiver algumas centenas de doninhas.

É necessário modificar a condição do laço para terminar quando a doninha desejada for achada. Você pode escrever esse laço de duas formas diferentes. A primeira é reformular o laço, tratando-o com uma instrução Do While na qual a condição de finalização leve em consideração tanto o final da matriz quanto o próprio fato de encontrar a doninha.

Figura 6.21

 

Convertendo o laço For para Do While, torna-se possível definir um teste de condição mais preciso. Esse laço será encerrado quando a variável W ultrapassar o valor máximo, ou então quando na variável Encontrado  for armazenado um valor diferente de -1 (o que acontece quando for achado o elemento Siegmund).

O método alternativo consiste em manter o laço For, mas interromper o processamento quando o elemento desejado for encontrado. O Visual Basic oferece a instrução Exit com esta finalidade:

Figura 6.22

Page 145: Iniciando No Visual Basic

Ao atingir a instrução Exit, a execução será imediatamente transferida para a instrução seguinte à instrução Next W.

As duas alternativas são aceitáveis. A primeira tem a vantagem de estabelecer explicitamente as condições de encerramento do laço, simplificando a compreensão do código do programa. O segundo método é ligeiramente mais eficiente, pois o laço não tem de executar um teste adicional sobre o conteúdo da variável Encontrado a cada iteração do laço. Quando o elemento procurado é achado, o laço termina. Entretanto, a instrução Exit que termina o laço encontra-se "perdida" no meio das instruções, podendo passar despercebida para alguém que esteja lendo o programa. Minha preferência pessoal é pelo uso do método mais eficiente.

As três versões desse código contêm um problema comum: a instrução Print. A codificação assume que tenha sido encontrado o elemento procurado, mesmo que isso não tenha acontecido. A versão correta deveria substituir a instrução Print pelo seguinte código:

lf Encontrado = -1 Then

MsgBox "Não foi encontrado"

Else

Print Doninhas(Encontrado).Peso

End If

Determinando o Tamanho da Matriz em Tempo de

Execução

Ao escrever uma instrução Dim para declarar uma matriz, está-se efetivamente preestabelecendo o tamanho da matriz. Pode ser que você conheça exatamente de que tamanho deverá ser a matriz, ou talvez saiba seu tamanho máximo. (Por exemplo, você pode saber que trabalhar com mais de 21 doninhas é muito difícil.) Em tais casos, uma matriz de tamanho fixo é o ideal. O problema ocorre quando não se conhece o tamanho da matriz. Suponha, por exemplo, que você deseje vender o seu programa de tratamento de doninhas para outras pessoas. Como você deve dimensionar a matriz ?

Você pode simplesmente escolher um número arbitrariamente grande, achando que será suficiente, porém encontrará dois problemas com essa abordagem. Primeiro, é necessária muita memória; a instrução

Page 146: Iniciando No Visual Basic

Dim reserva memória para a matriz completa, esteja ou não sendo usada. Em segundo lugar, você está correndo o risco de vender o programa para alguém que queira criar mais doninhas do que você acha praticável; o seu programa falhará e você terá um cliente insatisfeito.

Para resolver essa questão, o Visual Basic oferece a instrução ReDim, que redimensiona uma matriz. ReDim não é uma declaração, é uma instrução que pode ser executada várias vezes durante um processamento do programa. Para usar a instrução ReDim, você deve retirar a indicação da dimensão da matriz (tamáximo) de seu programa. Essa omissão avisará que se trata de uma matriz dinâmica (aquela cuja dimensão ou tamanho pode modificar-se). Examine esse fragmento de programa que serve apenas para ilustrar como ReDim funciona:

Dim Teste() As Integer 'Na seção de declarações gerais

'Em algum procedimento de evento

For Tamanho = 10 To 50 Step 10

' Redimensiona a matriz teste

ReDim Teste(Tamanho) As Integer

Next Tamanho

Como a declaração original da matriz Teste não contém o componente tamáximo, o Visual Basic irá reconhecê-la como uma matriz dinâmica. Em algum ponto, o laço For será executado. Na primeira passagem do laço, Teste é redimensionada como uma matriz de 11 elementos (com elementos numerados de 0 a 10). Na próxima passagem, Teste será redimensionada. como uma matriz de 21 elementos. Quando o laço estiver completo, Teste estará dimensionada como uma matriz de 51 elementos. Eis a sintaxe da instrução ReDim:

ReDim [Preserve] variável (tamáxímo) [As tipo]

A sintaxe se parece com a da instrução Dim, exceto pelo fato de a palavra reservada Preserve poder ser incluída, e o valor tamáximo poder ser qualquer expressão inteira. Quando ReDim é usada sem Preserve, qualquer cópia existente da matriz será desconsiderada, e uma matriz completamente nova será criada. Se você usar ReDim com Preserve, os valores armazenados na matriz antiga serão preservados na nova matriz. Caso a nova dimensão da matriz seja

Page 147: Iniciando No Visual Basic

menor que a anterior, os valores com índices maiores do que a nova dimensão não serão preservados.

Usando Matrizes de Controles

Além das matrizes de valores de dados, o Visual Basic permite-lhe definir matrizes de objetos de controle, que são úteis quando você estiver trabalhando com vários controles que executem essencialmente a mesma ação. As matrizes de controles compartilham os mesmos procedimentos de eventos. Por exemplo, se você tiver uma matriz de três botões de comando, será chamado o mesmo procedimento Click quando qualquer um dos botões receber um clique.

O Visual Basic permite-lhe diferenciar os itens de uma matriz de controles dentro do procedimento de evento compartilhado mediante a passagem do valor do índice como um argumento para o procedimento. Vejamos como isso funciona. Em um form vazio, crie dois botões de comando. Configure a propriedade Name dos dois botões para btnTeste. Quando tentar configurar a propriedade Name do segundo botão, o Visual Basic apresentará uma caixa de diálogo que lhe pergunta se você deseja ou não criar uma matriz de controles:

Figura 6.23

Dê um clique em Yes na caixa de diálogo. Agora, abra a janela de código, dando um clique duplo em qualquer um dos dois botões. Você verá que foi incluído um parâmetro Index em cada procedimento de evento, conforme mostrado aqui:

Private Sub btnTeste_Click (Index As Integer)

End Sub

Esse procedimento de evento será chamado quando for dado um clique em qualquer um dos dois botões; a propriedade Index do botão que recebeu o clique é passada como um parâmetro inteiro, identificando o botão acionado.

Quando você cria uma matriz de controles, o Visual Basic assinala um índice para cada objeto. Usando a janela de propriedades, examine a propriedade Index para os dois botões de comando criados.

Figura 6.24

Page 148: Iniciando No Visual Basic

O primeiro botão tem a Propriedade Index igual a 0. O segundo tem o valor 1. Você pode modificar a propriedade Index em tempo de desenvolvimento para dar valores especiais para a propriedade Index desses botões. Essa propriedade não pode ser modificada enquanto o programa estiver sendo processado.

Você se refere a um elemento de uma matriz de controles, especificando o nome da matriz seguido pelo valor da propriedade Index, entre parênteses. Por exemplo, esse procedimento Click configura os títulos dos botões de comando no seu form, com o valor da hora em que for dado um clique neles.

Sub btnTeste_Click (Index As Integer)

btnTeste(Index).Caption = Format(Now, "hh:mm:ss")

End Sub

As matrizes de controles são particularmente úteis com botões de opção. Você pode definir todos os botões de opção dentro de uma moldura como uma matriz de controles e então usar a propriedade Index ou a propriedade Caption em instruções de assinalamento. Por exemplo, você poderia usar o procedimento Click com uma matriz de controles de botões de opção mostrada na Figura 6.25.

Private Sub OpcCor_Click (Index As Integer)

MinhaDoninha.Cor = OpcCor(Index).Caption

End Sub

Figura 6.25 Uma matriz de controle de botões de opção.

Uma simplificação interessante para a criação de matrizes de controles consiste na criação do primeiro objeto de controle e na configuração de suas propriedades. Depois, você pode copiar e colá-lo tantas vezes quanto necessário para criar controles adicionais que terão o mesmo tamanho e com configurações de propriedades idênticas.

Identificando melhor os controles

Numa matriz de controles, todos os controles são referenciados pelo índice na matriz. Esta não é uma forma de deixar claro para quem lê o código qual controle é qual. Uma forma de contornar isso é utilizando a propriedade Tag, comum a praticamente todos os controles. Tag

Page 149: Iniciando No Visual Basic

pode ser configurada para qualquer valor de string que você queira. Usando Tag para dar nomes aos controles, seus testes de identificação dos controles dentro dos procedimentos de evento não seriam pelo índice, mas sim pelo valor da propriedade Tag. Exemplo:

Private Sub OpcCor_Click(Index As Integer)

Select Case OpcCor(Index).Tag

Case "Marrom"

instruções

Case "Preta"

instruções

Case "Cinza"

instruções

Case "Parda"

instruções

End Select

End Sub

Page 150: Iniciando No Visual Basic

Usando Procedimentos e Funções no Visual Basic

A maioria dos procedimentos que você escreveu nos capítulos anteriores foram procedimentos de eventos - isto é, eles foram projetados especialmente para responder a eventos específicos disparados pelo usuário ou pelo sistema. Este capítulo mostra-lhe como escrever e usar procedimentos genéricos (incluindo sub-procedimentos e procedimentos de funções) que executam uma certa tarefa quando são chamados explicitamente por outras instruções do programa (em vez de serem disparados por um evento). Este capítulo explora também o uso de parâmetros, que permite ao programa passar certos valores para os procedimentos e funções que chama. Como você verá, até mesmo objetos do Visual Basic podem ser passados como argumento. Finalmente, este capítulo aborda alguns procedimentos de eventos avançados, como aqueles que lhe permitem rastrear o movimento do mouse e implementar recursos do tipo arrastar e soltar.

Procedimentos Genéricos

As primeiras aplicações que você escreveu tinham um controle de fluxo linear: após uma instrução ser executada, era executada a próxima instrução seqüencial. No capitulo anterior, você começou a trabalhar com desvios condicionais (instruções If) e com laços, que modificam a ordem na qual as instruções são executadas

Da mesma forma que laços, os procedimentos permitem que seu programa execute um conjunto de procedimentos mais de uma vez. Entretanto, em vez de executar repetidamente um conjunto de instruções, os procedimentos permitem que você agrupe instruções num conjunto que possa ser executado quando necessário. Por exemplo, um procedimento de evento do Visual Basic é executado quando o usuário faz uma certa ação; um procedimento genérico é executado quando é chamado por uma instrução do aplicativo.

Considere um programa que simule as ações de uma criança pequena passeando de automóvel. Este código ilustra o comportamento conhecido como

"choramingas" :

Resposta = lnputBox("Ainda não chegamos ?")

Page 151: Iniciando No Visual Basic

lf Resposta = "Não" Then

MsgBox "Estou cansado"

End If

Em um programa que simule o comportamento de crianças, é de se esperar que essas linhas sejam duplicadas um boa quantidade de vezes. Porém, em vez de codificar múltiplas cópias dessas instruções, você pode agrupá-las em um procedimento e executá-lo simplesmente invocando o seu nome. Inclua uma declaração do procedimento, dando-lhe um nome descritivo:

Sub Choro ()

Dim Resposta As String

Resposta = lnputBox("Ainda não chegamos ?")

lf Resposta = "Não" Then

MsgBox "Estou cansado"

End lf

End Sub

Com esse procedimento, os fragmentos dos dois programas que seguem são equivalentes:

Figura 7.1

Fluxo de Controle

Obviamente, os procedimentos afetam o fluxo de controle de execução de um programa. Quando o Visual Basic encontra o nome de um procedimento, ele guarda a posição atual no programa e então se move para executar o procedimento designado. Quando é encontrado o final do procedimento, ele retorna à posição original do programa e continua a execução a partir daquele ponto. Esse processo é conhecido como chamada de procedimento, pois o programa "chama" o procedimento. Como o Visual Basic pode rastrear centenas de níveis de chamadas, um procedimento chamado por um programa pode conter dentro de si próprio uma chamada de procedimento e assim por diante.

Page 152: Iniciando No Visual Basic

Parâmetros

Suponha que você esteja escrevendo um programa que precise, em algum ponto, imprimir os inteiros de 1 a 10. Em outro ponto, o mesmo programa precisa imprimir os inteiros de 1 a 17. A codificação para essas duas rotinas é mostrada a seguir:

 

Primeira Rotina Segunda Rotina

For Contador = 1 To 10 For Contador = 1 To 17

Print Contador Print Contador

Next Contador Next Contador

Como essas rotinas são muito semelhantes, é muito simples generalizar -

isto é, fazer com que o mesmo código sirva para os dois propósitos. A única

diferença entre os dois é o valor final no laço For, que pode ser substituído por uma variável. Depois disso você poderá usar um procedimento único, chamando-o após armazenar na variável o valor final desejado, conforme mostrado a seguir. (Assuma que a instrução Dim ContFinal As Integer aparece na seção de declarações gerais do programa.)

 

Figura 7.2

Como se pode ver, o uso combinado de variáveis e procedimentos permite que você encontre soluções genéricas para os programas mais facilmente, além de colocar à sua disposição excelentes ferramentas de programação. Entretanto, há alguns problemas práticos com a implementação feita anteriormente. Em particular, você precisa declarar variáveis globais (públicas) ou em nível de módulo para fazer a comunicação entre o programa principal e o procedimento que está sendo chamado. Além disso, é preciso que as variáveis locais aos procedimentos tenham nomes diferentes das variáveis globais. Do contrário, a chamada de um procedimento poderá fazer com que o valor de uma variável global seja sobreposto por valores locais ao procedimento.

Page 153: Iniciando No Visual Basic

O Visual Basic resolve essas questões, permitindo que os procedimentos aceitem parâmetros que sejam tratados como variáveis locais ao procedimento, porém inicializados pela codificação que chama o procedimento. A rotina chamadora inicializa essas variáveis com a colocação de um conjunto de valores após o nome do procedimento a ser chamado. Eis a sintaxe para uma tal chamada de procedimento:

name[ value[, value] ... ]

Observe que os argumentos são separados por vírgulas. A rotina chamadora tem de saber os nomes dos parâmetros, pois o assinalamento destes valores às variáveis locais ao procedimento chamado será feito segundo a ordem de especificação dos parâmetros.

Na declaração do procedimento, os parâmetros são declarados dentro dos parênteses que seguem o nome do procedimento. O Visual Basic permite que os procedimentos tenham vários parâmetros. Eis a sintaxe para declaração de procedimento que inclua parâmetros:

Sub name ([parâmetro [As tipo], [parâmetro [As tipo]] ... ])

End Sub

Veja como ficou o exemplo anterior, refeito com o uso de parâmetros:

 Figura 7.3

 

Para ilustrar o uso de múltiplos parâmetros, você poderia modificar o procedimento PrintCont para aceitar tanto o valor inicial quanto o valor final, conforme mostrado a seguir:

 

Figura 7.4

 

Procedimentos de Funções

A partir dos exemplos precedentes, você deve ter reparado que, quando se trata de chamadas de procedimentos genéricos, a comunicação é feita apenas num sentido - isto é, a rotina chamadora

Page 154: Iniciando No Visual Basic

passa valores para o procedimento que executa alguma ação, mas não retorna qualquer valor para a rotina chamadora. No entanto, você pode usar um tipo especial de procedimento, chamado procedimento de função (ou simplesmente função), que retorna valor ao chamador. A maioria da funções internas do Visual Basic faz isso.

Ao declarar uma função, você deve declarar o tipo de valor que ela retorna, bem como os parâmetros necessários, como mostra a definição de sintaxe:

 

Figura 7.5

 

Como você pode ver, há duas diferenças entre um procedimento de função e um subprocedimento. Um procedimento de função é delimitado pelas instruções Function e End Function, enquanto um subprocedimento requer Sub e End Sub. E, como mostra a definição sintática, em algum lugar dentro do corpo da função, você deve assinalar um valor (expressão) ao nome da função. Esse é o valor que será retornado para a rotina chamadora. Por exemplo, esta função retorna o maior valor entre dois inteiros:

Function MaxInt (X As Integer, Y As Integer) As Integer

If X > Y Then

MaxInt = X

Else

MaxInt = Y

End If

End Function

A sintaxe para a chamada de um procedimento de função é ligeiramente diferente da sintaxe usada para chamar um subprocedimento. Como a função retorna um valor, ela pode ser chamada em qualquer lugar em que uma expressão seja válida. Os parâmetros da função são, portanto, delimitados por parênteses para separá-los de outras partes de uma expressão. Aqui estão algumas instruções chamando a função MaxInt:

Page 155: Iniciando No Visual Basic

Print MaxInt(7, 14)

DuasVezesMaior = MaxInt(3, 4) * 2

lf MaxInt(PrimeiraOpção, SegundaOpção) > 20 Then

Quando a função a ser chamada não requer parâmetros, basta usar o nome da função, como se fosse uma variável. A função interna Now do Visual Basic (que retorna data e hora atuais) é um exemplo de função que não requer a passagem de parâmetros.

Escrevendo Procedimentos

A discussão que se segue usa o termo procedimento para se referir à idéia geral de rotina que pode ser chamada. Quando necessário, o termo procedimento de função (ou simplesmente função) ou o termo subprocedimento será aplicado para dar maior clareza à exposição.

Para criar um procedimento que possa ser chamado em Visual Basic, você deve abrir a janela de código. A partir do menu Tools, escolha a opção Add Procedure. Na caixa de diálogo Add Procedure, digite o nome do novo procedimento, escolha entre Sub ou Function, dando um clique num dos dois botões de opção. Escolha entre público e privado também clicando em uma das opções.Dê um clique no botão OK. O Visual Basic criará então um novo item na caixa de procedimentos da janela de código, já inserindo a instrução End apropriada para o tipo de procedimento que estiver sendo criado. Agora, você pode incluir as declarações de parâmetros necessárias ao seu procedimento.

Nota: você deve ter notado as opções property e event na caixa de diálogo Add Procedure. Trataremos destas opções quando falarmos sobre Classes e Objetos.

Vamos escrever um programa simples chamado Conversão de Temperatura, para executar uma conversão simples de temperatura entre as escalas Celsius e Fahrenheit. Abra um novo projeto e coloque uma barra de deslocamento vertical, seis rótulos e duas caixas de texto no form, dispondo-os como mostrado na Figura 7.7. Configure as propriedades dos objetos de acordo com a tabela mostrada na Figura 7.6.

O programa permitirá ao usuário ajustar a barra de deslocamento para qualquer configuração de temperatura entre os pontos rotulados como -40 e 212 na escala Fahrenheit ou entre as temperaturas

Page 156: Iniciando No Visual Basic

correspondentes -40 e 100 na escala Celsius. O aplicativo então exibirá o valor da temperatura para a configuração escolhida nas duas escalas, Fahrenheit e Celsius. Repare que a configuração da propriedade Min para a barra de deslocamento é maior do que a configuração para Max. Essa forma de configuração faz com que a barra de deslocamento coloque o extremo superior de sua faixa de variação no topo, ao contrário do que acontece quando a configuração da propriedade Min é menor do que a da propriedade Max .

Figura 7.6 O projeto inicial do form, para o aplicativo Conversão de Temperatura.

Figura 7.7 Configuração de propriedades para o aplicativo Conversão de Temperatura.

Por questões de simplicidade, o programa sempre "pensará" em termos de graus Celsius, fazendo a conversão para obter a temperatura em Fahrenheit. Em primeiro lugar, você deve escrever a função que retorna a temperatura Fahrenheit quando o programa fornecer a temperatura em graus Celsius. Comece abrindo a janela de código do form. A partir do menu Tools, escolha a opção Add Procedure. Na caixa de diálogo, digite CParaF, escolha o botão de opção Function e dê um clique em OK. Então, edite a nova função como segue (inicie adicionando as declarações do parâmetro e do tipo de valor a ser retornado na instrução Function):

Function CParaF (TempC As Integer) As Integer

CParaF = Cint(TempC * 9 / 5 + 32)

End Function

A função CParaF aplica a fórmula padrão de conversão métrica. Recebendo a temperatura em graus Celsius como parâmetro, ela retorna a temperatura equivalente na escala Fahrenheit. Para simplificar a saída e o uso da barra de deslocamento, os valores estão restritos a inteiros. (A função CInt converte valor em ponto flutuante para inteiro, por arredondamento.)

Agora, você pode escrever o código que lê o valor da barra de deslocamento e exibe os valores das temperaturas. Introduza o seguinte subprocedimento abaixo da função:

Sub ExibeTemp ()

Dim TempC As Integer

Page 157: Iniciando No Visual Basic

TempC = Clnt(VscTermômetro.Value)

TxtGrausC.Text = Str$(TempC)

TxtGrausF.Text = Str$(CParaF(TempC))

End Sub

Após introduzir a primeira linha (a instrução Sub), repare que o Visual Basic adiciona o nome do procedimento à caixa de procedimentos e inclui a instrução End Sub no código que você está escrevendo. Como você pode ver, é possível criar novos procedimentos, tanto por meio da opção Add Procedure do menu Tools quanto da introdução da instrução Function ou Sub em qualquer lugar da janela de código.

O código para o procedimento ExibeTemp lê o valor da barra de deslocamento, VscTermômetro.Value, armazenando-o na variável TempC. O valor é exibido na caixa de texto TxtGrausC. Então, a caixa de texto TxtGrausF é configurada com o resultado gerado pela função de conversão CParaR

Finalmente, selecione o objeto VscTermômetro (a barra de deslocamento) na caixa de objetos da janela de código e edite seus procedimentos de evento como mostrado aqui:

Private Sub VscTermômetro_Change ()

ExibeTemp

End Sub

Private Sub VscTermômetro_Scroll ()

ExibeTemp

End Sub

Com isso, toda vez que o usuário alterar a barra de deslocamento, o procedimento ExibeTemp fará seu trabalho. Processe o aplicativo para ver se ele funciona como esperado. O resultado dever parecer-se com o exemplo mostrado na Figura 7.8.

Figura 7.8 Processando o aplicativo Conversão de Temperatura.

Pensando no Futuro

Page 158: Iniciando No Visual Basic

Pode parecer que você fez alguns trabalhos desnecessários ao escrever o código para o aplicativo Conversão de Temperatura. No final das contas, se cada procedimento é usado apenas uma única vez, por que não fazer todos os cálculos em uma linha só e agrupar todas as instruções no procedimento de evento Change da barra de deslocamento? O código do programa resultante deve parecer-se com o mostrado a seguir:

Sub VscTermômetro_Change ()

Dim TempC As Integer

TempC = CInt(VscTermômetro.Value)

TxtGrausC.Text = Str$(TempC)

TxtGrausF.Text = Str$(Clnt(TempC * 9 / 5 + 32))

End Sub

De fato, esse programa é perfeitamente aceitável, e trabalha tão bem quanto a primeira versão. Porém, o programa original de Conversão de Temperatura é melhor pelos seguintes motivos:

Ele substitui fórmulas por nomes de funções no programa principal.

Nomes adicionam clareza e ajudam a explicar o que está acontecendo no programa.

Ele contém rotinas genéricas que podem ser usadas novamente. Será muito simples copiar a função CParaF para outro programa.

Seus procedimentos são partes que podem ser manipuladas com facilidade, se você decidir modificar o programa.

Como uma ilustração, considere uma melhoria do programa. Na versão atual, é preciso usar uma barra de deslocamento para configurar uma certa temperatura. Porém, poderia ser de grande ajuda permitir ao usuário introduzir diretamente o valor da temperatura e então levar o programa a fazer a conversão. Usando os blocos de construção que você criou, será relativamente simples fazer isso. Caso você tivesse escrito o programa como uma peça única, esse tipo de modificação poderia requerer duplicação ou até mesmo reescrever o código.

Page 159: Iniciando No Visual Basic

Generalizando

As melhores ferramentas são as que podem ser usadas em mais de um serviço. Com freqüência, você pode facilmente converter poucas linhas de um código especifico, proveitoso apenas num certo contexto, em uma rotina genérica. Considere o código que você escreveu no Capitulo 6 para pesquisar um determinado nome de doninha; a versão completa é mostrada na Figura 7.9. A Figura 7.10 apresenta uma versão que usa um procedimento genérico derivado do código original. Essa segunda versão oferece uma rotina que encontrará qualquer doninha pelo nome, podendo ser útil várias vezes no programa.

Figura 7.9 Código do programa que pesquisa uma doninha pelo nome.

 

Figura 7.10 Código do programa contendo um procedimento genérico que pode pesquisar qualquer doninha.

Reciclando Código

Hoje você está escrevendo programas para acompanhar doninhas. Amanhã poderá tratar-se de micos-leões. E quando você estiver escrevendo seus programas para micos, será muito prático poder dizer: "Ei, algumas semanas atrás, eu escrevi alguma coisa semelhante a isso". Se você escreve rotinas genéricas, é possível simplesmente recuperar o código de um programa velho e usá-lo no novo programa. Esse código já foi depurado, há menor quantidade de trabalho a realizar e seu projeto será completado mais rapidamente. O que mais você poderia desejar?

Ainda que seja ótimo reutilizar um código desenvolvido por você mesmo, normalmente é antiético (e com freqüência ilegal) copiar diretamente um código escrito por outra pessoa. No entanto, você está liberado para copiar o código dos programas de exemplo que acompanham o Visual Basic; a Microsoft garante a permissão para cópia dos códigos.

Como Trabalham os Parâmetros

Até agora, você usou parâmetros apenas para passar argumentos para os procedimentos. Porém, os parâmetros são muito mais flexíveis do que isso. Vamos dar uma olhada nos dois mecanismos

Page 160: Iniciando No Visual Basic

que se encontram disponíveis no Visual Basic para passagem de argumentos.

Passagem por Referência

Quando os parâmetros foram introduzidos pela primeira vez, eu os descrevi como se fossem variáveis locais. Na verdade, nem sempre é esse o caso. Considere o subprocedimento Increment que adiciona 1 ao valor do parâmetro, X:

Sub Increment (X As Integer)

X = X + 1

End Sub

Caso X seja uma variável local, esse procedimento será inútil. O valor do parâmetro da rotina chamadora seria assinalado a X, e o procedimento incrementaria esse valor e em seguida terminaria sua execução destruindo efetivamente as variáveis locais. Na realidade, X é uma referência ao valor original da rotina chamadora, e qualquer modificação em X altera o valor original. Se o código mostrado a seguir chamasse o procedimento Increment, seria impresso o valor 4:

Dim A As Integer

A = 3

Increment A

Print A

Uma vez que o parâmetro X não passa de uma referência ao valor de uma variável, não será alocada memória no subprocedimento Increment para armazenar esse valor. O Visual Basic apenas armazena a informação de que X é uma referência. O uso de referência permite ao Visual Basic operar mais eficientemente. Essa eficiência não é muito representativa quando se trata de variáveis inteiras. No entanto, considere o procedimento DeLado, que imprime seu parâmetro string entre parênteses:

Sub DeLado (Str As String)

Print "("

Print Str

Page 161: Iniciando No Visual Basic

Print ")"

End Sub

Se os parâmetros fossem realmente variáveis locais, o Visual Basic teria de alocar espaço para cada string passada para o procedimento, e copiar a string a cada chamada. Como as strings podem conter centenas de caracteres, seria muito mais simples criar uma referência à string original.

Passagem por Valor

Você também pode fazer com que os parâmetros trabalhem de outra forma - isto é, como variáveis locais. Se você iniciar a declaração do parâmetro com a palavra-chave ByVal, o Visual Basic alocará memória local para o parâmetro e copiará o valor do argumento correspondente para o parâmetro. Eis um exemplo desse tipo de declaração:

Sub Increment (ByVal X As Integer)

X = X + 1

End Sub

A passagem por referência geralmente é mais eficiente, porém a passagem por valor dá origem a variáveis locais que algumas vezes são necessárias nos seus programas. Por exemplo, vejamos a função que calcula X elevado à potência Y, isto é, X ^ Y. Esse cálculo usa multiplicações repetidas (por exemplo, X ^ 3 é igual a X . X . X). Por questões de simplicidade, essa função ignorará valores negativos para o expoente. O parâmetro Y especifica a quantidade de multiplicações necessárias. O valor de Y é decrementado após cada multiplicação, e o cálculo termina quando Y chega a 0.

Function Potência (X As Single, _

ByVal Y As Integer) As Single

Dim Result As Single

Result = 1

Do While Y > 0

Result = Result * X

Page 162: Iniciando No Visual Basic

Y=Y-1

Loop

Potência = Result

End Function

Uma vez que você deseja modificar Y na função, porém não quer que seja alterado o valor original da variável que foi passada, deve declarar Y com a palavra-chave ByVal. Examine o seguinte fragmento de código, que chama a função Potência:

'Aproximar E elevado a N, usando as séries de Taylor

Result = 1

For Aprox = 1 to 10

Result = Result + Potência(N, Aprox) / Factorial(Aprox)

Next Aprox

O programador espera que essa rotina faça o laço 10 vezes enquanto estiver fazendo o seu cálculo. Entretanto, se a função Potência que ela está chamando não usar a palavra-chave ByVal, essa rotina jamais sairá do laço, entrando em looping infinito. Após a função Potência ser chamada pela primeira vez, Aprox seria zerada (pois a variável local Y iria tornar-se uma referência a Aprox). A função Factorial seria chamada com o valor errado e então a instrução For incrementaria Aprox e iniciaria o laço novamente. Como Potência continua a zerar a variável Aprox, o laço For jamais terminaria.

Uma boa regra prática é que qualquer declaração de parâmetro para o tipo Integer, Long ou Single deveria ser uma declaração ByVal (isto é, o parâmetro deveria ser passado por valor), a menos que a rotina chamadora espere que o procedimento modifique o valor que está sendo passado. Por outro lado, strings e matrizes, por questões de eficiência, deverão ser passadas por referência. Controles e tipos de dados definidos pelo usuário (tal como DoninhaTFB) podem ser passados apenas por referência.

Para outros tipos de dados como double, currency e variant, a decisão não é tão simples. A boa prática de programação sugere que você passe esses parâmetros por valor, pois dessa forma estará menos

Page 163: Iniciando No Visual Basic

sujeito a usar uma variável parâmetro incorretamente. Entretanto, é mais eficiente passar esses parâmetros por referência.

Meu conselho é considerar em primeiro lugar os bons princípios de programação. Passar inicialmente todas as variáveis (exceto strings, matrizes e tipos definidos pelo usuário) por valor. Após completar a construção de seu programa e depois de testá-lo, você poderá investigar como melhorar o seu desempenho. Então, se o seu programa passar a operar incorretamente, após a remoção de algumas palavras-chave ByVal, você saberá onde olhar para encontrar os problemas.

Passagem de Parâmetros de Matriz

Você pode declarar um parâmetro de matriz como faz com qualquer outro parâmetro, omitindo da declaração a dimensão da matriz. Por exemplo, esta função calcula a média dos elementos de qualquer matriz de valores com dupla precisão.

Function Média (DMatriz( ) Double, _ByVal Dcont As Integer) As Double

Dim Total As Double, Ix As Integer

Total = 0

For lx = 0 To Dcont - 1

Total = Total + DMatriz(lx)

Next Ix

If Dcont = 0 Then

Média = 0

Else

Média = Total / Dcont

End If

End Function

O parâmetro DMatriz é declarado como uma matriz do tipo Double, porém a sua dimensão não é declarada. Esse código é um outro

Page 164: Iniciando No Visual Basic

exemplo de uma solução generalizada. Como a dimensão não é declarada, essa mesma função pode ser chamada com argumentos que sejam matrizes de qualquer dimensão. (Basta que os elementos sejam do tipo Double.)

Para passar uma matriz como argumento para um procedimento, use apenas o nome da variável matriz seguido de um par de parênteses vazio. Este fragmento de código mostra como o procedimento Média pode ser usado:

Dim MeusDados(100) As Double, ltensLidos As Integer

ItensLidos = CargaDados(MeusDados( ), 100)

Print "A média dos valores é : " & _

Média(MeusDados( ), ltensLidos)

MeusDados é declarado como uma matriz com dimensão 100. O procedimento CargaDados (não mostrado aqui) é chamado, sendo passadas como parâmetros a matriz MeusDados e a dimensão máxima da matriz.

Provavelmente, a rotina CargaDados preenche o maior número de elementos da matriz possível, retornando como valor a quantidade real de itens preenchidos. A seguir, o programa imprime a média. A chamada à Média retorna a matriz e a quantidade de elementos que foram preenchidos por CargaDados.

Naturalmente, quando necessário, você pode passar elementos individuais de matrizes. Basta indexar a matriz para indicar o elemento a ser passado, como nesta linha de código:

Print "A raiz quadrada do item 3 é " & Sqr(MeusDados(3))

Você pode modificar o aplicativo Banco do Capitulo 6 para usar a função

Média, como mostrado na Figura 7.11. Cada vez que você der um clique no botão Média, o programa redimensionará a matriz dinâmica ListaValor para acomodar a quantidade de itens na caixa de lista. Como a caixa de lista contém uma matriz de strings; em vez de números, cada elemento deve ser convertido à medida que for copiado para ListaValor. Então, o programa passa a matriz como argumento para a função Média.

Page 165: Iniciando No Visual Basic

Figura 7.11 Uma modificação no aplicativo Banco.

Esse programa modificado é um pouco mais longo do que o aplicativo original. Porém, você criou uma nova ferramenta - a função Média - que pode ser usada em vários lugares. Por exemplo, para ampliar o programa Banco para trabalhar com mais de uma conta, você pode chamar a função Média para cada conta, em vez de escrever um laço separado para cada uma. Se você tiver de escrever um programa que calcule a média pluviométrica, pode carregar o programa Banco, copiar a função Média e colocá-la no novo programa.

Alocação Local

Em função da discussão sobre escopo feita no Capitulo 3, você já está familiarizado com variáveis locais. Agora que você está trabalhando com parâmetros similares às variáveis locais, será útil verificar a maneira pela qual o Visual Basic gerencia a memória usada por variáveis locais.

Quando você inicia um programa, o Visual Basic sabe quantas variáveis globais existem e aloca memória para elas. No entanto, ele não sabe quantas variáveis locais existem ou quando cada procedimento do programa será chamado. Variáveis locais e parâmetros são criados quando o procedimento que os contém é chamado, e são destruídos quando o procedimento acaba. Se um procedimento for chamado novamente, as variáveis são recriadas. Esse processo não apenas retarda a alocação de memória até que ela seja necessária, mas permite que a memória seja reutilizada por variáveis que pertençam a procedimentos diferentes. Os computadores modernos executam essa alocação temporária e a liberação muito eficientemente.

No entanto, algumas vezes você pode querer que o valor armazenado em uma variável local não seja perdido quando o procedimento que a contém for encerrado. Você poderia declarar uma variável em nível de módulo ou pública, mas essa solução não seria ideal se a variável viesse a ser usada apenas em um procedimento.

O Visual Basic oferece a palavra-chave Static para tratar dessa questão. Se você usa Static em vez de Dim dentro de um procedimento, as variáveis declaradas dessa forma terão escopo local, visível apenas dentro daquele procedimento; no entanto, serão permanentes, como se fossem declaradas em nível de módulo. O Visual Basic inicializa todas as variáveis Static como 0, tornando-as úteis para situações como a que se segue:

Page 166: Iniciando No Visual Basic

Sub Command1_Click ()

Static Contador As Integer

Contador = Contador + 1

MsgBox "Este botão já foi pressionado" & _

Str$(Contador) & "vezes."

End Sub

Abra um novo form, inclua um botão de comando simples com o procedimento acima e tente executar o programa. Então, mude a palavra-chave Static para Dim para verificar que, no caso de uma variável puramente local, o programa não funciona.

Objetos Do Visual Basic como Parâmetros

Os procedimentos que você escreveu até agora têm passado apenas valores numéricos, matrizes e strings como parâmetros. O Visual Basic também permite-lhe passar controles e forms. A sintaxe é similar: basta usar a palavra-chave Control ou Form, em vez de String, Integer, e assim por diante, na declaração do procedimento.

Essa característica lhe dá a habilidade de escrever código totalmente genérico. Por exemplo, suponha que você esteja escrevendo um aplicativo com uma certa quantidade de botões na tela. Em vários pontos do aplicativo, você deseja dar atenção especial a um botão particular, colocando a característica itálica em seu título e configurando a sua cor de fundo para vermelho. O seguinte subprocedimento faz isso:

Sub Atenção (Botão As Control)

Botão.FontItalic = True

Botão.BackColor = vbRed

End Sub

Você passa um objeto como um parâmetro usando o seu nome. Você poderia passar para esse subprocedimento um botão chamado btnNext, com a instrução Atenção btnNext.

Page 167: Iniciando No Visual Basic

Similarmente, você pode declarar um parâmetro como sendo um form. Você pode configurar ou examinar as propriedades do form e chamar os seus métodos. Pode passar o form pelo nome ou usar a variável interna Me (eu), que é o form ativo no momento.

O Aplicativo Evasivo

Vamos desenvolver um aplicativo, chamado Evasivo que faz uma brincadeira com o usuário. Ele exibirá uma mensagem de erro, como se tivesse ocorrido uma falha durante sua inicialização. O usuário verá uma caixa de diálogo com dois botões de comando, Cancel e Retry. Entretanto, o que acontece quando o usuário dá um clique em um desses botões não é habitual. O botão caminhará para um ponto qualquer do form, e o usuário jamais será capaz de cancelar a execução do programa dando um clique num dos botões. Esse aplicativo ilustra como você pode passar objetos como parâmetros e como usar o método Move - um método que pode ser implementado para a maioria dos controles do Visual Basic.

Cada botão de comando deverá ter o mesmo comportamento. De certa forma, você pode assegurar isso, chamando o mesmo procedimento para cada um dos botões. No entanto, uma das ações do procedimento será mover o botão para uma nova posição. Essa ação requer uma chamada ao método Move dos botões, exigindo que você passe o botão como um parâmetro.

Crie um novo projeto e arranje dois campos de rótulo e dois botões de comando no form como mostrado na Figura 7.12. A Figura 7.13 lista as configurações de propriedades que serão necessárias.

Figura 7.12 O projeto inicial do form para o aplicativo Evasivo.

Figura 7.13 Configuração de propriedades para o aplicativo Evasivo.

 

 A Figura 7.14 contém o código do programa para o aplicativo Evasivo, e a

Figura 7.15 mostra como o aplicativo ficará quando o usuário processá-lo.

 

Figura 7.14 Código de programa para o aplicativo Evasivo.

Page 168: Iniciando No Visual Basic

Figura 7.15 Processando o aplicativo Evasivo.

O procedimento Salto usado nesse aplicativo pode ajustar a posição não apenas dos dois botões de comando, mas de quase qualquer tipo de controle que lhe seja passado como parâmetro, pois a maioria dos controles possui o método Move. Entretanto, algumas vezes você pode querer executar tipos de processamento especiais, que sejam específicos a certos tipos de objetos. O Visual Basic oferece a instrução If TypeOf para determinar o tipo de controle do parâmetro. Ela funciona da mesma maneira que a instrução If convencional; apenas a primeira linha de sua sintaxe é diferente.

If TypeOf objeto Is TipoObjeto Then

Se você quisesse que o procedimento Salto distinguisse botões de opção de outros tipos de controles, a primeira linha da instrução If TypeOf deveria ser

semelhante a isto:

If TypeOf CtI Is OptionButton Then

Procedimentos de Eventos Avançados

Esta seção examina procedimentos de eventos do Visual Basic mais complexos do que os procedimentos Click e DblClick. Essas técnicas permitem-lhe construir aplicativos com tratamento mais sofisticado para teclado e mouse, e implementar uma técnica gráfica chamada arrastar e soltar (drag and drop).

Eventos de Mouse

Nossos exemplos anteriores levaram em consideração o mouse apenas quando usado para dar um clique em um objeto. O máximo que você fez foi escrever um código para os procedimentos de evento Click ou DblClick. No entanto, certos tipos de aplicativos requerem que as atividades do mouse sejam acompanhadas mais de perto.

Um programa de desenho ou pintura, por exemplo, precisa saber a posição do mouse quando você está arrastando um gráfico ou criando uma nova imagem. Um jogo pode usar a posição do mouse para controlar alguns de seus aspectos. Porém, o Visual Basic não contém um objeto mouse. Em vez disso, o evento MouseMove é disparado quando a posição do mouse se modifica. Com freqüência, os eventos de mouse são associados com forms e caixas de imagem, porém eles

Page 169: Iniciando No Visual Basic

podem ser usados também com os outros objetos. Com propósitos de ilustração esta seção irá concentrar-se apenas nos forms.

Cada form possui estes três procedimentos padrões:

Figura 7.16

O Visual Basic chama esses procedimentos quando o usuário interage com

o mouse. O evento MouseDown ocorre sempre que um botão do mouse é pressionado. O evento MouseUp é sinalizado quando o botão do mouse (que se encontrava pressionado) é liberado. O evento MouseMove ocorre quando a posição do mouse é alterada. A Figura 7.17 descreve os parâmetros que são passados para esses procedimentos de eventos.

 

Figura 7.17 Parâmetros dos procedimentos de eventos do mouse.

 

A melhor forma de ilustrar estes eventos é a criação de um aplicativo de exemplo. Criaremos aqui o aplicativo Desenho de Linha. Esse aplicativo usa o método Line, um método gráfico para desenho de um form. (Discutiremos o método Line em maiores detalhes no Capítulo 11.)

 

Figura 7.18 Código de programa para o aplicativo Desenho de Linha.

 

Quando você processar o aplicativo, a variável Desenhando será inicialmente configurada como False. Porém, quando o botão esquerdo do mouse for pressionado, a variável será configurada para True. Quando o botão for liberado, Desenhando passará a ser False novamente. À medida que você mover o mouse, mantendo o botão pressionado, o programa traçará a linha a partir da última posição conhecida (CurrentX, CurrentY), até a posição atual do mouse. Se você mantiver a tecla Shift pressionada enquanto traça uma linha, a sua cor será alterada para vermelho até você soltar a tecla Shift.

Page 170: Iniciando No Visual Basic

Nota: Mouses com um único botão têm esse botão definido como left-button (botão esquerdo). Se o seu mouse tiver dois botões e você alterou o Painel de Controle do Windows para inverter os botões esquerdo e direito do mouse, o Visual Basic passará o valor vbLeftButton quando for pressionado o botão da direita e vice-versa.

Eventos de Teclado

O Capitulo 6 introduziu o evento KeyPress, que é disparado para certos objetos quando o usuário está digitando. O Visual Basic permite um grau de controle ainda mais refinado com os eventos KeyUp e KeyDown, que são disparados quando o usuário pressiona e solta uma tecla. Apenas aplicativos muito específicos requererão o uso desses eventos, entretanto a ajuda do Visual Basic contém informações completas a esse respeito.

Os forms possuem outra característica muito útil relacionada ao teclado. Normalmente, o pressionamento de teclas é enviado diretamente para o objeto (por exemplo, uma caixa de texto) que está ativo no momento. Entretanto, configurando a propriedade KeyPreview de um form para True, você fará com que os procedimentos de eventos KeyPress, KeyDown e KeyUp do form sejam disparados em primeiro lugar. Esses procedimentos podem filtrar a informação a ser passada para os procedimentos de eventos KeyPress, KeyDown e KeyUp dos objetos.

Por exemplo, para registrar cada tecla pressionada pelo usuário, você poderia definir a seguinte função (suponha que SalvarTudo seja declarada como uma variável string em nível do form):

Sub Form_KeyPress (KeyAscii As Integer)

SalvarTudo = SalvarTudo & Chr$(KeyAscii)

End Sub

Caso a propriedade KeyPreview do Form seja configurada para True e o procedimento de tratamento de tecla em nível do form vier a modificar a variável KeyAscii, o procedimento de evento KeyPress do objeto atualmente ativo receberá a tecla modificada. Se o procedimento em nível do form configurar KeyAscii para 0, o procedimento KeyPress do objeto não será chamado.

Arrastar e Soltar

Page 171: Iniciando No Visual Basic

O Visual Basic fornece também um suporte especial para outra forma de interação com usuários; chamado arrastar e soltar. As palavras arrastar e soltar referem-se ao uso do mouse para deslocar um objeto exibido para outro lugar. Você deve ter visto esse processo no Explorer, que lhe permite mover arquivos de uma pasta para outra, arrastando-se os ícones dos arquivos.

Você permite que um objeto do Visual Basic (normalmente uma caixa de imagem ou controle de imagem) seja arrastado configurando a sua propriedade DragMode para 1. Quando DragMode é configurada para 1, o controle não recebe mais o evento Click ou MouseDown. Em vez disso, o objeto se movimenta quando o usuário dá um clique nele, começando a arrastá-lo. O item que está sendo arrastado é chamado de objeto-fonte, e o item que recebe o evento DragDrop é chamado de destino. Quando o usuário solta o objeto-fonte (soltando o botão do mouse), o Visual Basic envia o evento DragDrop para o objeto de destino. Adicionalmente, eventos DragOver são enviados para quaisquer objetos sobre os quais passar o objeto-fonte.

O mecanismo arrastar e soltar permite-lhe projetar uma interação simples e prática com os usuários, na qual podem ser executadas várias tarefas, sem o uso de comandos, menus ou botões. Esse método é muito intuitivo em diversas situações e freqüentemente mais veloz do que outros métodos.

Para demonstrar o mecanismo arrastar e soltar, vamos escrever um aplicativo chamado Correio Eletrônico, que simulará o ambiente de trabalho para a troca eletrônica de mensagens. Ele permitirá que você crie novas mensagens e arraste-as para uma caixa postal, a partir da qual elas poderão ser distribuídas para a rede. (Será apresentado aqui apenas o mecanismo arrastar e soltar. O código completo para um sistema de mensagens eletrônicas ocuparia o livro inteiro.)

Inicie pela criação de um novo projeto. Inclua dois botões de comando, sete pequenos controles de imagem, conforme mostrado na Figura 7.19. Os três controles de imagem na parte inferior do form armazenarão cópias mestras de ícones, a exemplo do que foi feito com alguns controles de imagens no aplicativo Caça-níqueis do Capítulo 6. Após inicializar esses controles, você pode redimensionar o form para eliminá-los da área de visão. Os ícones usados neste aplicativo podem ser encontrados no diretório de ícones do CD deste pacote.

Configure as propriedades dos três controles de imagens inferiores (Image5, Image6 e Image7), como listado na Figura 7.20. A

Page 172: Iniciando No Visual Basic

propriedade Tag é ignorada pelo Visual Basic; você pode usá-la para armazenar qualquer texto identificador que desejar. Esse aplicativo usa a propriedade Tag para distinguir ícones de cartas dos outros tipos de ícones.

Figura 7.19 O projeto inicial do form para o aplicativo Correio Eletrônico

Figura 7.20 Configuração de propriedades para os três controles de imagens inferiores no aplicativo Correio Eletrônico.

Configurando-se a propriedade DragMode do objeto Image7 (ícone de carta) para 1, possibilita-se ao usuário arrastar as cartas ao longo da janela. A configuração da propriedade Index para 0 transforma o ícone de carta em uma matriz de controles, contendo até agora apenas um elemento. (Dentro de instantes você verá como o código do programa usará essa matriz.) A Figura 7.21 mostra-lhe como a linha inferior de controle de imagens deve ficar após essa configuração de propriedades.

 

Figura 7.21 Os três ícones inferiores usados no aplicativo Correio Eletrônico.

 

Agora, configure as propriedades dos outros objetos, conforme indicado pela Figura 7.22. Após modificar as dimensões do form para que as três imagens inferiores não apareçam, o seu form deverá parecer-se com o mostrado na Figura 7.23. Os controles de imagens que aparecem na parte superior da janela servirão como caixas postais, para as quais os ícones de cartas podem ser arrastados. Os ícones que você vê sobre a "mesa de trabalho" (a caneta, o telefone e o clipe) não podem ser distribuídos pelo correio. A caixa postal exibirá o ícone de caixa vazia (aquele de Image5) quando estiver vazia, e o ícone de caixa cheia (o de lmage6) quando o usuário arrastar uma carta para a caixa postal. Os botões de comando permitirão ao usuário criar novas cartas (com o ícone de carta) e limpar a caixa postal.

Figura 7.22 Configuração de propriedades restantes usadas no aplicativo Correio Eletrônico.

Figura 7.23 O projeto final do form para o aplicativo Correio Eletrônico.

Page 173: Iniciando No Visual Basic

O código para esse aplicativo requer a seguinte declaração:

Dim ProxCarta As Integer

Dois procedimentos são necessários em nível do form. O procedimento Form_Load inicializa o ícone da caixa postal e a variável ProxCarta; o procedimento Form_DragDrop move o controle para o ponto que o usuário indicar:

Sub Form_Load ( )

ImgCorreio.Picture = ImgCaixaVazia.Picture

ProxCarta = 1

End Sub

Sub Form_DragDrop (Source As Control, X As Single, Y As Single)

Source.Move X, Y

End Sub

A janela básica mostra apenas três ícones. Você deve escrever a codificação para o botão MsgNova, para permitir ao usuário criar novos objetos-cartas.

Sub btnNova_Click ( )

Load lmgCarta(ProxCarta)

lmgCarta(ProxCarta).Left = btnNova.Left - 2000 + ProxCarta * 100

lmgCarta(ProxCarta).Top = ScaleHeight - 500

lmgCarta(ProxCarta).Visible = True

ProxCarta = ProxCarta + 1

End Sub

O primeiro programa chama o procedimento Load. Como lmgCarta é uma matriz de controles, Load cria um novo controle, dando-lhe o índice especificado por ProxCarta. Após o Visual Basic criar o novo membro da matriz de controles (ImgCarta), esse novo membro recebe

Page 174: Iniciando No Visual Basic

uma posição na janela e torna-se visível. Então, a variável ProxCarta é incrementada de forma que o próximo evento Click crie uma nova carta.

O botão Limpar Caixa simplesmente reconfigura o ícone (a propriedade Picture) da caixa postal para o valor default:

Sub btnLimp_Click ( )

lmgCorreio.Picture = ImgCaixaVazia.Picture

End Sub

A caixa postal requer o seu próprio procedimento arrastar e soltar. Quando um controle é arrastado para a caixa, o programa verifica a propriedade Tag do objeto-fonte. Caso não seja uma carta, o procedimento provoca o seu encerramento, não permitindo que o objeto seja colocado sobre a caixa postal. Do contrário, o procedimento Unload remove o ícone da carta da tela e faz com que a propriedade Picture da caixa postal seja configurada para o ícone de ImgCaixaCheia.

Sub ImgCorreio_DragDrop (Source As Control, X As Single, Y As Single)

If Source.Tag <> "Carta" Then

Beep

Exit Sub

End If

Unload Source

lmgCorreio.Picture = lmgCaixaCheia.Picture

End Sub

Processe esse aplicativo e tente dar cliques no botão MsgNova algumas vezes, para criar novas cartas. Excluindo a caixa postal, todas as imagens que estão na janela do aplicativo podem ser arrastadas. Arrastar uma carta para a caixa postal modifica o ícone da caixa postal, e dar um clique no botão Limpar Caixa restaura o ícone da caixa postal. Note que o programa não permitirá que você arraste o telefone, a caneta ou o clipe para a caixa postal.

Page 175: Iniciando No Visual Basic

O programa usa a variável ProxCarta para especificar um valor continuamente crescente para os elementos subseqüentes da matriz de controles ImgCarta.

Page 176: Iniciando No Visual Basic

O Poder das Classes no Visual BasicA partir da versão 4 do Visual Basic, o programador passou a poder criar seus próprios objetos. Um objeto é uma instância de uma classe assim como Siegmund é uma instância do tipo DoninhaTFB. Uma classe é um tipo de dado que o usuário cria contendo tudo o que já vimos sobre tipos de dados definidos pelo usuário e muito mais. Além de variáveis uma classe tem um comportamento. Isto quer dizer que dentro de uma classe você não apenas cria variáveis para armazenar dados, mas também pode criar procedimentos que serão executados quando chamados. Estes procedimentos são chamados métodos da classe. Um método pode ser público ou não. Se for público, poderá ser chamado de qualquer ponto do programa. Caso seja privativo da classe, somente o código de um outro método da própria classe poderá comandar a sua execução.

Esta mesma distinção entre público e privado se aplica às variáveis contidas na classe. Essas variáveis são chamadas variáveis membros da classe. Uma variável membro também pode ser privativa à classe e somente poder ser acessada por métodos da classe, ou ser pública e ter seu conteúdo livremente acessado de qualquer ponto do programa. A esta característica de proteção que a classe pode dar ao seu conteúdo se dá o nome de encapsulamento. O encapsulamento, porém, não é uma barreira definitiva para o acesso ao conteúdo das variáveis privativas da classe. Isto porque uma variável privada pode ser acessada indiretamente pelo mundo exterior à classe. O modo como isto é feito é usando um método público da classe que nos permita ler ou alterar o valor da variável. Agora você deve estar se perguntando: mas se é para tornar uma variável passível de ser alterada por partes do programa externas à classe, porque então não torná-la pública de um vez? A resposta para isto é que muitas vezes você quer ter controle sobre a faixa dos valores que serão atribuídos a uma variável e também o tipo de dado que se pode atribuir a ela. No método que se usa para acessar a variável, esta verificação pode ser feita antes que algo de errado seja atribuído ela.

Ao procedimento que nos dá acesso à variável damos o nome de propriedade. Externamente à classe uma propriedade é vista como um único nome, mas que internamente à classe representa dois ou três procedimentos diferentes. Dependendo do papel que o nome da propriedade desempenha numa expressão, um dos procedimentos é chamado. Se a propriedade está sendo referida para se obter o seu valor, é chamado o procedimento Get_NomeDaPropriedade. Se a propriedade está sendo referida para se atribuir um valor a ela, é

Page 177: Iniciando No Visual Basic

chamado o procedimento Let_NomeDaPropriedade (para tipos de dados comuns) ou Set_NomeDaPropriedade (para objetos).

Outra vantagem que as classes oferecem é chamada de polimorfismo. Por polimorfismo entende-se a possibilidade de atribuir-se um mesmo nome a diferentes procedimentos. Uma classe pode ter um procedimento (um método) com o nome Calcular, que signifique fazer o cálculo de uma área. Enquanto isso uma outra classe pode ter um método com o mesmo nome para calcular o total de uma lista de compras.

Vejamos agora com mais detalhamento como trabalhar com classes.

Criando suas Próprias Classes e Objetos

Além das classes e objetos que o Visual Basic e outras aplicações lhe oferecem, você pode criar suas próprias classes e usá-las para criar objetos em tempo de execução dos seus programas.

Você inicia a criação de uma classe pela adição de um módulo de classe ao seu projeto. Abrindo o menu Project e selecionando Add Class Module, uma caixa de diálogo surgirá dando lhe três opções para a criação do módulo de classe. Uma, Class Module,  lhe permite adicionar um módulo de classe vazio para ser completado por você outra opção, Vb Class Builder, lhe dá acesso a um assistente de criação de classes que lhe poupa parte do trabalho de codificação da nova classe; a terceira opção refere-se à criação de Add-Ins, um tema complexo que vai além do propósito desta discussão. A segunda opção é sem dúvida a mais prática, mas antes que você a utilize é interessante conhecer passo-a-passo os detalhes da criação de uma classe seguindo o caminho mais trabalhoso. Vamos supor aqui que você tenha iniciado o procedimento de criação de uma classe e feito a opção por criar um módulo de classe vazio. Nos tópicos seguintes expomos o que constitui uma classe e o que fazer para criar suas classes.

Como é Constituída uma Classe?

Uma classe pode possuir propriedades, métodos e eventos. Em geral, propriedades representam informações sobre um objeto, enquanto métodos representam ações que um objeto pode realizar. Em outras palavras, as propriedades descrevem o objeto e os métodos são o seu comportamento. Quanto aos eventos, estes são procedimentos que um objeto chama dentro de um outro objeto que o contém.

Page 178: Iniciando No Visual Basic

Propriedades

O modo mais simples de adicionar uma propriedade a uma classe é criando uma variável dentro da classe e declarando-a como pública. Exemplo: Public variável as string. Desta forma poderemos atribuir valores à variável em qualquer parte do código da aplicação. Mas este não é o modo mais correto e usual de se criar uma propriedade. Costumamos querer que as propriedades de nossos objetos sejam acessadas de modo controlado pelo próprio objeto. Isto é, queremos poder definir, por exemplo, que uma propriedade é somente para leitura ou ter a garantia de que os valores atribuídos a ela se situam dentro de uma determinada faixa. A forma que usamos para conseguir isto e a criação dos procedimentos de propriedade. Procedimentos de propriedade são procedimentos usados para se ter acesso ao valor de uma variável interna à classe usada para guardar o valor de uma propriedade. Os procedimentos de propriedade se dividem em dois tipos: procedimentos de leitura do valor da propriedade e procedimentos de atribuição de valor à propriedade. Nos procedimentos de leitura inserimos o código que retorna o valor da variável usada para guardar o valor da propriedade no interior da classe. Nos procedimentos de atribuição de valor inserimos o código responsável pela atribuição de valor e - se for o caso - validação do valor que se está tentando atribuir à propriedade. Caso queiramos que uma propriedade seja apenas de leitura, não criaremos procedimentos de atribuição de valores a ela. Qualquer tentativa de atribuir valor a uma propriedade que não tenha uma procedimento para atribuição gerará uma erro.

A criação dos procedimentos de propriedades seguem determinadas regras. Os procedimentos usados para retornar o valor da propriedade têm o seu nome composto pela palavra Getseguida de um caracter de sublinhado ( _ ) e pelo nome da propriedade. Estes procedimentos retornam um valor do tipo de dados da variável que armazena o valor da propriedade. Os procedimentos de atribuição têm seus nomes formados pela palavra Let ou Set seguida de um caractere de sublinhado ( _ ) e do nome da propriedade. Estes procedimentos recebem como argumento o novo valor que se quer atribuir à propriedade. A seguir exibimos a sintaxe de criação desses procedimentos.

Public | Private Get_NomePropriedade () As Tipo

Código usado para retornar o valor da propriedade.

Ex.: NomePropriedade = mvarDataCriação, onde mvarDataCriação

Page 179: Iniciando No Visual Basic

é a variável que armazena o valor da propriedade no interior da classe.

Isto faz com que o procedimento retorne este valor.

End Property

Public | Private Let_NomePropriedade ( novovalor As Tipo )

Código usado para armazenar o valor da propriedade.

Ex.: mvarDataCriação = novovalor, onde mvarDataCriação

é a variável que armazena o valor da propriedade no interior da classe e

novovalor é o valor que se quer atribuir à propriedade recebido como

argumento pelo procedimento de atribuição.

End Property

Public | Private Set_NomePropriedade ( novovalor As Tipo )

Código usado para armazenar o valor da propriedade.

Ex.: Set mvarDataCriação = novovalor, onde mvarDataCriação

é a variável que armazena o valor da propriedade no interior da classe e

novovalor é o valor que se quer atribuir à propriedade.

End Property

Você pode estar se perguntando sobre o porquê de termos dois tipos diferentes de procedimentos de atribuição de valores às propriedades, uns com nome iniciando por Let e outro por Set. A razão para isto é que ocorre às vezes de uma propriedade armazenar valores que são referências a objetos. Nestes casos o procedimento usado para atribuir valores à propriedade tem seu nome iniciado por Set e no seu código devemos usar a instrução Set para atribuir o valor à variável da propriedade. Variáveis usadas para armazenar referências a objetos não têm seus valores atribuídos pelo uso simples do sinal de atribuição ( = ), mas carecem também que se use a instrução Set antes do seu nome. Exemplo: Set varForm = Form1; esta instrução armazena uma referência ao objeto Form1 na variável varForm.

Há casos, no entanto, em que a propriedade pode armazenar tanto referências a objetos como a tipos de dados comuns. Caso a variável interna tenha sido declarada como sendo do tipo Variant, poderemos atribuir qualquer tipo de dado à propriedade. Nestes casos nos

Page 180: Iniciando No Visual Basic

utilizamos da técnica de usar apenas o procedimento Let e declaramos o tipo de dado do seu argumento como Variant. Antes de fazermos a atribuição de valor à propriedade, verificamos o tipo do dado que está sendo passado e optamos pela forma correta de fazermos esta atribuição. Veja abaixo como isto é feito:

Public Let_NomePropriedade ( novovalor as Variant )

If IsObject(novovalor) Then ‘função IsObject retorna True se novovalor é objeto

Set varPropriedade = novovalor

Else

VarPropriedade = novovalor

End If

End Property

Até aqui vimos como criamos os procedimentos de propriedade dentro da classe, mas fora da classe estes procedimentos não são utilizados com os mesmos nomes que usamos para criá-los na classe. Para atribuirmos valor a uma propriedade ou termos como retorno o seu valor atual, utilizamos apenas o nome da propriedade. Baseado na papel que o nome da propriedade esteja desempenhando numa expressão é que o Visual Basic vai decidir qual procedimento da propriedade chamar. Se o nome da propriedade estiver à esquerda de um sinal de atribuição, o Visual Basic sabe que tem que chamar um procedimento usado para armazenar o valor da propriedade ( nome iniciado por Let_ ou Set_ ). Se o nome da propriedade estiver à direita de um operador de atribuição ou em qualquer outra situação em que se espera um valor de retorno, o Visual Basic chamará o procedimento da propriedade usado para retornar seu valor ( nome iniciado porGet_ ). Exemplo:

Data = Arquivo1.DataCriação

‘É chamado o procedimento Get_DataCriação, que retorna o valor da ‘propriedade DataCriação do objeto Arquivo1.

Arquivo1.DataCriação = Now

‘É chamado o procedimento Let_DataCriação para atribuir a data

‘retornada pela função Now à propriedade DataCriação do objeto Arquivo1.

Page 181: Iniciando No Visual Basic

Métodos

Os métodos nada mais são do que os procedimentos e funções públicos de uma classe. Para chamar um método de fora do código da classe, basta usar o nome do objeto seguido de um ponto e do nome do método. Exemplo: Form1.Show; esta instrução faz com que o método Show do objeto Form1 seja executado.

Os métodos de uma classe têm acesso às variáveis privadas da classe.

Eventos

Como já foi dito acima, eventos são procedimentos chamados por um objeto em um outro objeto que o contém como resposta a um acontecimento que lhe ocorre. Os eventos podem ser disparados pelo próprio objeto em alguma parte do seu código utilizando-se da instrução RaiseEvent. Pode-se também utilizar o artifício de criar um método só para disparar um evento dentro do objeto. Um método assim seria chamado de fora do objeto para disparar o evento no seu interior.

Para definir um evento dentro de uma classe não se cria um procedimento de evento dentro do módulo da classe. O que se faz é usar a instrução Event para atribuir um nome ao evento e definir sua lista de argumentos, ou seja, as informações que serão passadas ao procedimento de tratamento do evento. Este procedimento sim será codificado dentro do objeto que contenha o objeto disparador do evento caso se queira tratar o evento. Veja como é a sintaxe da instrução Event:

Public Event NomeEvento ( [ByVal] argumento As Tipo [, ...] )

Após ter sido definido o evento na classe, ele poderá ser tratado por um procedimento de evento dentro de um módulo que contenha uma declaração de variável do tipo da classe disparadora do evento, e que tenha sido declarada com a palavra-chave WithEvents. Vejamos um exemplo de como isto funciona.

Crie um novo projeto e adicione um módulo de classe. Selecione a propriedade Name do módulo de classe na janela de propriedades e atribua CMensagem como novo nome para a classe. No módulo da classe, adicione as seguintes linhas de código:

‘Definição do evento chamado Mensagem

Page 182: Iniciando No Visual Basic

Public Event Mensagem ( texto As String )

‘Método público para disparar o evento Mensagem de fora da classe

Public Sub DispararEvento ( argumento As String )

RaiseEvent Mensagem (argumento )

End Sub

Agora, entre na janela de código do formulário Form1. Adicione as seguintes linhas de código na seção de declarações gerais do módulo de Form1:

Private WithEvents Msg As CMensagem

Examine a relação de objetos que aparecem na caixa de objetos da janela de código. Verifique que além do objeto Form1, também aparece o objeto Msg. Se você selecioná-lo, verá na caixa de procedimentos o nome do evento Mensagem. Este é o resultado de termos acrescentado a palavra chave WithEvents na declaração da variável Msg. WithEvents é usada para informar que a variável será usada para armazenar uma referência a um objeto que possui eventos, e que queremos tratar estes eventos dentro do módulo. Assim como você está acostumado a ver a relação de todos os procedimentos de evento para os controles adicionados ao formulário, você vê agora os eventos para o objeto Msg na lista de procedimentos de evento. Do mesmo modo como escreve código para tratar os eventos dos controles, você pode fazê-lo para tratar o evento Mensagem do objeto Msg.

Dê um duplo clique sobre o evento Mensagem na lista para que apareça o seu procedimento. Agora escreva o seguinte código dentro do procedimento do evento:

MsgBox texto

No procedimento Form1_Load acrescente:

‘Cria uma nova instância da classe CMensagem e

‘armazena uma referência a ela em Msg.

Set Msg = New Cmensagem

‘Dispara o evento Mensagem em Msg

Page 183: Iniciando No Visual Basic

Msg.DispararEvento "Isto é uma mensagem!"

Pronto. Agora pressione F5 para executar.

Tão logo o formulário Form1 inicie a sua carga, você verá a mensagem "Isto é uma mensagem!" como resultado da chamada ao método DispararEvento que ativa o evento Mensagem no objeto Msg.

Numa outra situação, você poderia desejar que um objeto container de um objeto disparador de eventos fosse informado todas as vezes que uma determinada propriedade do objeto contido sofresse alteração. Seria o caso então de se criar um evento para isso e dispara-lo com RaiseEvent dentro do procedimento de atribuição de valor da propriedade.

Eventos Comuns a Todas as Classes

Além dos eventos que você define para suas classes, elas têm em comum com todas as demais dois eventos particularmente interessantes: initialize e terminate. Estes eventos são disparados quando da criação de um objeto da classe e quando da sua destruição respectivamente. O tratamento destes eventos, ao contrário dos eventos que você define, ocorre no interior do módulo da classe. Para ver o arcabouço destes procedimentos entre no módulo da classe CMensagem criada no exemplo acima e selecione Class na caixa de objetos da janela de código. Ao fazer esta seleção, examine a caixa de procedimentos e veja que os nomes dos eventos Initialize e Terminate estão relacionados. Caso queira executar algum código de inicialização ou de encerramento para os objetos da classe, é nos procedimentos de tratamento destes eventos que tal código deve ser adicionado.

Criando e Destruindo Objetos

Já vimos no exemplo da classe CMensagem o uso da palavra New para criar uma instância de um objeto da classe. Ali, o uso de New foi feito fora da declaração da variável porque não é permitido declarar uma variável com WithEvents e na mesma instrução de declaração utilizar a palavra New. Mas, na ausência de WithEvents, você pode declarar uma variável e ao mesmo tempo usar New para que, na primeira vez que a variável for usada no código, um objeto da classe da variável seja criado e a variável passe a conter uma referência a este objeto. Veja um exemplo:

Private Msg As New CMensagem ' Declaração da variável

Page 184: Iniciando No Visual Basic

Msg.DispararEvento "Já sou um objeto!"

 

No exemplo acima nenhuma mensagem seria produzida, porque nenhum procedimento de evento poderia tratar o evento disparado - já que a variável não foi declarada usando WithEvents -, mas ilustra a não necessidade de se usar a instrução Set Msg = New CMensagem para criar um objeto da classe quando se usa New já na declaração.

O processo de criação de objetos a partir das suas classes é mais simples do que o processo de destruição desses objetos. Um objeto só pode ser eliminado da memória quando não há mais nenhuma referência a este objeto em qualquer variável. Há duas formas de as variáveis deixarem de referenciar um objeto: uma é quando são destruídas por saírem do escopo do código que está sendo executado; outra é quando lhes é atribuído um novo valor. Os programadores costumam atribuir o valor Nothing a toda variável de objeto que não precise mais referenciar um objeto. Desta forma o objeto libera a memória tão logo deixe de ser necessário para a aplicação. Exemplo:

Set varObjeto = Nothing

Há uma observação, no entanto, a ser feita sobre isso no que diz respeito aos objetos criados com a palavra New na declaração da variável: tais objetos não deixam de existir quando se atribui Nothing às variáveis que os contêm. A explicação para isto vem do fato de que ao usar New numa declaração de variável, o compilador faz com que uma instancia da classe (um objeto) seja criado e atribuído à variável no caso de ela já não estar armazenando referência a um objeto. Quando você atribui Nothing à variável, está limpando-a de qualquer referência a um objeto, mas também está referenciando-a dentro do seu código. Isto produz uma nova instanciação de objeto e nova atribuição à variável. Evite, portanto, o uso da palavra New nas declarações de variáveis. Declare as variáveis de objeto de modo simples e depois atribua um valor de objeto usando Set variável = New ClasseDoObjeto em alguma parte do código.

Referências Circulares entre Objetos

Há um problema que pode passar desapercebido para os programadores iniciantes no uso de objetos que é o das referências

Page 185: Iniciando No Visual Basic

circulares. Referências circulares ocorrem quando um objeto tem uma variável membro usada para armazenar uma referência a outro objeto, e este outro objeto por sua vez contém uma variável que faz referência ao primeiro objeto. Nestes casos um objeto não pode ser destruído porque há uma referência a ele dentro do outro e vice-versa. A solução para isto é atribuir Nothing às variáveis membros de cada um para só então atribuir Nothing às variáveis externas aos objetos que guardam referências a eles.

Page 186: Iniciando No Visual Basic

Depuração e Tratamento de Erros no Visual Basic

Este capítulo se concentra nos enganos ou erros cometidos durante a codificação e o que fazer com eles. Independentemente da experiência que você tenha como programador, raramente os seus programas serão processados sem erros logo na primeira tentativa. E não importa o quão comportados sejam os usuários que trabalharão com os seus programas, eles tendem a encontrar ou provocar uma certa quantidade de erros durante a execução dos programas. Visualizaremos em primeiro lugar o processo de localização e remoção de bugs (erros) e então veremos os meios para tratar os erros de execução, à medida que ocorrem.

Bugs são aqueles insetos que infestam programas que você tem certeza de que estão perfeitos, apesar de não estarem produzindo os resultados corretos. Curiosamente, um dos primeiros bugs registrados em computadores era realmente um inseto. O computador Mark 11 era um computador eletromecânico construído em 1945. Um dia o computador misteriosamente parou de trabalhar. Uma busca cansativa finalmente revelou que havia uma traça presa entre os pontos de contato de um relê. Grace Murray Hopper, um dos criadores da linguagem COBOL e um pioneiro na indústria de computadores, retirou o infeliz lepidóptero, colocando-o no livro de registros com a anotação "Primeiro bug real encontrado".

Entretanto, os bugs discutidos neste capitulo são erros de lógica contidos nos seus programas. Naturalmente, você pode cometer vários tipos de erros que impedem seu programa de ser executado - por exemplo, tentar assinalar um valor string para uma variável do tipo double. O Visual Basic sinaliza esses erros simples assim que os encontra, facilitando a sua localização e correção. Os bugs realmente interessantes são os que você precisa encontrar e corrigir por si próprio.

Chama-se depuração o processo de localização e correção de bugs. Ao contrário dos processos tradicionais de exterminação de pestes, a depuração de programas de computador não tem efeitos colaterais, a menos que você leve em consideração as horas sem dormir e as incontáveis xícaras de café que podem ser necessárias para resolver um bug "cabeludo".

Page 187: Iniciando No Visual Basic

Depurar um programa pode ser interessante e até mesmo excitante. Trilhar e eliminar um bug de software normalmente traz um sentimento real de satisfação, seja em função da sensação de concertar o seu programa, de uma sensação de realização ou, ainda, devido apenas à própria emoção de caçar. O exercício mental pode ser elucidativo, permitindo-lhe examinar e analisar seu próprio mecanismo de pensamento.

Ferramentas de Depuração

Por mais que queiramos negar, todos os bugs realmente são erros de programação. Entretanto, alguns erros se manifestam de forma tão rara ou sobre condições tão anormais que parecem movidos por uma inteligência maligna, que sente prazer em nos confundir. O erro mais comum é uma rotina que simplesmente não funciona. Quando você encontrar um problema desse tipo, desejará usar algumas das ferramentas que o Visual Basic oferece para depuração.

À medida que trabalhar com as várias ferramentas de depuração, você descobrirá que alguns dos botões da barra de ferramentas Debug do Visual Basic representam atalhos simplificadores. Esta barra de ferramentas não é visível como a barra de ferramentas padrão, mas você pode torná-la visível selecionando-a no menu View/Toolbars. A Figura 9.1 identifica os botões da barra de ferramentas Debug.

 

Figura 9.1 Os botões da barra de ferramentas Debug.

 

A Janela Immediate

Como você já sabe, o pressionamento de Ctrl-Break em qualquer instante durante a execução de seu programa interromperá o aplicativo e ativará a janela Immediate. Se um certo procedimento estiver sendo processado quando o programa for interrompido, você verá também a janela de código desse procedimento. Nesse ponto, você pode introduzir e processar instruções de Visual Basic na janela Immediate . Cada instrução pode conter apenas uma linha. A instrução é executada dentro da janela Immediate ao se pressionar a tecla Enter. O código na janela de código não se altera.

Page 188: Iniciando No Visual Basic

Normalmente, você desejará apenas imprimir o valor de variáveis e expressões que lhe interessam. Porém, pode-se ir muito além disso. De fato, você pode executar quase todas as instruções de programação do Visual Basic; por exemplo, pode modificar uma variável ou executar um procedimento dentro da janela Immediate . Observe, no entanto, que você pode apenas modificar variáveis locais, parâmetros do procedimento atual e variáveis em nível de módulo ou públicas. Não é possível examinar ou alterar variáveis locais a outros procedimentos que não o atual. É possível também modificar o valor de quaisquer propriedades que possam ser alteradas em tempo de execução.

Como uma demonstração, crie um novo projeto que contenha apenas um botão de comando. Inclua o procedimento geral DoStuff e o procedimento Click para o botão de comando, conforme mostrado pela Figura 9.2.

Figura 9.2 O código de programa para o aplicativo Girar os Polegares.

Pressione F5 para iniciar o aplicativo. Dê um clique no botão de comando e pressione Ctrl-Break para que o Visual Basic pare o aplicativo e exiba a janela de código, que será semelhante à mostrada na Figura 9.3. (São boas as chances de que o programa seja interrompido na rotina DoStuff; caso isso não aconteça, pressione F5 para reiniciar o programa e tente interrompê-lo novamente.)

Figura 9.3 A janela de código de um programa interrompido.

Na janela de código mostrada na Figura 9.3, a linha Next B aparece em destaque, porque é a próxima instrução a ser executada pelo Visual Basic. Na janela Immediate, você poderia introduzir a instrução Print B (ou apenas ? B) para ver quantas vezes a instrução For realizou o laço. Você poderia introduzir Print A para ver o valor atual de A. Entretanto, não poderia digitar Print C ou Print D para examinar as outras variáveis do programa, mesmo que elas contenham valores, pois a janela Immediate está limitada ao escopo do procedimento executado no momento. Se introduzir as instruções Print C ou Print D, o Visual Basic assumirá que você está apenas usando variáveis não-declaradas no procedimento atual e imprimirá uma linha em branco. Você tem acesso a todas as variáveis e propriedades de escopo global ou em nível de módulo, tornando possível a execução de instruções como Print Command1.Caption e Print Form1.Height.

Para modificar uma propriedade ou uma variável na janela Immediate , você deve usar as mesmas instruções e expressões que são usadas

Page 189: Iniciando No Visual Basic

em um programa. Por exemplo, você pode diminuir o tamanho da janela de um form, executando a instrução Form1.Height = Form1.Height/2. Ou pode executar qualquer subprocedimento, ou método, introduzindo o seu nome. Por exemplo, ao introduzir a instrução Print, você está chamando o método Print do objeto representado pela janela Immediate (um objeto chamado Debug). Você não está limitado aos procedimentos internos do Visual Basic; pode também executar qualquer um dos procedimentos que escreveu.

Expressões de Vigilância

Quando você deseja apenas examinar o valor de uma variável, o Visual Basic oferece uma técnica rápida que dispensa o uso de instruções Print. Estando no modo de interrupção (Break Mode), posicione o cursor do mouse sobre o nome de uma variável na janela de código - tente fazer isso com a variável B do procedimento DoStuff - e você verá o valor da variável aparecer num pequeno retângulo próximo a ela.

Você também pode incluir uma expressão vigiada na janela Watch , para poder acompanhar o seu valor todas as vezes que interromper a execução do programa. Para incluir uma expressão selecionada, dê um clique com o botão direito do mouse sobre o nome da variável na janela de código e selecione Add Watch no menu apresentado, ou escolha a opção Add Watch do menu Debug. Na caixa de diálogo Add Watch, mostrada na Figura 9.4, dê um clique no botão OK para fazer com que a expressão vigiada selecionada apareça na janela Watch.

Figura 9.4 A caixa de diálogo Add Watch.

Você pode também incluir uma expressão a ser vigiada na janela Watch sem antes ter de selecioná-la. Basta digitar a expressão desejada diretamente na caixa de texto da caixa de diálogo Add Watch. O quadro Context da caixa de diálogo permite-lhe especificar o procedimento ou módulo no qual as variáveis de sua expressão estão definidas - isso poderá ser necessário, por exemplo, quando você tiver duas variáveis com o mesmo nome, uma em nível de form e outra local. (Discutiremos o quadro Watch Type da caixa de diálogo mais adiante.)

A Figura 9.5 apresenta o aspecto da janela Watch após a inclusão de duas expressões que serão vigiadas. Essas expressões exibem a variável D no procedimento Command1_Click e a variável B no procedimento DoStuff.

Page 190: Iniciando No Visual Basic

Figura 9.5 A janela Watch com expressões que serão vigiadas.

Se você quiser editar ou remover uma expressão vigiada, incluída na janela Watch, selecione a opção Edit Watch do menu Debug e faça as modificações necessárias na caixa de diálogo Edit Watch que será exibida.

A Arvore de Chamadas (Onde Estou?)

No exemplo simples da seção anterior (o aplicativo Girar os Polegares), era bem evidente o que aconteceria quando o programa fosse interrompido. Porém, num aplicativo mais complexo, a seqüência de eventos pode não ser tão clara assim. Nesse caso, você pode selecionar a opção Call Stack do menu View para produzir uma caixa de diálogo que mostre as chamadas a procedimentos ativos no programa.

A Figura 9.6 mostra a caixa de diálogo Call Stack (Pilha de Chamadas) para o programa Girar os Polegares. A primeira linha da caixa de diálogo exibe o procedimento atual - neste caso, o procedimento DoStuff, que está no módulo Form1. Esse procedimento foi chamado a partir do procedimento de evento Command1_Click, também contido no módulo Form1. O rastreamento das chamadas termina aqui, pois a chamada ao procedimento Click foi disparada por um evento gerado pelo usuário. Em um programa complexo, a caixa de diálogo Call Stack poderia exibir muitas entradas, indicando o aninhamento das chamadas a procedimentos. Você pode dar um clique duplo em qualquer uma das entradas (ou selecionar uma entrada e dar um clique no botão Show) para exibir o código do procedimento em questão.

Figura 9.6 A árvore de chamadas para um programa interrompido.

Pontos de Interrupção (Break Points) e Instruções Stop

Ao pressionar Ctrl-Break para interromper o programa Girar os Polegares, você não tem muito controle sobre o ponto onde o programa será interrompido. Porém, o Visual Basic permitirá que você marque explicitamente uma ou mais instruções como pontos de interrupção, locais nos quais a execução do programa parará, dando-lhe a oportunidade de vasculhar o programa para tentar diagnosticar os seus problemas. Você pode configurar pontos de interrupção antes de executar o programa ou então após interromper a sua execução. Para configurar um ponto de interrupção, abra a janela de código para o procedimento desejado e dê um clique na região acinzentada na

Page 191: Iniciando No Visual Basic

lateral da janela de código à esquerda da instrução onde a execução deverá parar. Ou então selecione a instrução e pressione F9 ou escolha a opção Toggle BreakPoint do menu Debug. O Visual Basic colocará a linha destacada para indicar a presença de um ponto de interrupção.

Para remover um ponto de interrupção, basta refazer um dos procedimentos acima para a instrução selecionada. Caso tenham sido estabelecidos vários pontos de interrupção, pode-se selecionar a opção Clear All BreakPoints (remover todos os pontos de interrupção) do menu Debug para eliminá-los de uma única vez.

Pode-se conseguir o mesmo efeito de estabelecimento de pontos de interrupção, incluindo-se instruções Stop. Essa técnica não é tão conveniente quanto o uso de pontos de interrupção, pois exige um esforço maior de codificação. Porém, com pontos de interrupção, o Visual Basic interrompe o programa toda vez que a execução atingir um desses pontos. Com o uso de instruções Stop, você pode ser muito mais específico, assegurando que o programa parará apenas em determinadas condições. Por exemplo, o fragmento de código a seguir interromperia seu programa após ser executado 10 vezes e somente se o valor da variável A fosse menor do que 0.

Static ContadorParada As Integer

ContadorParada = ContadorParada + 1

If ContadorParada > 10 And A < 0 Then

Stop

End If

Após seu programa ser interrompido, seja por meio de pontos de interrupção, seja por instruções Stop, você pode fazer a execução prosseguir, pressionando F5 ou escolhendo a opção Continue do menu Run do Visual Basic. Se tiver usado instruções Stop, precisará lembrar-se de removê-las do programa. Os pontos de interrupção estarão ativos apenas para a sessão atual do Visual Basic.

O uso de instruções Stop pode ser descrito como uma técnica invasiva - ou seja, e preciso modificar fisicamente a estrutura de seu programa. Outro exemplo de técnica invasiva é a escrita na janela Immediate (Debug) em um capítulo anterior. A instrução Debug.Print seguida por uma expressão faz com que o valor da expressão seja escrito na

Page 192: Iniciando No Visual Basic

janela Immediate , sem causar qualquer interrupção do programa. A colocação de algumas poucas instruções desse tipo ao longo de programas "doentes" poderá ajudá-lo a descobrir o ponto onde os problemas começam a ocorrer. Entre os usos mais comuns estão a impressão do nome dos procedimentos que começaram a ser executados, e a exibição do valor de certas variáveis.

Apesar das técnicas invasivas permitirem-lhe executar operações mais sofisticadas, as técnicas não-invasivas, como pontos de interrupção, são preferíveis, pois evitam que você deixe dentro do programa "paciente" o equivalente a uma esponja ou a um bisturi. Se você se esquecesse de remover uma instrução Stop de um procedimento raramente executado antes de compilar o programa, você (ou, pior ainda, um cliente que estivesse usando o seu programa) poderia ter um choque quando a mensagem "Stop statement encountered" ("Encontrada instrução Stop") aparecesse no meio de um aplicativo, encerrando-o imediatamente e enviando toda e qualquer informação para a terra do nunca.

Pontos de Vigilância

Há uma outra técnica não-invasiva, chamada de ponto de vigilância, que avisa ao Visual Basic para interromper o programa quando uma condição particular for atingida (em contraste com o ponto de interrupção, que especifica a parada quando uma determinada linha de código for alcançada) ou quando o valor de uma expressão se modificar.

Para assinalar um ponto de vigilância, destaque a expressão especifica no seu código e escolha a opção Add Watch do menu Debug, ou selecione a opção Add Watch primeiro e depois digite a expressão na caixa de texto da caixa de diálogo Add Watch. Nessa caixa de diálogo (mostrada anteriormente na Figura 9.4), mova-se para a seção Watch Type (tipo de vigilância), selecione o botão de opção marcado como Break When Value is True (parar quando a expressão for verdadeira) e dê um clique no botão OK. O Visual Basic incluirá a expressão na janela Immediate . Se desejar que o programa pare quando o valor da expressão se modificar, deve selecionar o botão de opção marcado como Break When Value Changes (parar quando a expressão se modificar) na caixa de diálogo Add Watch.

Em qualquer um dos casos, ao ser retomada a execução do programa, o Visual Basic: avaliará a expressão que será vigiada após a execução de cada instrução, interrompendo-o quando ocorrer a condição especificada.

Page 193: Iniciando No Visual Basic

Pontos de vigilância são ferramentas muito poderosas, mas têm um lado negativo. Apesar de não-invasivos, os pontos de vigilância tornam mais lenta a execução de seu programa, pois as expressões que serão vigiadas precisam ser continuamente testadas. A melhor técnica é o uso combinado de pontos de interrupção com pontos de vigilância. Assinale um ponto de interrupção na posição do programa onde você suspeita que algo esteja errado. O programa pode ser executado a toda velocidade até aquele ponto. A partir daí, você pode ativar um ou mais pontos de vigilância e continuar a execução mais lentamente.

Passo a Passo

Outra técnica de depuração não-invasiva é a passo a passo, que lhe permite executar o seu programa uma instrução de cada vez. Ela é essencialmente equivalente à configuração de um ponto de interrupção, uma instrução adiante da posição atual, executando a instrução do momento e removendo o ponto de interrupção. Quando você caminha passo a passo através das instruções de seu programa, consegue examinar o efeito da execução de cada instrução.

O percurso passo a passo é controlado pela tecla F8 (ou pela opção Step Into do menu Debug, muito embora seja bem mais prático usar a tecla de função). Você pode iniciar a execução passo a passo, quando o seu programa não está sendo processado. Cada vez que F8 for pressionado, o Visual Basic executará uma instrução e o destaque marcando a próxima linha na janela de código avançará. Se a instrução executada contiver uma chamada a um procedimento escrito pelo usuário, a janela de código modifica-se e o destaque aparece ao redor da primeira linha executável do procedimento recém-chamado. Caso seja executada uma instrução que contenha mais de uma chamada, você percorrerá passo a passo cada um dos procedimentos, na ordem em que forem chamados. Por exemplo, considere o programa mostrado na Figura 9.7. (Os números de referência do lado esquerdo foram incluídos apenas para identificar as várias linhas do programa.)

Se você processar esse programa com um ponto de interrupção assinalado na linha 3 (A = 4), o destaque aparecerá inicialmente na linha 3. Quando você pressiona F8 para iniciar a execução passo a passo, a caixa avança para as linhas 4, 8, 9, 12, 13 e 5. (Já que as linhas 7 e 11 são vistas como declarações, e não como linhas executáveis, a ferramenta de depuração irá saltá-las. Se você configurar um ponto de interrupção em uma declaração, quando o

Page 194: Iniciando No Visual Basic

programa for interrompido, o destaque aparecerá na próxima linha executável.)

Figura 9.7 Código de programa demonstrando a execução passo a passo.

Se você estiver executando um programa passo a passo e atingir um procedimento que já tenha sido suficientemente depurado, pode evitar a sua execução passo a passo. Se mantiver a tecla Shift pressionada enquanto pressiona F8, ou se der um clique no submenu Step Over do menu Debug, o Visual Basic fará a execução da instrução apenas no procedimento atual, executando as chamadas a outros procedimentos como se fossem instruções simples. Se usar Shift-F8 para percorrer o programa mostrado na Figura 9.7, você irá mover-se da linha 3 para a linha 4 e para a linha 5. O Visual Basic executará as linhas de 7 até 9 e de 11 até 13, evitando que você tenha de percorrer os dois procedimentos de função, instrução a instrução, pois você tem certeza de que estão corretos. Caso você chegue a entrar num dos procedimentos chamados e queira sair da execução passo a passo dentro do procedimento, pode clicar na opção Step Out do menu Debug ou pressionar a combinação de teclas Ctrl-Shift-F8. Nesse caso, todas as instruções restantes do procedimento atual serão executadas e a execução só será interrompida na posição imediatamente seguinte à sua chamada.

Você tem liberdade para alternar entre as três formas de percurso passo a passo, instrução a instrução, procedimento a procedimento ou entrada no procedimento e saída com Step Out, durante uma sessão de depuração. Observe que um ponto de interrupção colocado dentro de um procedimento causará a parada da execução, mesmo que você esteja fazendo o percurso procedimento a procedimento.

Experimente essas técnicas com o programa Girar os Polegares mostrado na Figura 9.2. Em primeiro lugar, use F9 para assinalar um ponto de interrupção na instrução Next D no procedimento Command1_Click. Pressione F5 para processar o programa e dê um clique no botão de comando para atingir o ponto de interrupção.

Pressione F9 novamente para remover o ponto de interrupção. Depois, mantendo a tecia Shift pressionada, pressione F8 algumas vezes. Você permanecerá no procedimento Command1_Click (ainda que observe uma pequena pausa enquanto o procedimento DoStuff está sendo processado). Quando você retornar à instrução Next D, pressione F8 duas vezes sem usar a tecla Shift. Esses dois passos

Page 195: Iniciando No Visual Basic

simples irão colocá-lo dentro do procedimento DoStuff, onde você pode continuar a técnica passo a passo.

Finalmente temos a janela Locals, que pode ser exibida selecionando Locals Window no menu View. Essa janela lhe permite acessar para consulta e modificação o conteúdo de todas as variáveis e objetos que sejam visíveis ao procedimento atual. As variáveis e seus valores são apresentados numa estrutura de árvore. No caso de objetos, as suas propriedades e variáveis membro podem ser acessadas expandindo o nó em que são apresentados.

Estratégias de Depuração

Normalmente, é bem fácil localizar a origem de um problema em um programa; com freqüência, é evidente que tudo está funcionando, com exceção de um botão ou de um certo cálculo. Você pode então aplicar a técnica clássica de granulosidade decrescente. O termo granulosidade refere-se ao tamanho dos blocos de programa que precisam ser executados. Você pode iniciar usando pontos de interrupção que lhe permitam executar grandes pedaços do programa sem interrupção. À medida que se aproximar do ponto onde as coisas começam a dar errado, você poderia mudar para passo a passo procedimento por procedimento e então para passo a passo instrução por instrução, até determinar o ponto exato onde acontece o erro.

Evidentemente, o parágrafo anterior assume com otimismo que a origem de seus problemas seja uma simples instrução. Freqüentemente isso não é assim. Você pode descobrir que fez suposições sobre o valor de variáveis ou sobre a entrada feita pelo usuário que simplesmente não são verdadeiras, e isso irá forçá-lo a reescrever algumas partes de seu programa. Como há uma forte tendência a assumir tais suposições como verdadeiras durante a sua sessão de depuração, pode-se tornar muito difícil determinar o que está dando errado. Em momentos como esses, você poderá verificar essas suposições, criando a codificação necessária para tal. Por exemplo, se você assume que um certo parâmetro jamais terá um valor menor do que 10 ou maior do que 50, pode inserir a seguinte codificação no início do procedimento que contém o tal parâmetro:

lf Param < 10 Or Param > 50 Then

Debug.Print "Suposição inválida sobre a variável 'Param.' "

Stop

Page 196: Iniciando No Visual Basic

End If

Muito embora se trate de uma técnica invasiva, a codificação para validação de suposições, por vezes, pode ajudá-lo a encontrar os bugs mais rapidamente do que o uso das técnicas não-invasivas, especialmente no caso de programas longos ou complexos.

Finalmente, naquelas ocasiões em que você não tem a menor idéia do que está dando errado, pode recorrer à técnica Elmer Fudd, segundo a qual você aplica uma matriz de 12 verdades e mentiras para "despachar o programa para qualquer lugar" se ele não começar a funcionar direito. Entretanto, por mais satisfação que isso possa trazer, seria altamente improdutivo.

Há uma outra alternativa. Você pode usar uma pesquisa binária, que é uma variação da abordagem de granulosidade decrescente. A estratégia de uma pesquisa binária é igual à usada em jogos de adivinhação. Se o seu adversário escolhe um número de 1 a 100, você consegue determinar o número com no máximo oito tentativas. A sua primeira tentativa deve sempre ser 50. Seu oponente deve dizer se você acertou, se está acima ou abaixo. Se estiver acima você deve tentar 25; se abaixo, 75. A cada tentativa, você elimina metade das alternativas restantes.

Similarmente, quando você possui um programa complexo e não tem qualquer idéia de onde procurar o problema, coloque um ponto de interrupção na metade do aplicativo. Ao ser atingida a interrupção, examine o valor das variáveis mais importantes. Se parecer que está tudo bem, coloque o próximo ponto de interrupção no ponto médio entre a posição atual e o final do programa. Do contrário, coloque o ponto de interrupção no ponto médio entre o inicio do programa e o ponto atual e reinicie o processamento do programa. Essa técnica deve conduzi-lo mais rapidamente à vizinhança do problema, permitindo que então você mude para a técnica de depuração passo a passo, ou outra técnica mais apropriada.

Não hesite em utilizar os recursos de depuração do Visual Basic para testar suas teorias sobre o que está acontecendo de errado com o seu programa. Por exemplo, se você descobrir que esqueceu de incrementar uma variável, não abandone o processo de depuração para corrigir o programa. Use a janela Immediate para configurar a variável com o valor que imagina estar correto e deixe a execução do programa continuar. Por vezes, você perceberá que o que parece ser a origem do problema na realidade é um efeito colateral do problema real.

Page 197: Iniciando No Visual Basic

Pode-se usar ainda as ferramentas de depuração para fazer experiências com o fluxo de controle de seu programa. Digamos que você tenha interrompido seu programa em um certo ponto dentro de um procedimento e tenha concluído que está faltando uma instrução If para saltar algumas linhas. Você pode configurar a próxima instrução a ser executada, dando um clique nela e então selecionando a opção Set Next Statement do menu Debug. Você pode selecionar qualquer instrução dentro do procedimento do momento, mesmo que seja anterior à instrução atual, porém não pode especificar uma instrução de outro procedimento como a próxima instrução a ser executada.

Tratamento de Erros

Até agora, este capítulo concentrou-se nos erros de programação que podem causar uma falha do aplicativo ou o retorno de resultados inválidos. Outra classe de problemas, chamada de erros de execução (runtime errors), também podem fazer com que seu programa venha a falhar. Os erros de execução quase sempre provêm de condições que você não pode controlar, tais como falta de memória ou de espaço em disco, um engano por parte do usuário ao tentar abrir um arquivo que já foi aberto por outros aplicativos e assim por diante. Outros erros de execução são bugs, indicativos de erros de lógica no seu programa, tais como indexação além do limite dimensionado para uma matriz.

Quando ocorre um erro de execução, o Visual Basic normalmente exibe uma caixa de diálogo de mensagem e encerra o aplicativo. No entanto, você pode obter o controle sobre o tratamento desses erros por meio da codificação de algumas rotinas. Essa técnica, chamada de captura de erros, permite ao seu programa detectar e possivelmente contornar o problema, ou pelo menos encerrar a execução do programa mais amigavelmente. Você estabelece seu controle sobre o sistema, habilitando a captura de erros. Quando você escreve um procedimento que captura erros, sua estrutura geral deve ser semelhante a esta:

Sub declaração

[Instruções]

On Error GoTo Rótulo

[Instruções]

Exit Sub

Page 198: Iniciando No Visual Basic

Rótulo:

Codificação para tratamento do erro

End Sub

A instrução On Error GoTo Rótulo, onde Rótulo identifica o código para tratamento de erros, habilita a captura de erros. Se ocorrer um erro de execução na instrução que se segue à instrução On Error GoTo Rótulo, o controle será transferido imediatamente para o código de tratamento de erros, identificado por Rótulo. Rótulo poderá ser qualquer identificador que você venha a escolher e, quando usado para marcar um determinado local do seu código, deve terminar com dois-pontos (:).

Para desabilitar a captura de erros mais adiante, dentro do mesmo procedimento, você pode usar a instrução On Error GoTo 0. A partir desse ponto, qualquer erro de execução que venha a ocorrer será tratado diretamente pelo Visual Basic, e não pela rotina de tratamento de erros dentro de seu procedimento. Essa capacidade de ativar e desativar a captura de erros será útil se apenas um pequena parte de seu código estiver propensa a conter erros de execução.

A captura de erros ficará ativa apenas no procedimento que contiver a instrução On Error GoTo Rótulo. Quando um procedimento se encerra, a captura de erros retorna à rotina que originalmente chamou o procedimento. Caso essa rotina não contenha manipulador de erros, a captura de erros será desativada.

Uma vez que a execução de seu programa seja movida para a rotina de tratamento de erros de um procedimento, você pode testar o valor de retorno da função Err para descobrir a origem do erro. Err retorna um inteiro indicando o tipo de erro - erro 7, por exemplo, indica que você extrapolou a memória disponível; erro 53 indica que o programa não consegue encontrar o arquivo designado; e assim por diante. A lista completa dos código de erros aparece no sistema de ajuda on-line do Visual Basic e em seu manual de referência.

Evidentemente, o seu manipulador de erros não será obrigado a tratar de todos os tipos de erros. O erro 53, por exemplo, poderá ocorrer somente quando você tentar acessar um arquivo. Se seus procedimentos não têm acesso a arquivos, você não precisa tratar o erro 53.

Page 199: Iniciando No Visual Basic

Após determinar o tipo de erro que ocorreu, você tem quatro alternativas. A mais simples é devolver o erro para o Visual Basic. Você consegue isso com a instrução Error. A instrução Error requer apenas um argumento e provoca imediatamente o erro de execução designado pelo argumento. A inclusão da instrução Error Err no final de sua codificação para tratamento de erros fará com que o Visual Basic trate os erros que você não quis testar.

As outras três alternativas envolvem a retomada da execução do programa. A inclusão da instrução Resume em sua rotina de tratamento de erros fará com que a execução seja retomada após a correção do erro. Você pode usar as seguintes variações:

 

Figura 9.8

 

Considere o código de programa mostrado na Figura 9.9, que gera um erro quando tenta fazer uma divisão por zero.

 

Figura 9.9 Código de programa que inclui tratamento de erros.

 

Quando você executar esse procedimento, as instruções serão processadas seqüencialmente até atingir a linha 6. Nesse ponto, será disparado o erro 11 (divisão por zero) e o controle do programa passará para a linha 10. A codificação de tratamento de erro assinalará o valor 2 para a variável XX e a instrução Resume fará com que a linha 6 seja processada novamente. Desta vez, a expressão não gerará erro. A instrução 7 imprimirá o valor 5, e o procedimento será encerrado.

Caso fosse usada a instrução Resume Next na linha 12, o programa continuaria na linha 7, que imprimiria o valor 10 (valor inalterado de YY), pois a linha 6 não teria sido executada corretamente. Finalmente, se a instrução na linha 12 fosse Resume ISair, a execução seria retomada na linha 8, provocando o encerramento da rotina sem imprimir qualquer valor.

É importante observar que a instrução Resume aplica-se somente ao procedimento no qual aparece. Tomemos o exemplo da Figura 9.9, e

Page 200: Iniciando No Visual Basic

modifiquemos o código para incluir dois procedimentos, conforme mostrado na Figura 9.10, onde aparece o tratamento de erros com múltiplos procedimentos.

 

Figura 9.10 Código de programa que demonstra o tratamento de erros com múltiplos procedimentos.

Ao executar esse código, você verá a seguinte saída:

Início

Entrando

Entrando

5

Saindo

Feito

Se você usasse uma instrução Resume Next em vez de Resume, a seguinte saída seria produzida:

Início

Entrando

Feito

Em ambos os casos, a rotina de tratamento de erros faz a execução ser retomada dentro do procedimento que contém o manipulador de erros, e não na instrução que realmente causou o erro no procedimento Bugged. Se você deseja que seu programa seja capaz de retomar a execução normal dentro do procedimento Bugged, terá de incluir uma rotina de tratamento de erros nesse procedimento.

 

Page 201: Iniciando No Visual Basic

Programação Gráfica no Visual Basic

Este capítulo é uma introdução à programação gráfica do Visual Basic. Trabalhar com gráficos pode ser divertido, embora não seja necessariamente fácil. Naturalmente, o Windows é em essência um ambiente gráfico; lembre-se de que os melhores programas escritos para Windows fazem uso desse recurso.

Forms e Caixas de Imagem

Até este ponto, a maioria dos "desenhos" que você criou em Visual Basic foi feita em tempo de desenvolvimento. O Visual Basic também suporta métodos gráficos que lhe permitem escrever no vídeo em tempo de execução, realizando tarefas tais como impressão de texto, desenho de linhas, tracejamento de círculos, modificação de cores e assim por diante. Esses métodos estão associados a forms, caixas de imagens e a um tipo especial de objeto chamado Printer. A discussão a seguir concentra-se nos forms, porém as propriedades e métodos descritos aplicam-se também às caixas de imagens.

A impressão e o objeto Printer serão discutidos no capítulo 12.

Gerenciamento de Vídeo

As imagens em seu monitor são reflexo direto do conteúdo da memória de vídeo, um banco de RAM que pertence à placa controladora de vídeo. As imagens na tela são compostas por vários pontos individuais chamados de pixels (abreviatura para picture elements - elementos de imagem). A quantidade de pixels que compõe o vídeo determina quanta memória RAM é necessária. Um monitor monocromático requer apenas um bit para cada pixel. Quando o bit correspondente em RAM está no estado ON, o pixel no vídeo é iluminado. Quando o bit está em OFF, o pixel fica escuro. Se, por exemplo, a resolução do vídeo é de 640 por 320 pixels, serão usados 204.800 bits (640 x 320) ou 25.600 bytes da memória de vídeo para controlar a exibição.

Em um monitor colorido, é preciso mais de um bit para controlar o pixel, pois a cor é criada por meio de uma combinação de intensidades variáveis de vermelho, verde e azul. Dependendo do tipo de controladora, podem ser necessários de 4 a 32 bits por pixel para controlar o monitor colorido. (Quanto mais bits, mais cores poderão ser exibidas simultaneamente.) Em sistemas com maiores recursos,

Page 202: Iniciando No Visual Basic

com grandes monitores coloridos, apenas a RAM de vídeo chega a atingir 4 megabytes.

Exibindo Gráficos

Todas as imagens de vídeo , desde linhas multicoloridas a textos simples, são criadas por meio de uma configuração dos bits apropriados na memória de vídeo. Os métodos gráficos do Visual Basic fazem toda a configuração de bits para você. Esses métodos gráficos, chamados de Print, Line, Circle e PSet, traçam textos, linhas, arcos e pontos individuais no vídeo. Além disso, um método chamado Point determina a cor de um ponto, e o método CIs limpa o form.

Em ambientes onde apenas um programa controla a exibição, a imagem traçada no vídeo permanece nele. O Windows, no entanto, é um ambiente multitarefa. Após ser traçada uma imagem sobre um form, o usuário pode mudar para um segundo aplicativo que traçará alguma coisa em algum lugar do vídeo . A confusão tem início quando o usuário, ao sair desse segundo aplicativo, espera rever a imagem criada pelo primeiro aplicativo, possivelmente sobreposta pelo segundo aplicativo.

O Windows resolve esse problema com o evento Paint, que é tratado por um procedimento de evento do Visual Basic. Se a exibição de um aplicativo for sobreposta por alguma outra janela, o Windows enviará o evento Paint para o aplicativo "sobreposto" quando este retomar o controle da exibição, permitindo que ele recrie a imagem do vídeo. O mesmo processo ocorre (sem interferência do aplicativo) quando você minimiza uma janela contendo imagens ou controles e então faz a sua restauração.

Um aplicativo simples pode demonstrar o que está acontecendo. Crie um novo projeto. Inclua o seguinte código como procedimento Click do form e então processe o programa:

Sub Form_Click ()

Print "Alô

End Sub

Dê alguns cliques no form para fazer com que o texto apareça no vídeo. Agora, minimize o form ou mova a janela de algum outro aplicativo sobre o form. Quando você restaurar o form, ativando-o novamente, poderá ver que o texto terá desaparecido.

Page 203: Iniciando No Visual Basic

Nesse caso, quando o form foi restaurado, o Visual Basic chamou o seu procedimento Form_Paint. Porém, como ele não tinha sido criado, nada aconteceu. Obviamente, se você tem intenção de escrever aplicativos gráficos, precisará codificar o procedimento de evento Paint para poder reconstruir as imagens. Isso requer um planejamento cuidadoso. A melhor abordagem é colocar toda a codificação gráfica no próprio procedimento Paint. Quando o programa estiver pronto para traçar a imagem pela primeira vez, chame esse procedimento diretamente. Com isso, tudo estará estruturado de forma que a chamada automática que o Visual Basic faz para o procedimento de evento Paint reconstrua as imagens necessárias.

Tente modificar o programa que você acabou de escrever para usar essa técnica. Em primeiro lugar, introduza o seguinte código na seção de declarações gerais:

' Inicializado como 0 pelo Visual Basic

Dim ContClick As Integer

Então, inclua estes dois procedimentos de eventos:

Sub Form_Click ()

ContClick = ContClick + 1

Form_Paint

End Sub

Sub Form_Paint ()

Dim I As Integer

' Limpar a tela, posicionando a

‘ impressão no topo do form.

Cls

For I = 1 To ContClick

Print "Alô"

Next I

Page 204: Iniciando No Visual Basic

End Sub

Ao processar essa versão do programa, tente minimizar ou sobrepor alguma outra janela à janela do form. Você verá que a exibição sempre retorna à aparência anterior quando o form é restaurado.

A Propriedade AutoRedraw

O Visual Basic também oferece uma técnica simples para recomposição de imagens. Todo form tem uma propriedade AutoRedraw, que por default é False. Caso essa propriedade seja configurada para True, o próprio Visual Basic tratará toda a recomposição.

Para testar isso, use o código original do programa Alô (sem incluir o procedimento Form_Paint):

Sub Form_Click ()

Print "Alô"

End Sub

Agora, configure a propriedade AutoRedraw para True, e pressione F5 para processar o aplicativo. Desta vez, o conteúdo do form não será perdido quando a sua janela for sobreposta ou minimizada, apesar de o programa não conter o procedimento Form_Paint.

Naturalmente, isso é uma armadilha. Ao configurar a propriedade AutoRedraw para True, você simplesmente transfere a responsabilidade sobre o gerenciamento da exibição para o Visual Basic. O Visual Basic desempenhará essa tarefa, alocando uma certa quantidade de memória (a quantidade de bits necessários para armazenar uma duplicata das imagens do aplicativo). Quando você traça desenhos no form , o Visual Basic atualiza a cópia na tal "memória de backup". Quando se torna necessário restaurar o form, o Visual Basic recupera a cópia na memória de backup, transportando-a para a memória de vídeo do sistema.

Portanto, é fundamental escolher entre programas simples que requeiram quantidade maior de memória, ou programas complexos que demandem menos memória. Enquanto você está escrevendo programas simples, aplicativos com um único form, provavelmente é mais adequado assinalar a propriedade AutoRedraw como True. Entretanto, à medida que seus aplicativos ficarem maiores, você desejará economizar a memória despendida com cópias de seus

Page 205: Iniciando No Visual Basic

forms, e assim será necessário escrever os procedimentos Form_Paint.

Nota: Em aplicativos que não usem métodos gráficos, a propriedade AutoRedraw deve sempre ser configurada como False. Caixas de texto, rótulos, caixas de listas, caixas combinadas e outros controles semelhantes não são afetados pelos eventos Paint, tornando desnecessárias cópias de backup.

Coordenadas do Vídeo

O Visual Basic oferece um sistema de coordenadas default que especifica as localizações de objetos dentro de um form. Esse sistema, ilustrado na Figura 11.1, assinala as coordenadas (0,0) para o canto superior esquerdo do form; com valores que crescem à medida que você se movimenta para a direita ao longo do eixo horizontal e para baixo ao longo do eixo vertical. As propriedades Top e Left de um objeto indicam seu deslocamento a partir do ponto de origem (0,0).

  

Figura 11.1 O sistema de coordenadas do Visual Basic .

As propriedades Top, Left, Width e Height são medidas em twips. Como você deve se lembrar do Capitulo 5, um twip é a unidade de medida equivalente a 1/1440 de polegada ou 1/20 de um ponto. (Um ponto é aproximadamente 1/72 de polegada, isto é, a medida tipográfica padrão usada para dimensionamento de fontes de caracteres.) Assim, um objeto que tenha 1/2 polegada de altura e 2 polegadas de largura tem as propriedades Height e Width configuradas como 720 e 2880, respectivamente.

Caso seja mais confortável trabalhar com outras unidades de medida, você pode modificar a configuração da propriedade ScaleMode do form, para que o Visual Basic adote outra unidade para o sistema de coordenadas. A Figura 11.2 descreve as unidades de medida correspondentes às várias configurações da propriedade ScaleMode.

Pode-se ver facilmente o efeito da modificação da configuração de ScaleMode. Coloque um objeto da caixa de ferramentas em um form e examine a configuração das propriedades Top, Left, Height e Width do objeto. Modifique então a ScaleMode do form para 5; um controle cuja propriedade Height estava configurada em 720 (twips) terá agora a

Page 206: Iniciando No Visual Basic

configuração 0,5 polegada. Se você mudar a ScaleMode para 6, a Height (altura) passará para 12,7 milímetros.

 

Figura 11.2 Configurações para a propriedade ScaleMode.

 

A configuração 4 para ScaleMode, que mede em caracteres, é um tanto quanto estranha, pois usa medidas diferentes para as escalas horizontal e vertical. Com as outras unidades de medida, um objeto que tem lados iguais é um quadrado. Ao usar caracteres como unidade de medida, um objeto com altura 6 e largura 12 é um quadrado com 1 polegada de lado.

ScaleMode 0

Ao configurar ScaleMode para 0, você poderá usar sua própria escala de medida. Para definir um sistema particular de unidades de medida, deve-se configurar as propriedades ScaleHeight e ScaleWidth. Por exemplo, se você assinalar ScaleWidth para 500, está dizendo ao Visual Basic para usar uma escala que contenha 500 unidades como largura total do form. Se, depois disso, você configurar a propriedade Width de um rótulo para 250, ele terá a largura correspondente à metade da largura do form, conforme mostrado na Figura 11.3. A propriedade ScaleHeight é configurada de forma similar. A unidade para altura (height) não precisa ter qualquer relação com a unidade de largura (Width).

Figura 11.3 Trabalhando com unidades de medida definidas pelo usuário.

Além das escalas horizontal e vertical, você também pode definir um ponto de origem diferente do canto superior esquerdo. A nova posição é definida pelas propriedades ScaleLeft e ScaleTop, que por default são 0. Assinalando novos valores para essas duas propriedades, você define um novo sistema de coordenadas. Por exemplo, assinalando 3 para ScaleLeft e -4 para ScaleTop, modifica-se as coordenadas do ponto de origem de (0,0) para (3,4). As coordenadas do canto inferior direito são definidas como (ScaleLeft + ScaleWidth, ScaleTop + ScaleHeight). Assim, se você configurar ScaleHeight para 17 e ScaleWidth para 10, as coordenadas do canto inferior direito passam a ser (13,13) no novo sistema de medidas, como mostra a Figura 11.4.

Page 207: Iniciando No Visual Basic

Figura 11.4 Sistema de coordenadas definido pelo usuário.

Se você quiser visualizar o form como um sistema de coordenadas cartesianas padrão, com ponto (0,0) no centro do form, conforme mostrado na Figura 11.5, assinale um valor positivo para a propriedade ScaleTop, e o seu correspondente valor negativo para a propriedade ScaleLeft. A Figura 11.5 ilustra um sistema de coordenadas onde o canto superior esquerdo foi definido como (-40,40), a propriedade ScaleWidth contém 80 e a propriedade ScaleHeight contém -80.

Figura 11.5 Sistema de coordenadas cartesianas definido pelo usuário.

A escala pode ser configurada pelo programa de duas formas diferentes: configurando as propriedades individualmente ou usando o método Scale. A sintaxe do método é a seguinte:

[objeto.]Scale [(Ieft, top)-(right, bottom)]

Observe que a sintaxe inclui apenas as coordenadas dos cantos superior esquerdo e inferior direito. O Visual Basic calcula as propriedades ScaleHeight e ScaleWidth a partir desses pontos. Assim, a instrução para configuração da escala para o form na Figura 11.5 deveria ser Scale (-40, 40)-(40, -40). Usar o método Scale sem parâmetros faz com que a escala de medida seja configurada para twips e reconfigurada a origem para o canto superior esquerdo, com coordenadas (0,0).

Equações e Grades

Se você está pensando que essas informações e mais alguns trocados podem valer um café e nada mais, espere um pouco. Na realidade, um sistema de medidas bem configurado pode simplificar consideravelmente a sua vida. Suponhamos que você esteja escrevendo um programa para representar funções matemáticas graficamente e que seja necessário construir o gráfico da equação y = x ^ 2 - 3x + 12 dentro do domínio -10 <= x <= 10. Usando a escala e o ponto de origem padrões, você teria de calcular a quantos twips para baixo e para a direita traçar os eixos, transformar cada valor de y e x para twips e adicionar o deslocamento do ponto de origem. Porém, se você definir uma sistema de coordenadas apropriado para a situação, precisará apenas calcular os valores de y e x; o Visual Basic faz o resto. A Figura 11.6 contém o programa que traça esse gráfico.

Page 208: Iniciando No Visual Basic

Figura 11.6 Código de programa para representar uma equação graficamente.

Dado um valor de X, a função FofX calcula Y de acordo com a fórmula.

Observe que o restante do programa trabalha independentemente da fórmula contida em FofX. O código principal é o procedimento Form_Paint, que é chamado pelo Visual Basic sempre que se torna necessário atualizar a área de exibição.

Em primeiro lugar, o programa configura a escala para o sistema padrão de coordenadas cartesianas, por meio da instrução Scale. A seguir, são traçados os eixos, por meio do método Line. Em sua forma mais simples, o método Line tem a seguinte sintaxe:

[objeto.]Line [(x1,y1)]-(x2,y2)

Com isso, seria traçada uma linha do ponto (x1,y1) até o ponto (x2,y2).

Finalmente, o programa plota o gráfico usando uma variante do método Line, sem especificação do ponto inicial. Nesse caso, o Visual Basic assume como ponto inicial a última posição conhecida cujas coordenadas estão armazenadas nas propriedades CurrentX e CurrentY do form. CurrentX e CurrentY precisam ser configuradas apenas uma vez no programa; após a execução de cada instrução Line, o Visual Basic atualiza a configuração dessas propriedades.

Você pode abrir um novo form, incluir esse código e executá-lo sem controles ou rotinas adicionais. Um exemplo da saída é mostrado na Figura 11.7.

Figura 11.7 O gráfico para a função FofX.

Repare que o código mostrado na Figura 11.6 usou o valor default (1) para Step. Para melhorar a resolução do gráfico (plotar uma quantidade maior de pontos), inclua a cláusula Step na instrução For, conforme mostrado aqui:

For X = -10 To 10 Step 0.1

Ainda que não tenha plotado qualquer gráfico desde a escola secundária, você achará muito útil um sistema de medidas definido pelo usuário para tarefas como desenho de tabuleiro de xadrez ou para a construção de grades para jogos semelhantes ao GO. Você

Page 209: Iniciando No Visual Basic

pode definir uma escala personalizada que tenha a dimensão de sua grade - por exemplo, 0 a 8 (ou 1 a 9) para tabuleiro de xadrez. Então, em vez de ter de calcular a localização das linhas, você poderá traçá-las nas posições 0, 1, 2 e assim por diante. O código mostrado na Figura 11.8 traça a grade de 8 por 8 que aparece na Figura 11.9.

Figura 11.8 Código de programa para desenhar uma grade 8 por 8.

Figura 11.9 Uma grade 8 por 8 traçada pelo programa mostrado na Figura 11.8.

Como mencionado anteriormente, todas as propriedades e métodos discutidos aqui aplicam-se tanto a forms quanto a caixas de imagens. Por exemplo, cada caixa de imagem pode ter seu próprio sistema de coordenadas personalizado por intermédio das propriedades de escala. Você deve incluir o nome do controle caixa de imagem quando fizer referência a essas propriedades e métodos; do contrário, o sistema assumirá que se trata de métodos e propriedades do form e não do objeto. Por exemplo, se você tivesse um objeto caixa de imagem cuja propriedade Name fosse configurada para MeuDesenho, poderia traçar uma grade de 8 por 8 dentro da caixa de imagem com o código mostrado na Figura 11.10.

Figura 11.10 Uma grade 8 por 8 traçada dentro de uma caixa de imagens.

Cores

Retornemos por alguns instantes ao gráfico mostrado na Figura 11.7. Para diferenciar a linha plotada dos eixos do sistema de coordenadas, seria interessante traçar os eixos em outra cor. O método Line permite-lhe, por meio de parâmetros opcionais, configurar a cor da linha a ser traçada. Alternativamente, pode-se configurar a propriedade ForeColor do form, que especifica a cor a ser usada para traçar qualquer coisa no form (incluindo os textos a serem impressos). As Figuras 10.11 e 10.12 contêm o código que traça os eixos do gráfico em verde e desenha a linha com a cor default. O código na Figura 11.11 especifica a cor por meio do método Line; o código na Figura 11.12 altera a propriedade ForeColor do form.

 

Figura 11.11 Código de programa para configurar cores de gráfico com o uso do método Line.

Page 210: Iniciando No Visual Basic

Figura 11.12 Código de programa para configurar cores de gráfico com o uso da propriedade ForeColor do form.

As duas rotinas usam a função RGB para criar uma cor. Essa função (cujo nome é abreviatura de Red "vermelho", Green "verde" e Blue "azul") requer três argumentos, cada qual um inteiro no intervalo de 0 a 255. O primeiro argumento especifica a intensidade da cor vermelha, o segundo, a intensidade da cor verde e o terceiro controla a cor azul. Um argumento 0 indica total ausência de cor; 255 indica máxima intensidade. A função retorna um inteiro do tipo Long, que representa uma cor no sistema RGB. A Figura 11.13 lista algumas cores comuns e suas representações no sistema RGB.

Figura 11.13 Configurações de RGB para algumas cores comuns.

Nota: Ainda que a função RGB teoricamente permita um máximo de 16 milhões de cores, o limite prático será determinado pelo tipo de hardware de seu vídeo . O padrão VGA, por exemplo, permite que somente 16 cores sejam exibidas simultaneamente.

Adicionalmente à configuração da propriedade ForeColor, você pode modificar a cor de fundo (background) do form, alterando a sua propriedade BackColor. Caso o valor dessa propriedade seja modificado em tempo de execução, todos os gráficos existentes serão apagados.

O Visual Basic inclui também constantes especiais para as cores correspondentes às configurações de cores dos elementos da interface definidas no Painel de Controle. Por exemplo, a instrução ForeColor = ACTIVE_TITLE_BAR configura a cor de desenho do form para ser a cor especificada no Painel de Controle para as barras de titulo de janelas. Essas constantes globais estão listadas na Figura 11.14. (Note que a definição das constantes na Figura 11.14 inicia-se com 0x, indicando que os valores aparecem em notação hexadecimal.) O uso dessas constantes, em vez de cores fixas, assegurará que seus aplicativos se adaptem ao mapeamento de cores definido pelo usuário, e levará os aplicativos a ter um aspecto mais profissional.

As seguintes constantes podem ser usadas em qualquer parte do seu código no lugar dos seus valores reais:

Figura 11.14 Constantes definidas para cores no Visual Basic.

Números Hexadecimais

Page 211: Iniciando No Visual Basic

O sistema numérico hexadecimal (base 16) usa 16 símbolos para representar valores numéricos: os algarismos de 0 a 9 e as letras A (equivalente ao decimal 10), B, C, D, E e F (equivalente ao decimal 15). Como foi explicado no Capítulo 2, analogamente a outros sistemas numéricos, o valor de cada posição no sistema hexadecimal, ou hex, cresce em potências de 16. Por exemplo, o número hex 1A3 representa a soma de 1 x 16 ^ 2 (256), 10 x 16 ^ 1 (160) e 3 x 16 ^ 0 (3); assim, o decimal equivalente é 419.

A notação hexadecimal é usada com freqüência em programação como uma forma abreviada para representar os números binários usados pelo computador. Uma vez que qualquer um dos 16 dígitos hexadecimais pode ser representado por 4 bits, 2 dígitos hexadecimais (um para cada 4 bits) podem ser representados em 1 byte de oito bits, nos quais se baseiam tanto a memória do computador quanto as áreas de armazenamento em discos. Assim, 1 byte de área de armazenamento pode conter 256 números hexadecimais diferentes (0 até FF).

Você pode usar valores hexadecimais em qualquer lugar onde o Visual Basic aceite um número. Basta colocar o prefixo &H ou 0x para sinalizar que o valor está em notação hexadecimal.

Outros Métodos e Propriedades de Desenho

A propriedade DrawWidth determina a largura de cada linha traçada. A configuração para essa propriedade é sempre medida em pixels. Assim, o valor 1 faz com que seja traçada a linha mais fina, com largura de 1 pixel. O valor 2 permite o desenho de linhas com 2 pixels, e assim por diante.

As propriedades DrawStyle e DrawMode afetam como as linhas aparecem na tela. DrawStyle é similar à propriedade BorderStyle de um objeto linha. Configurações de 0 a 6 indicam quando o traçado da linha é sólido, pontilhado, tracejado ou alguma combinação desses estilos.

A propriedade DrawMode é um pouco mais complexa. Suas 16 configurações determinam como a imagem que está sendo traçada se comporta em relação às outras que já estão na tela. Por exemplo, a configuração default (13 - Copy Pen) faz com que a imagem seja traçada sobreposta a todos os gráficos existentes. Com essa configuração, a execução da instrução Line (0, .5)-(2, .75) duas vezes seguidas daria a impressão de traçar apenas uma linha, pois a segunda iria sobrepor-se à primeira. Porém, se DrawMode fosse 6 -

Page 212: Iniciando No Visual Basic

Invert, a primeira execução da instrução faria com que a linha fosse traçada em cor de fundo inversa, enquanto a segunda execução inverteria novamente, fazendo a linha traçada praticamente desaparecer. Outras configurações de DrawMode combinam cores de diversas formas e permitem a criação de efeitos especiais; veja o manual de referência do Visual Basic para maiores informações.

As propriedades FilIColor e FillStyle afetam a aparência de preenchimento de círculos e polígonos. Essas propriedades são similares às propriedades FilIColor e FilIStyle de controles de contornos descritos no Capitulo 5.

O Visual Basic oferece três métodos para auxiliar no processo de desenho: PSet para configurar um ponto (ou pixel) para uma certa cor; Line para traçar linhas e retângulos; e CircIe para criar círculos, arcos e elipses. (Abordaremos esses métodos em detalhes daqui a instantes.) Além disso, o método CIs limpa um form ou caixa de imagem; e o método Point opera como uma função, retornando a cor do ponto especificado.

O método CIs limpa, ou apaga, textos e gráficos do objeto especificado - mais precisamente, ele configura cada pixel com a cor de fundo. Da mesma forma que outros métodos discutidos nesta seção, o método CIs, quando você não faz referência ao objeto, atua sobre o form atual.

O método Point tem a seguinte sintaxe:

[objeto,]Point (x, y)

Ele retorna código de cor RGB para o pixel localizado nas coordenadas (x, y), onde x é a posição no eixo horizontal e y, a posição no eixo vertical. As coordenadas são medidas nas unidades especificadas pela propriedade ScaleMode do form ou da caixa de imagem.

O Método PSet

Para configurar um único ponto para uma certa cor, use o método PSet. Este método tem a seguinte sintaxe:

[objeto,]PSet [Step](x, y)[, cor]

As coordenadas (x, y) referem-se à posição absoluta, medida nas unidades especificadas pela propriedade ScaleMode do objeto sobre o qual você está desenhando. Entretanto, se as coordenadas forem

Page 213: Iniciando No Visual Basic

precedidas pela palavra-chave Step, elas serão o deslocamento relativo à posição atual (dada pelas propriedades CurrentX e CurrentY). Por exemplo, Step(2, 10) refere-se à posição atual mais 2 unidades horizontalmente e 10 unidades verticalmente - isto é, a posição (CurrentX + 2, CurrentY + 10).

Você pode configurar um ponto para qualquer cor. Se uma cor não for especificada, o método PSet assinala para o ponto a configuração de cor da propriedade ForeColor. Esse método pode ser útil para apagar um único pixel; basta configurar o pixel com a cor de fundo atual (configuração da propriedade BackColor).

Observe que a dimensão e a aparência do ponto são afetadas pela forma como você configura as propriedades DrawWidth e DrawMode. Por exemplo, quando a propriedade DrawWidth é configurada para 1, o método PSet configura a cor de um único pixel. No entanto, quando DrawWidth é configurada para um valor maior do que 1, o ponto será dimensionado e centralizado nas coordenadas especificadas.

O Método Line

O método Line, que traça linhas ou retângulos, usa a seguinte sintaxe:

[objeto.] Line [[Step](x1, y1)]-[Step](x2, y2)[,[cor][, B[F]]]

O primeiro par de coordenadas (x1, y1) especifica o ponto inicial da linha. Se você omitir as coordenadas do ponto inicial, será assumida a posição corrente como ponto inicial. É obrigatório incluir o segundo par de coordenadas, (x2, y2), que especifica o ponto final. Você também pode especificar a cor da linha.

Quando você inclui a letra B (de box - caixa) na instrução Line, é traçado o retângulo com os cantos opostos localizados nos dois pares de coordenadas especificados. Esse retângulo será preenchido com a configuração de cor da propriedade FilIColor e com o estilo indicado pela propriedade FilIStyle. Você ainda pode incluir a letra F na instrução Line, para que o retângulo seja preenchido com a mesma cor com que foi traçado. Você só pode especificar F se for especificado B. (Isto é, a opção de preenchimento é válida apenas quando um retângulo estiver sendo traçado.)

São mostrados alguns exemplos de desenho com o método Line nas Figuras 10.15, 10.16 e 10.17. Cada um usa a instrução Scale (-2, 2)-(2, -2) e a instrução Line mostrada na figura.

Page 214: Iniciando No Visual Basic

 

Figura 11.15 Traçando uma linha com o método Line.

Figura 11.16 Traçando um retângulo com o método Line.

Figura 10.17 Traçando um retângulo cheio como método Line.

 

O Método Circle

O método Circle é o mais complexo dos métodos de desenho. Você pode usá-lo para traçar círculos, elipses, arcos e "pedaços de pizza". (Um pedaço de pizza é um arco com raios conectando as extremidades do arco ao centro.)

A sintaxe completa para o método Circle é a seguinte:

[objeto.]Circle [Step](x, y), raio[, [cor][, [início][, [final][, aspecto]]]]

Você deve sempre especificar as coordenadas do centro (x, y) quando usar o método Circle; este método não assume a posição atual como default. Quando um círculo é traçado, CurrentX e CurrentY são configurados para as coordenadas especificadas para o centro.

Para traçar um círculo, basta informar a origem e o raio. Para estreitar um círculo, transformando-o em uma elipse, você deve modificar a razão de aspecto. Os círculos têm razão de aspecto 1,0. Valores de aspecto maiores do que 1 dão origem a elipses altas e estreitas; valores menores do que 1 criam elipses baixas e largas. Assim, um valor de aspecto 4,0 traçará uma elipse à Stan Laurel (o magro), enquanto um valor 0,4 dará origem a uma elipse à Oliver Hardy (o gordo), conforme mostrado nas Figuras 10.18 e 10.19. Observe que você deve especificar todas as vírgulas intermediárias existentes na instrução Circle, mesmo quando não informa os valores para cada parâmetro.

 

Figura 11.18 Traçando uma elipse à Stan Laurel com o método Circle.

Figura 11.19 Traçando uma elipse à Oliver Hardy com o método Circle.

 

Page 215: Iniciando No Visual Basic

Para traçar um arco em vez de um circulo ou elipse completos, deve-se especificar os parâmetros início e final na instrução Circle. Esses valores devem ser fornecidos em radianos (desenterre aquele livro de trigonometria), podendo variar de 0 a 2 pi. A Figura 11.20 mostra o valor em radianos para pontos estratégicos ao longo do círculo.

Figura 11.20 Pontos ao longo do círculo especificados em radianos.

Se você se sentir mais confortável usando graus em vez de radianos, defina a constante PI e use a seguinte função:

Function GrausToRadianos (Graus As Single) As Single

GrausToRadianos = Graus * PI / 180.0

End Function

Agora, tudo o que você tem a fazer é passar para GrausToRadianos um valor em graus, e a função retornará o valor correspondente em radianos.

Para traçar pedaços de pizza, você deve usar valores negativos para início e final na instrução Circle. Valores negativos fazem com que o Visual Basic trace as linhas de raio no ângulo especificado pelo valor absoluto do parâmetro. Para que as linhas de raio sejam traçadas, é preciso que os dois parâmetros sejam negativos. O Visual Basic não preencherá um arco ou um pedaço de pizza "aberto". As Figuras 10.21 e 10.22 mostram alguns exemplos.

Figura 11.21 Traçando um pedaço de pizza com o método CircIe.

Figura 11.22 Traçando um círculo menos um pedaço de pizza com o método Circle.

 

Considerações de Hardware para Programas Gráficos

Se tiver interesse em escrever programas gráficos que sejam realmente úteis para outras pessoas, você deve considerar cuidadosamente o projeto de seus programas e, em particular, deve levar em consideração o tipo de hardware no qual os programas serão executados. Por exemplo, conforme discutido anteriormente neste capítulo, a decisão sobre quando usar a propriedade AutoRedraw ou o procedimento Paint para reconstrução da área de exibição pode ser muito importante. Lembre-se de que a quantidade de memória

Page 216: Iniciando No Visual Basic

requerida para o Visual Basic manter as cópias de seus forms depende do hardware no qual o programa é processado. Por exemplo, você pode ter desenvolvido um programa para um sistema monocromático, porém o usuário poderá ter um monitor colorido com resolução de 1280 x 1024, cujos requisitos de memória são substancialmente maiores do que os de seu equipamento. Usar AutoRedraw em tal sistema poderia facilmente esgotar a memória disponível.

Ou pode ser que você tenha desenvolvido o programa em um computador de alta resolução. O que acontece se o usuário tiver um sistema com baixa resolução? No seu sistema, um texto com 6 pontos pode parecer apenas um pouco fino, porém talvez não seja legível em um laptop com baixa resolução. Se você tem intenção de desenvolver programas para revender, pode ser interessante examinar as propriedades TwipsPerPixelX e TwipsPerPixelY dos objetos Screen e Printer. (O objeto Screen representa o vídeo completo. Seu programa pode examinar as propriedades do objeto Screen para determinar questões sobre o tipo de fonte a usar e onde colocar as caixas de diálogo.)

 

Page 217: Iniciando No Visual Basic

Impressão no Visual BasicO trabalho de impressão de relatórios no Visual Basic pode ser feito basicamente de três formas:

Utilizando o objeto Printer com seus métodos e propriedades; Fazendo chamadas a funções da API do Windows; Utilizando o gerador de relatórios Crystal Reports, distribuído

com o Visual Basic.

Trataremos aqui apenas da primeira alternativa, remetendo o leitor para o "Visual Basic 5.0 Programmer’s Guide to the Win32 API" - que acompanha este pacote - para a teoria e exemplos de como utilizar a API do Windows na geração de relatórios. Quanto ao Crystal Reports, embora seja uma ferramenta poderosa para geração de relatórios, muitas vezes o programador não consegue contornar os limites da ferramenta para realizar tudo o que deseja. Em futuras atualizações deste produto trataremos do assunto.

Nota: As futuras atualizações estarão disponíveis na Internet conforme instruções que acompanham este produto.

Imprimindo com o Objeto Printer

O objeto Printer é a representação da impressora dentro do Visual Basic.

Através dos seus métodos e propriedades você pode definir praticamente tudo que precisa para suas tarefas de impressão.

Inicialmente referenciando a impressora padrão do sistema, o objeto Printer pode ser modificado para referenciar uma outra impressora instalada. Na coleção Printers você encontrará uma referência para cada impressora presente na instalação. Usando a instrução Set, é possível atribuir ao objeto Printer qualquer uma destas referências. Assim: Set Printer = Printers(1), por exemplo, fará com que o objeto Printer tenha suas propriedades modificadas para refletir as atuais configurações da impressora Printers(1), e qualquer tarefa de impressão concluída pelo objeto Prnter será destinada a esta impressora.

Numa tarefa de impressão, devemos levar em conta várias informações que determinarão o resultado final. Algumas destas informações estão listadas abaixo:

Page 218: Iniciando No Visual Basic

O tamanho do papel a ser usado para imprimir o relatório;

O área imprimível dentro da página;

As margens que separam os limites da área imprimível dos limites da página física;

As fontes a serem usadas na geração do texto;

Os atributos dos elementos gráficos presentes no relatório, tais como cores, espessuras de linhas, modos de desenho, etc.

O número de cópias do relatório;

O número de páginas;

A orientação da saída em relação ao papel (retrato ou paisagem).

 

Os parâmetros para geração de relatórios podem ser fixados pelo programador ou permitir que a interação com o usuário determine vários desses parâmetros. Essa interação normalmente é feita através de uma caixa de diálogo de impressão, usando o método ShowPrinter do controle de diálogos comuns. Após o retorno da caixa de diálogo, as propriedades do controle de diálogos comuns são verificadas para que o programa responda às escolhas do usuário. A criação de uma classe para exibição de diálogos de impressão também pode ser uma alternativa para ter-se maior flexibilidade na escolha de quais opções disponibilizar para o usuário. Existem casos em que é necessário deixar ao usuário até mesmo a possibilidade de modificar a fonte usada para impressão do relatório, já que nem sempre a fonte escolhida pelo programador é a que melhor se ajusta á impressora do usuário. Exemplo de casos assim são os relatórios que devem ser impressos em fontes do dispositivo nas impressoras matriciais.

Iniciamos uma tarefa de impressão escolhendo a impressora para a qual será destinado nosso relatório e configurando as propriedades da página de impressão. Como já vimos acima, a coleção Printers contém todas as impressoras disponíveis para o sistema. Em tempo de execução podemos verificar a propriedade DeviceName dessas impressoras e identificar uma que estejamos querendo atribuir ao objeto Printer para se tornar a impressora padrão da aplicação. Feito isto, devemos configurar a página sobre a qual iremos imprimir.

Page 219: Iniciando No Visual Basic

O tamanho da página pode ser escolhido atribuindo à propriedade PaperSize uma das constantes para os tamanhos pré-definidos listados na figura abaixo ou utilizando as propriedades Height e Width do objeto Printer.

Figura 12.1

As propriedades Height e Width têm precedência sobre a propriedade PaperSize. Ao atribuir valores a essas propriedades, PaperSize é automaticamente configurada para vbPRPSUser (tamanho definido pelo usuário).

Os valores atribuídos a Height e Width são entendidos sempre como estando em twips (1/1440 de polegada) e correspondem às dimensões físicas da página. A área realmente imprimível na página é obtida com as propriedades ScaleWidth, ScaleHeight, ScaleLeft e ScaleTop. Os valores em que estão expressas essas propriedades depende da propriedade ScaleMode. Em ScaleMode, você define as unidades de medida usadas para posicionar texto e gráficos impressos na página. Veja na tabela abaixo as opções para essas unidades.

Figura 12.2

Ao modificar alguma das propriedades ScaleHeight, ScaleWidth, ScaleTop ou ScaleLeft, você cria o seu próprio sistema de coordenadas.

Uma vez que definimos qual o tamanho do papel e obtivemos o tamanho da área imprimível, falta-nos saber quais são as margens que separam a área imprimível da área física total da página. O objeto Printer não possui nenhuma propriedade ou método que retorne essa informação, mas dentro das DLLs do Windows existe uma função que pode ser chamada para retornar-nos essa informação: GetDeviceCaps. Essa é uma função da API do Windows, que retorna diversas informações sobre um dispositivo informado. Como toda função residente em DLLs, GetDeviceCaps precisa ser declarada antes que possamos fazer chamadas a ela em uma aplicação Visual Basic. A declaração de GetDeviceCaps, bem como as de inúmeras outras funções da API do Windows, pode ser obtida usando o API Text Viewer, que acompanha o Visual Basic 5.0. Com o API Text Viewer é possível também obter-se as declarações de constantes e tipos de dados definidos pelo usuário requeridos nas chamadas a funções da API. Por questão de simplificação apresentamos abaixo a

Page 220: Iniciando No Visual Basic

declaração de GetDeviceCaps e das constantes usadas para obtenção das margens que precisemos obter.

Figura 12.3

Incluindo estas declarações em um módulo padrão da aplicação podemos chamar GetDeviceCaps de qualquer parte do código para obtermos informações sobre o dispositivo identificado pelo parâmetro hdc. As duas constantes declaradas são usadas para obtenção das margens esquerda e superior que separam os limites da página física da área imprimível. Os valores retornados estarão em número de pontos da impressora e dependerão da resolução presentemente selecionada na configuração do dispositivo. Antes de usá-los em cálculos, será preciso convertê-los para a unidade de medida adequada.

Serão necessárias duas chamadas a GetDeviceCaps para obter as margens de impressão: uma, passando PHYSICALOFFSETX como argumento nIndex para obter a margem esquerda ; e outra, passando PHYSICALOFFSETY para obter a margem superior. Como argumento para hdc, passamos Printer.Hdc. O cálculo das margens direita e inferior pode ser feito usando as medidas físicas da página total - obtidas com as propriedades Height e Width -, as margens obtidas com GetDeviceCaps e as medidas da área imprimível obtidas com as propriedades ScaleWidth e ScaleHeight. Este cálculo só pode ser feito após a redução de todas as medidas a uma unidade comum.

Para converter as medidas obtidas com as chamadas a GetDeviceCaps para as medidas que estivermos usando, podemos recorrer inicialmente às propriedades TwipsPerPixelX e TwipsPerPixelY do objeto Printer. Estas propriedades nos retornam o número de twips ocupado por cada ponto do dispositivo. Isso nos permite converter os pontos obtidos nas chamadas a GetDeviceCaps para twips. Multiplicando Printer.TwipsPerPixelX pelo número de pontos da margem esquerda, obtemos, em twips, o valor dessa margem. Fazemos o mesmo com Printer.TwipsPerPixelY e a margem superior. Uma vez convertidas as margens para twips, fica fácil convertê-las para outra unidade.

Vamos seguir nosso estudo supondo que estamos trabalhando com a unidade twips. Antes de enviar qualquer texto ou gráfico para a página, precisamos definir a posição dentro da página em que imprimiremos. Isto é feito com o uso das propriedades CurrentX e CurrentY. Com estas propriedades definimos as coordenadas cartesianas para a posição em que se dará a próxima impressão que

Page 221: Iniciando No Visual Basic

fizermos sobre a página. CurrentX e CurrentY estão sempre em unidades definidas pela propriedade ScaleMode. Para o uso dos métodos gráficos, consulte a documentação do Visual Basic que contém maiores detalhes sobre o significado de CurrentX e CurrentY em cada caso.

Feita a escolha da posição para a nossa próxima ação de envio de dados, podemos iniciar a montagem do conteúdo da página. Para enviar texto usamos o método Print do objeto Printer. Veja um exemplo de uso do método Print: Printer.Print "Isto é uma string.". A string entre aspas poderia ser substituída pelo nome de uma variável contendo uma string, por exemplo:Printer.Print varStr. Neste caso seria impresso o conteúdo da variável varStr.

A combinação do método Print com as propriedades relativas a fontes do objeto Printer, nos possibilitam imprimir texto com aspectos variados. Utilizando, por exemplo, a propriedade FontName, podemos definir o nome da fonte em que será impresso qualquer texto que enviemos para a página após a sua atribuição. Os textos anteriormente enviados permanecem inalterados. Na sequência veremos um exemplo do uso dessas propriedades.

Uma vez que tenhamos criado todo o conteúdo de uma página, desejaremos passar para a seguinte. Isto é feito com uma chamada ao método NewPage do objeto Printer. A página que acabou de ser criada é salva, mas não é enviada para a impressora ainda. Somente após o término da geração do relatório é que todas as páginas estarão disponíveis para impressão. O método NewPage cria uma página vazia com as propriedades CurrentX e CurrentY configuradas para o canto superior esquerdo da nova página.

Criada a última página do relatório, podemos sinalizar o seu término com uma chamada a EndDoc. Isso fará com que a aplicação envie o relatório para um arquivo em disco de onde poderá ser transferido para a impressora pelos mecanismos gerenciadores de impressão do Windows.

O que foi visto até aqui descreve em linhas gerais a impressão com o objeto Printer. Para ver um exemplo de impressão, procure pela aplicação ExempPrt no diretório Exemplos\ExemploPrt deste CD. Você encontrará uma pequena aplicação, onde poderá ver o uso do que foi visto acima e de mais alguns recursos de uso comum nas tarefas de impressão com o objeto Printer.

 

Page 222: Iniciando No Visual Basic

Trabalhando com Bancos de Dados no VB

Nota: Nas primeiras seções que se seguem serão expostas algumas idéias básicas sobre bancos de dados. Se você já tem um conhecimento introdutório sobre o tema, poderá saltar algumas dessas seções.

Um sistema de banco de dados é simplesmente um sistema de manutenção de arquivos e informações relacionadas. Imagine um banco de dados como um grande armário para o arquivamento de informações. Dentro das gavetas - os arquivos - guardamos de maneira ordenada as informações necessárias para o exercício de alguma atividade. Se contratarmos um escriturário para manter o arquivo teremos o equivalente a um sistema gerenciador de banco de dados. Em outras palavras, um banco de dados pode ser considerado um conjunto de arquivos de dados, capaz de oferecer diversos recursos automáticos ao usuário de modo que diversas operações podem ser realizadas, a saber:

A adição e remoção de arquivos do banco de dados;

A inserção e remoção de dados dos arquivos existentes;

A recuperação e a atualização de dados nos arquivos existentes.

Fica claro, portanto, que um sistema de banco de dados compõe-se , basicamente, de dois subsistemas. O primeiro deles envolve simplesmente o armazenamento físico dos dados. O segundo envolve um subsistema capaz de manter e recuperar as informações armazenadas. Este seria, na analogia do armário, o escriturário responsável pela manutenção do arquivo. Ambos os subsistemas são cruciais para a realização da tarefa. Suponha que o mecanismo de organização dos dados no arquivo físico fosse grosseiramente projetado. Certamente o trabalho do arquivista seria um fracasso.

Sistemas de Banco de Dados

Os sistemas de bancos de dados mantêm informações significativas para pessoas ou empresas - informações necessárias para o processo de tomada de decisões para estas mesmas pessoas ou empresas. Um sistema de banco de dados tem por finalidade manter informações e disponibilizá-las quando solicitadas.

Page 223: Iniciando No Visual Basic

Para maior eficiência em uma organização, os sistemas de bancos de dados costumam apresentar duas características básicas, representando sua maior vantagem:

Integração. O banco de dados pode ser imaginado como a unificação de diversos depósitos de dados de outra forma distintos, eliminando total ou parcialmente qualquer redundância. Uma conseqüência da integração do banco de dados é que, em geral, um usuário só estará interessado em um subconjunto dos dados, fazendo com que cada usuário perceba o banco de dados de maneira distinta de todos os demais.

Compartilhamento. Parcelas isoladas de dados podem ser compartilhadas por diversos usuários de um banco de dados. Todos os usuários podem ter acesso á mesma parcela de dados, usando-a com finalidades diversas. Diferentes usuários podem ter acesso às mesmas parcelas de dados ( acesso concorrente ).

Tais características de um banco de dados corporativo permitem à organização o controle centralizado de suas informações operacionais e gerenciais. Isto pode ser decisivo para a organização facilitando e agilizando a tomada de decisões.

Sistema Gerenciador de Banco de Dados

Entre o armazenamento físico dos dados no banco de dados e os usuários e aplicações do sistema encontra-se o sistema gerenciador de banco de dados ( Database Management System - DBMS). Todas as solicitações de acesso ao banco de dados, sejam elas dos usuários diretos ou dos aplicativos, são manipuladas pelo DBMS, isolando os usuários dos detalhes de armazenamento a nível de hardware.

Os Usuários

Na ponta final do processo encontram-se os usuários. Não apenas os beneficiários das informações mantidas pelo sistema. Todos aqueles que, de uma forma ou de outra, são obrigados a se relacionar com o banco de dados (físico) através do DBMS são usuários do sistema, a saber:

O programador, responsável pelos aplicativos que utilizam o banco de dados.

O usuário final, que interage com o sistema a partir dos aplicativos.

Page 224: Iniciando No Visual Basic

O administrador do banco de dados, a quem cabe organizar, padronizar e manter o acesso aos dados da empresa.

Os Dados

Independente de quaisquer outras considerações, um banco de dados não passa de uma coleção de dados operacionais - informações importantes para organizações e indivíduos. Por mais avançado e eficiente que seja o DBMS, se os dados não forem armazenados com uma estruturação lógica clara e consistente, todo este aparato será em vão.

Considere o caso mais simples de um caderno de telefones. Eu desejo anotar o telefone da empresa Couves & Repolhos Ltda., especializada em atendimento médico de emergência. Assim, anoto o telefone na letra C, usando o critério do nome da empresa. Numa emergência, quando a informação é extremamente necessária, é bem possível que eu esqueça o nome da empresa. Como o telefone não foi anotado também nas letras E - emergência - e M - médicos, a recuperação da informação será penosa. A organização do banco de dados foi ineficaz. Se, num caso simples como este a organização lógica do armazenamento da informação é crítica, imagine o problema - bem mais complexo - de projetar um banco de dados para atender às necessidades de uma grande empresa. E o melhor DBMS do mundo não pode resolver este problema.

Consideremos agora a natureza do dado armazenado no banco de dados. De maneira nenhuma, no exemplo anterior, eu pensaria em anotar na minha caderneta de telefones, o nome de todos os médicos e paramédicos da empresa Couves & Repolhos Ltda. Essa informação, do meu ponto de vista, é transitória, não é essencial à minha tomada de decisão.

Assim, há duas classes de informações que não deverão compor a organização lógica do meu banco de dados, ainda que circulem em torno do sistema como um todo:

Os dados temporários. Aquelas informações que entram no sistema, mas são transitórias. Ainda que provoquem alterações nos dados operacionais, tais informações não devem fazer parte do banco de dados. Um exemplo bem simples é um dado calculado. De forma alguma ele deve ser armazenado. Quando for necessário, calcule-o a partir dos dados permanentes.

Page 225: Iniciando No Visual Basic

Os dados de saída - mensagens e resultados procedentes do sistema. Ainda que derivadas dos dados operacionais, tais informações não fazem parte do banco de dados em si.

Ainda que as qualidades de um DBMS não garantam uma organização eficaz dos dados - esta é uma tarefa dos projetistas do sistema específico - a natureza desta organização dependerá das características do sistema gerenciador, sendo limitada por elas.

Isto porque o DBMS age como um intermediário entre o aplicativo e os dados. Sendo assim, a maneira como o sistema admite a organização dos dados influirá criticamente no resultado final. O DBMS manipula todos os acessos ao banco de dados. Quando o usuário emite uma solicitação de acesso, usando, por exemplo SQL ou um aplicativo de front-end específico, o DBMS:

Intercepta a solicitação e analisa-a;

Determina as permissões de acesso do usuário e define a estrutura de armazenamento;

Executa as operações necessárias no banco de dados armazenado.

Os diversos esquemas de armazenamento e recuperação da informação serão, portanto, decisivos para o projeto de estruturação do banco de dados.

A Organização dos Dados em Tabelas

O termo tabela faz parte do cotidiano de quem lida com banco de dados. Agrupar informações em tabelas é a forma comum de se organizar dados na maioria dos sistemas de armazenamento. Antes, porém, que a informação seja agrupada em tabelas é preciso submete-la a um agrupamento de nível mais básico: o registro. Um registro é um conjunto de informações que descrevem alguma coisa de modo satisfatório para algum propósito. Suponhamos que você queira anotar o endereço de alguém numa agenda. Inicialmente você anota o nome da pessoa, depois a rua, o número, bairro, cidade. Se para o seu propósito de localização futura da pessoa estes dados bastam, você acaba de criar um registro desta pessoa na sua agenda. Caso você não tenha uma agenda, mas queira organizar suas informações de endereços numa folha de papel, uma alternativa é criar uma tabela, onde cada coluna será usada para relacionar uma das partes do endereço a ser anotado. Você terá então uma coluna para o nome da pessoa, outra para a rua, outra para o número e

Page 226: Iniciando No Visual Basic

assim por diante. Cada novo endereço será escrito na primeira linha vaga da tabela após os últimos dados que já foram adicionados. Você pode dar um nome para a sua tabela, por exemplo, endereços de clientes. Se fizer também uma tabela para endereços de amigos, poderá dar a ela outro nome. Cada coluna da tabela também pode receber um nome que clarifique qual parte do endereço está escrita nela. No caso de endereços pode ficar fácil compreender qual coluna corresponde ao nome, qual à rua, mas nada garante que alguém não irá confundir bairro com cidade se não for posto um título em cada coluna para deixar as coisas mais claras. Se o indivíduo que for examinar a sua tabela for um computador então, não tenha dúvidas de que ele precisará de tudo muito claro. Se esta tabela vier a ser parte de um banco de dados computadorizado, cada linha da tabela será um registro e cada coluna um campo de registro. Com o computador sabendo identificar cada coluna da tabela por um nome de campo, poderemos pedir a ele que nos apresente os registros ora ordenados por nome, ora por endereço ou por qualquer outro campo que faça parte do registro da tabela. A este conjunto de campos e à posição relativa que ocupam dentro do registro chamamos de LayOut do registro.

Sistemas Relacionais

Nos últimos anos, o modelo relacional tem se tornado um padrão para o projeto de bancos de dados. Isto se dá em razão do poder do modelo relacional em si e também porque ele oferece uma linguagem padrão de comunicação chamada SQL (Structured Query Language) que permite a muitas ferramentas e produtos de banco de dados trabalharem juntos de uma maneira consistente e compreensível. Num sistema relacional:

Os dados são percebidos pelos usuários como tabelas;

As operações à disposição do usuário (por exemplo, de recuperação dos dados) geram novas tabelas a partir das antigas.

O usuário de um sistema não-relacional, ao contrário, vê outras estruturas de dados e necessita de operações diferentes para manipulá-los. Por exemplo, o IMS, um sistema hierárquico, apresenta os dados sob a forma de um conjunto de estruturas de árvore. As operações para manipular tais estruturas incluem, por exemplo, mecanismos para percorrer caminhos para cima e para baixo nos galhos da árvore.

RDBMS Mono-usuários Tradicionais

Page 227: Iniciando No Visual Basic

Nota: RDBMS é abreviatura de Relational DataBase Management System.

Gerenciadores tradicionais de bancos de dados relacionais, como o dBase e o Paradox, utilizam arquivos separados para cada tabela, índice ou coleção de índices disponível no sistema. Neles as tabelas usam registros de comprimento fixo. Por exemplo, num campo caractere, a especificação do tamanho máximo de cada campo é feita de tal forma que valores inferiores ao máximo são automaticamente preenchidos com espaços em branco. Os RDBMS Btrieve, por exemplo, admitem armazenamento de campos caractere de tamanho variável, promovendo uma importante economia de espaço.

Porém, a manipulação dos dados nas tabelas e a manipulação dos índices nestes tipos de RDBMS é responsabilidade da aplicação. Esta traduz comandos de alto nível, como o comando SQLSELECT ou o comando dBase LIST, em instruções de baixo nível. São estas as instruções que manipulam diretamente os registros das tabelas.

RDBMS Cliente-Servidor

Os sistemas cliente-servidor diferem grandemente dos sistemas mono-usuários.

A primeira distinção é que o comando SQL emitido pela aplicação de front-end é executado pelo servidor (back-end). Quando a estação envia um comando SELECT para o servidor, somente os registros correspondentes às especificações da consulta são retornados à estação. O servidor é responsável pela execução dos comandos enviados pelas estações, controlando os acessos concorrentes ao banco de dados e a consistência das entradas.

Bancos de Dados Locais e Remotos

Antes de situarmos o dispositivo de banco de dados do VB ( o Microsoft Jet Database Engine) na família de bancos de dados relacionais, é conveniente fazermos mais algumas distinções. Um sistema de banco de dados, como já sabemos, possui três componentes: os dados armazenados, o sistema gerenciador e o aplicativo de front-end. Do ponto de vista físico, tais componentes podem se localizar todos na mesma máquina, configurando um sistema mono-usuário. Podem, contudo, localizar-se em diferentes computadores ligados por uma rede. Por exemplo, os dados armazenados podem residir num servidor de arquivos central e a interface com o usuário (o aplicativo) em diferentes estações de

Page 228: Iniciando No Visual Basic

trabalho, permitindo acesso concorrente de diversos usuários aos mesmos dados.

Cliente-Servidor vs. Remoto

Uma importante distinção nas aplicações de bancos de dados projetados para ambientes de rede consiste na diferença entre banco de dados remoto e banco de dados cliente-servidor. Num sistema cliente-servidor, o dispositivo gerenciador de banco de dados está localizado no servidor central, ao lado dos dados armazenados. O mesmo dispositivo gerenciador apode servir a muitas aplicações clientes ao mesmo tempo, manipulando os dados armazenados e retornando os registros solicitados para cada aplicação local. Num sistema remoto, o dispositivo gerenciador de banco de dados se localiza no mesmo computador onde reside a aplicação do usuário; apenas os dados residem num computador remoto.

O Microsoft Jet - um RDBMS Não-Tradicional

O gerenciador de banco de dados do VB, o Microsoft Jet - Inteiramente compatível com o Microsoft Access - não é um sistema cliente servidor. Ele é um dispositivo de acesso a banco de dados residente em DLLs ligadas ao programa em tempo de execução. Havendo diversas cópias da aplicação em diversas estações, cada uma delas terá sua cópia local do dispositivo Jet, ainda que acessem a mesma base de dados remota. Esta distinção não tem alcance meramente teórico. Ao contrário, esta característica afeta a performance global do sistema. Num sistema cliente-servidor, trafegam pela rede, grosso modo, apenas aos comandos de consulta e atualização e os subconjuntos de dados eventualmente solicitados. Numa arquitetura como a do Jet - como dados e gerenciador localizam-se em máquinas diferentes - muito mais informações trafegarão pela rede.

É possível, contudo, criar aplicações cliente-servidor em VB, conectando-as a uma fonte de dados com suporte à ODBC ( Open Database Connectivity), tal como o Microsoft SQL Server. Nestes casos, as consultas são passadas diretamente ao dispositivo servidor ou utilizam procedimentos remotos nele armazenados.

Ainda que não seja um gerenciador cliente-servidor, o Microsoft Jet pertence a uma categoria diferente dos RDBMS tradicionais, porque tem pouca semelhança com sistemas como o dBase e o Paradox. O dispositivo RDBMS incorporado ao VB possui muitas características

Page 229: Iniciando No Visual Basic

em comum com os bancos de dados cliente-servidor, em particular com o Microsoft SQL Server. Tais características comuns são:

Todas as tabelas e índices do banco de dados são armazenados num único arquivo com a extensão .MDB.

Os campos de data suportam informação de hora.

Os campos suportam valores nulos (Null).

Admite o armazenamento permanente de comandos SQL.

O tamanho dos campos OLE Object (LongBinary) é limitado apenas pelo espaço em disco e não pela estrutura do arquivo.

É possível forçar a integridade referencial entre as tabelas e a integridade de domínio - entre os campos - da tabela.

Inclui capacidades de manutenção de segurança de acesso.

Inclui, automaticamente ou por programa, capacidade para gerenciar o acesso concorrente.

Tais características tornam o Microsoft Jet - e o Microsoft Access - ideais para aplicações de banco de dados robustas, mas de características intermediárias entre os grande sistemas cliente-servidor e os pequenos sistemas mono-usuários. Como linguagem de programação, porém, o VB não sofre essa restrição, permitindo a conexão com sistemas cliente-servidor via tecnologia ODBC. Neste caso, a interface de programação poderá ter que se adaptar às características do RDBMS específico.

Conceitos Básicos dos Bancos de Dados Relacionais

Já falamos um pouco sobre alguns desses conceitos - tabelas, registros e campos - mas aqui vamos procurar relacioná-los a outros ainda não citados. Ainda sobre tabelas devemos lembrar que:

É desejável, mas não essencial, que cada registro dentro de uma tabela tenha um conjunto de campos cuja combinação de valores seja capaz de individualizar inequivocamente o registro dentro da tabela. Esse conjunto é chamado identificador e é boa prática de projeto de banco de dados a sua existência.

Um campo que possua a capacidade de ser um identificador é chamado de chave primária. Por definição, um conjunto de valores

Page 230: Iniciando No Visual Basic

dos campos constituintes da chave primária deve ser único para cada registro. Registros em tabelas relacionadas podem ter valores idênticos aos da chave primária de uma das tabelas. O valor idêntico ao da chave primária é conhecido como chave externa.

A tabela abaixo resume os principais termos utilizados no projeto e implementação de sistemas de bancos de dados relacionais.

Figura 13.1

Modelagem de Dados

É o momento de fundamentarmos toda a teoria discutida ao longo deste capítulo com orientações precisas sobre o problema principal - e, portanto, o primeiro a ser enfrentado - no desenvolvimento de um sistema de banco de dados: como projetar a base de dados da aplicação? A melhor maneira de tratarmos do assunto é, certamente, com a ajuda de um exemplo concreto de modelagem de dados.

Exemplo de Projeto de um Banco de Dados

Vamos supor que você foi contratado por uma firma distribuidora de material de limpeza para desenvolver um sistema de controle da atividade. Naturalmente, seu cliente não sabe com exatidão o que quer. Como sempre, ele sabe apenas que precisa automatizar o negócio, de modo a favorecer o aumento de produtividade e a expansão das suas atividades. O sistema atual - um controle desordenado através de fichas de papelão - atingiu o seu limite. Mantê-lo significa contratar novos empregados e ver boa parte das receitas se escoando em prejuízos causados pelo descontrole. Sua tarefa é, portanto, evitar o caos.

Como este não é um manual sobre análise de sistemas, passaremos por alto pelos passos necessários para alcançar a fase que nos interessa. Diremos apenas que, após algum esforço, você chegou a algumas conclusões sobre o funcionamento do negócio da empresa, a saber:

A firma - Limpa Tudo Materiais de Limpeza Ltda. - obtém seus produtos de um conjunto de empresas fornecedoras. Estas podem ou não ser os fabricantes originais. Cada uma delas fornece um ou mais itens para o estoque, acontecendo algumas vezes que duas diferentes empresas forneçam o mesmo produto. A decisão sobre de qual comprar é feita com base numa série de critérios gerenciais fora do domínio do sistema a ser desenvolvido.

Page 231: Iniciando No Visual Basic

O pedido de novos itens é feito através de contatos telefônicos com cada fornecedor. Geralmente, cada empresa possui um ou mais empregados encarregados de atender aos pedidos do seu cliente. Tais pedidos são feitos sempre que o estoque de um item baixa até uma quantidade considerada mínima pela firma.

A baixa do item do estoque é feita pelo funcionário do almoxarifado sempre que é levado pelo pessoal da entrega e não quando é feito o pedido. Isto faz com que alguns pedidos não possam ser atendidos antes de um novo fornecimento.

Os clientes da Limpa Tudo - também empresas - solicitam periodicamente quantidades variáveis de cada item, pelo telefone.

Para atender a seus muitos clientes, a Limpa Tudo mantém um grupo de vendedores. Estes recebem uma comissão de 5% por cada venda efetuada.

A equipe de entrega recebe um roteiro prévio, contendo as diversas faturas, onde são relacionados os itens entregues e o preço dos produtos.

Naturalmente, esse levantamento é insuficiente para o desenvolvimento de um sistema real, mas deve bastar para o nosso exemplo de modelagem de dados. Assim, com algum esforço, você chegou aos requisitos básicos do aplicativo. O sistema deve cumprir, no mínimo, as seguintes tarefas:

Controlar os itens em estoque. O sistema deve efetuar uma baixa "virtual" do produto quando o pedido é feito e uma baixa "real" quando é entregue. Deste modo, o pessoal da Limpa Tudo saberá exatamente quando solicitar um novo fornecimento, sem precisar manter estoques exagerados e sem deixar de atender nenhum cliente com prontidão.

Faturar os pedidos aos fornecedores, quando um item em estoque estiver abaixo de um limite crítico.

Faturar os pedidos dos clientes, baixando, no ato da solicitação, o item do estoque.

Controlar as vendas de cada empregado, visando o cálculo das comissões.

Manter um cadastro de clientes.

Manter um cadastro de fornecedores.

Page 232: Iniciando No Visual Basic

Oferecer um catálogo de produtos aos clientes.

Fornecer uma lista de itens para entrega, bem como faturas e os diversos relatórios necessários ao controle total do negócio.

Os Diversos Documentos de Entrada

O próximo passo será analisar os diversos documentos e controles mantidos pela Limpa Tudo. Tais documentos servirão de ponto de partida para a criação das múltiplas tabelas gerenciadas pelo sistema. Vejamos cada caso.

O primeiro documento relevante será o utilizado no almoxarifado, para o controle de produtos em estoque. A Limpa Tudo mantém atualmente um fichário de cartolina com as seguintes informações:

Nome e descrição do produto.

Data da entrada de novos itens no estoque.

Quantidade de itens acrescentados nesta data.

Data de saída de alguns itens do estoque.

Quantidade de itens baixados nesta data.

Quantidade total de itens atualmente em estoque.

Quantidade mínima de itens a serem mantidos em estoque.

Nome e CGC das empresas fornecedoras do produto.

Endereço de cada empresa fornecedora.

Telefone de cada empresa fornecedora e nome dos diversos vendedores responsáveis pelo contato com a Limpa Tudo.

Preço corrente do produto cobrado por cada uma das empresas fornecedoras.

O almoxarifado da Limpa Tudo é razoavelmente organizado. Como o empregado deste setor é o responsável pelos pedidos de fornecimento, ele mantém controle sobre cada pedido de fornecimento efetuado, visando cobrar eventuais demoras e auxiliar o patrão no planejamento do fornecimento. Este controle é feito num livro comum,

Page 233: Iniciando No Visual Basic

onde cada folha registra as informações a seguir, descartadas sempre no atendimento do pedido pelo fornecedor:

CGC e Razão Social do fornecedor.

Endereço e telefones para contato do fornecedor.

Nomes dos diversos contatos na empresa.

Nome e quantidade do item solicitado.

Data do pedido e data prevista para a entrega.

O almoxarifado mantém ainda um catálogo completo de todos os fornecedores, também num fichário de cartolina. É este o documento consultado para montar o controle de pedidos de fornecimento e possui as seguintes informações:

Nome e CGC da empresa fornecedora.

Endereço completo do fornecedor, contendo rua e número, CEP, cidade e estado.

Os diversos telefones utilizados para contatar a empresa.

O nome de cada um dos contatos no fornecedor.

Uma lista com o nome, a descrição e o preço de cada um dos produtos fornecidos.

A equipe de vendas, como não poderia deixar de ser, mantém também um conjunto de documentos visando controlar sua atividade e (sobretudo!) as comissões devidas a cada um. O primeiro documento referido será o mantido para cada venda efetuada. Este contém as seguintes informações:

Nome e CGC da empresa cliente.

Endereço completo do cliente.

Nome de cada um dos itens vendidos.

Quantidade e preço unitário de cada um dos itens vendidos.

Preço total de cada conjunto de produtos.

Page 234: Iniciando No Visual Basic

Valor total da fatura.

Data da venda.

Nome do vendedor e valor da comissão pela venda.

Este documento é emitido em diversas vias, destinadas ao almoxarifado, para providenciar a entrega, à contabilidade, etc. Uma das cópias fica em poder do vendedor e é o seu controle de comissões, apresentado periodicamente ao patrão, para recebimento dos valores devidos.

Obviamente, a equipe de vendas mantém um cadastro completo de todos os clientes, mesmo os eventuais. Este cadastro, sob a forma do velho fichário de cartolina, serve não apenas como fonte de consulta mas também como fonte de dados para marketing ativo. O fichário possui as seguintes informações:

Razão social e CGC da empresa cliente.

Endereço completo do cliente.

Os diversos telefones para contato com o cliente, bem como o nome dos empregados responsáveis.

Uma lista contendo o nome e a descrição dos itens habitualmente adquiridos pelo cliente.

A equipe de vendas mantém um catálogo completo de todos os itens disponíveis, contendo as seguintes informações:

Nome de cada item.

Descrição do item.

Preço de venda do item.

O último documento de interesse é o relatório utilizado pelo pessoal da entrega no ato do despacho para os diversos clientes. As seguintes informações são relevantes para a Limpa Tudo:

CGC e nome da empresa cliente.

Endereço para entrega dos produtos.

Nome do item entregue.

Page 235: Iniciando No Visual Basic

Quantidade entregue.

Preço total.

Transformação em Tópicos

O primeiro passo na criação das tabelas é definir o tópico de cada uma. Em outras palavras, precisamos definir a entidade do negócio representada pela tabela. Como ficou evidente na seção anterior, a Limpa Tudo é uma empresa bastante organizada. Sendo assim, podemos utilizar os próprios documentos de entrada nessa definição.

Neste primeiro momento, definiremos apenas o tópico de cada tabela e as informações relacionadas a ele, sem quaisquer preocupações quanto à redundância dos dados. Este passo é fundamental, já que uma tabela é um conjunto de informações referentes a um tópico determinado. Além disso, já daremos nomes definitivos para cada item de dados, de acordo com as convenções permitidas pelo Microsoft Jet.

Evidentemente, a entidade-chave no sistema será o Produto vendido pela Limpa Tudo. A Figura 13.2 descreve, sumariamente, o tópico Produtos. Os campos com asterisco representam aquelas informações passíveis de repetição dentro do tópico:

Figura 13.2: O tópico Produtos.

O segundo tópico a ser descrito é o de Fornecedores, listado na Figura 13.3:

Figura 13.3: O tópico Fornecedores.

O próximo tópico abordado - os Clientes - fecha o conjunto de entidades básicas representadas. Veja a Figura 13.4:

Figura 13.4: O tópico Clientes.

Note que não incluímos na tabela um campo para armazenar os itens habitualmente adquiridos pelo cliente, mantido pelos documentos da Limpa Tudo. Não o fizemos porque essa informação tem finalidade estatística e pode ser facilmente obtida da tabela de pedidos, vista mais adiante. Isso sugere uma importante recomendação: não armazene informações calculadas ou que possam ser obtidas por outros meios, ainda que indiretos. Tais informações não são essenciais. A única razão para armazená-las decorre de

Page 236: Iniciando No Visual Basic

considerações de performance. Contudo, nestes casos, deve-se avaliar cuidadosamente os ganhos obtidos.

O próximo tópico descrito será o Estoque. Aqui será importante distinguir a posição corrente dos itens em estoque do fluxo de entrada e saída dos produtos. Este será mantido em separado, já que representa um tópico diverso, com finalidade diversa - um histórico de operações. A Figura 13.5 lista, então, o tópico:

Figura 13.5: O tópico Estoque.

Abordaremos agora o fluxo diário de itens em estoque. A Figura 13.6 lista a definição do tópico Transações:

Figura 13.6: O tópico Transações.

Como se pode notar, não incluímos as informações referentes ao fornecedor e ao preço do produto, mantidas no documento da Limpa Tudo, visto na seção anterior. Tais informações não se referem ao assunto representado pelo tópico presente.

Tratemos agora do pedido de Fornecimento, tópico listado na Figura 13.7:

Figura 13.7: O tópico Fornecimento.

A Figura 13.8 lista o próximo tópico relevante - o pedido de Vendas:

Figura 13.8: O tópico Vendas.

Normalização

Ao longo da seção anterior, preocupamo-nos somente em definir cada assunto ou tópico e as informações necessárias para descrevê-lo por completo. Em momento algum analisamos o problema da organização eficiente de cada um. Há grupos de informações repetidas dentro de um mesmo tópico; há também informações repetidas desnecessariamente entre tópicos. Devemos eliminar esta redundância.

Um outro problema é que as entidades básicas estão definidas por seus nomes. Isto pode ocasionar inconsistência dos dados, já que nomes longos podem ser informados, favorecendo erros de digitação e dificultando a localização. É comum a utilização de códigos numéricos para essas entidades.

Page 237: Iniciando No Visual Basic

Um outro problema no qual podemos avançar é definir claramente o tipo de dado requerido por cada um dos campos, para garantirmos rigorosa consistência entre eles desde já. Campos conceitualmente afins devem receber, além de um mesmo nome, tipos de dados rigorosamente iguais.

Logo no tópico Produtos encontramos matéria para discussão. Ele possui duas informações passíveis de repetição dentro da tabela - Nome do Fornecedor e Preço de Compra - ambas relacionadas. Esta redundância deve ser eliminada. Não admita grupos de informações repetidas dentro de uma tabela. Neste caso, divida as informações em duas tabelas.

Uma outra questão diz respeito à Categoria do produto. Este campo possui, por definição, um conjunto definido de valores possíveis, conhecidos de antemão. Assim, é conveniente codificarmos o campo, colocando sua descrição em outra tabela. Embora a economia de bytes seja pequena, o princípio é útil. Encontrando valores de um campo selecionáveis de um conjunto limitado de valores possíveis, é conveniente situá-los numa tabela em separado -conhecida como tabela de autoconsulta.

Assim, o tópico Produtos pode ser organizado em três tabelas separadas,

listada na Figura 13.9:

Figura 13.9: O tópico Produtos dividido em tabelas.

O tópico fornecedores também padece de alta redundância. Os campos Nome do Produto e Preço de Compra, relacionados a um Fornecedor, já estão definidos na tabela Produtos Por Fornecedor. Podem, portanto, ser eliminados. Cidade e UF podem compor uma tabela em separado pela mesma razão usada para criar a tabela Categorias. Apenas o CEP basta para definir uma cidade e um estado.

Note também que as informações sobre o Telefone e o Contato, parte integrante do tópico Fornecedores, podem se repetir. Como já vimos, nestes casos devemos criar uma outra tabela. Esta, entretanto, será conceitualmente distinta, por exemplo, da tabela Categorias ou da tabela de Localidades.

Em primeiro lugar, cada registro na tabela Fornecedores poderá se referir a inúmeros registros na tabela de Telefones. Além disso, não

Page 238: Iniciando No Visual Basic

faz sentido mantermos um registro na tabela de Telefones sem um correspondente na tabela de Fornecedores. Neste caso, devemos criar o que se convencionou chamar uma tabela-filha. Esta é uma tabela na qual todas as entradas compartilham algumas informações comuns, armazenadas em outra tabela. No momento, isso não terá efeitos práticos. A razão dessa consideração ficará clara na próxima seção.

Vale, porém, uma observação. Sempre que criar uma tabela-filha, assegure-se de que as atualizações efetuadas na tabela-pai se propaguem para a filha. Além disso, não admita registros órfãos (sem correspondência na tabela-pai) na tabela-filha.

Desse modo, podemos criar as tabelas definidas a seguir para melhor representar o tópico Fornecedores:

Figura 13.10: O tópico Fornecedores dividido em tabelas.

O tópico Clientes não apresenta nada de novo. Os campos Cidade e UF já estão definidos na tabela Localidades e podem ser eliminados. Os campos Telefone e Contato devem receber o mesmo tratamento da tabela Telefones dos Fornecedores, criando-se uma tabela-filha. Assim, precisamos criar somente as tabelas descritas a seguir:

Figura 13.11: O tópico Clientes tratado.

O tópico Estoque também pode ser reduzido. Os campos Nome do Produto, Descrição e Categoria podem ser substituídos pelo código do Produto, tal como definido na tabela Produtos. Assim, a tabela Estoque pode reduzir-se às definições listadas na Figura 13.12:

Figura 13.12: A tabela Estoque.

Nos tópicos Transações e Fornecimentos basta substituir os campos Nome do Produto e Razão Social pelos seus respectivos códigos. Os tópicos podem ser, então, definidos como naFigura 13.13:

Figura 13.13: As tabelas Transações e Fornecimento.

O tópico Vendas requer algumas considerações. O campo Preço de Venda é redundante, já que foi definido na tabela Produtos. Os campos referentes ao produto e à quantidade vendida podem repetir-se, já que uma mesma venda pode abranger inúmeros itens. A solução é, portanto, criar uma tabela-filha. Para referirmos as informações repetidas podemos criar um número identificador único, normalmente utilizado para fins de controle fiscal.

Page 239: Iniciando No Visual Basic

Um outro aspecto refere-se ao nome do vendedor. Do mesmo modo que o campo Categoria do produto, podemos criar uma tabela de autoconsulta de Vendedores e atribuir um código inequívoco a cada um deles. Outra questão refere-se às comissões. Em princípio, a comissão é única e calculada a partir do valor total da venda. Pode ser possível, entretanto, a utilização de comissões crescentes por faixas de valores, visando estimular o negócio. Justifica-se, assim, uma tabela específica.

O tópico, então, pode ser definido como descrito na Figura 13.14:

Figura 13.14: O tópico Vendas normalizado.

Relacionamento Entre Tabelas

O passo seguinte é definir os diversos relacionamentos entre as tabelas. Como já vimos, o relacionamento se define a partir da duplicação de atributos de diferentes tabelas: a chave primaria na tabela primária e a chave externa na tabela dependente. Cabe, portanto, definirmos a chave primária de cada tabela a ser relacionada às demais. Como já sabemos, a chave primária individualiza um registro, não podendo, portanto, conter valores repetidos em mais de um registro da tabela.

A Figura 13.15 lista os campos sugeridos como chave primária da base de dados que viemos modelando:

Figura 13.15: As chaves primárias de campo único do base de dados da Limpa Tudo.

Evidentemente, não pudemos definir uma chave primária de campo único para aquelas tabelas que representam os históricos das operações da Limpa Tudo. Nessas tabelas, um único campo não pode identificar um registro. O mesmo não pode ser dito, porém, da combinação de alguns campos de cada tabela. Por exemplo, na tabela Faturas, a combinação de um código de Fatura e de um código de Produto identifica univocamente o registro. A Figura 13.16 lista as demais chaves primarias do banco de dados:

Figura 13.16: As chaves primárias de mais de um campo da base de dados da Limpa Tudo.

Por que essa preocupação em garantir que todas as tabelas possuam chaves primárias? No Microsoft Jet, só é possível estabelecer relacionamentos entre tabelas a partir de campos definidos como

Page 240: Iniciando No Visual Basic

chaves primárias. Em essência, um relacionamento exprime uma ligação entre a chave primária de uma tabela e a chave externa de uma tabela dependente.

Estamos prontos, agora, para definir os relacionamentos entre as diversas tabelas. Comecemos pelo tópico Produtos. Você se lembra que dividimos o tópico em três tabelas relacionadas - Produtos, Categorias e Produtos Por Fornecedor. Trata-se, pois, de definir claramente como elas se relacionam.

Um registro na tabela Categorias pode referenciar vários registros na tabela Produtos. E mais: havendo necessidade de se alterar uma determinada codificação de categoria de produto, essa atualização deve-se propagar para a tabela dependente; é o caso de se impor a integridade referencial no relacionamento, forçando a propagação de eventuais atualizações.

Por outro lado, um registro na tabela de Produtos pode referenciar vários registros na tabela Produtos Por Fornecedor, na medida em que um mesmo item pode ser fornecido por diferentes empresas. Aqui também deve-se impor integridade referencial entre as tabelas: removendo-se um registro na tabela de Produtos, ele deve ser também removido na tabela dependente.

Graficamente, o relacionamento entre as três tabelas do tópico pode ser expresso como na Figura 13.17.

O tópico Fornecedores relaciona as tabelas Fornecedores, Telefones dos Fornecedores e Localidades. Um registro na tabela Fornecedores pode referir mais de um registro na tabela Telefones dos Fornecedores, devendo-se prever exclusões em cascata dos registros, já que a tabela dependente é uma tabela-filha. A tabela Localidades possui relação um-para-vários com a tabela Fornecedores, devendo-se também prever atualizações, mas não exclusões, em cascata. Graficamente, o relacionamento pode se exprimir como na Figura 13.18.

Figura 13.17: Relacionamentos do tópico Produtos.

Figura 13.18: Relacionamentos do tópico Fornecedores.

No tópico Clientes - composto pelas tabelas Clientes, Localidades e Telefones dos Clientes - o relacionamento é precisamente o mesmo que no tópico Fornecedores. Observe apenas que a tabela Localidades possui o mesmo tipo de relacionamento simultaneamente

Page 241: Iniciando No Visual Basic

com duas tabelas. Graficamente, o relacionamento do tópico pode ser expresso como na Figura 13.19.

Continuemos. Um registro na tabela Estoque possui um relacionamento direto, de um-para-um, com um único registro da tabela Produtos. Um registro na tabela Fornecedores possui um relacionamento um-para-vários com a tabela Produtos Por Fornecedor. Em ambos os casos, deve-se impor a integridade referencial dos dados promovendo exclusões em cascata sempre que houver uma exclusão na tabela determinante da dependência.

Figura 13.19: Relacionamentos do tópico Clientes.

A tabela Produtos possui relacionamento de um-para-vários também com as tabelas Fornecimento e Transações. É conveniente impor a integridade referencial dos dados visando evitar a existência de registros órfãos nas tabelas dependentes.

Analisemos agora o tópico Vendas. Este é composto das tabelas Vendas, Faturas e Vendedores. Em primeiro lugar, devemos assinalar que entre Vendas e Faturas existe uma relação de um-para-vários - relacionamento estabelecido pelo campo Fatura - onde se deve impor integridade referencial, garantindo exclusões em cascata, sempre que um registro na tabela-pai (Vendas) for removido. Por outro lado, um registro na tabela Vendedores pode referir vários registros na tabela Vendas. Neste relacionamento, devemos impor a integridade referencial dos dados, garantindo que as eventuais alterações na tabela Vendedores se propaguem, automaticamente, para a tabela dependente. O relacionamento do tópico pode ser representado como na Figura 13.20:

Figura 13.20: Relacionamentos do tópico Vendas.

Analisemos, agora, os relacionamentos finais. Um registro na tabela de Clientes pode corresponder a vários registros na tabela de Vendas. Neste caso, devemos garantir que eventuais atualizações na tabela primária se propaguem para a tabela dependente, impondo a integridade referencial dos dados. Graficamente, o relacionamento global das diversas tabelas da base de dados pode ser representado como na Figura 13.20:

Figura 13.21: Os relacionamentos da base de dados da Limpa Tudo.

 

Page 242: Iniciando No Visual Basic

O Microsof Jet Database Engine e o VB

O Microsoft Jet e os Tipos de Dados

O Jet suporta uma grande quantidade de diferentes tipos de dados, garantindo total compatibilidade tanto com o Microsoft Access quanto com os tipos de dados definidos pelo padrão ANSI da SQL. A figura abaixo ilustra os tipos de dados disponíveis no mecanismo Jet e no padrão SQL associado, além de sua compatibilidade com os diversos tipos de dados do VB.

Figura 14.0 Os tipos de dados suportados pelo Microsoft Jet

Modos de Interação da Aplicação com o Microsoft Jet Engine

O Visual Basic oferece duas formas de comunicação entre aplicações e o mecanismo Jet: o controle Data e os objetos de acesso a dados (DAO).

O controle Data faz parte da caixa de ferramentas padrão e pode ser inserido em formulários como qualquer outro controle. Seu papel é fazer intermediação entre a aplicação e um banco de dados de modo a automatizar tarefas comuns como inclusões, alterações, exclusões e navegação em meio à massa de registros.

Enquanto o controle Data lhe dá poder para acessar bancos de dados existentes com pouca programação, o modelo DAO é uma completa interface de programação que lhe dá total controle sobre o banco de dados. Esses dois recursos, porém, não são mutuamente exclusivos, podendo em muitas ocasiões até mesmo ser desejável combiná-los. Trataremos de início dos objetos de acesso a dados por ser um estudo que nos dará elementos para compreender melhor o uso do controle Data.

Biblioteca de Objetos de Acesso a Dados (DAO)

Um dos mais importantes recursos do Visual Basic é a sua biblioteca de objetos de acesso a dados ou DAO (Data Access Objects). São objetos que você pode criar em tempo de execução para acessar dados tanto em arquivos de banco de dados do Access - o banco de dados nativo do Visual Basic - como em outros tipos de banco de dados locais como dBase, Paradox e também acessar dados em

Page 243: Iniciando No Visual Basic

bancos de dados cliente-servidor como o Microsoft SQL Server usando a tecnologia ODBC.

Os objetos de acesso a dados estão organizados numa hierarquia, na qual muitos objetos pertencem a coleções de objetos, que também, por sua vez, pertencem a outros objetos que lhes estão acima na ordem hierárquica. A completa hierarquia da DAO está ilustrada abaixo.

Figura 14.1: A hierarquia da DAO

Estamos usando a palavra objeto para nos referirmos aos data access objects, mas na verdade não são objetos e sim de classes. Do mesmo modo como você cria instâncias de suas próprias classes, você o faz com os objetos de acesso a dados. Veremos isso nos exemplos. Antes faremos uma breve introdução aos objetos da DAO.

O Objeto DBEngine

No topo da hierarquia da DAO está o objeto DBEngine e corresponde ao dispositivo Microsoft Jet de acesso a dados. O objeto DBEngine é usado para ajustar os parâmetros do sistema de banco de dados utilizado pelo VB e para definir a área de trabalho default. O DBEngine é o único objeto que você não pode instanciar. Ele é criado automaticamente quando sua aplicação faz a primeira referência a um objeto da DAO.

O Objeto Workspace

Logo abaixo do objeto DBEngine, na hierarquia da DAO, está o objeto Workspace (área de trabalho). Esse objeto é utilizado para criar e identificar uma sessão de trabalho para um usuário. Ele contém os bancos de dados abertos e provê controle sobre transações simultâneas e segurança de acesso.

Um objeto Workspace default - Workspace(0) - é criado automaticamente na primeira referência a um objeto DAO pela aplicação. Ele pode ser inicializado com um Username (nome de usuário) e com uma Password (senha). Ao contrário de outros objetos Workspace, a área de trabalho default está sempre disponível, não podendo ser fechada nem removida da coleção Workspaces.

Objeto Database

O objeto Database representa um banco de dados, nativo do Jet ou não. É utilizado para definir as tabelas do banco de dados,

Page 244: Iniciando No Visual Basic

relacionamentos entre tabelas, consultas armazenadas, além de permitir a abertura de objetos Recordset - que veremos mais adiante.

Objeto TableDef

O objeto TableDef corresponde a uma definição de tabela armazenada. Cada TableDef da coleção TableDefs representa a definição de uma tabela no banco de dados corrente, ou uma tabela externa anexada à base de dados. Neste último caso o objeto TableDef não pode ter seus atributos alterados.

Objeto QueryDef

O objeto QueryDef representa uma consulta escrita em linguagem SQL armazenada no banco de dados. Uma consulta armazenada é um comando SQL pré-compilado. É possível ler e modificar o código SQL de um objeto QueryDef, ajustar seus parâmetros e, então , executar a consulta.

Objeto Recordset

O objeto Recordset corresponde a uma visão ponteirada de uma tabela ou do conjunto de registros resultantes de uma consulta a uma ou mais tabelas. Uma visão ponteirada é o armazenamento de registros numa área de memória (buffer), apontando para um registro de cada vez, chamado registro corrente. O ponteiro (registro corrente) pode ser reposicionado em qualquer registro utilizando-se os métodos move, seek ou find. Ele permite a navegação, atualização e remoção das tabelas subjacentes ao recordset. Como a visão dos dados de um banco, o Recordset não contém ele mesmo os dados: apenas aponta para eles. Nesse sentido não é armazenado no banco, tendo utilização temporária. Quando um recordset é fechado, ele é removido da coleção Recordsets e todos os recursos associados são removidos da memória.

É possível a criação de três tipos de recordsets:

Tipo tabela: Um recordset tipo tabela corresponde a uma tabela do banco de dados. Quando um recordset desse tipo é aberto, o programador passa a ter acesso à tabela subjacente.

Tipo dynaset: Um recordset do tipo dynaset corresponde a uma tabela "virtual" resultante de uma consulta feita a uma ou mais tabelas. Ao ser atualizada, todas as alterações feitas no objeto se refletem imediatamente nas tabelas subjacentes.

Page 245: Iniciando No Visual Basic

Tipo snapshot: Um recordset do tipo snapshot é um conjunto estático de dados, similar ao dynaset porém não admite atualização. Outra diferença é que os snapshots têm o conjunto de registros carregado na memória. Se de um lado isso os torna mais rápidos, por outro cria o problema de haver conflitos com limitações de memória. Ajustam-se melhor para pequenas quantidades de registros que não precisam ser editados.

Objeto Field

O objeto Field corresponde a uma coluna de dados contendo um tipo de dado comum e um conjunto de atributos. É apenas um campo do banco de dados. Nesse sentido, os objetos TableDef, QueryDef, Recordset, e Index possuem coleções Fields. A coleção de objetos Field associada ao ponteiro de um recordset descreve um registro. Os dados do recordset são lidos e atualizados através da propriedade Value do objeto Field. Quando o ponteiro do recordset é movido e passa a apontar para um novo registro, todos os objetos Field da coleção Fields são automaticamente atualizados.

Objeto Index

O objeto Index representa um índice associado a um objeto TableDef ou Recordset, sempre do tipo tabela. O Índice corrente pode ser especificado num recordset tabela atribuindo-se um dos índices da coleção Indexes à sua propriedade Index. A atribuição da propriedade Index permite reordenar rapidamente os registros de uma tabela.

Objeto Parameter

O objeto Parameter representa um parâmetro de consulta armazenada no banco de dados. A coleção Parameters dos objetos QueryDef e Recordset permite ao programador acessar as informações contidas no parâmetro da consulta .

 

Segurança de Acesso

Objeto User

O objeto User é utilizado para definir e garantir a segurança do banco de dados. Adicionando ou removendo membros à coleção Users, criam-se ou removem-se contas de acesso para os usuários do sistema. Cada objeto User é criado com um nome uma senha. As

Page 246: Iniciando No Visual Basic

permissões de acesso aos objetos do sistema, tais como TableDef e QueryDef, podem ser definidas para os usuários individualmente.

Objeto Group

Um objeto Group representa uma coleção de usuários com os mesmos direitos de acesso. O objeto DBEngine suporta um conjunto de grupos no acesso ao sistema. Cada usuário dentro de um grupo herda as permissões de acesso a todos os objetos acessados pelo Group.

Objeto Container

Os objetos Container são utilizados em conjunto com os objetos Document para enumerar todos os objetos armazenados no banco de dados, incluindo aqueles definidos por aplicações clientes. O principal uso dos objetos Container é enumerar todos os objetos armazenados no banco de dados , definindo permissões de acesso e usuários proprietários.

Objeto Document

Os objetos Document são objetos de um tipo comum que partilham um Container. Permissões de acesso podem ser definidas para um objeto Document, alterando privilégios de segurança.

Objeto Relation

O objeto Relation é utilizado para definir o relacionamento entre campos de dois objetos TableDef. Cada objeto Database possui uma única coleção de objetos Relation. O Jet pode forçar determinadas condições de atualização dos dados associados aos campos dos objetos Relation visando manter a integridade referencial dos dados do banco. A adição ou remoção de objetos Relation cria ou remove relações entre tabelas do banco de dados.

Objeto Property

O objeto Property representa uma propriedade associada a um objeto do banco de dados. Tanto as propriedades "intrínsecas" quanto as propriedades definidas pelo programador são armazenadas na coleção Properties associada ao objeto. É possível criar novas propriedades adicionando novos objetos Property à coleção Properties. Tais propriedades podem ser armazenadas no banco de dados e referem-se somente ao objeto especificado e não aos demais objetos da mesma classe.

Page 247: Iniciando No Visual Basic

Os seguintes objetos DAO suportam a definição de novas propriedades:

Database

TableDef

QueryDef

TableDef.Index

TableDef.Field

QueryDef.Field

Praticando com os Objetos da DAO

É o momento de colocar em prática os inúmeros conceitos estivemos expondo. Usaremos a versão de 32 bits na criação das tabelas. Assim, não deixe de incluir uma referência à Microsoft DAO 3.5 Object Library na opção References do menu Project do VB5.

A Criação do Banco de Dados

O primeiro passo será a criação de um arquivo no formato Microsoft Access. Normalmente os programadores criam o banco de dados no Microsoft Access e não no VB. É muito mais cômodo utilizar a interface amigável do Access para criar todas as tabelas, campos, consultas, ... do que escrever código em VB para construir a estrutura do banco de dados. Como, no entanto, o programador de VB deve conhecer bem as relações entre os objetos da DAO, o estudo dos meios de construção de um banco de dados por código é de grande importância.

Sempre que um arquivo de banco de dados é aberto - ou criado - é necessário que especifiquemos uma área de trabalho onde abri-lo. Caso nenhuma área seja definida, o VB, automaticamente, abre o arquivo na área de trabalho default, endereçada pelo índice 0 da coleção Workspaces do objeto DBEngine. No entanto, é sempre boa prática de programação a definição explícita de uma área de trabalho.

A criação do banco de dados pode ser feita pelo método CreateDatabase( ) do objeto Workspace. A referência retornada pelo método pode ser utilizada, imediatamente, para criar tabelas, etc.

Page 248: Iniciando No Visual Basic

Método CreateDatabase

O método CreateDatabase( ) cria um novo objeto Database, salva o banco de dados no disco e retoma uma referência ao objeto criado. Aplicável somente aos objetos Workspace.

Sintaxe

Set ObDatabase = ObWorkspace.CreateDatabase(nomeDoArquivo, localização[, opções])

O seguinte fragmento de código cria um banco de dados na versão 3.0 da DAO chamado BASE32.MDB no diretório corrente:

 

Dim BaseDeDados As Database

Set BaseDeDados = DBEngine.Workspaces(0). _

CreateDatabase(App.Path & "\Base32.Mdb", _

dbLangGeneral, dbVersion30)

 

Utilizamos a área de trabalho default para abrir o banco de dados, referindo-a explicitamente. As constantes utilizadas como argumentos para o método são definidas no próprio VB: a constante dbLangGeneral indica a criação de um banco de dados com ordenamento de strings compatível com a Língua Portuguesa; a constante dbVersion30 indica um banco de dados no formato do Microsoft Access para Windows 95. Note apenas que tal formato é incompatível com versões anteriores da DAO ou do próprio Access.

O objeto Database retomado pelo método pode ser utilizado imediatamente para a definição das tabelas do arquivo. Observe que se o arquivo existir, um erro será gerado em tempo de execução.

Criando Tabelas

A criação de uma tabela requer as seguintes condições mínimas:

1 . Uma referência a um objeto Database onde será adicionada a tabela. Se o arquivo não existir, deve ser criado; caso contrário, deve ser aberto.

Page 249: Iniciando No Visual Basic

2. A criação de um objeto TableDef, através do método CreateTableDef( ). Este representará a

tabela criada.

3. A criação dos objetos Field necessários para representar a totalidade dos campos da tabela, feita através do método CreateField( ).

4. A atualização das propriedades de cada objeto Field, na medida das necessidades da tabela.

5. A anexação de cada objeto Field à coleção TableDefs, com o método Append.

6. A anexação do objeto TabIeDef criado à coleção Databases, também com o método Append.

Vamos criar uma tabela como exemplo. Utilizemos a definição dada à tabela Categorias, no Capítulo 13. A Figura 14.2 lista as propriedades de cada campo da tabela:

Figura 14.2: As definições da tabela Categoria.

Como o arquivo BASE32.MDB já existe - criamos no código para CreateDatabase -, precisamos abrí-lo, utilizando o método OpenDatabase( ), aplicável somente a um objeto Workspace.

Método OpenDatabase

O método OpenDatabase( ) abre o banco de dados especificado numa sessão, determinada por um objeto Workspace, e retorna uma referência a um objeto Database. O banco de dados aberto é automaticamente adicionado à coleção Databases da área de trabalho.

Sintaxe

Set ObDatabase = ObWorkspace.OpenDatabase(nomeDoArquivo [,

modoExclusivo[, somenteParaLeitura[, fonteDeDados]]])

O passo seguinte será a criação de um objeto TableDef para referir a tabela a ser criada. Isto é feito pelo método CreateTableDef( ), aplicável somente aos objetos Database.

Page 250: Iniciando No Visual Basic

 

Método CreateTableDef

 

Cria um objeto TableDef para representar uma nova tabela do banco de dados.

Sintaxe

Set ObTabIeDef = ObDatabase.CreateTableDef([nomeDaTabela[, _

atributos[, fonteDeDados[, informaçãoDeConexão]]]])

Como vimos, cada um dos campos da tabela será representado por um objeto Field, criado pelo método CreateField( ) aplicado ao objeto TabIeDef anteriormente criado.

Método CreateField

Cria um objeto Field para representar um novo campo de banco de dados, aplicável aos objetos Index, Relation e TableDef.

Sintaxe

Set ObField = ObVariável.CreateField([nomeDoCampo[, tipoDeDado[, tamanho]]])

O seguinte fragmento de código cria uma nova tabela no banco de dados aberto:

 

Figura 14.3

 

O código acima, por razões didáticas, segue rigorosamente o passo-a-passo sugerido para a criação de uma tabela. Nós definimos cada uma das propriedades dos campos utilizando um objeto Field e anexando à coleção Fields do objeto TableDef criado para representar a tabela. Isso foi feito com o método Append.

Método Append

Page 251: Iniciando No Visual Basic

Adiciona um novo objeto de acesso a banco de dados a uma coleção. Aplicável a todas as coleções da DAO.

Sintaxe

Coleção.Append novoObjeto

Após cada definição ter sido criada, anexamos o objeto TableDef à coleção TableDefs do banco de dados, referido pela variável Database BaseDeDados. Isso também foi feito com o método Append.

Adicionando Índices

A criação de um índice para uma tabela requer os seguintes passos:

1. Um objeto TableDef ao qual anexar a definição de índice. Se a tabela não existir, deverá ser criada como exposto anteriormente; caso contrário, sua definição deverá ser aberta na forma Set ObTableDef = ObDatabase.TableDefs("NomeDaTabela").

2. Um objeto Index, criado com o método CreateIndex( ) aplicado ao objeto TableDef.

3. A atualização das propriedades do objeto Index, quando for o caso.

4. Um objeto Field para cada campo componente da chave de índice, criados com o método CreateField( ), mostrado anteriormente.

5. A anexação de cada objeto Field ao objeto Index criado para armazenar a definição do índice. Isto é feito pelo método Append, tal como já falamos.

6. A anexação do objeto Index ao objeto TabIeDef aberto, também com o método Append.

Exemplo:

Figura 14.4: A definição de tabela Clientes.

Propriedades para o índice primário da tabela:

Figura 14.5: A definição do índice primário da tabela Clientes.

Note que ajustar a propriedade Unique do índice não é estritamente necessário, já que um índice primário (propriedade Primary igual a

Page 252: Iniciando No Visual Basic

True) é, por definição, sempre único. O fragmento de código seguinte cria a tabela Clientes e seu índice primário:

Figura 14.6

Todo o código até a criação do objeto Index funciona da mesma maneira que no exemplo anterior. Apenas utilizamos um novo meio de expressar as mesmas ações. Para criar o índice, utilizamos o método CreateIndex( ), aplicável somente a um objeto TableDef e ajustamos suas propriedades de acordo com a definição de um índice primário.

Método CreateIndex

Cria um objeto Index para representar um novo índice de uma tabela.

Sintaxe

Set ObIndex = ObTableDef.CreateIndex([nomeDoÍndice])

O passo seguinte foi criar a expressão de indexação do objeto. Ora, uma expressão de índice é, simplesmente, uma lista de campos componentes. Assim, para cada campo da expressão, criamos um objeto Field para representá-lo. Isso foi feito com o método CreateField( ), já conhecido. Note que apenas especificamos o nome do campo, uma vez que sua definição já existe.

A criação final do índice envolveu apenas anexar o objeto Field ao objeto Index, definindo uma expressão de indexação e anexar este ao objeto TableDef. Tudo com o método Append.

Adicionando Relações

A definição de um relacionamento pela DAO envolve os seguintes passos:

1. Um objeto Database, referindo um banco de dados aberto. Naturalmente, as tabelas a relacionar devem existir e ser estruturadas de tal forma que o relacionamento possa ser estabelecido. O campo a relacionar deve ser a chave primária da tabela origem e do mesmo tipo na tabela dependente (a chave externa).

2. A criação de um objeto Relation, feita pelo método CreateRelation(, aplicável somente a um objeto Database.

Page 253: Iniciando No Visual Basic

3. A definição das propriedades do relacionamento; basicamente a tabela origem (propriedade Table) e a tabela dependente (propriedade ForeignTable).

4. Definir a natureza do relacionamento (se um-para-um ou um-para-vários, se a integridade referencial deve ser preservada, etc.), ajustando a propriedade Attributes do objeto. Consulte a documentação do VB para as constantes predefinidas disponíveis.

5. A criação de um objeto Field, utilizando o já conhecido método CreateField, para definir o campo comum da relação.

6. A definição da chave externa do relacionamento, ajustando a propriedade ForeignName do objeto Field para o campo relacionado.

7. A adição do campo à coleção Fields do objeto Relation e a sua adição à coleção Relations do objeto Database aberto, para criar efetivamente o relacionamento.

Método CreateRelation( )

Cria um novo objeto Relation para a especificação de um relacionamento entre tabelas.

 

Sintaxe

Set ObRelation = ObDatabase.CreateRelation([nomeDaRelação[, _

tabelaOrigem [, tabelaDependente [, atributos ]]]])

Uma vez mais, utilizaremos como exemplo uma das definições feitas no capítulo anterior. Vamos definir o relacionamento entre a tabela Produtos e a tabela Produtos Por Fornecedor. A Tabela 3.5 lista as definições do relacionamento:

Figura 14.7: As definições do relacionamento entre a tabela Produtos e a tabela Produtos Por Fornecedor.

O seguinte fragmento de código cria o referido relacionamento:

Figura 14.8

 

Page 254: Iniciando No Visual Basic

Objeto Relation

Propriedades

A propriedade Attributes indica as características do objeto. A propriedade ForeignTable especifica tabela dependente na relação. A propriedade Table especifica a tabela primária na relação definida.

Sintaxe

Objeto.Attributes [= valorConstante]

ObRelation.ForeignTable [= nomeDaTabela]

ObRelation.Table  [= nomeDaTabela]

O código-fonte segue, rigorosamente, o passo-a-passo anterior, não merecendo maiores comentários. Note apenas que não precisamos definir o tipo de relacionamento um-para-vários, atribuído por default. Além disso, a imposição da integridade referencial dos dados é atribuída por default à propriedade Attributes. Caso precise utilizar mais de uma constante, apenas some seus valores. Por exemplo, a declaração dbRelationUnique + dbRelationUpdateCascade define um relacionamento de um-para-um com atualização em cascata.

ForeignName

Propriedade

Especifica o campo utilizado como chave externa de uma relação. Por definição, o campo deve pertencer à tabela dependente e se relacionar a um campo definido como chave primária na tabela de origem da relação.

Sintaxe

ObField.ForeignName [= nomeDoCampo  ]

A Criação de Consultas

Como foi visto nas primeiras seções deste capítulo, o Microsoft Jet oferece amplo suporte à utilização da SQL. É possível não apenas a execução de declarações SQL, como também o seu armazenamento no banco de dados. Uma vez armazenada a consulta, ela pode ser alterada ou removida.

Page 255: Iniciando No Visual Basic

Nesta seção, enfocaremos apenas o armazenamento e a remoção de consultas de um banco de dados, deixando para mais adiante a sua utilização. Não discutiremos, porém, a própria linguagem SQL. Mais informações sobre SQL podem ser encontradas na apostila específica de SQL, que acompanha este manual.

Como vimos no sumário da DAO, o Microsoft Jet fornece um objeto QueryDef para a manipulação de declarações SQL armazenadas no banco de dados. Além disso, todo objeto Database possui uma coleção QueryDefs, contendo informações sobre todas as consultas armazenadas.

A criação e o armazenamento de uma consulta num banco de dados requerem somente os seguintes passos:

1. Um objeto Database, referindo o banco de dados onde a consulta será armazenada.

2. A criação de um objeto QueryDef, através do método CreateQueryDef( ), para o armazenamento da consulta. Observe que o método pode salvar, automaticamente, a consulta no banco de dados.

3.. A especificação da declaração geradora da consulta, atribuindo-se uma declaração válida à propriedade SQL do objeto QueryDef.

Método CreateQueryDef( )

Cria um objeto QueryDef, podendo armazenar a definição da consulta SQL no banco de dados.

Sintaxe

Set ObQueryDef = ObDatabase.CreateQueryDef([ nomeDaConsulta  ][, declaraçãoSQL  ])

Para o nosso exemplo, suponhamos que seja necessário um relatório contendo os seguintes dados: Descrição da categoria do produto, Nome do Produto e Preço de Venda. O objetivo básico do relatório é fornecer uma lista abrangente de produtos aos clientes. Para isso, são necessários dados da tabela

Produtos e da tabela Categorias, utilizando-se uma consulta simples para extraí-los.

O fragmento de código a seguir ilustra a criação da consulta:

Page 256: Iniciando No Visual Basic

Figura 14.9

 

A Modificação de Estrutura do Banco de Dados

Uma vez criado um banco de dados, a alteração da sua estrutura sofre algumas restrições. Índices, campos e relacionamentos não podem ter suas propriedades alteradas. Para isso, é necessário primeiro remover o objeto, recriando-o com a nova configuração. A remoção de um objeto de uma coleção qualquer é feita com o método Delete.

Método Delete

Aplicado a um Recordset, o método Delete remove o registro corrente. Aplicado a uma coleção, remove o objeto especificado.

Sintaxe

ObRecordset.Delete

Objeto.Coleção.Delete nomeDoObjeto

Mesmo a remoção de alguns objetos sofre restrições, a saber:

Não é possível remover um campo que faça parte de uma expressão de índice ou de uma relação. Para isso, é necessário, primeiro, remover o índice ou a relação.

Não é possível remover um índice que esteja mantendo uma relação. Para isso, é necessário remover, primeiro, a relação.

Não é possível remover uma tabela que esteja suportando um relacionamento. É preciso, primeiro, remover a relação.

A alteração de uma consulta armazenada envolve apenas a alteração da propriedade SQL do objeto QueryDef. O seguinte fragmento de código ilustra a remoção de uma tabela e a alteração de uma consulta SQL:

Figura 14.10

 

Manutenção do Banco de Dados

Page 257: Iniciando No Visual Basic

Visando incrementar a performance do acesso ao banco de dados, sempre crítica num sistema relacional, o Microsoft Jet (e o Microsoft Access) não removem as páginas de registros eventualmente deletadas do banco de dados. Esse artifício, embora garanta uma performance adequada aos aplicativos de acesso, consome consideráveis quantidades de disco, já que os arquivos tendem a se expandir mais do que o crescimento dos registros.

Por outro lado, erros de sistema ocorridos durante operações críticas podem danificar o banco de dados. Se o dano não for extenso, é possível corrigi-lo.

Para estes casos, são indispensáveis recursos de manutenção do bancos de dados, como compactação e correção de erros. O Microsoft Jet fornece ferramentas suficientes para tratar o problema. É o que veremos nesta seção.

Compactando um

Arquivo

O objeto de sistema DBEngine suporta um método CompactDatabase, que copia todos os dados de um banco de dados para outro. No processo, o arquivo é otimizado, resultando na recuperação de espaço eventualmente desperdiçado.

Método CompactDatabase

Copia e compacta um banco de dados, permitindo a alteração de versão, definição de ordenamento e criptografia do arquivo.

Sintaxe

DBEngine.CompactDatabase arquivoAntigo, arquivoNovo  [, localização  [,

opções]]

Não é possível compactar um banco de dados aberto. Além disso, não se deve utilizar o mesmo nome no processo, já que o arquivo anterior será removido, mesmo que a compactação não se complete.

Para ilustrar o método, criaremos uma rotina de uso geral razoavelmente segura para a compactação de bancos de dados compatíveis com o Microsoft Access. Veja o código nas três figuras que se seguem:

Page 258: Iniciando No Visual Basic

Figura 14.11: Função CompactDatabase.

Figura 14.12: Função para obter arquivo temporário.

Figura 14.13: Função para verificar existência de arquivo.

O objetivo básico da rotina é tornar mais fácil e completamente seguro o processo de compactação.

De uma forma geral, a compactação de um banco de dados envolve os seguintes passos:

1. Criar um novo arquivo de dados, compactado.

2. Se a compactação foi bem-sucedida, remover o arquivo original.

3. Renomear o arquivo compactado com o nome de arquivo anterior.

Evidentemente, é preciso ter certeza de que o novo nome não corresponde a um arquivo existente. Caso contrário, ele seria sobrescrito. Tudo isso faz com que uma rotina de compactação tenha uma razoável quantidade de linhas de código. Só isso já justifica a existência de uma rotina genérica para automatizar essa complexidade.

Análise

CompactDatabase( )

A função recebe três parâmetros e retoma um lógico indicando se a operação foi bem-sucedida:

Uma string contendo o path completo e o nome do banco de dados a compactar.

Uma string opcional com informações de localização. Se o parâmetro não for passado, a função assume a constante predefinida dbLangGeneral.

Um inteiro opcional com a definição de criptografia. Caso o parâmetro não seja passado, a função assume o valor 0 (sem criptografia).

O primeiro passo da rotina é, portanto, validar seus argumentos, como descrito acima. A seguir, obtemos um nome de arquivo temporário da função TempNam( ), discutida mais adiante, ainda nesta seção. Se, por qualquer motivo, a função falhar, a rotina retoma um valor False.

Page 259: Iniciando No Visual Basic

Estamos, então, prontos para compactar o banco de dados, utilizando o DBEngine. Claro que precisamos monitorar eventuais erros no processo. Ainda assim, visando aumentar a segurança do processo (afinal, a rotina remove o banco de dados anterior), testamos novamente o sucesso da compactação. Simplesmente tentamos abrir o novo banco de dados, ainda monitorando erros. Se isso for possível, o banco foi corretamente compactado.

O passo final é remover o banco de dados antigo e renomear o novo banco de dados. Se o banco de dados temporário tiver sido criado num diretório diferente daquele onde se localizava o anterior, o comando Name moverá o arquivo e o renomeará.

TempNam( )

A função recebe os seguintes parâmetros, todos opcionais:

O prefixo do nome de arquivo temporário gerado. Caso o parâmetro não seja passado, a função assume o valor "~AXC".

A extensão do arquivo, incluindo o ponto. O valor default é ".TMP".

O caminho para o diretório onde se deseja criar o arquivo temporário. Caso o parâmetro esteja ausente, a função assume o diretório especificado nas variáveis ambientais "TEMP" e "TMP" ou, na ausência destas, o diretório corrente.

O primeiro procedimento da função é verificar os argumentos e assumir os valores default, se for o caso. A seguir, validamos o argumento Path. Isso é feito de maneira extremamente simples: apenas salvamos o diretório corrente e tentamos mudar para o path especificado. Se a operação não for bem-sucedida, o path é inválido e a função retorna. Caso contrário, retomamos ao diretório corrente e seguimos em frente.

Depois, construímos um path completo, incluindo a definição de drive e removemos a contrabarra final. Estamos prontos para gerar um nome temporário na instrução seguinte, concatenando o path e o prefixo do arquivo. A seguir, inicializamos o gerador de números aleatórios para a criação do restante do nome do arquivo.

A geração e teste do nome do arquivo é feita dentro de um loop. Os quatro caracteres restantes do arquivo são gerados aleatoriamente pela função Rnd e, formatados apropriadamente, são armazenados na variável TempName. Esta é concatenada à variável TempFile para a

Page 260: Iniciando No Visual Basic

criação de um caminho e nome completos de arquivo. Por fim, o loop testa se o arquivo já existe, chamando a função ArquivoExiste( ), comentada mais adiante. Se o arquivo existir, a função retorna True e o loop retorna. Caso contrário, um arquivo temporário foi gerado e a função o retorna.

Note que a função não cria efetivamente o arquivo, como a função da API do Windows GetTempFileName( ), apenas gera um nome válido para um arquivo inexistente.

ArquivoExiste( )

Para testar a existência do arquivo apenas tentamos abri-lo no modo compartilhado, tendo o cuidado de utilizar um modo de operação que não o danifique. Se a operação gerar um erro, mais especificamente o código de erro 53, o arquivo não existe no path especificado.

Reparando um Arquivo

Para reparar um arquivo danificado, utilizamos o método RepairDatabase, aplicável exclusivamente ao objeto DBEngine. A operação realizada por ele recupera um arquivo invalidado por uma operação incompleta de leitura e escrita de página de dados. Este tipo de dano ocorre freqüentemente quando o sistema é desligado subitamente, ainda com o arquivo aberto.

Método RepairDatabase

Recupera um arquivo Access danificado.

Sintaxe

DBEngine.RepairDatabase nomeDoArquivo

É preciso notar que nem todos os tipos de danos podem ser recuperados. Além disso, a operação de recuperação não otimiza o arquivo, deixando inúmeras páginas desnecessárias alocadas, consumindo espaço em disco. Assim, após uma recuperação bem-sucedida, é conveniente a compactação do banco de dados.

A rotina listada a seguir efetua as operações de reparação e compactação subsequente:

Figura 14.14: Reparando um banco de dados

Análise

Page 261: Iniciando No Visual Basic

A função RepairDatabase( ) recebe os seguintes parâmetros:

O nome do banco de dados a reparar. Note que o arquivo deve estar fechado para que a operação possa se realizar sem erros.

Uma string opcional contendo as informações de localização. Se o valor não for declarado, a rotina assume a constante predefinida dbLangGeneral.

Um inteiro opcional, definindo a criptografia do arquivo. Seu valor default é 0 (sem criptografia).

Os dois últimos parâmetros não são necessários à reparação do banco de dados. Servem, contudo, para a compactação realizada imediatamente após.

Realizamos a compactação executando o método RepairDatabase( ), como indicado. A seguir, se nenhum erro ocorreu, compactamos o banco de dados através da função CompactDatabase( ), já discutida. E isso é tudo.

Navegação num Banco de Dados

Evidentemente, a criação e alteração da estrutura de um banco de dados, bem como a manutenção da sua integridade e otimização são tarefas eventuais na programação comercial. Só com estes recursos, a DAO não seria útil. A principal utilização dos objetos disponibilizados pela DAO é na edição e navegação de um banco de dados.

O Microsoft Jet Database Engine disponibiliza dois mecanismos distintos de execução das diferentes tarefas relacionadas a um banco de dados:

Um mecanismo navegacional, representado pelo conjunto de objetos da DAO, para a movimentação entre os registros individuais de um banco de dados.

Um mecanismo relacional, baseado na Linguagem Estruturada de Consultas (SQL), para o processamento de massas relacionadas de registros do banco de dados.

A boa programação em VB utilizará os dois mecanismos em conjunto, obtendo o melhor de dois mundos. De uma forma geral, utilizaremos a SQL para extrair uma visão particular dos registros do banco de dados e os objetos da DAO para editar e visualizar cada registro em particular. Por outro lado, sempre que for necessário atualizar grandes

Page 262: Iniciando No Visual Basic

massas de registros segundo critérios consistentes, daremos preferência à SQL.

Nesta seção, conheceremos os diversos recursos navegacionais disponibilizados pelo Microsoft Jet. Uma discussão mais ampla da SQL pode ser encontrada na apostila que acompanha este manual.

Abrindo o Banco de Dados

Evidentemente, todas operações num banco de dados se iniciam após sua abertura. Isso é feito, como já sabemos, pelo método OpenDatabase( ), já amplamente utilizado nos exemplos deste capítulo. No entanto, há ainda alguns aspectos a discutir.

A versão 5 do Visual Basic foi especialmente remodelada para operar, no que concerne ao tratamento de bancos de dados, em ambientes multiusuário. Ora, pelas razões vistas, o acesso a um banco de dados num ambiente multiusuário deve obedecer a um conjunto de, requisitos e restrições, distintos dos sofridos em ambientes monousuário, especialmente numa arquitetura cliente-servidor. Destacamos em particular:

Deve-se definir um conjunto de regras de permissão e acesso para cada grupo de usuários do sistema.

A conexão de um usuário ao sistema - uma sessão - deve ser especificada com referência às regras de permissão e acesso ao banco de dados.

Conseqüentemente, as transações que estiverem ocorrendo no sistema devem estar de acordo com as regras especificadas.

Assinalamos anteriormente que a definição da segurança de acesso ao banco de dados não pode ser realizada no escopo do Visual Basic. Este só é capaz de utilizar um banco de dados cuja segurança foi estabelecida no Microsoft Access ou em outro gerenciador compatível. Assim, no VB, o primeiro passo é definir uma sessão para o logon do usuário.

Uma sessão define uma seqüência de operações executadas pelo Microsoft Jet. Ela se inicia na conexão do usuário ao sistema e termina no seu logoff. Todas as operações executadas durante uma sessão formam o escopo de uma transação e estão sujeitas às permissões determinadas pela segurança de acesso definida para o usuário.

Page 263: Iniciando No Visual Basic

Definindo uma Área de Trabalho

No Microsoft Jet, uma sessão é implementada pela criação (ou utilização) de um objeto Workspace.

É através deste objeto que uma sessão é iniciada e gerenciada. Numa sessão, é possível a abertura de diversos bancos de dados, a manipulação de transações e a garantia da segurança de acesso baseada em senhas e identificadores de usuário.

Uma transação é definida como uma série de alterações nos dados ou no esquema de um banco de dados.

No Microsoft Jet, cada sessão é definida pelos seguintes passos:

A sessão é iniciada quando um objeto Workspace é criado pelo método CreateWorkspace( ), quando é definido um nome para a sessão, um identificador de usuário e uma senha.

Os diversos bancos de dados necessários são abertos na área de trabalho definida pelo já conhecido método OpenDatabase( ).

Os dados do banco de dados são manipulados em transações, definidas pelos métodos BeginTrans, CommitTrans e Rollback.

Os diversos bancos de dados são fechados.

A sessão se encerra quando o objeto Workspace é fechado pelo método Close.

Método CreateWorkspace( )

Cria um objeto Workspace, iniciando uma sessão e definindo uma nova área de trabalho.

Sintaxe

Set ObWorkspace = DBEngine.CreateWorkspace( nomeDaSessão, identificadorDoUsuário, senha)

Assinalamos anteriormente que, ao ser inicializado, o Microsoft Jet cria um objeto Workspace default, referido pelo índice 0 na coleção Workspaces do DBEngine. Sempre que não houver necessidade de condições especiais de segurança de acesso, esta sessão pode ser utilizada livremente.

Page 264: Iniciando No Visual Basic

Métodos BeginTrans, CommitTrans e

Rollback

Os métodos aplicáveis aos objetos Workspace e Database gerenciam as transações de uma sessão. Uma transação é iniciada por BeginTrans e terminada por CommitTrans, podendo ser abortada por Rollback.

Sintaxe

Objeto.BeginTrans

Objeto.CommitTrans

Objeto.Rollback

A utilização de transações melhora a performance geral da atualização de um banco de dados. Elas permitem ao Jet acumular diversas atualizações e gravá-las numa única operação. Uma das vantagens mais evidentes de tratar as diversas operações como um todo é que elas serão bem-sucedidas ou falharão em conjunto, auxiliando na preservação da integridade dos dados.

Imagine a seguinte situação. Por qualquer motivo, é necessário atualizar a base de dados através de três consultas de atualização consecutivas, que processam grandes massas de registros. A operação só pode ser considerada bem-sucedida se todas as consultas forem executadas. Assim, antes de executar a primeira consulta, utilize o método BeginTrans. Somente quando o método CommitTrans for executado a operação será completada, num único passo.

Método Close

Fecha um objeto de acesso a banco de dados. Aplicável aos objetos Workspace, Database e Recordset.

Sintaxe

Objeto.Close

O código a seguir ilustra a utilização de uma sessão no Visual Basic, para atualizar a tabela de Produtos definida anteriormente

Figura 14.15: Utilizando uma sessão no Visual Basic.

Page 265: Iniciando No Visual Basic

Este é um exemplo bem simples de transação. Poderíamos ter utilizado múltiplas consultas, combinadas com diversas operações de E/S no banco de dados via objetos da DAO. O resultado seria sempre o mesmo.

Abrindo Tabelas e Consultas

Uma vez iniciada uma sessão e aberto(s) o(s) banco(s) de dados, estamos livres para manipular os dados de inúmeras e diferentes maneiras. Sempre que desejamos extrair uma determinada visão dos dados armazenados, de uma tabela a uma consulta englobando múltiplas tabelas, recorremos aos objetos Recordset. Há três tipos de recordsets:

Tabela - refere-se a uma tabela local (não ODBC) armazenada num banco de dados. Este é o único tipo de recordset com suporte à localização indexada.

Dynaset - um conjunto dinâmico de dados, podendo se referir tanto a uma tabela, local ou não, quanto ao resultado de uma consulta SQL. Um dynaset pode ser editado normalmente.

Snapshot - um objeto do mesmo tipo de um Dynaset, exceto que não admite edição de dados. Como o Microsoft Jet não precisa manter uma série de referências e ponteiros, como nos dynasets, a operação com um snapshot tende a ser mais rápida.

Seja qual for o tipo de recordset, ele é criado sempre pelo método OpenRecordset( ). Ao executá-lo, podemos especificar tanto a fonte de dados (um comando SQL, uma tabela anexada, uma tabela local, etc.) quanto o tipo de recordset a ser criado. Se nenhum tipo de recordset for especificado, o método tenta criar um do tipo tabela, se possível.

Método OpenRecordset

Cria um novo objeto Recordset, representando qualquer conjunto de dados extraídos de um banco de dados. Aplicável aos objetos Database, QueryDef, Recordset e TableDef.

Sintaxe

Set Objeto = ObDatabase.OpenRecordset( fonteDeDados [, tipo [, opções]])

Set Objeto = ObjetoFonte.OpenRecordset([ tipo  [, opções  ]])

Page 266: Iniciando No Visual Basic

Além dos comandos SQL, há inúmeras maneiras de personalizar a visão dos dados obtida num recordset. A primeira delas é ordenando os dados obtidos.

Os registros num recordset do tipo tabela aparecem na ordem em que foram originalmente adicionados ao banco de dados. Isso, geralmente, de nada serve. Há duas maneiras básicas de ordenar um recordset deste tipo:

Através da sua propriedade Index, atribuindo a ela um dos índices predefinidos para a tabela.

Através da criação de um novo objeto Recordset a partir do primeiro, após ajustar a propriedade Sort deste último para um critério de ordenação.

Não é possível alterar a ordenação de um dynaset ou snapshot já criado. Ao contrário da tabela, é necessária a criação de um novo recordset com o critério de ordenação requerido.

Um outro mecanismo fundamental de personalização dos dados extraídos por um recordset é o estabelecimento de filtros.

A propriedade Sort dos objetos Recordset retorna ou determina a ordenação do conjunto de dados extraído. Ela requer uma string contendo uma cláusula SQL ORDER BY válida, sem a expressão-chave da linguagem.

Da mesma maneira que a propriedade Sort, é possível alterarmos a propriedade Filter de um recordset existente e, então, extrairmos um novo recordset dele. Este novo recordset apontará apenas para os registros correspondentes ao critério de filtro selecionado.

A propriedade Filter dos objetos Recordset retorna ou determina o critério de seleção dos registros de um conjunto de dados. Ela requer uma string contendo uma cláusula SQL WHERE válida, sem a palavra-chave da linguagem.

O fragmento de código a seguir ilustra a abertura de tabelas e a ordenação e filtragem dos registros:

Figura 14.16: Abrindo tabela, ordenando e filtrando registros

O exemplo fala por si. Note apenas a utilização de apóstrofos para delimitar o valor do CEP desejado ,no ajuste da propriedade Filter do objeto obDynaset. Esta é a convenção para indicar que o valor incluso

Page 267: Iniciando No Visual Basic

é uma string e não um objeto do próprio banco de dados. Selecionar a condição CEP 20002000 sem os apóstrofos não retomará registros.

Abrindo uma Consulta Parametrizada

Lembre-se de que, no exemplo anterior, o recordset obtido pela condição de filtro do objeto obDynaset não retornava o cadastro completo do fornecedor, apenas os campos armazenados na tabela Fornecedores. Como os campos Cidade e UF pertencem à tabela relacionada Localidades, eles não seriam devolvidos.

Vamos supor agora, que você precisasse do endereço completo para, digamos, uma mala direta. Neste caso, você precisaria também dos dois campos armazenados na tabela Localidades. Na programação em Clipper, por exemplo, você deveria abrir ambas as tabelas, relacionar os campos através do comando SET RELATION e codificar inteiramente um algarismo de extração dos dados. Nada disso é necessário com o Microsoft Jet. Uma simples declaração SQL é capaz de fazer a mágica.

Para que possamos utilizar os registros retornados por uma declaração SQL de extração de dados, devemos atribuir o resultado da consulta a um objeto Recordset. Como vimos mais acima, isso pode ser feito também com o método OpenRecordset( ). Neste caso, passamos como parâmetro ao método a declaração que extrairá os dados. Veja o exemplo de código a seguir:

Figura 14.17

O código acima produz o mesmo resultado do exemplo anterior, onde ajustamos a propriedade Filter do objeto obDynaset. Neste caso, contudo, executamos diretamente no dispositivo Jet uma consulta seleção de registros e atribuímos o seu resultado a um objeto Recordset.

Este exemplo, contudo, é pouco realista. Dificilmente saberemos de antemão, num ambiente programado e não interativo, o valor do CEP desejado. Provavelmente, ele será obtido, em tempo de execução, através de um diálogo, onde o usuário informará o valor desejado para a mala direta. O que precisamos, neste caso, é de uma consulta parametrizada.

As consultas parametrizadas são armazenadas previamente no banco de dados. Quando necessárias, elas são abertas e seus parâmetros

Page 268: Iniciando No Visual Basic

atribuídos. A partir daí, podemos criar um recordset com o valor atribuído agindo como filtro.

Para criar uma consulta parametrizada é preciso preceder o texto da instrução SELECT com uma cláusula PARAMETERS, onde definimos os parâmetros da consulta com seus nomes e tipos de dados. A cláusula PARAMETERS tem a seguinte sintaxe:

PARAMETERS nomeparâmetro tipodado ;

Poderíamos transformar a consulta anterior em uma consulta parametrizada , incluindo uma cláusula PARAMETERS no seu início e modificando sua cláusula INNER JOIN para WHERE. Os colchetes aqui servem para indicar que o valor entre eles é um parâmetro. Veja como ficaria:

"PARAMETERS [CódigoPostal] Text; SELECT Fornecedores.[Razão Social],

Fornecedores.Endereço, Fornecedores.CEP, Localidades.Cidade, Localidades.UF

FROM Localidades, Fornecedores WHERE Localidades.CEP = Fornecedores.CEP AND

Fornecedores.CEP = [CódigoPostal]"

Em tempo de execução, abrimos a definição da consulta e atribuímos seu parâmetro, extraindo então um recordset.

Veja o fragmento de código seguinte:

Figura 14.18: Abrindo uma consulta parametrizada.

Utilizamos a coleção Parameters do objeto QueryDef para obter e atribuir o parâmetro desejado. O código acima produz o mesmo resultado que no exemplo anterior. Exceto que, numa aplicação real, o valor atribuído ao parâmetro seria obtido de uma variável ou de um controle de janela de diálogo.

Fechando Tudo

Ao longo dos últimos exemplos não nos preocupamos em fechar os recordsets e bancos de dados abertos. Utilizamos uma característica da DAO: o recordset ou banco de dados (numa palavra, o objeto) é fechado automaticamente, sempre que a variável que o referencia sai

Page 269: Iniciando No Visual Basic

de escopo. Como utilizamos variáveis locais para referir os diversos objetos, não foi preciso fechá-los.

Isso, no entanto, não é boa prática de programação. Preocupe-se sempre em fechar cada um dos objetos utilizados com o já conhecido método Close. Lembre-se apenas de que, como numa pilha de pratos sujos, o último a entrar deve ser o primeiro a sair. Feche os objetos sempre do nível inferior da hierarquia (Recordset, QueryDef ou TableDef, Database e Workspace, nessa ordem). Caso contrário, a pilha de pratos cai e um erro é gerado em tempo de execução.

Localizando um Registro

Na programação de front-ends de sistemas de bancos de dados é comum a necessidade de localizar um registro específico num recordset. A biblioteca de Objetos de Acesso a Bancos de Dados fornece um bom conjunto de mecanismos de localização de registros.

Localização Indexada

A mais rápida, já conhecida dos programadores de outras linguagens com filosofia de banco de dados diferente, como o Clipper ou o Paradox, é a pesquisa indexada. Ela só é possível em objetos Recordset do tipo tabela, desde que o índice apropriado tenha sido definido como o índice de controle. Se você tentar localizar um registro sem um índice aberto ou por uma chave diferente do índice corrente, um erro é gerado.

Para localizar registros numa tabela indexada procedemos da seguinte forma:

1. Criamos um Recordset do tipo tabela e o atribuímos a um objeto.

2. Alteramos a propriedade Index do objeto para o nome do índice desejado.

3. Utilizamos o método Seek para localizar um registro cujo valor corresponde à chave especificada.

Método Seek

Localiza um registro numa tabela indexada. Aplicável somente a um Recordset do tipo tabela.

Sintaxe

Page 270: Iniciando No Visual Basic

ObRecordset.Seek stringDeComparação, listaDeChaves

Quaisquer dos operadores de comparação podem ser utilizados como argumento para o método. Caso a chave de índice possua mais de um campo, uma lista de valores correspondente deve ser especificada.

Veja o fragmento de código a seguir:

Figura 14.19: Localizando um registro com Seek

Primeiro, definimos o índice PrimaryKey como o índice de controle de ordenação do recordset. A seguir, pesquisamos o código de Produto número 2. Note que especificamos um tipo de dado estritamente compatível com a chave de índice. Por fim, como seria de se esperar, verificamos se a busca falhou, testando o valor da propriedade NoMatch.

Propriedade NoMatch

A propriedade retorna um lógico indicando se a última operação de busca realizada num recordset falhou.

Sintaxe

ObRecordset.NoMatch

Localização Seqüencial

Como dissemos, a pesquisa indexada só pode ser utilizada nos recordsets do tipo tabela. Isso não quer dizer, contudo, que o Microsoft Jet não forneça mecanismos suficientes para a localização de registros em dynasets ou snapshots. Ao contrário. Os seguintes métodos podem ser utilizados:

FindFirst - localiza o primeiro registro que satisfaça ao critério especificado a partir do início do recordset.

FindLast - localiza o último registro que satisfaça o critério especificado a partir do fim do recordset.

FindNext - localiza o próximo registro que satisfaça o critério especificado a partir da posição corrente.

FindPrevious - localiza o registro anterior que satisfaça ao critério especificado a partir da posição corrente.

Page 271: Iniciando No Visual Basic

O critério especificado aos métodos geralmente corresponde a uma cláusula SQL WHERE válida, sem a palavra-chave da linguagem. Normalmente, buscamos um valor idêntico a um critério para um determinado campo. Como no método Seek, podemos, contudo, utilizar quaisquer dos operadores de comparação.

O fragmento de código a seguir executa a mesma operação do exemplo anterior. Desta vez operamos sobre um dynaset, daí a utilização do método FindFirst:

Figura 14.20: Localizando com FindFirst

Note o modo como especificamos o conteúdo da expressão a ser buscada. Não utilizamos delimitadores no valor 2 porque não se trata de tipo de dado string!

Movendo-se nos Registros

Como já assinalado, o mecanismo navegacional (por oposição ao mecanismo relacional) disponibilizado pela DAO se baseia no conceito de movimento pelos registros de um recordset para localizar um ou mais registros. Como também assinalamos, tais mecanismos são ineficientes para o processamento de grandes massas de registros. Nestes casos, deve-se utilizar os comandos SQL suportados pelo Microsoft Jet. No entanto, para operações de alcance limitado, esse mecanismo é inteiramente satisfatório, sobretudo quando se quer processar um único registro.

A localização de um registro particular é indispensável porque somente os campos do registro podem ser editados, a menos que utilizemos consultas de ação. Assim, métodos para saltarmos entre os registros de um recordset são indispensáveis. O Microsoft Jet disponibiliza os seguintes métodos:

MoveFirst - salta para o primeiro registro lógico de um recordset.

MoveLast - salta para o último registro lógico de um recordset.

MoveNext - salta para o próximo registro lógico de um recordset.

MovePrevious - salva para o registro lógico anterior de um recordset.

No caso de utilizarmos tais métodos, é indispensável determinarmos os limites de um recordset. Caso contrário, um erro será gerado quando tentarmos fazer uma referência sem um registro corrente. Os objetos Recordset possuem as seguintes propriedades:

Page 272: Iniciando No Visual Basic

BOF - determina se foi atingido o início lógico do recordset.

EOF - determina se foi atingido o fim lógico de recordset.

O fragmento de código a seguir ilustra a navegação por todo um recordset, enviando o conteúdo de um de seus campos para a impressora:

Figura 14.21: Navegando num recordset

Editando o Banco de Dados

Uma vez localizado o registro desejado, é hora de editá-lo. A DAO fornece os seguintes métodos de edição de um recordset (evidentemente do tipo dynaset ou tabela):

Edit - copia o registro corrente para um buffer temporário para edição dos dados.

AddNew - cria um novo registro para um recordset e aloca o buffer de edição.

Update - copia o conteúdo do buffer de edição para o registro corrente ou o novo registro criado.

O fragmento de código a seguir ilustra a utilização dos métodos de edição:

Figura 14.22: Editando o Banco de Dados

Usando o Controle Data Para Acessar um Banco de Dados

O controle data automatiza uma série de tarefas comuns no acesso a dados, mas não faz isto sozinho. Para que sua capacidade seja posta em uso ele precisa estar ligado a outros controles que são utilizados para apresentar as informações colhidas do banco de dados na tela. Cabe ao controle Data o uso destes controles para realizar seus objetivos.

Vejamos como utilizar o controle data para manipular uma tabela do Banco de Dados de exemplo Biblio.mdb. Se você fez a instalação padrão do Visual Basic, este arquivo pode ser encontrado no diretório VB. Crie um novo projeto no Visual Basic. Selecione o controle Data na caixa de ferramentas e acrescente-o ao formulário Form1. Na janela de propriedades, ajuste a sua propriedade Align para 2 - Align Bottom. Selecione a propriedade DatabaseName e clique no botão de

Page 273: Iniciando No Visual Basic

reticências. A caixa de diálogo DatabaseName surgirá para que você localize o banco de dados que será acessado pelo controle Data. Localize o arquivo Biblio.mdb e clique em Abrir. Selecione agora a propriedade RecordSource do controle Data e de um clique na seta para baixo para visualizar as opções de configuração do valor desta propriedade. Uma lista com vários nomes de tabelas pertencentes ao Biblio.mdb aparecerão. Selecione a tabela Authors da lista. Agora, quando o formulário Form1 for carregado, o banco de dados Biblio.mdb será aberto automaticamente pelo controle Data e uma consulta será feita à tabela Authors para obter como retorno o seu conjunto de registros. A este conjunto de registros retornados damos o nome de recordset. Mas e então? Onde será apresentado este recordset?

Para fazer a apresentação dos registros da tabela Authors, vamos criar três caixas de texto e ligá-las ao controle Data1. Cada uma será usada pelo controle Data1 para apresentar um dos campos do registro atual. Chamamos de registro atual o registro que atualmente pode ser exibido, alterado ou excluído do recordset. Podemos navegar dentro de um recordset mudando o registro atual através de comandos de avanço e retrocesso.

Para ligar as caixas de texto ao controle Data1 usamos a propriedade DataSource das caixas de texto. Atribua o valor Data1 a esta propriedade para as três caixas de texto. Essa atribuição fará com que o controle Data1 possa exibir informações da tabela Authors nestas caixas de texto, mas ainda falta definir que informação será esta em cada caso.

Selecione a propriedade DataField na caixa de texto Text1. Clique na seta para baixo para ver as opções de valor. As opções apresentadas correspondem aos nomes dos campos da tabela Authors acessada pelo controle Data1. Configure a propriedade DataField como Au_Id para Text1, Author para Text2 e Year Born para Text3. Feito isto, inicie a aplicação. Você verá na caixa de texto Text1 um número que corresponde ao conteúdo do campo Au_Id na tabela Authors, em Text2 é exibido o nome do autor. Em Text3, infelizmente, poucos registros da tabela Authors possuem informação de data de nascimento (Year Born) do autor, por essa razão será difícil ver alguma informação nesta caixa de texto. Mas você pode navegar pela tabela clicando nos botões de seta do controle Data1 e vez por outra verá um registro com informação no campo Year Born.

Page 274: Iniciando No Visual Basic

SQL - Linguagem Estruturada de Consultas e o VB

A linguagem estruturada de consultas (Structured Query Language), é uma linguagem de alto nível para manipulação de dados dentro do modelo relacional. É de tal ordem sua importância para a indústria dos bancos de dados relacionais que ela acabou por se tornar o mecanismo mais popular de acesso aos grandes bancos de dados cliente/servidor. Quando o primeiro sistema gerenciador de banco de dados relacional foi desenvolvido, no início da década de 70, o primeiro mecanismo de acesso aos dados ali mantidos foi uma forma primitiva de SQL.

O sucesso da linguagem foi tal que obrigou o Instituto Americano de Padrões (ANSI) a padronizar as implementações do produto. Assim, a maior parte - senão todas - as implementações da linguagem seguem de perto o padrão ANSI definido. As pequenas variações existentes não afetam a padronização global e costumam ser incorporadas para complementar as capacidades da linguagem. Ainda que tais variações possam aumentar a complexidade da migração de um ambiente para outro, elas não afetam a estratégia global de portabilidade entre plataformas. Se é o caso de desenvolver aplicações portáteis, o padrão ANSI - suportado por todos os produtos, de uma forma geral - deve ser seguido rigorosamente. Ainda que se percam alguns pontos em desempenho e facilidade, a portabilidade estará garantida.

Para nós, programadores em VB, a compreensão e a utilização da SQL é decisiva por alguns bons motivos:

É poderosa e flexível. É muito mais rápida a recuperação e a manipulação de dados utilizando a SQL que os objetos disponíveis na DAO. Com uma única instrução SQL podemos substituir dezenas ou mesmo centenas de linhas de código baseadas nos objetos da biblioteca DAO.

É um padrão na indústria. Como a SQL, com pequenas variações, é suportada pelos mais importantes bancos de dados relacionais, podemos criar programas de front-end para a administração de bancos de dados relativamente independentes do back-end. Por exemplo, podemos escrever um aplicativo voltado para administração de um banco de dados Access e, sem alterações significativas, portá-lo de modo a utilizar o Microsoft SQL Server ou outro banco de dados ODBC.

Page 275: Iniciando No Visual Basic

Freqüentemente, a implementação da linguagem SQL incorporada ao Microsoft Jet será utilizada para desempenho máximo, em conjunto com os objetos da DAO. Uma utilização comum poderá ser selecionar um subconjunto dos dados através de uma instrução SQL, gerar um objeto Recordset e manipulá-lo com os métodos navegacionais disponibilizados pela DAO. Com isso, o programador obterá o melhor de dois mundos. Além disso, essa estratégia costuma facilitar a portabilidade do aplicativo: deve variar somente o mecanismo de conexão com a fonte de dados SQL, tudo o mais permanecendo constante.

Neste capítulo, procuraremos abordar de uma forma ampla, os fundamentos e a capacidade do dialeto SQL suportado pelo Microsoft Jet Database Engine, tal como implementado na versão 5 do VB. O objetivo básico do capítulo será, então, prover o programador de uma ferramenta poderosa e portátil, capaz de tornar a programação de aplicativos de front-end para bancos de dados uma tarefa simples.

O objetivo fundamental da SQL é fornecer ao usuário de um RDBMS uma interface de alto nível, capaz de isolá-lo completamente das complexidades de implementação do sistema. Com tal objetivo em mente, desenvolveu-se uma linguagem totalmente não-procedural. Ao usuário da SQL não cabe definir como o gerenciador do banco de dados executará uma tarefa em particular, mas somente o que deve ser feito.

Vamos imaginar um exemplo para que isso fique claro. Suponhamos que você precise atualizar uma tabela de comissões sobre a venda dos vendedores da empresa. Por padrão, a empresa paga 5% de comissão sobre o valor faturado numa venda. Como medida de estímulo, a empresa resolveu pagar comissão de 7.5% para todas das vendas maiores que R$ 1.600,00, mas somente para vendas efetuadas a partir de 15 de fevereiro de 1998. No modelo navegacional da DAO você poderia escrever, por exemplo, o seguinte código:

Figura 15.1

 

Está claro, no exemplo, o modelo procedural da operação de atualização, expresso no seguinte algoritmo:

1. Posicionamos o ponteiro de arquivo no primeiro registro lógico.

Page 276: Iniciando No Visual Basic

2. Verificamos se o registro corrente corresponde ao critério desejado.

3. Se a verificação é verdadeira, atualizamos o campo desejado.

4. Seguimos para o próximo registro.

5. Repetimos os passos 2 a 4 até encontrar o fim do arquivo.

A mesma atualização utilizando a SQL poderia ser feita da seguinte forma:

Figura 15.2: Usando SQL para atualizar banco de dados

Note a diferença radical dessa abordagem. Em momento nenhum nos preocupamos em determinar como a atualização deve ser feita. Apenas especificamos o que deve ser feito. Solicitamos ao Jet atualizar o campo Comissão da tabela Comissões para 0.075 sempre que o registro satisfaça ao critério especificado. Isso foi feito por um comando muito próximo da linguagem utilizada para descrever a tarefa.

Evidentemente, o sistema gerenciador é incapaz de compreender a linguagem de alto nível empregada. Antes de ser executada, ela deve ser traduzida para uma linguagem procedural ao nível da máquina. O ponto principal a ressaltar, contudo, é que essa tradução é feita pelo dispositivo gerenciador e não pelo programador. Este pode continuar a pensar em termos da tarefa a ser executada e não de como executá-la. Isso torna mais simples a programação, de modo que mais pessoas podem escrever os mesmos programas em menos tempo. Naturalmente, a complexidade não é estranha a determinadas instruções SQL. No entanto, essa complexidade será sempre inferior à sua equivalente programada.

Um outro ponto a ressaltar diz respeito ao que você pode fazer com o VB e a SQL, ainda que não utilize o Jet. Como já assinalamos, o Jet não é um dispositivo cliente\servidor. Ele reside no mesmo computador do aplicativo de front-end. Assim, utilizando um banco de dados remoto, o tráfego na rede é equivalente quando utilizada a DAO ou a SQL. No entanto, o mesmo código escrito visando o banco de dados Access pode ser, facilmente, portado, por exemplo, para a utilização do SQL Server como fonte de dados. Ambos os dispositivos compreendem o mesmo dialeto da linguagem SQL. Numa consulta de seleção de registros, por exemplo, trafegarão na rede somente o comando SQL e os registros selecionados. Essa abordagem, portanto,

Page 277: Iniciando No Visual Basic

implica um ganho de performance impossível sem a utilização da SQL.

Sintaxe do SQL

Uma declaração SQL pode consistir dos seguintes componentes:

Uma declaração de parâmetros. Quando uma declaração requer parâmetros, isto é, valores somente disponíveis em tempo de execução a partir da interação com o usuário, é conveniente - ainda que opcional - a declaração explícita dos parâmetros utilizados. Tal declaração deve ser feita da seguinte forma: PARAMETERS nomeDoParâmetro tipoDeDado; Qualquer quantidade de parâmetros, dentre os tipos de dados suportados pelo dispositivo Jet (ou pelo sistema gerenciador ao qual o aplicativo está conectado via ODBC), é inteiramente válida.

O comando SQL. Este componente informa ao gerenciador a ação a ser executada. Por exemplo, a declaração SELECT * FROM Clientes solicita ao dispositivo gerenciador que retorne todos os campos da tabela Clientes.

Cláusulas opcionais. Informam ao dispositivo gerenciador as condições segundo as quais os registros serão selecionados, tais como ordenações, condições lógicas de filtro, agrupamentos, etc. Se o comando SQL informa ao dispositivo o que fazer, as cláusulas opcionais especificam os registros a serem incluídos no processamento e o critério específico dessa inclusão.

Comandos SQL

É costume tratar a SQL como composta de subconjuntos de comandos - linguagens - para a execução de diferentes tarefas. Tal como a DAO, a SQL suporta tanto uma linguagem de definição de dados (DDL) - para a criação e alteração de tabelas e índices quanto uma linguagem de manipulação de dados (DML) - para a seleção e atualização dos dados armazenados nas tabelas. A Figura 15.3 sumariza os diversos comandos suportados pela SQL incorporada ao VB:

Figura 15.3: Os comandos SQL suportados pelo VB.

Cláusulas SQL

Page 278: Iniciando No Visual Basic

As cláusulas são modificadores utilizados para definir os dados a serem selecionados para a manipulação. A Figura 15.4 sumariza as diversas cláusulas suportadas pela SQL no VB5:

Figura 15.4: As cláusulas suportadas pela SQL do Visual Basic.

Operadores

A SQL suporta dois tipos de operadores:

Os operadores lógicos, utilizados para conectar expressões, normalmente numa cláusula WHERE.

Os operadores de comparação, utilizados para comparar os valores de duas expressões.

A Figura 15.5 sumariza, por tipo, os operadores suportados pela SQL do VB:

Figura 15.5: Os operadores SQL suportados pelo Visual Basic.

Funções Agregadas

Além dos comandos vistos anteriormente, a SQL suporta ainda um conjunto de funções pré-definidas. Tais funções, utilizadas numa cláusula SELECT, referem-se a determinados grupos de registros e retomam um valor aplicável ao grupo. A Figura 15.6 sumariza as funções suportadas pelo Jet:

Figura 15.6: As funções agregados suportados pela SQL do Visual Basic.

Como já foi dito, a DDL é um subconjunto de comandos SQL capazes de criar e modificar a estrutura de uma tabela, incluindo os seus índices. De uma forma geral, a DDL pode substituir boa parte das operações efetuadas pelos objetos da DAO, tal como discutimos anteriormente. No entanto, há algumas limitações para as operações com a DDL:

Somente os bancos de dados nativos do Jet - no formato do Microsoft Access - admitem os comandos DDL a partir do VB.

Apenas um limitado número de propriedades de tabelas, campos e índices é abarcado pelos comandos DDL.

Operações com a DDL

Page 279: Iniciando No Visual Basic

Com DDL, é possível:

Criar e remover uma tabela, definindo as propriedades básicas (nome, tipo e tamanho) dos campos;

Alterar a estrutura de uma tabela, incluindo e removendo campos;

Criar e remover um índice.

Trataremos agora circunstanciadamente de cada bloco de operações.

Criando e Removendo Tabelas

Para criar uma tabela com um comando DDL, apenas especificamos os nomes, tipo de dado e tamanho, se for o caso, de cada campo numa cláusula CREATE TABLE. Os nomes dos campos não precisam ser delimitados por aspas. Contudo, nomes de campos contendo espaços devem ser delimitados por colchetes.

Na criação de uma tabela com a DDL, apenas as propriedades Name, Type e Size do equivalente objeto Field são especificadas. As demais propriedades suportadas pelo objeto, como ValidationRule, ForeignName, etc., não são suportadas. Se necessárias, a tabela deve ser modificada com o auxílio da DAO.

O seguinte fragmento de código cria uma tabela Clientes no banco de dados Base32.Mdb, para a empresa Limpa Tudo Materiais de Limpeza Ltda., tal como já foi descrito:

Dim db As Database

Set db = Workspaces(0).CreateDatabase (App.Path & _

"\Base32.Mdb", dbLangGeneral, dbVersion30)

db.Execute "CREATE TABLE Clientes " & _

"(Cliente TEXT (4), CGC TEXT " & _

"(14), RazãoSocial TEXT (30), " & _

"Endereço TEXT (50), CEP TEXT (8))"

db.Close

Page 280: Iniciando No Visual Basic

A remoção de uma tabela em SQL é tão simples quanto utilizando a DAO. O seguinte fragmento de código remove a tabela criada no exemplo anterior:

Dim db As Database

Set db = Workspaces(0).OpenDatabase(App.Path & _

"\Base32.Mdb")

db.Execute "DROP TABLE Clientes"

db.Close

Modificando Tabelas

Do mesmo modo que na DAO, não é possível alterar as propriedades de um campo já anexado a uma tabela. Sendo assim, utilizando os comandos DDL, é possível apenas remover um campo (coluna) ou anexar um novo à tabela. Portanto, a alteração de uma das propriedades do campo, via SQL, requer que ele seja primeiro removido e depois novamente incluído com as características alteradas. Note-se uma vez mais que apenas o nome, o tipo de dado e o tamanho de um campo podem ser especificados.

O seguinte fragmento de código altera a estrutura da tabela Clientes, criada na seção anterior:

Dim db As Database

Set db = Workspaces(0).OpenDatabase (App.Path & _

"\Base32.Mdb")

db.Execute "ALTER TABLE Clientes " & _

"DROP COLUMN Cliente"

db.Execute "ALTER TABLE Clientes " & _

"ADD COLUM Cliente SHORT"

db.Close

Criando e Removendo Índices

Page 281: Iniciando No Visual Basic

Há três diferentes maneiras de criarmos um índice utilizando os comandos SQL:

Na criação da tabela, após a especificação do comando CREATE TABLE. É possível, neste momento, criar um índice a partir de uma única coluna ou a partir de diversas. Apenas acrescente a cláusula CONSTRAINT especificando os campos e propriedades do índice.

Utilizando o comando CREATE INDEX isoladamente. Neste caso, pode-se também especificar as diversas propriedades do índice, bem como definir regras de validação com a cláusula WITH.

Utilizando o comando ALTER TABLE. Apenas utilize a combinação de palavras-chave ADD CONSTRAINT após o comando ALTER TABLE.

Como se pode notar, utilizamos a cláusula CONSTRAINT para criar ou remover um índice junto com os comandos CREATE TABLE e ALTER TABLE. Com esta cláusula é possível também definir uma chave primária ou externa, definir relacionamentos e forçar a integridade referencial dos dados.

O seguinte fragmento de código cria um índice primário para a tabela Clientes utilizando o campo Cliente:

Dim db As Database

Set db = Workspaces(0).OpenDatabase(App.Path & _

"\Base32.Mdb")

db.Execute "ALTER TABLE Clientes " & _

"ADD CONSTRAINT Cliente " & _

" PRIMARY KEY (Cliente)"

db.Close

O fragmento de código seguinte cria uma nova tabela, chamada Telefones dos Clientes e, a seguir, estabelece um relacionamento por chave externa com a tabela Clientes, através do campo Cliente:

Dim db As Database

Set db = Workspaces(0).OpenDatabase(App.Path & _

Page 282: Iniciando No Visual Basic

"\Base32.Mdb")

db.Execute "CREATE TABLE [Telefones dos Clientes] " & _

"(Cliente SHORT, Telefone TEXT (10), " & _

"Contato TEXT (30)) "

db.Execute "ALTER TABLE [Telefones dos Clientes] " & _

"ADD CONSTRAINT TelefonesCliente " & _

"FOREIGN KEY (Cliente) " & _

"REFERENCES Clientes (Cliente)"

db.Close

O fragmento de código seguinte ilustra a utilização do comando CREATE INDEX para indexar a tabela anterior utilizando o campo Telefone:

Dim db As Database

Set db = Workspaces(0).OpenDatabase (App.Path & _

"\Base32.Mdb")

db.Execute "CREATE INDEX Telefones " & _

"ON [Telefones dos Clientes] (Telefone)"

db.Close

Para remover um índice existente, apenas utilize o comando DROP com referência ao índice desejado. Por exemplo, para remover o índice Telefones da tabela Telefones dos Clientes, utilize o seguinte comando:

db.Execute "DROP INDEX Telefones " & _

"ON [Telefones dos Clientes]"

Método Execute

Page 283: Iniciando No Visual Basic

Executa um comando SQL no banco de dados especificado. Note que o método só é válido para consultas de ação, onde não são retomados registros.

Sintaxe

ObDatabase.Execute comandoSQL [, opções ] ObQueryDef.Execute [ [ opções ]

Extração de Dados das Tabelas

De longe, a utilização mais comum da linguagem SQL - mais especificamente do subconjunto conhecido como DML, a linguagem de manipulação de dados - é na recuperação de subconjuntos dos dados para posterior tratamento. É o que se convencionou chamar Consultas. Aliás, o maior poder da SQL não se revela no subconjunto DDL, mas principalmente na sua capacidade de selecionar um conjunto complexo de registros segundo um conjunto, também complexo, de condições e tratá-lo num único passo.

O Comando SELECT

Na SQL, é o comando SELECT o utilizado na recuperação de dados. A forma básica do comando SELECT é a seguinte:

SELECT nomesDosCampos FROM nomeDaTabela [cláusulas]

Assim, a forma mais simples de uma consulta poderia ser a que segue, aplicada a uma das tabelas definidas para a Limpa Tudo:

SELECT * FROM Fornecedores

A instrução anterior seleciona todos os campos da tabela Fornecedores e retorna um subconjunto dos dados, que pode ser visualizado no Microsoft Access, conforme a Figura 15.7:

Figura 15.7: Uma consulta de seleção.

Naturalmente, não é obrigatória a seleção de todos os campos da tabela. Pode-se selecionar qualquer quantidade desejada de campos. O comando a seguir recupera apenas dois campos da tabela Estoque do mesmo banco de dados:

SELECT Produto, [Quantidade Estocada] FROM Estoque

A Cláusula WHERE

Page 284: Iniciando No Visual Basic

É possível também determinar que a seleção dos registros seja feita com base num determinado critério. Aliás, essa é a utilização mais comum. Para isso, nós adicionamos determinadas cláusulas ao comando SQL. A cláusula básica para a especificação de critérios de seleção é a cláusula WHERE.

A cláusula determina as condições de extração dos registros. Assim, na sua forma básica, ela utiliza os operadores da linguagem para determinar o mecanismo de seleção utilizado pelo comando. Um exemplo da utilização da cláusula pode ser o que segue:

SELECT Produto, [Nome do produto] FROM Produtos WHERE Categoria = 1

A cláusula anterior, aplicada ao banco de dados definido para a empresa Limpa Tudo, retorna os registros exibidos no exemplo da Figura 15.8:

Figura 15.8: Uma consulta de seleção com cláusula condicional

Costuma ser necessário que uma consulta satisfaça a múltiplos critérios de seleção. Por exemplo, você pode desejar visualizar os produtos da categoria 2 - Detergentes. Assim, você escreve o seguinte comando:

SELECT Produto, [Nome do Produto], [Preço de Venda] FROM Produtos WHERE Categoria = 2

Você deseja discutir com um cliente da Limpa Tudo uma grande venda de um desses produtos. Sabe, porém, que o cliente não deseja pagar mais que setenta centavos por unidade. Assim, você solicita a seguinte consulta:

SELECT Produto, [Nome do Produto], [Preço de Venda] FROM Produtos WHERE [Preço de Venda] <= 0.70

Como você pode notar, o que você efetivamente deseja é ainda um subconjunto dos dados produzidos pelas duas queries. Na verdade, apenas aquele subconjunto de registros comuns a ambas as consultas. Para obter tal resultado, você deve, evidentemente, compor a cláusula condicional de tal modo que apenas esse subconjunto específico seja retornado pelo dispositivo gerenciador. Assim, o comando deve ser escrito da seguinte forma, que recupera tão somente os produtos desejados:

Page 285: Iniciando No Visual Basic

SELECT Produto, [Nome do Produto], [Preço de Venda] FROM Produtos WHERE Categoria = 2 AND [Preço de Venda] <= 0.70

Lembre-se de que a estratégia fundamental, quando se trata da utilização da linguagem SQL no contexto de aplicações cliente-servidor, é reduzir o universo de registros selecionados ao mínimo possível, de modo a melhorar a eficiência do tráfego dos dados. Assim, boa parte do esforço do programador na composição de consultas de seleção estará voltado para a definição de cláusulas WHERE tais que reduzam ao máximo possível o resultado da query.

Não suponha que qualquer artifício de programação utilizando a DAO possa substituir a eficiência da linguagem SQL. Os modernos gerenciadores de banco de dados relacionais possuem mecanismos de otimização eficientes e são capazes de criar estratégias de recuperação as mais velozes no contexto do comando executado.

Especificando um Intervalo para os Registros

Uma outra necessidade comum é a especificação de um intervalo de valores de um determinado campo para a seleção dos registros. Imaginemos que seja necessário visualizar todas as vendas efetuadas na segunda quinzena do mês de janeiro de 1998. Para isso precisamos utilizar a cláusula BETWEEN na condição lógica de seleção. Veja o exemplo a seguir:

SELECT Vendas.Data, Produtos.[Nome do Produto],

Faturas.[Quantidade Vendida] FROM

(Vendas INNER JOIN Faturas ON

Vendas.Fatura = Faturas.Fatura)

INNER JOIN Produtos

ON Faturas.Produto = Produtos.Produto

WHERE (Vendas.Data BETWEEN CVDate('16/01/98')

AND CVDate('31/01/98'))

Especificando uma Lista de Condições

Page 286: Iniciando No Visual Basic

Suponhamos agora que você deseje todos os produtos categorizados como 1- Saponáceo, 2 - Detergente e 5 -Água Sanitária. Isso pode ser obtido pela seguinte cláusula:

SELECT Produto, [Nome do Produto] FROM Produtos

WHERE Categoria = 1 OR Categoria = 2 OR Categoria = 5

Na verdade, o que se deseja aqui é um conjunto de registros que satisfaçam a uma lista de condições alternativas. Uma forma mais compacta de obter o mesmo resultado é o comando:

SELECT Produto, [Nome do Produto] FROM produtos

WHERE Categoria IN (1, 2, 5)

Verificando a Ocorrência de Valores NULL

Na definição da base de dados da Limpa Tudo, feita anteriormente, especificamos uma tabela-filha Telefones dos Fornecedores, onde armazenávamos também o nome dos empregados responsáveis pelo fornecimento. Você se lembra de que o campo criado para representar a informação - Contato - não era obrigatório, podendo assumir valor NULL. Além disso, especificamos que diversos telefones e contatos poderiam ser consignados a um mesmo fornecedor. Suponhamos agora que seja necessário visualizar os telefones e os contatos de algumas empresas. O seguinte comando SQL poderia ser usado:

SELECT Fornecedor, Telefone, Contato

FROM [Telefones dos Fornecedores]

WHERE Fornecedor IN (23, 41, 168)

No entanto, você não deseja telefones que não estejam associados a nenhum contato. Assim, alguns registros da consulta resultante não são necessários e podem ser eliminados. A seguinte declaração não inclui tais registros:

SELECT Fornecedor, Telefone, Contato

FROM [Telefones dos Fornecedores]

WHERE Fornecedor IN (23, 41,168)

AND Contato <> ""

Page 287: Iniciando No Visual Basic

O comando, utilizado com o Microsoft Jet, elimina os registros com valor NULL para o campo Contato. No entanto, tais tipos de campos podem variar de sistema para sistema, o que tornaria a consulta menos portátil. Desse modo, a linguagem SQL implementa um mecanismo genérico para testarmos a ocorrência de um valor NULL. Aquela consulta pode, então, numa forma mais genérica, ser escrita da seguinte forma, obtendo o mesmo resultado:

SELECT Fornecedor, Telefone, Contato

FROM [Telefones dos Fornecedores]

WHERE Fornecedor IN (23, 41, 168)

AND Contato IS NOT NULL

Ordenando as Consultas

Não faz sentido, no modelo relacional, questionarmos a ordenação física dos registros (linhas) numa tabela. O problema só passa a ter significado no momento da recuperação dos dados, uma vez que a ordenação só faz sentido para o usuário e não para o próprio modelo lógico dos dados.

A linguagem SQL fornece a cláusula ORDER BY visando a especificação da ordem particular na qual os registros serão retornados do dispositivo gerenciador de bancos de dados. O seguinte comando retorna uma lista em ordem alfabética de todos os clientes da Limpa Tudo:

SELECT [Razão Social] FROM Clientes

ORDER BY [Razão Social]

Extraindo Dados de Múltiplas Tabelas

Quando tratamos da modelagem de dados, insistimos no fato de que nenhuma informação redundante deveria ser mantida numa tabela. Nestes casos, o tópico deveria ser dividido em duas ou mais tabelas, estabelecendo-se um relacionamento entre elas através de um campo comum a ambas. Isso significa que, via de regra, os dados necessários para a eficiente manipulação de uma base de dados estão contidos em mais de uma tabela.

Não há nenhuma complicação adicional em se extrair dados de diversas tabelas armazenadas num mesmo banco de dados.

Page 288: Iniciando No Visual Basic

Simplesmente informe após a cláusula FROM o nome das diversas tabelas necessárias. A partir daí, passa a ser relevante declarar explicitamente de qual tabela o campo deve ser extraído na cláusula SELECT. Isso é feito precedendo o nome do campo pelo nome da tabela e separando-os com o operador ponto.

No entanto, algumas considerações devem ser feitas. Quando separamos dados afins em múltiplas tabelas, geralmente as relacionamos através de um campo-chave (a chave externa). Quando isso acontece, não é possível simplesmente declarar as diversas tabelas de onde os dados devem ser extraídos sem determinar o tipo de relacionamento desejado entre os campos-chave. Sendo assim, deve haver um mecanismo para declarar o relacionamento entre as tabelas. Um exemplo simples nos ajudará a ilustrar o problema. Suponhamos que a Limpa Tudo precise mandar uma mala direta para todos os seus clientes, divulgando os novos e fantásticos descontos dados para seus produtos. Assim, é necessário retornar um endereço completo na forma exigida pela empresa de correios. Como você se recorda, os campos necessários para a mala direta - Razão Social, Endereço, CEP, Cidade e UF - estão armazenados em duas tabelas - Clientes e Localidades.

Você se recorda também que estabelecemos uma relação um-para-vários entre ambas através do campo CEP, onde Clientes é a tabela dependente. Assim, nem todos os registros da tabela Localidades nos interessam, apenas aqueles com uma correspondência direta na tabela Clientes. Esta correspondência é definida na expressão Localidades.CEP = Clientes.CEP.

Vamos supor agora que nem todos os clientes da Limpa Tudo devem ser incluídos na mala direta, apenas aqueles que adquiriram produtos no ano de 1998. Assim, precisamos incluir na consulta também a tabela Vendas. Os campos dessa tabela não serão utilizados na mala direta; servem apenas para filtrar os registros da tabela Clientes.

Na modelagem do banco de dados, definimos que para cada registro na tabela Clientes, poderiam existir vários registros na tabela Vendas, relacionados pela chave Clientes. A condição de relacionamento da consulta é, portanto, expressa pela relação Clientes.Cliente = Vendas.Cliente. O relacionamento global entre as três tabelas componentes da mala direta pode ser graficamente expresso pela Figura 15.9:

Figura 15.9: Gerando uma mala direta.

Page 289: Iniciando No Visual Basic

Como dissemos, a tabela Vendas será utilizada somente como um filtro para os registros da tabela Clientes. Queremos extrair somente aqueles registros que satisfaçam a duas condições:

Estejam, simultaneamente, em ambas as tabelas. Essa, como se sabe, é a condição relacionando as tabelas.

Estejam armazenados na tabela Vendas com uma data qualquer do ano de 1998. A condição WHERE de filtro seria, portanto, Vendas.Data > CVDate('01/01/98')

Essa complexa rede de relacionamentos deve ser expressa na cláusula FROM da nossa consulta. O mecanismo básico para a expressão desse critério de relacionamento é a cláusula SQLINNER JOIN... ON. Nós declaramos que a tabela A deve ser combinada à tabela B (INNER JOIN) sempre que os campos-chave corresponderem a um determinado valor de comparação (ON). A complexidade do relacionamento das tabelas do exemplo pode ser expressa pelo aninhamento das cláusulas INNER JOIN.

A cláusula INNER JOIN combina registros de duas tabelas sempre que campos comuns satisfaçam a um determinado valor de comparação. Note que a tentativa de utilizar campos Memo ou OLE Object na comparação gera um erro. Campos numéricos podem ser comparados mesmo que possuam diferentes tipos de dados.

A extração dos registros desejados do banco de dados da Limpa Tudo pode ser feita utilizando a declaração SQL listada a seguir, onde deve ser notado o aninhamento de ligações:

SELECT Clientes.[Razão Social], Clientes.CGC,

Clientes.Endereço, Clientes.CEP, Localidades.Cidade,

Localidades.UF FROM (Localidades

INNER JOIN Clientes ON Localidades.CEP = Clientes.CEP)

INNER JOIN Vendas ON Clientes.Cliente = Vendas.Cliente

WHERE (Vendas.Data>CVDate('01/01/98'))

Em alguns casos, contudo, podemos querer selecionar todos os registros de uma das tabelas, tenham ou não correspondência com os registros de outra. Nestes casos, utilizamos as cláusulasLEFTJOIN e RIGHTJOIN.

Page 290: Iniciando No Visual Basic

A cláusula LEFT JOIN seleciona todos os registros da primeira tabela (à esquerda da declaração), mesmo que não tenham correspondência com os registros da segunda tabela. A cláusulaRIGHT JOIN  faz a mesma coisa em sentido inverso, referenciando a segunda tabela (à direita da declaração).

Acessando Tabelas Externas

Algumas vezes, é necessária a extração de dados de tabelas armazenadas em fontes de dados externas. Tais fontes representam bancos de dados não nativos, mas acessíveis pelo Microsoft Jet, tais como dBase, Paradox, FoxPro, etc. Nestes casos, especificamos o banco de dados e o tipo da conexão através da cláusula IN. Por exemplo, podemos selecionar todos os campos de arquivo dBase III das seguintes maneiras:

SELECT * FROM Arquivo IN "Drive:\Diretório" "dBase III;";

SELECT * FROM Arquivo IN "" [dBase III; DATABASE=Drive:\Diretório;];

Condições de filtragem e ordenações podem ser especificadas normalmente. Deve-se atentar, contudo, para as diferenças entre os diversos tipos de bancos de dados e a maneira do Microsoft Jet conectá-los.

Filtrando Resultados de uma Consulta

Há diferentes maneiras de filtrar e agrupar os dados numa consulta. Para isso, a linguagem SQL incorpora um bom número de cláusulas e predicados com essa finalidade. Trataremos apenas das mais utilizadas, a saber:

O predicado DISTINCT. Omite os registros contendo dados duplicados dentro de uma seleção. Imagine que você deseja uma visão geográfica dos clientes de uma empresa. Uma das possibilidades pode ser, por exemplo, uma consulta selecionando somente o campo Cidade da base de dados. Neste caso, faz sentido selecionar apenas um registro para cada valor distinto obtido, eliminando-se a redundância. Um exemplo poderia ser a declaração SELECT DISTINCT Cidade FROM Localidades.

O predicado TOP. Retorna somente uma determinada quantidade de registros compondo o início ou o fim de um intervalo especificado. Por exemplo, suponha que você deseje localizar os dez maiores clientes

Page 291: Iniciando No Visual Basic

da sua empresa. Isso poderia ser feito por uma declaração como SELECT TOP 1O Cliente FROM Clientes ORDER BY Faturamento DESC.

A cláusula GROUP BY. Combina, num único registro, registros com um mesmo valor para um campo especificado. Caso se utilize as funções SUM ou COUNT, um valor agregado é criado para cada registro que satisfaça a condição especificada. Por exemplo, para obter uma consulta ordenada de itens em estoque, é possível utilizar a declaração SELECT Produtos.[Nome do Produto], Estoque.[Quantidade Estocada] FROM Estoque INNER JOIN Produtos ON (Produtos.Produto = Estoque. Produto) AND (Estoque.Produto = Produtos. Produto) GROUP BY Produtos.[Nome do Produto], Estoque.[Quantidade Estocada].

A cláusula HAVING. Especifica quais registros agrupados (por uma cláusula GROUP BY) serão retornados. Tais registros deverão satisfazer a uma condição especificada. Por exemplo, para obter apenas os itens em estoque cuja quantidade é inferior a 50, pode-se utilizar a declaração SELECT Produtos.[Nome do Produto], Estoque. [Quantidade Estocada] FROM Estoque INNER JOIN Produtos ON (Produtos.Produto = Estoque.Produto) AND (Estoque.Produto = Produtos.Produto) GROUP BY Produtos.[Nome do Produto], Estoque.[Quantidade Estocada] HAVING (Estoque.[Quantidade Estocada]<50).

Subconsultas e Consultas de Referência Cruzada

Não há, praticamente, limite para a complexidade de uma query. Nós vimos um exemplo dessa complexidade quando enfocamos a cláusula INNER JOIN. Há outros tópicos a abordar.

Subconsultas

Uma subconsulta é simplesmente uma declaração SELECT dentro de uma outra declaração SELECT ou declarações de ação, vistas mais adiante. É possível utilizar uma subconsulta nas mais diversas circunstâncias:

No lugar de uma expressão na lista de campos de uma declaração SELECT;

Dentro de uma cláusula WHERE;

Dentro de uma cláusula HAVING.

Page 292: Iniciando No Visual Basic

 

Para selecionar os registros da consulta principal que satisfaçam a comparação com quaisquer dos registros da consulta secundária, utilizamos os predicados ANY ou SOME. Para selecionar somente os registros da consulta principal que satisfaçam a comparação com todos os registros da consulta secundária, utilizamos o predicado ALL. Para selecionar somente os registros da consulta principal para os quais existam valores idênticos na consulta secundária, utilizamos o predicado IN.

Tentemos um exemplo simples. Queremos uma lista de todos os fornecedores da Limpa Tudo cujos produtos, sejam eles quais forem, tenham preço inferior a R$ 1,00. Podemos utilizar a seguinte consulta para a seleção dos registros apropriados: SELECT * FROM Fornecedores "WHERE Fornecedor = ANY (SELECT * FROM [Produtos Por Fornecedor] WHERE [Preço de Compra] < 1@).

Consultas de Referência Cruzada

A consulta de referência cruzada é utilizada quando desejamos resumir dados em um formato de linhas e colunas. Com tais consultas, usamos valores de um campo ou expressão particular como cabeçalhos de coluna e cabeçalhos de linha, de modo a visualizar dados num formato mais compacto do que com uma consulta seleção.

Para a criação de uma consulta de referência cruzada, utilizamos a instrução TRANSFORM antes da declaração SELECT usada para recuperar os registros e especificamos a função de agregação que opera sobre o dado selecionado.

Consultas de Ação

Um conjunto amplo de operações é possível com a SQL. Ela é particularmente eficiente no processamento de grandes massas de registros. Vejamos alguns exemplos.

Consultas de Criação de Tabelas

É possível a criação de uma tabela a partir dos resultados de uma consulta em particular. Neste caso, em vez de utilizamos o objeto Recordset criado pelo comando SQL, fazemos com que ele crie uma tabela onde os registros serão armazenados. Isto é feito acrescentando-se a cláusula INTO à instrução SELECT, especificando o nome da tabela a ser criada.

Page 293: Iniciando No Visual Basic

As consultas de criação de tabela podem ser utilizadas para arquivar registros antigos, fazer cópias de reserva ou de exportação para outro banco de dados ou, ainda, como base para relatórios que exibem dados de uma época específica.

Quando uma tabela é criada a partir de uma consulta, os campos dessa nova tabela herdam os tipos de dados e o tamanho do campo de cada campo das tabelas de origem da consulta, mas nenhuma outra propriedade de campo ou de tabela é transferida. É possível, contudo, definir um campo de chave primária para a nova tabela.

Para criar uma tabela temporária contendo os dez melhores clientes da empresa, utilize o seguinte comando SQL: SELECT TOP 10 Cliente INTO [Melhores Clientes] FROM Clientes ORDER BY Faturamento DESC.

Consultas de Anexação

É possível acrescentar registros de uma tabela ou consulta ao final de uma outra tabela, no mesmo banco de dados ou em um diferente. São as chamadas consultas de anexação, criadas utilizando-se o comando INSERT INTO antes da declaração SELECT que gera a consulta. Neste caso, especificamos a tabela onde os registros serão anexados. Caso a tabela de destino se localize num outro banco de dados, este deverá ser especificado numa cláusula IN.

Se a tabela à qual se está anexando registros incluir um campo de chave primária, os registros anexados precisam ter o mesmo campo, ou um equivalente, do mesmo tipo de dados. O Microsoft Jet anexará os registros se tanto os valores repetidos quanto os vazios resultarem no campo de chave primária.

A seguinte declaração cria uma cópia de backup de uma das tabelas da Limpa Tudo: INSERT INTO Clientes IN 'BACKUP.MDB' SELECT * FROM Clientes.

Consultas de Atualização de Tabelas

Uma consulta de atualização altera um conjunto de registros de acordo com o critério especificado. É utilizada para alterar um grupo de registros especificados com critérios definidos. É possível a utilização de expressões numa consulta de atualização para realizar essas alterações. Utilizamos a cláusula UPDATE para especificar a tabela a ser atualizada e a cláusula SET para determinar os campos que deverão ser alterados e os respectivos valores a serem

Page 294: Iniciando No Visual Basic

considerados. A consulta utilizada como exemplo logo no início deste capítulo é uma consulta de atualização de tabela.

Remoção de Registros

Uma consulta de exclusão remove um conjunto de registros de acordo com o critério especificado. É utilizada para excluir um grupo de registros especificados com critérios definidos. É possível utilizar uma consulta de exclusão para excluir registros de uma tabela simples ou de tabelas múltiplas, desde que o relacionamento entre elas seja do tipo um para um. Para excluir registros de tabelas múltiplas em um relacionamento um para vários é necessário executar duas consultas.

Em alguns casos, executar consultas de exclusão pode excluir registros de tabelas relacionadas, mesmo que elas não estejam incluídas na consulta. Isto pode acontecer quando a consulta contém uma tabela que está do lado um de um relacionamento um para vários e a integridade referencial dos dados força a exclusão em cascata para este relacionamento. Quando os registros desta tabela são excluídos, estão sendo excluídos também os registros relacionados da tabela "vários".

A seguinte consulta remove todos os registros da tabela Clientes que não adquiriram produtos da Limpa Tudo no ano de 1997: DELETE * FROM Clientes WHERE Cliente = ANY ( SELECT * FROM Clientes INNER JOIN Vendas ON Clientes.Cliente = Vendas.Cliente WHERE Vendas.Data < CVDate(‘01/01/97’)) .

 

Page 295: Iniciando No Visual Basic

OOP no Visual BasicEmbora este não seja um artigo extenso e ocupe uma pequena parte no conjunto das informações que lhe estão sendo enviadas neste CD, considero-o especialmente interessante na medida em que pode significar uma contribuição para a padronização de suas aplicações. O tratamento do assunto não se esgotará aqui, mas será continuado nas atualizações futuras a este pacote de Visual Basic. Você poderá acessar essas atualizações com sua senha de acesso à nossa página na Internet . O tema a ser tratado aqui é a orientação a objeto, uma abordagem relativamente nova no desenvolvimento de sistemas para fins comerciais e que tem se tornado o tema do momento quando se fala em metodologia de trabalho na área de sistemas informatizados. Não pretendo fazer uma grande explanação sobre a OOP, mas apenas introduzirei as idéias básicas da OOP para, em seguida, apresentar uma forma que considero racional de organizar uma aplicação em Visual Basic explorando os seus modernos recursos de orientação a objeto. O modelo que discutirei está baseado na arquitetura documento-vista, já velha conhecida dos programadores de C++ que utilizam a biblioteca de classes de fundamentos da Microsoft (MFC). No meio dos programadores em Visual Basic, no entanto, este assunto é pouco conhecido.

O que significa "Baseado em Objetos"?

Sob um ponto de vista superficial, a expressão "baseado em objetos" significa que o software é organizado como uma coleção de objetos separados que incorporam tanto a estrutura como o comportamento dos dados. Isto contrasta com a programação convencional, segundo a qual a estrutura e o comportamento dos dados têm pouca vinculação entre si. Existe alguma discordância sobre quais são exatamente as características exigidas pela abordagem baseada em objetos, mas geralmente elas incluem quatro aspectos: identidade, classificação, polimorfismo e herança.

Características dos Objetos

Identidade significa que os dados são subdivididos em entidades discretas e distintas, denominadas objetos. Um parágrafo em um documento, uma janela na minha estação de trabalho e a rainha branca no jogo de xadrez são exemplos de objetos. Os objetos podem ser concretos, como um arquivo em um sistema de arquivos, ou conceituais, como uma norma de escalonamento em um sistema operacional de multiprocessamento ou uma operação em um

Page 296: Iniciando No Visual Basic

programa. Cada objeto tem sua própria identidade, que lhe é inerente. Em outras palavras, dois objetos são distintos mesmo que todos os valores de seus atributos (como nome e tamanho) sejam idênticos.

No mundo real um objeto limita-se a existir, mas, no que se refere a uma linguagem de programação, cada objeto dispõe de um único indicador, pelo qual ele pode ser referenciado inequivocamente. O indicador pode ser implementado de diversas maneiras, como um endereço na memória, um elemento de uma matriz ou um valor exclusivo de um atributo. As referências dos objetos são uniformes e independentes do conteúdo dos mesmos, permitindo a criação de objetos mesclados, tal como um diretório de um sistema de arquivos que contenha tanto arquivos como subdiretórios.

Classificação significa que os objetos com a mesma estrutura de dados (atributos) e o mesmo comportamento (operações) são agrupados em uma classe. Parágrafo, Janela e Peça de Xadrez são exemplos de classes. Uma classe é uma abstração que descreve propriedades importantes para uma aplicação e ignora o restante. Qualquer escolha de classes é arbitrária e depende da aplicação.

Cada classe descreve um conjunto possivelmente infinito de objetos individuais. Cada objeto é dito ser uma instância de sua classe. Cada instância da classe tem seu próprio valor para cada atributo, mas compartilha os nomes de atributos e operações com as demais instâncias da mesma classe. Um objeto contém uma referência implícita à sua própria classe; ele "sabe que tipo de coisa ele é".

Polimorfismo significa que a mesma operação pode atuar de modos diversos em classes diferentes. A operação move (mover), por exemplo, pode atuar de modo diferente nas classes Janela e Peça de Xadrez. Uma operação é uma ação ou transformação que um objeto executa ou a que ele está sujeito. Right-justify (justificar à direita), display (exibir) e move (mover) são exemplos de operações. Uma implementação específica de uma operação por uma determinada classe é chamada de método. Como uma operação baseada em objetos é polimórfica, pode haver mais de um método para a sua implementação.

No mundo real uma operação é simplesmente uma abstração de um comportamento análogo entre diferentes tipos de objetos. Cada objeto "sabe como" executar suas próprias operações. Entretanto, uma linguagem de programação baseada em objetos seleciona automaticamente o método correto para implementar uma operação com base no nome da operação e na classe do objeto que esteja

Page 297: Iniciando No Visual Basic

sendo operado. O usuário de uma operação não precisa saber quantos métodos existem para implementar uma determinada operação polimórfica. Novas classes podem ser adicionadas sem que se modifique o código existente, são fornecidos métodos para cada operação aplicável nas novas classes.

Herança é o compartilhamento de atributos e operações entre classes com base num relacionamento hierárquico. Uma classe pode ser definida de forma abrangente e depois ser refinada em sucessivas subclasses mais definidas. Cada subclasse incorpora, ou herda, todas as propriedades da sua superclasse e acrescenta suas próprias e exclusivas características. As propriedades da superclasse não precisam ser repetidas em cada subclasse. Por exemplo, Janela Rolante e Janela Fixa são subclasses da superclasse Janela. Estas duas subclasses herdam as propriedades de Janela, como uma região visível na tela. Janela Rolante acrescenta uma barra de rolagem e limites de rolagem. A capacidade de identificar propriedades comuns a várias classes de uma superclasse comum e de fazê-las herdar as propriedades da superclasse pode reduzir substancialmente as repetições nos projetos e programas e é uma das principais vantagens dos sistemas baseados em objetos.

O Visual Basic e a OOP

A partir da versão 4, o Visual Basic teve um importante acréscimo à sua massa de recursos: as classes. Podendo criar suas próprias classes, os programadores em Visual Basic passaram ter como organizar suas aplicações dentro de uma ótica de programação orientada para objetos. O problema agora passa a ser "o que fazer para tirar o máximo de proveito deste novo recurso?". Acredito que uma das fontes de resposta a esta pergunta pode ser buscada nas práticas de programação em linguagens orientadas a objeto mais tradicionais, como a C++. Por esta razão decidi examinar a já conhecida arquitetura documento-vista, sobre a qual está baseada a biblioteca de classes de fundamentos (MFC) que acompanha o Visual C++. Nem tudo pode ser transposto para o Visual Basic, mas ainda assim acredito que os ganhos em estruturação e racionalidade para as aplicações é compensador.

A arquitetura documento-vista, como o próprio nome já diz, está fundamentada na relação entre um documento e sua(s) vista(s). Por documento entenda-se um conjunto de informações gravadas em disco e que podem ser tomadas como uma unidade a ser apresentada. Por exemplo, um arquivo de texto pode ser tratado como um documento, mas uma tabela dentro de um banco de dados Access

Page 298: Iniciando No Visual Basic

também pode ser tratada como um documento já que pode ser tomada como uma unidade a ser apresentada.

Nessa relação o documento é representado pela classe - CDocument - que contém toda a funcionalidade para centralizar o controle das diferentes formas da apresentação dos dados. As diferentes formas de apresentação de um documento correspondem às suas vistas, e estas são construídas a partir da classe CView. Cabe à classe CDocument manter uma coleção das suas vistas a cada momento. Quando uma vista é usada para modificar os dados em disco, a classe CDocument é informada pela vista da modificação e, se for o caso, pode ser solicitada a comunicar todas as demais vistas para que se atualizem. Quando uma vista é fechada, antes de encerrar sua atividade, ela comunica a classe CDocument para que faça a sua remoção da coleção de vistas.

Cabe à vista todo o trabalho de interação com o usuário seja na apresentação dos dados na tela, seja na remessa de informações do documento para a impressora. Cada vista do documento é um formulário com um conjunto de métodos de uso comum, tais como: localizar, substituir, copiar, colar, imprimir, visualizar impressão. Para cada vista estes métodos serão implementados de uma forma compatível com os dados que a vista apresenta e também com o formato dessa apresentação. O importante é que, sendo este conjunto de métodos nomeados de modo igual em todas as vistas, outros objetos não terão que se comportar de modo diferente nas suas relações com as vistas a cada vez que se modifique a vista ativa na aplicação. Por exemplo, a janela principal tem no menu Editar uma série de submenus que podem significar ações diferentes a serem tomadas dependendo de qual vista de um documento esteja ativa no momento. Copiar pode representar uma coisa se a vista ativa estiver exibindo uma tabela em formato de grade, mas pode significar outra coisa se o que estiver sendo exibindo for um gráfico baseado na tabela. Não cabe, portanto, à janela principal saber o que deve ser copiado, mas sim à vista ativa. Chamando o método copiar da vista, a janela principal lava as mãos e deixa à vista o trabalho de fazer a cópia do que deve ser copiado. O mesmo vale para o menu Localizar, por exemplo. Se uma vista exibe um documento tipo texto, a janela de localização é de um tipo, mas se o que está sendo exibido é um recordset, evidentemente que a janela a ser exibida é de outro tipo, com outra funcionalidade. Seguindo esta linha de divisão de responsabilidades, podemos levar nossas aplicações a um alto grau de reutilização de código e modularidade, além de torná-las mais rapidamente compreensíveis na medida em que seguem um padrão que se repete.

Page 299: Iniciando No Visual Basic

A arquitetura documento-vista não pode responder por toda uma aplicação. È apenas uma relação central em torno da qual gravitam outras classes que têm papel importante na estrutura da aplicação. Por exemplo, alguém tem que coordenar a criação e encerramento dos documentos. Este trabalho é feito por uma classe chamada CDocTemplate. DocTemplate é abreviatura para algo que, em português, seria "modelo de documento". Um modelo de documento reúne algumas informações importantes para a manipulação dos documentos de um determinado tipo. Como um conjunto de informações gravadas em disco, o documento pode precisar ser aberto como um arquivo. Isto exige a identificação do documento pela extensão presente no nome do arquivo. Dependendo da extensão no nome do arquivo, uma rotina diferente será chamada para abri-lo e uma vista apropriada será criada para exibi-lo. Quem faz este trabalho é a classe CDocTemplate. Para cada tipo de documento presente em uma aplicação, você deve providenciar um objeto da classe CDocTemplate inicializado com as informações necessárias para manipular aquele tipo de documento. Do mesmo modo que os objetos da classe CDocument mantêm uma coleção com referências às suas vistas de momento, os objetos CDocTemplate mantêm uma coleção de todos os objetos CDocument mantidos por eles a cada instante.

Os objetos CDocTemplates por sua vez, também precisam ser coordenados dentro da aplicação. Quem se incumbe desta tarefa é o objeto App. Não aquele que o Visual Basic lhe fornece, mas sim um que você cria para encapsular o objeto App do Visual Basic e acrescentar-lhe outros atributos e capacidades. O objeto App mantém uma coleção de todos os modelos de documentos presentes na aplicação. No momento em que o usuário clica sobre o menu Arquivo\Abrir, o objeto App é solicitado a percorrer essa coleção em busca de informações para a caixa de diálogo. Cada objeto CDocTemplate tem uma propriedade onde está armazenada uma string de filtro a ser usada na caixa de diálogo Abrir Arquivo. Antes que o objeto App mostre a caixa de diálogo Abrir Arquivo, ele coleta estas strings para compor o conjunto de filtros de arquivos que a caixa de diálogo deve possibilitar ao usuário abrir. O mesmo vale para o menu Arquivo\Novo.

Não estamos aqui nos aprofundando no assunto da forma devida, mas apenas dando uma idéia geral do que pode ser feito dentro dessa linha de raciocínio. Temos um exemplo da aplicação destas idéias no projeto que se encontra no arquivo mfcnovb.zip. Apesar de estar incompleto dá para ter uma idéia do que pode ser feito nesta linha.

 

Page 300: Iniciando No Visual Basic