Está en la página 1de 22

Usando Procedimentos e Funes no Visual Basic

A maioria dos procedimentos que voc escreveu nos captulos anteriores foram procedimentos de eventos - isto , eles foram projetados especialmente para responder a eventos especficos disparados pelo usurio ou pelo sistema. Este captulo mostra-lhe como escrever e usar procedimentos genricos (incluindo sub-procedimentos e procedimentos de funes) que executam uma certa tarefa quando so chamados explicitamente por outras instrues do programa (em vez de serem disparados por um evento). Este captulo explora tambm o uso de parmetros, que permite ao programa passar certos valores para os procedimentos e funes que chama. Como voc ver, at mesmo objetos do Visual Basic podem ser passados como argumento. Finalmente, este captulo aborda alguns procedimentos de eventos avanados, como aqueles que lhe permitem rastrear o movimento do mouse e implementar recursos do tipo arrastar e soltar. Procedimentos Genricos As primeiras aplicaes que voc escreveu tinham um controle de fluxo linear: aps uma instruo ser executada, era executada a prxima instruo seqencial. No capitulo anterior, voc comeou a trabalhar com desvios condicionais (instrues If) e com laos, que modificam a ordem na qual as instrues so executadas Da mesma forma que laos, os procedimentos permitem que seu programa execute um conjunto de procedimentos mais de uma vez. Entretanto, em vez de executar repetidamente um conjunto de instrues, os procedimentos permitem que voc agrupe instrues num conjunto que possa ser executado quando necessrio. Por exemplo, um procedimento de evento do Visual Basic executado quando o usurio faz uma certa ao; um procedimento genrico executado quando chamado por uma instruo do aplicativo. Considere um programa que simule as aes de uma criana pequena passeando de automvel. Este cdigo ilustra o comportamento conhecido como "choramingas" : Resposta = lnputBox("Ainda no chegamos ?") lf Resposta = "No" Then MsgBox "Estou cansado" End If

Em um programa que simule o comportamento de crianas, de se esperar que essas linhas sejam duplicadas um boa quantidade de vezes. Porm, em vez de codificar mltiplas cpias dessas instrues, voc pode agrup-las em um procedimento e execut-lo simplesmente invocando o seu nome. Inclua uma declarao do procedimento, dando-lhe um nome descritivo: Sub Choro () Dim Resposta As String Resposta = lnputBox("Ainda no chegamos ?") lf Resposta = "No" Then MsgBox "Estou cansado" End lf End Sub Com esse procedimento, os fragmentos dos dois programas que seguem so equivalentes: Figura 7.1 Fluxo de Controle Obviamente, os procedimentos afetam o fluxo de controle de execuo de um programa. Quando o Visual Basic encontra o nome de um procedimento, ele guarda a posio atual no programa e ento se move para executar o procedimento designado. Quando encontrado o final do procedimento, ele retorna posio original do programa e continua a execuo 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 nveis de chamadas, um procedimento chamado por um programa pode conter dentro de si prprio uma chamada de procedimento e assim por diante. Parmetros 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 codificao 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 so muito semelhantes, muito simples generalizar isto , fazer com que o mesmo cdigo sirva para os dois propsitos. A nica diferena entre os dois o valor final no lao For, que pode ser substitudo por uma varivel. Depois disso voc poder usar um procedimento nico, chamando-o aps armazenar na varivel o valor final desejado, conforme mostrado a seguir. (Assuma que a instruo Dim ContFinal As Integer aparece na seo de declaraes gerais do programa.)

Figura 7.2 Como se pode ver, o uso combinado de variveis e procedimentos permite que voc encontre solues genricas para os programas mais facilmente, alm de colocar sua disposio excelentes ferramentas de programao. Entretanto, h alguns problemas prticos com a implementao feita anteriormente. Em particular, voc precisa declarar variveis globais (pblicas) ou em nvel de mdulo para fazer a comunicao entre o programa principal e o procedimento que est sendo chamado. Alm disso, preciso que as variveis locais aos procedimentos tenham nomes diferentes das variveis globais. Do contrrio, a chamada de um procedimento poder fazer com que o valor de uma varivel global seja sobreposto por valores locais ao procedimento. O Visual Basic resolve essas questes, permitindo que os procedimentos aceitem parmetros que sejam tratados como variveis locais ao procedimento, porm inicializados pela codificao que chama o procedimento. A rotina chamadora inicializa essas variveis com a colocao de um conjunto de valores aps o nome do procedimento a ser chamado. Eis a sintaxe para uma tal chamada de procedimento: name[ value[, value] ... ] Observe que os argumentos so separados por vrgulas. A rotina chamadora tem de saber os nomes dos parmetros, pois o assinalamento destes valores s variveis locais ao procedimento chamado ser feito segundo a ordem de especificao dos parmetros. Na declarao do procedimento, os parmetros so declarados dentro dos parnteses que seguem o nome do procedimento. O Visual Basic permite que os procedimentos tenham vrios parmetros. Eis a sintaxe para declarao de procedimento que inclua parmetros: Sub name ([parmetro [As tipo], [parmetro [As tipo]] ... ])

