Inicializando e Finalizando Aplicativos de Forma Rápida e Sem Problemas Escrito por: William Costa Rodrigues i wcostarodrigues@yahoo.com.br Junho 2005 Página 1 de 7
1 Introdução Neste artigo abordarei alguns aspectos que possibilitará inicializar uma aplicação de forma mais rápida, de forma mais produtiva e finalizar um aplicativo sem problemas de erro. Além dedar uma pincelada em declaração de variáveis e imagens. Bom estudo e espero que este artigo seja útil a todos. 2 Inicialização Um artifício que muitos desenvolvedores sempre utilizam é a tela de abertura. Esta tela tem vários objetivos. O principal deles é fazer uma divulgação do software, ou seja, fazer com que o usuário identifique a logomarca ou tela do software ao vê-los em algum lugar. Entretanto a tela de inicialização poderá ser mais que isto, por exemplo, ela poderá carregar todas as variáveis necessárias para o sistema, ou seja, variáveis que serão utilizadas pelo aplicativo num primeiro momento. Abaixo segue um exemplo fictício de uma tela de abertura (Figura 1), onde nela foram adicionados alguns labels e um Timer. Figura 1. Tela de abertura do software Lizaro Database Manager em modo Design Time. Quanto ao designer da tela nada demais, entretanto no evento Timer do controle Timer o desenvolvedor poderá adicionar rotinas que irão atribuir a variáveis (prédefinidas) valores (Código 1). Ainda na tela de apresentação ou abertura do software o programador poderá não só setar as variáveis internas, mas também variáveis externas, oriundas do registro, por exemplo. Código 1. Rotina para carregar as variáveis iniciais do programa no evento Timer do controle Timer nomeado tmini Private Sub tmini_timer() Me.lblStatus.Caption = "Obtendo as variáveis do programa..." DoEvents 'dá um pequeno intervalo a até a próxima ação stitulo = App.Title & " v" & App.Major & "." & App.Minor 'retorna o título do aplicativo sversion = " Versão" & App.Major & "." & Format(App.Minor, "00") & "." & Format(App.Revision, "0000") 'retorna a versão do executável na formatação 0.00.0000 scopyright = App.LegalCopyright sdescapp = App.FileDescription 'Retorna a deescrição do executável DoEvents Página 2 de 7
Me.lblStatus.Caption = "Listando fontes existentes..." DoEvents Me.lblStatus.Caption = "Carregando configurações do sistema..." 'Ler do registro do Windows valores setados pelo sistema TPws = GetSetting(sTitulo, "Config", "TPws", 0) TPLeft = GetSetting(sTitulo, "Config", "TPLeft", 0) TPTop = GetSetting(sTitulo, "Config", "TPTop", 0) TPWidth = GetSetting(sTitulo, "Config", "TPWidth") TPHeight = GetSetting(sTitulo, "Config", "TPHeight") slastfile = GetSetting(sTitulo, "Config", "slastfile", "") ToolBarVis = GetSetting(sTitulo, "Config", "ToolBarVis", True) DoEvents 'dá um pequeno intervalo a até a próxima ação GetCollecFont 'chama a função para listar as fontes instaladas no computador tmini.enabled = False Unload Me TelPrin.Show O andamento que é especificado no Label lblstatus, que inicialmente tem mostra o texto "Inicializando aguarde..." 'e importante para que o usuário tenha a noção do andamento da inicialização da aplicação e não tenha a sensação que o aplicativo "travou" (Figura 2), mas não é somente a trav;es de um label que podemos demonstrar o progresso de uma determinada rotina, aí é onde entra a criatividade do desenvolvedor. Assim poderemos utilizar outros recursos gráficos, como o controle ProgressBar (Figura 3), mas não abuse, pois muito recurso poderá surtir o efeito contrário e deixar sua aplicação lenta na inicialização. Figura 2. Tela de abertura do software Lizaro Database Manager em modo Run Time. Página 3 de 7
Figura 3. Tela de abertura do software Lizaro Visual Basic Dicas v4.0 demonstrndo o progressode inicialização. Vale ressaltar que as variáveis devem de preferência ser declaradas (sempre), pois ajuda e muito ao desenvolvedor rastrear com maior facilidade eventuais erros na elaboração de rotinas. Particularmente eu sempre declaro as variáveis que irão compor as informações básica do sistema num módulo intitulado mmain (Código 2), que é o módulo principal de minha aplicações. Outro procedimento de padronização que sempre faço é sempre inicializar minha aplicações através do Sub Main (Código 2). Código 2. Variáveis públicas do sistema e o rotina Sub Main bem simples Option Explicit Public stitulo Public sversion Public scopyright Public sdescapp Public cfontinst Public TPws Public TPLeft Public TPTop Public TPWidth Public TPHeight Public slastfile Public ToolBarVis As New Collection As Boolean Public Sub Main() frmabert.show 1 A partir daí surge uma questão. Qual a vantagem de declarar variáveis e atribui valores a estas na tela inicial do programa? A declaração de variáveis dá ao programa maior velocidade, pois quando declaramos temos a certeza que o tipo de variável será sob medida para o que pretendemos, ou seja, a aplicação não estará consumindo recursos a mais do que necessário. Um exemplo é declarar uma variável da seguinte forma: Dim i; está variável será do tipo Variant, que padrão para o Visual Basic. Para você ter uma idéia comparativa uma variável do tipo Variant é mais lento do que se você utilizar um tipo específico, devido às conversões necessárias e ocupa mais memória em virtude de um Página 4 de 7
overhead maior (CORNELL, 1998). Desta forma, vemos que a variável do tipo Variant não possui limites de armazenamento, tornando mais lenta a aplicação, entretanto se a variável i fosse declarada com Long ou Integer ocuparia menos memória, como pode ser vista na Tabela 1. Tabela 1. Tipo de variáveis sua capacidade de uso utilizada pelo Visual Basic (RODRIGUES, 2004). Tipo Capacidade Boolean True ou False Byte 0 a 256 Currency -922.337.203.685.477,5808 a -922.337.203.685.477,5807 Date Qualquer expressão de data válida. Double (Valores negativos) -1,79769313486232 E-308 a -4,94065645841247 E-324 (Valores positivos) 4,94065645841247 E-324 a 1,79769313486232 E-308 Integer -32.768 a 32.767 Long -2.147.483.648 a 2.417.483.647 Single (Valores negativos) -3,402823 E-38 a -1,401298 E-45 (Valores positivos) 1,401298 E-45 a 3,402823 E-38 String Qualquer tamanho Variant Variável Quando atribuímos a uma variável publica ou global (está última requer mais recursos do sistema) um valor, que ela carrega consigo até a aplicação seja finalizada ou o valor ser modificado ou mesmo zerado. Assim a qualquer momento poderemos utilizar a variável que ter que chamar uma rotina para isto. Bem um exemplo que podemos abordar é a adição do nome das fontes instaladas no sistema, em um Collection (Código 3). Qual a vantagem deste procedimento? Simples, quando adicionamos o nome destas fontes a esta Collection permitimos que a aplicação possa ler a partir da memória os valores atribuídos, assim torna mais rápido o acesso às informações, a pesar de alguns desenvolvedores considerarem que este procedimento consome mais recursos. Código 3. Rotina que atribui a uma coleção (Collection) todos os nomes das fontes instaladas na máquina. Public Sub GetCollecFont() Dim i As Long For i = 0 To Screen.FontCount cfontinst.add Screen.Fonts(i) Next i Outro aspecto a ser considerado é que imagens "pesadas" colocadas na tela de abertura consomem muita memória, principalmente se adicionadas no controle PictureBox, prefira o controle Image, pois consome menos recursos do sistema. Quando falo de imagens pesada é evitar imagens do tipo WMF, BMP, pois são imagens grandes, prefira utilizar JPG, com uma compactação de 10% ou mesmo sem compactação, mas lembre que uma compactação elevada pode causar distúrbio na imagem. Todos os aspectos abordados aqui irão depender da máquina que o aplicativo estará sendo "rodado", porém cuidado, muitas pessoas e mesmo empresa ainda utilizam máquinas Pentium 2 e K62, com clock que giram em torno dos 500MHz ou até mesmo menores, por exemplo, trabalho em três máquinas: em casa um Pentium MMX 166MHz (64 MHz Ram),onde desenvolvo a maioria dos meus sistemas, e um Pentium 4 2.8Ghz Página 5 de 7
(512 MHz Ram); no trabalho um AMD Athlon XP 2,4 GHz (256 MHz Ram), as diferenças incomparáveis,quando consideramos as maquinas mais moderna com o MMX, por isso devemos sempre planejar nossos sistema de acordo com a disponibilidade de recurso da máquina do cliente. A explicação de desenvolver em uma máquina obsoleta é simples, mantenho a compatibilidade de minhas aplicações em sistemas mais antigos, como o Windows 98, mas tenho sempre o cuidado de testar em máquinas mais modernas, para verificar possíveis incompatibilidades. 3 Finalizando um aplicativo com segurança Muitos desenvolvedores utilizam a função interna End para finalizar seus aplicativos, entretanto até a Microsoft em uma KB, recomenda a utilização desta função, devido à forma que ela interrompe a aplicação, ou seja, esta função interrompe bruscamente a aplicação, não descarregando por completo as variáveis do programa, assim a aplicação gera um erro no Kernel do Windows, que gerencia as variáveis. Assim uma alternativa para este problema é o Código 4, que inicialmente fecha todos os formulários e assim eliminando da memória todas as variáveis ainda ativas. No Código 4, há uma alternativa, para caso um dos formulários não seja encerrado, que é ativada pela variável do tipo Boolean, chamada Force. Existe duas formar de chamar a rotina UnloadAll, eu particularmente utilizo as duas, no menu de finalização programa (smnuexit) e no evento QueryUnload, principalmente se aplicação for do tipo MDI (Multiple Development Interface), neste evento ainda acrescento o função interna On Error Resume Next, para prevenir eventuais erros (Código 5). Existem uma série de exemplos na Internet sobre o assunto, mas alguns deles não funcionam a contento, pois já testei muito e o melhor até o momento é o apresentado no Código 4, pois trabalho com aplicações do tipo MDI. Código 4. Rotina para descarregar todos os formulários e encerrará a aplicação sem erros. Public Sub UnloadAll(Optional ByVal Force As Boolean = False) Dim i As Long On Error Resume Next For i = Forms.Count - 1 To 0 Step -1 Unload Forms(i) If Not Force Then If Forms.Count > i Then Exit Sub End If End If Next If Force Or (Forms.Count = 0) Then Close Código 5. Eventos em que podemos chamar a rotina UnloadAll. Private Sub smnuexit_click() UnloadAll Private Sub MDIForm_QueryUnload(Cancel As Integer, UnloadMode As Integer) On Error Resume Next UnloadAll Página 6 de 7
4 Considerações Finais Com as explanações feitas nos tópicos anteriores podemos considerar que um bom planejamento de variáveis e imagens utilizadas em nossas aplicações possibilitam não só um bom desempenho, mas também uma iniciliazação mais rápida. A rotina de finalização apresentada é uma solução para encerrar a aplicação sem erros, principalmente aplicações do tipo MDI. Espero que este artigo tenha ajudado a elucidar algumas questões sobre os tópicos abordados. Críticas e sugestões poderão ser encaminhadas para wcostarodrigues@yahoo.com.br. 5 Referências CORNELL, G. 1998. Visual Basic 5: Completo e Total. Trad.: L.G.E. UNONIUS. São Paulo: Makron Books, 778p. RODRIGUES, W.C. 2004. Microsoft Visual Basic: desvendando a linguagem de programação mais popular do mundo. Seropédica: Lizaro Soft, 115p. disponível em www.lizarosoft.cjb.net. RODRIGUES, W.C. 2005. Lizaro Visual Basic Dicas v4.0: Biblioteca de dicas do Visual Basic. Não publicado. i William Costa Rodrigues é Eng. Agrônomo, Pós-doutor em entomologia e programador autodidata. Desenvolve softwares em Visual Basic desde 2000, alem de atuar com Webdesigner. Página 7 de 7