End Sub Veja como ficou o exemplo anterior, refeito com o uso de parmetros: Figura 7.3

Para ilustrar o uso de mltiplos parmetros, 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 Funes A partir dos exemplos precedentes, voc deve ter reparado que, quando se trata de chamadas de procedimentos genricos, a comunicao feita apenas num sentido - isto , a rotina chamadora passa valores para o procedimento que executa alguma ao, mas no retorna qualquer valor para a rotina chamadora. No entanto, voc pode usar um tipo especial de procedimento, chamado procedimento de funo (ou simplesmente funo), que retorna valor ao chamador. A maioria da funes internas do Visual Basic faz isso. Ao declarar uma funo, voc deve declarar o tipo de valor que ela retorna, bem como os parmetros necessrios, como mostra a definio de sintaxe:

Figura 7.5

Como voc pode ver, h duas diferenas entre um procedimento de funo e um subprocedimento. Um procedimento de funo delimitado pelas instrues Function e End Function, enquanto um subprocedimento requer Sub e End Sub. E, como mostra a definio sinttica, em algum lugar dentro do corpo da funo, voc deve assinalar um valor (expresso) ao nome da funo. Esse o valor que ser retornado para a rotina chamadora. Por exemplo, esta funo 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 funo ligeiramente diferente da sintaxe usada para chamar um subprocedimento. Como a funo retorna um valor, ela pode ser chamada em qualquer lugar em que uma expresso seja vlida. Os parmetros da funo so, portanto, delimitados por parnteses para separ-los de outras partes de uma expresso. Aqui esto algumas instrues chamando a funo MaxInt: Print MaxInt(7, 14) DuasVezesMaior = MaxInt(3, 4) * 2 lf MaxInt(PrimeiraOpo, SegundaOpo) > 20 Then Quando a funo a ser chamada no requer parmetros, basta usar o nome da funo, como se fosse uma varivel. A funo interna Now do Visual Basic (que retorna data e hora atuais) um exemplo de funo que no requer a passagem de parmetros. Escrevendo Procedimentos A discusso que se segue usa o termo procedimento para se referir idia geral de rotina que pode ser chamada. Quando necessrio, o termo procedimento de funo (ou simplesmente funo) ou o termo subprocedimento ser aplicado para dar maior clareza exposio. Para criar um procedimento que possa ser chamado em Visual Basic, voc deve abrir a janela de cdigo. A partir do menu Tools, escolha a opo Add Procedure. Na caixa de dilogo Add Procedure, digite o nome do novo procedimento, escolha entre Sub ou Function, dando um clique num dos dois botes de opo. Escolha entre pblico e privado tambm clicando em uma das opes.D um clique no boto OK. O Visual Basic criar ento um novo item na caixa de procedimentos da janela de cdigo, j inserindo a instruo End apropriada para o tipo de procedimento que estiver sendo criado. Agora, voc pode incluir as declaraes de parmetros necessrias ao seu procedimento. Nota: voc deve ter notado as opes property e event na caixa de dilogo Add Procedure. Trataremos destas opes quando falarmos sobre Classes e Objetos. Vamos escrever um programa simples chamado Converso de Temperatura, para executar uma converso simples de temperatura entre as escalas Celsius

e Fahrenheit. Abra um novo projeto e coloque uma barra de deslocamento vertical, seis rtulos 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 usurio ajustar a barra de deslocamento para qualquer configurao de temperatura entre os pontos rotulados como -40 e 212 na escala Fahrenheit ou entre as temperaturas correspondentes -40 e 100 na escala Celsius. O aplicativo ento exibir o valor da temperatura para a configurao escolhida nas duas escalas, Fahrenheit e Celsius. Repare que a configurao da propriedade Min para a barra de deslocamento maior do que a configurao para Max. Essa forma de configurao faz com que a barra de deslocamento coloque o extremo superior de sua faixa de variao no topo, ao contrrio do que acontece quando a configurao da propriedade Min menor do que a da propriedade Max . Figura 7.6 O projeto inicial do form, para o aplicativo Converso de Temperatura. Figura 7.7 Configurao de propriedades para o aplicativo Converso de Temperatura. Por questes de simplicidade, o programa sempre "pensar" em termos de graus Celsius, fazendo a converso para obter a temperatura em Fahrenheit. Em primeiro lugar, voc deve escrever a funo que retorna a temperatura Fahrenheit quando o programa fornecer a temperatura em graus Celsius. Comece abrindo a janela de cdigo do form. A partir do menu Tools, escolha a opo Add Procedure. Na caixa de dilogo, digite CParaF, escolha o boto de opo Function e d um clique em OK. Ento, edite a nova funo como segue (inicie adicionando as declaraes do parmetro e do tipo de valor a ser retornado na instruo Function): Function CParaF (TempC As Integer) As Integer CParaF = Cint(TempC * 9 / 5 + 32) End Function A funo CParaF aplica a frmula padro de converso mtrica. Recebendo a temperatura em graus Celsius como parmetro, ela retorna a temperatura equivalente na escala Fahrenheit. Para simplificar a sada e o uso da barra de deslocamento, os valores esto restritos a inteiros. (A funo CInt converte valor em ponto flutuante para inteiro, por arredondamento.) Agora, voc pode escrever o cdigo que l o valor da barra de deslocamento e exibe os valores das temperaturas. Introduza o seguinte subprocedimento abaixo da funo: Sub ExibeTemp ()

Dim TempC As Integer TempC = Clnt(VscTermmetro.Value) TxtGrausC.Text = Str$(TempC) TxtGrausF.Text = Str$(CParaF(TempC)) End Sub Aps introduzir a primeira linha (a instruo Sub), repare que o Visual Basic adiciona o nome do procedimento caixa de procedimentos e inclui a instruo End Sub no cdigo que voc est escrevendo. Como voc pode ver, possvel criar novos procedimentos, tanto por meio da opo Add Procedure do menu Tools quanto da introduo da instruo Function ou Sub em qualquer lugar da janela de cdigo. O cdigo para o procedimento ExibeTemp l o valor da barra de deslocamento, VscTermmetro.Value, armazenando-o na varivel TempC. O valor exibido na caixa de texto TxtGrausC. Ento, a caixa de texto TxtGrausF configurada com o resultado gerado pela funo de converso CParaR Finalmente, selecione o objeto VscTermmetro (a barra de deslocamento) na caixa de objetos da janela de cdigo e edite seus procedimentos de evento como mostrado aqui: Private Sub VscTermmetro_Change () ExibeTemp End Sub Private Sub VscTermmetro_Scroll () ExibeTemp End Sub Com isso, toda vez que o usurio 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 Converso de Temperatura. Pensando no Futuro Pode parecer que voc fez alguns trabalhos desnecessrios ao escrever o cdigo para o aplicativo Converso de Temperatura. No final das contas, se cada procedimento usado apenas uma nica vez, por que no fazer todos os

clculos em uma linha s e agrupar todas as instrues no procedimento de evento Change da barra de deslocamento? O cdigo do programa resultante deve parecer-se com o mostrado a seguir: Sub VscTermmetro_Change () Dim TempC As Integer TempC = CInt(VscTermmetro.Value) TxtGrausC.Text = Str$(TempC) TxtGrausF.Text = Str$(Clnt(TempC * 9 / 5 + 32)) End Sub De fato, esse programa perfeitamente aceitvel, e trabalha to bem quanto a primeira verso. Porm, o programa original de Converso de Temperatura melhor pelos seguintes motivos:

Ele substitui frmulas por nomes de funes no programa principal.

Nomes adicionam clareza e ajudam a explicar o que est acontecendo no programa.


Ele contm rotinas genricas que podem ser usadas novamente. Ser muito simples copiar a funo CParaF para outro programa. Seus procedimentos so partes que podem ser manipuladas com facilidade, se voc decidir modificar o programa.

Como uma ilustrao, considere uma melhoria do programa. Na verso atual, preciso usar uma barra de deslocamento para configurar uma certa temperatura. Porm, poderia ser de grande ajuda permitir ao usurio introduzir diretamente o valor da temperatura e ento levar o programa a fazer a converso. Usando os blocos de construo que voc criou, ser relativamente simples fazer isso. Caso voc tivesse escrito o programa como uma pea nica, esse tipo de modificao poderia requerer duplicao ou at mesmo reescrever o cdigo. Generalizando As melhores ferramentas so as que podem ser usadas em mais de um servio. Com freqncia, voc pode facilmente converter poucas linhas de um cdigo especifico, proveitoso apenas num certo contexto, em uma rotina genrica. Considere o cdigo que voc escreveu no Capitulo 6 para pesquisar um determinado nome de doninha; a verso completa mostrada na Figura 7.9. A Figura 7.10 apresenta uma verso que usa um procedimento genrico derivado do cdigo original. Essa segunda verso oferece uma rotina que encontrar qualquer doninha pelo nome, podendo ser til vrias vezes no programa.

Figura 7.9 Cdigo do programa que pesquisa uma doninha pelo nome.

Figura 7.10 Cdigo do programa contendo um procedimento genrico que pode pesquisar qualquer doninha. Reciclando Cdigo Hoje voc est escrevendo programas para acompanhar doninhas. Amanh poder tratar-se de micos-lees. E quando voc estiver escrevendo seus programas para micos, ser muito prtico poder dizer: "Ei, algumas semanas atrs, eu escrevi alguma coisa semelhante a isso". Se voc escreve rotinas genricas, possvel simplesmente recuperar o cdigo de um programa velho e us-lo no novo programa. Esse cdigo 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 cdigo desenvolvido por voc mesmo, normalmente antitico (e com freqncia ilegal) copiar diretamente um cdigo escrito por outra pessoa. No entanto, voc est liberado para copiar o cdigo dos programas de exemplo que acompanham o Visual Basic; a Microsoft garante a permisso para cpia dos cdigos. Como Trabalham os Parmetros At agora, voc usou parmetros apenas para passar argumentos para os procedimentos. Porm, os parmetros so muito mais flexveis do que isso. Vamos dar uma olhada nos dois mecanismos que se encontram disponveis no Visual Basic para passagem de argumentos. Passagem por Referncia Quando os parmetros foram introduzidos pela primeira vez, eu os descrevi como se fossem variveis locais. Na verdade, nem sempre esse o caso. Considere o subprocedimento Increment que adiciona 1 ao valor do parmetro, X: Sub Increment (X As Integer) X=X+1 End Sub Caso X seja uma varivel local, esse procedimento ser intil. O valor do parmetro da rotina chamadora seria assinalado a X, e o procedimento incrementaria esse valor e em seguida terminaria sua execuo destruindo efetivamente as variveis locais. Na realidade, X uma referncia ao valor original da rotina chamadora, e qualquer modificao em X altera o valor

original. Se o cdigo 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 parmetro X no passa de uma referncia ao valor de uma varivel, no ser alocada memria no subprocedimento Increment para armazenar esse valor. O Visual Basic apenas armazena a informao de que X uma referncia. O uso de referncia permite ao Visual Basic operar mais eficientemente. Essa eficincia no muito representativa quando se trata de variveis inteiras. No entanto, considere o procedimento DeLado, que imprime seu parmetro string entre parnteses: Sub DeLado (Str As String) Print "(" Print Str Print ")" End Sub Se os parmetros fossem realmente variveis locais, o Visual Basic teria de alocar espao 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 referncia string original. Passagem por Valor Voc tambm pode fazer com que os parmetros trabalhem de outra forma isto , como variveis locais. Se voc iniciar a declarao do parmetro com a palavra-chave ByVal, o Visual Basic alocar memria local para o parmetro e copiar o valor do argumento correspondente para o parmetro. Eis um exemplo desse tipo de declarao: Sub Increment (ByVal X As Integer) X=X+1 End Sub A passagem por referncia geralmente mais eficiente, porm a passagem por valor d origem a variveis locais que algumas vezes so necessrias nos

seus programas. Por exemplo, vejamos a funo que calcula X elevado potncia Y, isto , X ^ Y. Esse clculo usa multiplicaes repetidas (por exemplo, X ^ 3 igual a X . X . X). Por questes de simplicidade, essa funo ignorar valores negativos para o expoente. O parmetro Y especifica a quantidade de multiplicaes necessrias. O valor de Y decrementado aps cada multiplicao, e o clculo termina quando Y chega a 0. Function Potncia (X As Single, _ ByVal Y As Integer) As Single Dim Result As Single Result = 1 Do While Y > 0 Result = Result * X Y=Y-1 Loop Potncia = Result End Function Uma vez que voc deseja modificar Y na funo, porm no quer que seja alterado o valor original da varivel que foi passada, deve declarar Y com a palavra-chave ByVal. Examine o seguinte fragmento de cdigo, que chama a funo Potncia: 'Aproximar E elevado a N, usando as sries de Taylor Result = 1 For Aprox = 1 to 10 Result = Result + Potncia(N, Aprox) / Factorial(Aprox) Next Aprox O programador espera que essa rotina faa o lao 10 vezes enquanto estiver fazendo o seu clculo. Entretanto, se a funo Potncia que ela est chamando no usar a palavra-chave ByVal, essa rotina jamais sair do lao, entrando em looping infinito. Aps a funo Potncia ser chamada pela primeira vez, Aprox seria zerada (pois a varivel local Y iria tornar-se uma referncia a Aprox). A funo Factorial seria chamada com o valor errado e ento a instruo For incrementaria Aprox e iniciaria o lao novamente. Como Potncia continua a zerar a varivel Aprox, o lao For jamais terminaria.

Uma boa regra prtica que qualquer declarao de parmetro para o tipo Integer, Long ou Single deveria ser uma declarao ByVal (isto , o parmetro 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 questes de eficincia, devero ser passadas por referncia. Controles e tipos de dados definidos pelo usurio (tal como DoninhaTFB) podem ser passados apenas por referncia. Para outros tipos de dados como double, currency e variant, a deciso no to simples. A boa prtica de programao sugere que voc passe esses parmetros por valor, pois dessa forma estar menos sujeito a usar uma varivel parmetro incorretamente. Entretanto, mais eficiente passar esses parmetros por referncia. Meu conselho considerar em primeiro lugar os bons princpios de programao. Passar inicialmente todas as variveis (exceto strings, matrizes e tipos definidos pelo usurio) por valor. Aps completar a construo de seu programa e depois de test-lo, voc poder investigar como melhorar o seu desempenho. Ento, se o seu programa passar a operar incorretamente, aps a remoo de algumas palavras-chave ByVal, voc saber onde olhar para encontrar os problemas. Passagem de Parmetros de Matriz Voc pode declarar um parmetro de matriz como faz com qualquer outro parmetro, omitindo da declarao a dimenso da matriz. Por exemplo, esta funo calcula a mdia dos elementos de qualquer matriz de valores com dupla preciso. Function Mdia (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 Mdia = 0 Else Mdia = Total / Dcont

End If End Function O parmetro DMatriz declarado como uma matriz do tipo Double, porm a sua dimenso no declarada. Esse cdigo um outro exemplo de uma soluo generalizada. Como a dimenso no declarada, essa mesma funo pode ser chamada com argumentos que sejam matrizes de qualquer dimenso. (Basta que os elementos sejam do tipo Double.) Para passar uma matriz como argumento para um procedimento, use apenas o nome da varivel matriz seguido de um par de parnteses vazio. Este fragmento de cdigo mostra como o procedimento Mdia pode ser usado: Dim MeusDados(100) As Double, ltensLidos As Integer ItensLidos = CargaDados(MeusDados( ), 100) Print "A mdia dos valores : " & _ Mdia(MeusDados( ), ltensLidos) MeusDados declarado como uma matriz com dimenso 100. O procedimento CargaDados (no mostrado aqui) chamado, sendo passadas como parmetros a matriz MeusDados e a dimenso mxima da matriz. Provavelmente, a rotina CargaDados preenche o maior nmero de elementos da matriz possvel, retornando como valor a quantidade real de itens preenchidos. A seguir, o programa imprime a mdia. A chamada Mdia retorna a matriz e a quantidade de elementos que foram preenchidos por CargaDados. Naturalmente, quando necessrio, voc pode passar elementos individuais de matrizes. Basta indexar a matriz para indicar o elemento a ser passado, como nesta linha de cdigo: Print "A raiz quadrada do item 3 " & Sqr(MeusDados(3)) Voc pode modificar o aplicativo Banco do Capitulo 6 para usar a funo Mdia, como mostrado na Figura 7.11. Cada vez que voc der um clique no boto Mdia, o programa redimensionar a matriz dinmica ListaValor para acomodar a quantidade de itens na caixa de lista. Como a caixa de lista contm uma matriz de strings; em vez de nmeros, cada elemento deve ser convertido medida que for copiado para ListaValor. Ento, o programa passa a matriz como argumento para a funo Mdia. Figura 7.11 Uma modificao no aplicativo Banco.

Esse programa modificado um pouco mais longo do que o aplicativo original. Porm, voc criou uma nova ferramenta - a funo Mdia - que pode ser usada em vrios lugares. Por exemplo, para ampliar o programa Banco para trabalhar com mais de uma conta, voc pode chamar a funo Mdia para cada conta, em vez de escrever um lao separado para cada uma. Se voc tiver de escrever um programa que calcule a mdia pluviomtrica, pode carregar o programa Banco, copiar a funo Mdia e coloc-la no novo programa. Alocao Local Em funo da discusso sobre escopo feita no Capitulo 3, voc j est familiarizado com variveis locais. Agora que voc est trabalhando com parmetros similares s variveis locais, ser til verificar a maneira pela qual o Visual Basic gerencia a memria usada por variveis locais. Quando voc inicia um programa, o Visual Basic sabe quantas variveis globais existem e aloca memria para elas. No entanto, ele no sabe quantas variveis locais existem ou quando cada procedimento do programa ser chamado. Variveis locais e parmetros so criados quando o procedimento que os contm chamado, e so destrudos quando o procedimento acaba. Se um procedimento for chamado novamente, as variveis so recriadas. Esse processo no apenas retarda a alocao de memria at que ela seja necessria, mas permite que a memria seja reutilizada por variveis que pertenam a procedimentos diferentes. Os computadores modernos executam essa alocao temporria e a liberao muito eficientemente. No entanto, algumas vezes voc pode querer que o valor armazenado em uma varivel local no seja perdido quando o procedimento que a contm for encerrado. Voc poderia declarar uma varivel em nvel de mdulo ou pblica, mas essa soluo no seria ideal se a varivel viesse a ser usada apenas em um procedimento. O Visual Basic oferece a palavra-chave Static para tratar dessa questo. Se voc usa Static em vez de Dim dentro de um procedimento, as variveis declaradas dessa forma tero escopo local, visvel apenas dentro daquele procedimento; no entanto, sero permanentes, como se fossem declaradas em nvel de mdulo. O Visual Basic inicializa todas as variveis Static como 0, tornando-as teis para situaes como a que se segue: Sub Command1_Click () Static Contador As Integer Contador = Contador + 1 MsgBox "Este boto j foi pressionado" & _ Str$(Contador) & "vezes." End Sub

Abra um novo form, inclua um boto de comando simples com o procedimento acima e tente executar o programa. Ento, mude a palavra-chave Static para Dim para verificar que, no caso de uma varivel puramente local, o programa no funciona. Objetos Do Visual Basic como Parmetros Os procedimentos que voc escreveu at agora tm passado apenas valores numricos, matrizes e strings como parmetros. O Visual Basic tambm permite-lhe passar controles e forms. A sintaxe similar: basta usar a palavrachave Control ou Form, em vez de String, Integer, e assim por diante, na declarao do procedimento. Essa caracterstica lhe d a habilidade de escrever cdigo totalmente genrico. Por exemplo, suponha que voc esteja escrevendo um aplicativo com uma certa quantidade de botes na tela. Em vrios pontos do aplicativo, voc deseja dar ateno especial a um boto particular, colocando a caracterstica itlica em seu ttulo e configurando a sua cor de fundo para vermelho. O seguinte subprocedimento faz isso: Sub Ateno (Boto As Control) Boto.FontItalic = True Boto.BackColor = vbRed End Sub Voc passa um objeto como um parmetro usando o seu nome. Voc poderia passar para esse subprocedimento um boto chamado btnNext, com a instruo Ateno btnNext. Similarmente, voc pode declarar um parmetro como sendo um form. Voc pode configurar ou examinar as propriedades do form e chamar os seus mtodos. Pode passar o form pelo nome ou usar a varivel interna Me (eu), que o form ativo no momento. O Aplicativo Evasivo Vamos desenvolver um aplicativo, chamado Evasivo que faz uma brincadeira com o usurio. Ele exibir uma mensagem de erro, como se tivesse ocorrido uma falha durante sua inicializao. O usurio ver uma caixa de dilogo com dois botes de comando, Cancel e Retry. Entretanto, o que acontece quando o usurio d um clique em um desses botes no habitual. O boto caminhar para um ponto qualquer do form, e o usurio jamais ser capaz de cancelar a execuo do programa dando um clique num dos botes. Esse aplicativo ilustra como voc pode passar objetos como parmetros e como usar o mtodo Move - um mtodo que pode ser implementado para a maioria dos controles do Visual Basic.

Cada boto de comando dever ter o mesmo comportamento. De certa forma, voc pode assegurar isso, chamando o mesmo procedimento para cada um dos botes. No entanto, uma das aes do procedimento ser mover o boto para uma nova posio. Essa ao requer uma chamada ao mtodo Move dos botes, exigindo que voc passe o boto como um parmetro. Crie um novo projeto e arranje dois campos de rtulo e dois botes de comando no form como mostrado na Figura 7.12. A Figura 7.13 lista as configuraes de propriedades que sero necessrias. Figura 7.12 O projeto inicial do form para o aplicativo Evasivo. Figura 7.13 Configurao de propriedades para o aplicativo Evasivo.

A Figura 7.14 contm o cdigo do programa para o aplicativo Evasivo, e a Figura 7.15 mostra como o aplicativo ficar quando o usurio process-lo.

Figura 7.14 Cdigo de programa para o aplicativo Evasivo. Figura 7.15 Processando o aplicativo Evasivo. O procedimento Salto usado nesse aplicativo pode ajustar a posio no apenas dos dois botes de comando, mas de quase qualquer tipo de controle que lhe seja passado como parmetro, pois a maioria dos controles possui o mtodo Move. Entretanto, algumas vezes voc pode querer executar tipos de processamento especiais, que sejam especficos a certos tipos de objetos. O Visual Basic oferece a instruo If TypeOf para determinar o tipo de controle do parmetro. Ela funciona da mesma maneira que a instruo If convencional; apenas a primeira linha de sua sintaxe diferente. If TypeOf objeto Is TipoObjeto Then Se voc quisesse que o procedimento Salto distinguisse botes de opo de outros tipos de controles, a primeira linha da instruo If TypeOf deveria ser semelhante a isto: If TypeOf CtI Is OptionButton Then Procedimentos de Eventos Avanados Esta seo examina procedimentos de eventos do Visual Basic mais complexos do que os procedimentos Click e DblClick. Essas tcnicas permitem-lhe construir aplicativos com tratamento mais sofisticado para teclado

e mouse, e implementar uma tcnica grfica chamada arrastar e soltar (drag and drop). Eventos de Mouse Nossos exemplos anteriores levaram em considerao o mouse apenas quando usado para dar um clique em um objeto. O mximo que voc fez foi escrever um cdigo 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 posio do mouse quando voc est arrastando um grfico ou criando uma nova imagem. Um jogo pode usar a posio do mouse para controlar alguns de seus aspectos. Porm, o Visual Basic no contm um objeto mouse. Em vez disso, o evento MouseMove disparado quando a posio do mouse se modifica. Com freqncia, os eventos de mouse so associados com forms e caixas de imagem, porm eles podem ser usados tambm com os outros objetos. Com propsitos de ilustrao esta seo ir concentrar-se apenas nos forms. Cada form possui estes trs procedimentos padres: Figura 7.16 O Visual Basic chama esses procedimentos quando o usurio interage com o mouse. O evento MouseDown ocorre sempre que um boto do mouse pressionado. O evento MouseUp sinalizado quando o boto do mouse (que se encontrava pressionado) liberado. O evento MouseMove ocorre quando a posio do mouse alterada. A Figura 7.17 descreve os parmetros que so passados para esses procedimentos de eventos.

Figura 7.17 Parmetros dos procedimentos de eventos do mouse.

A melhor forma de ilustrar estes eventos a criao de um aplicativo de exemplo. Criaremos aqui o aplicativo Desenho de Linha. Esse aplicativo usa o mtodo Line, um mtodo grfico para desenho de um form. (Discutiremos o mtodo Line em maiores detalhes no Captulo 11.)

Figura 7.18 Cdigo de programa para o aplicativo Desenho de Linha.

Quando voc processar o aplicativo, a varivel Desenhando ser inicialmente configurada como False. Porm, quando o boto esquerdo do mouse for pressionado, a varivel ser configurada para True. Quando o boto for liberado, Desenhando passar a ser False novamente. medida que voc mover o mouse, mantendo o boto pressionado, o programa traar a linha a partir da ltima posio conhecida (CurrentX, CurrentY), at a posio atual do mouse. Se voc mantiver a tecla Shift pressionada enquanto traa uma linha, a sua cor ser alterada para vermelho at voc soltar a tecla Shift. Nota: Mouses com um nico boto tm esse boto definido como left-button (boto esquerdo). Se o seu mouse tiver dois botes e voc alterou o Painel de Controle do Windows para inverter os botes esquerdo e direito do mouse, o Visual Basic passar o valor vbLeftButton quando for pressionado o boto da direita e vice-versa. Eventos de Teclado O Capitulo 6 introduziu o evento KeyPress, que disparado para certos objetos quando o usurio est digitando. O Visual Basic permite um grau de controle ainda mais refinado com os eventos KeyUp e KeyDown, que so disparados quando o usurio pressiona e solta uma tecla. Apenas aplicativos muito especficos requerero o uso desses eventos, entretanto a ajuda do Visual Basic contm informaes completas a esse respeito. Os forms possuem outra caracterstica 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 informao a ser passada para os procedimentos de eventos KeyPress, KeyDown e KeyUp dos objetos. Por exemplo, para registrar cada tecla pressionada pelo usurio, voc poderia definir a seguinte funo (suponha que SalvarTudo seja declarada como uma varivel string em nvel 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 nvel do form vier a modificar a varivel KeyAscii, o procedimento de evento KeyPress do objeto atualmente ativo receber a tecla modificada. Se o procedimento em nvel do form configurar KeyAscii para 0, o procedimento KeyPress do objeto no ser chamado.

Arrastar e Soltar O Visual Basic fornece tambm um suporte especial para outra forma de interao com usurios; 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 no recebe mais o evento Click ou MouseDown. Em vez disso, o objeto se movimenta quando o usurio d um clique nele, comeando 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 usurio solta o objetofonte (soltando o boto do mouse), o Visual Basic envia o evento DragDrop para o objeto de destino. Adicionalmente, eventos DragOver so enviados para quaisquer objetos sobre os quais passar o objeto-fonte. O mecanismo arrastar e soltar permite-lhe projetar uma interao simples e prtica com os usurios, na qual podem ser executadas vrias tarefas, sem o uso de comandos, menus ou botes. Esse mtodo muito intuitivo em diversas situaes e freqentemente mais veloz do que outros mtodos. Para demonstrar o mecanismo arrastar e soltar, vamos escrever um aplicativo chamado Correio Eletrnico, que simular o ambiente de trabalho para a troca eletrnica de mensagens. Ele permitir que voc crie novas mensagens e arraste-as para uma caixa postal, a partir da qual elas podero ser distribudas para a rede. (Ser apresentado aqui apenas o mecanismo arrastar e soltar. O cdigo completo para um sistema de mensagens eletrnicas ocuparia o livro inteiro.) Inicie pela criao de um novo projeto. Inclua dois botes de comando, sete pequenos controles de imagem, conforme mostrado na Figura 7.19. Os trs controles de imagem na parte inferior do form armazenaro cpias mestras de cones, a exemplo do que foi feito com alguns controles de imagens no aplicativo Caa-nqueis do Captulo 6. Aps inicializar esses controles, voc pode redimensionar o form para elimin-los da rea de viso. Os cones usados neste aplicativo podem ser encontrados no diretrio de cones do CD deste pacote. Configure as propriedades dos trs controles de imagens inferiores (Image5, Image6 e Image7), como listado na Figura 7.20. A 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 Eletrnico

Figura 7.20 Configurao de propriedades para os trs controles de imagens inferiores no aplicativo Correio Eletrnico. Configurando-se a propriedade DragMode do objeto Image7 (cone de carta) para 1, possibilita-se ao usurio arrastar as cartas ao longo da janela. A configurao 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 cdigo do programa usar essa matriz.) A Figura 7.21 mostra-lhe como a linha inferior de controle de imagens deve ficar aps essa configurao de propriedades.

Figura 7.21 Os trs cones inferiores usados no aplicativo Correio Eletrnico.

Agora, configure as propriedades dos outros objetos, conforme indicado pela Figura 7.22. Aps modificar as dimenses do form para que as trs imagens inferiores no apaream, o seu form dever parecer-se com o mostrado na Figura 7.23. Os controles de imagens que aparecem na parte superior da janela serviro 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) no podem ser distribudos 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 usurio arrastar uma carta para a caixa postal. Os botes de comando permitiro ao usurio criar novas cartas (com o cone de carta) e limpar a caixa postal. Figura 7.22 Configurao de propriedades restantes usadas no aplicativo Correio Eletrnico. Figura 7.23 O projeto final do form para o aplicativo Correio Eletrnico. O cdigo para esse aplicativo requer a seguinte declarao: Dim ProxCarta As Integer Dois procedimentos so necessrios em nvel do form. O procedimento Form_Load inicializa o cone da caixa postal e a varivel ProxCarta; o procedimento Form_DragDrop move o controle para o ponto que o usurio 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 bsica mostra apenas trs cones. Voc deve escrever a codificao para o boto MsgNova, para permitir ao usurio 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. Aps o Visual Basic criar o novo membro da matriz de controles (ImgCarta), esse novo membro recebe uma posio na janela e torna-se visvel. Ento, a varivel ProxCarta incrementada de forma que o prximo evento Click crie uma nova carta. O boto 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 prprio procedimento arrastar e soltar. Quando um controle arrastado para a caixa, o programa verifica a propriedade Tag do objeto-fonte. Caso no seja uma carta, o procedimento provoca o seu encerramento, no permitindo que o objeto seja colocado sobre a caixa postal. Do contrrio, 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 boto MsgNova algumas vezes, para criar novas cartas. Excluindo a caixa postal, todas as imagens que esto 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 boto Limpar Caixa restaura o cone da caixa postal. Note que o programa no permitir que voc arraste o telefone, a caneta ou o clipe para a caixa postal. O programa usa a varivel ProxCarta para especificar um valor continuamente crescente para os elementos subseqentes da matriz de controles ImgCarta.

Use RabJump e adicione cdigo automtico para GotFocus, LostFocus, KeyPress, KeyDown