dicas de vb

242
SUMÁRIO SUMÁRIO...................................................1 ARQUIVOS.......................................................8 Carregando um arquivo texto para um ListBox..................8 Checando se um arquivo texto está em branco..................8 Copiando Arquivos............................................ 9 Copiando Arquivos Através de Comandos do VB................9 Copiando Arquivos Através de API...........................9 Criando um arquivo texto em branco..........................10 Descobrindo e Alterando Atributos de Arquivos...............10 Excluindo Arquivos.......................................... 12 Excluindo Arquivos Através de Comandos do VB (SEM usar a Lixeira).................................................. 12 Excluindo Arquivos Através de API (USANDO a Lixeira)......12 Função que Abre um Arquivo Texto e Retorna seu Conteúdo.....13 Funçãos para Manipulação de Arquivos INI....................13 Gravar cada informação em uma linha nova de um arquivo......16 Imprimindo Arquivos Texto pelo VB...........................16 Procurar um arquivo em diretórios e subdiretórios...........16 Salvando o conteúdo de um TextBox num Arquivo Texto.........17 Verificando a Data da Última Alteração de um Arquivo........18 Verificando a existencia de um arquivo......................18 BANCO DE DADOS................................................19 Abrindo Bancos de Dados Externos - DAO & ADO................19 DAO....................................................... 19 ADO....................................................... 19 Abrindo Relatórios do Access pelo VB........................20 Abrir Banco de Dados com Senha - DAO & ADO..................20 DAO....................................................... 20 ADO....................................................... 20 Compactar Banco de Dados - DAO & ADO........................21 Antes de começar..........................................21 Compactar banco de dados protegido por senha - DAO & ADO....23 Problema.................................................. 23 Solução................................................... 23 Antes de começar..........................................23 Criando Banco de Dados com Tabelas e Índices via VB - DAO. . .26 Filtrar Recordset já aberto - DAO...........................27 Função que Cria a Clausula Where para Você..................29 Listando o Nome de Todas as Tabelas de um BD - ADO & DAO....30 Passar parametro para SQL armazenada em DB - ADO............31 1

Upload: marciano-canuto

Post on 28-Oct-2014

742 views

Category:

Documents


13 download

TRANSCRIPT

Page 1: Dicas de VB

SUMÁRIO

SUMÁRIO.........................................................................................................................1ARQUIVOS...................................................................................................................................8

Carregando um arquivo texto para um ListBox.........................................................................8Checando se um arquivo texto está em branco..........................................................................8Copiando Arquivos....................................................................................................................9Copiando Arquivos Através de Comandos do VB.........................................9Copiando Arquivos Através de API...................................................................9

Criando um arquivo texto em branco.......................................................................................10Descobrindo e Alterando Atributos de Arquivos.....................................................................10Excluindo Arquivos.................................................................................................................12

Excluindo Arquivos Através de Comandos do VB (SEM usar a Lixeira)...........................12Excluindo Arquivos Através de API (USANDO a Lixeira)................................................12

Função que Abre um Arquivo Texto e Retorna seu Conteúdo................................................13Funçãos para Manipulação de Arquivos INI............................................................................13Gravar cada informação em uma linha nova de um arquivo....................................................16Imprimindo Arquivos Texto pelo VB......................................................................................16Procurar um arquivo em diretórios e subdiretórios..................................................................16Salvando o conteúdo de um TextBox num Arquivo Texto......................................................17Verificando a Data da Última Alteração de um Arquivo.........................................................18Verificando a existencia de um arquivo...................................................................................18

BANCO DE DADOS...................................................................................................................19Abrindo Bancos de Dados Externos - DAO & ADO...............................................................19

DAO.....................................................................................................................................19ADO.....................................................................................................................................19

Abrindo Relatórios do Access pelo VB...................................................................................20Abrir Banco de Dados com Senha - DAO & ADO..................................................................20

DAO.....................................................................................................................................20ADO.....................................................................................................................................20

Compactar Banco de Dados - DAO & ADO...........................................................................21Antes de começar.................................................................................................................21

Compactar banco de dados protegido por senha - DAO & ADO............................................23Problema..............................................................................................................................23Solução.................................................................................................................................23Antes de começar.................................................................................................................23

Criando Banco de Dados com Tabelas e Índices via VB - DAO.............................................26Filtrar Recordset já aberto - DAO............................................................................................27Função que Cria a Clausula Where para Você.........................................................................29Listando o Nome de Todas as Tabelas de um BD - ADO & DAO..........................................30Passar parametro para SQL armazenada em DB - ADO.........................................................31Procurando no Banco de Dados (Find - FindFirst - FindNext) - DAO & ADO......................31

(DAO)..................................................................................................................................31(ADO)..................................................................................................................................32

Reparar Banco de Dados - DAO..............................................................................................34Salvar informações do Access para dBase - DAO...................................................................34Solução para a Aspa Simples (') em Strings de SQL...............................................................34Trabalhando com Recordsets Desconectados - ADO..............................................................35Trabalhando com Recordsets Dinâmicos - ADO.....................................................................35Usando o IIF em Consultas SQL.............................................................................................36

1

Page 2: Dicas de VB

Utilizando o ADO - [Básico]...................................................................................................36A. Abertura de Banco de Dados e de Tabelas......................................................................36B. Manipulação de Dados....................................................................................................38

Utilizar algum programa que compacte os DBs.......................................................................39CÁLCULOS.................................................................................................................................43

Calcula a idade em anos entre duas datas................................................................................43Calcula a Raiz Quadrada de um Número.................................................................................43Calculando a Diferença entre Duas Datas em Dias..................................................................43Calculo de Mensalidades..........................................................................................................43Contas corretas com ponto fluante...........................................................................................44Dias úteis entre duas datas.......................................................................................................44Descobrindo Dias no Ano........................................................................................................45Descobrindo Dias no Mês........................................................................................................45Trabalhando com Data Juliana.................................................................................................46

CONTROLES..............................................................................................................................47Alterando Propriedades de Controles (não Array) em um Loop.............................................47Alterando Propriedades de um Array de Controles em um Loop............................................47Coordenadas do controle em relaçao a area de trabalho..........................................................48Criando Objetos em Run Time (VB6.0)..................................................................................48Determinando a classe de qualquer objeto...............................................................................49Determinando se um objeto foi definido (Set).........................................................................49Manipulando Controles num Form Usando-se o Teclado.......................................................50Testar se um controle existe.....................................................................................................50ToolTipText personalizado......................................................................................................50Verificar se um controle está com o foco.................................................................................51Criação de AtiveXs..................................................................................................................52

Colocando as Tecla de Atalho para Funcionar num OCXs.................................................52Manipulando Propriedades do Form onde seu OCX Está....................................................52O Projeto está em Run ou Design Time?.............................................................................53Pegando o hWnd do Verdadeiro Container..........................................................................53Qual tipo de Compatibilidade devo Usar?...........................................................................54Registrando e Desregistrando ActiveX via Código VB.......................................................54

FlexGrid...................................................................................................................................56Deixando um FlexGrid Zebrado (com 2 Cores Intercaladas)..............................................56Exportar dados de FlexGrid para Excel...............................................................................56Para imprimir o conteudo de um FlexGrid...........................................................................58

ComboBox...............................................................................................................................59Abrir um ComboBox assim que receber o foco...................................................................59Ajustando a Largura do Drop-Down de um ComboBox.....................................................59Descobrindo a largura atual do Drop-Down........................................................................59Adicionando itens ao ComboBox em Run-Time.................................................................60Adicionando itens ao ComboBox em Design-Time............................................................61Auto preenche o ComboBox de acordo com o texto encontrado.........................................62Preenchendo um ComboBox com os Registros de um Banco de Dados.............................63

DbGrid......................................................................................................................................64Auto Ajustar Colunas no DBGrid........................................................................................64Destacando uma linha em um DBGrid................................................................................64Mudar de Coluna no DBGrid com TAB..............................................................................64Preenchendo o DBGrid via Código......................................................................................64

DriveListBox............................................................................................................................66

2

Page 3: Dicas de VB

Códigos Erro do DriveListBox............................................................................................66Form.........................................................................................................................................67

Animando a Barra de Título de um Form............................................................................67Arrastar um controle ou Formulário sem Título..................................................................68Carregar Várias Instancias do Mesmo Formulário..............................................................68Centralizar um Form MDIChild...........................................................................................68Criando forms de formatos especiais...................................................................................68Criando um Form Circular...................................................................................................69Crinado um Form com Cantos Arredondados......................................................................69Criando um Form Elíptico...................................................................................................70Criando um Form em forma de Estrela (Polígono)..............................................................71Criando um Form em forma de Triângulo...........................................................................72Criando um Form com forma do Logotipo do Windows.....................................................72Criando um Form no Formato da Imagem Desejada...........................................................73Criando uma Tela de Splash para seu Programa..................................................................75Degradê em Forms...............................................................................................................76Fazer um form maior que a tela...........................................................................................76Fechando todos os Forms Abertos.......................................................................................77Formulário ficar por cima de todos......................................................................................77Pintar um local do formulario com a cor escolhida.............................................................78Removendo o move..............................................................................................................78Removendo os Botões MIN-MAX de Forms MDI..............................................................78Saber se um form está aberto...............................................................................................79

Grid..........................................................................................................................................80Digitação em Grid................................................................................................................80

ImageList..................................................................................................................................81Alterando o Conteúdo da ImageList sem Desvincula-la da ToolBar...................................81

ListBox.....................................................................................................................................82Achar uma palavra num ListBox.........................................................................................82Colocando ScrollBar Horizontal num ListBox....................................................................82Desmarcar todos os itens de uma lista.................................................................................83Movendo itens em uma ListBox..........................................................................................83Multiplas Colunas em um ListBox......................................................................................84

ListView...................................................................................................................................86Ordenando Colunas da ListView.........................................................................................86

Masked Edit Box......................................................................................................................87Limpar o controle Masked Edit Box....................................................................................87

Menús.......................................................................................................................................88Colocando bitmaps em menus..............................................................................................88Menus popup em caixa de Texto..........................................................................................89

Microsoft Comm Control.........................................................................................................90Trabalhando com Microsoft Comm Control........................................................................90

PictureBox................................................................................................................................91Carregando figuras em Pictures...........................................................................................91Dimensões de um bitmap.....................................................................................................91Rolando textos em PictureBox.............................................................................................92Salvando e Pintando em cima de figuras.............................................................................92

RichTextBox............................................................................................................................94Imprimindo o Conteúdo de um RichTextBox......................................................................94Localizando um Texto num RichTextBox...........................................................................94

3

Page 4: Dicas de VB

Uso Geral do Controle RichTextBox...................................................................................94TextBox....................................................................................................................................96

Apenas Números num TexBox............................................................................................96Bloqueando funções Copiar e Colar em caixas de texto......................................................96Forçando Caracteres Maiúsculos ou Minúsculos.................................................................96O Caracter ENTER...............................................................................................................97Procurando Strings em um TextBox....................................................................................97Selecionando Texto do TextBox ao Receber Foco..............................................................99Rolar um TextBox linha a linha...........................................................................................99

ToolBar..................................................................................................................................100Deixando a ToolBar (do VB5) no Estilo Flat....................................................................100

True DbGrid...........................................................................................................................100Como ligar o True DbGrid a um Array..............................................................................100Deixando um True DBGrid Zebrado (com 2 Cores Intercaladas).....................................101Detectar a Linha Selecionada num True DBGrid..............................................................101Navegação de Linha no True DBGrid................................................................................102

DIRETÓRIOS............................................................................................................................103Capturar o caminho DOS de um arquivo...............................................................................103Criando múltiplos níveis de diretórios...................................................................................103Como interceptar mudanças em um diretório........................................................................103Diretório onde o Programa foi Instalado................................................................................106Função para Unir um Diretório a um Subdiretório................................................................107Pegar o Diretório de Arquivos Temporários (Windows\Temp).............................................108Pegar o Diretório do System..................................................................................................108Pegar o Diretório do Windows...............................................................................................109

HARDWARE.............................................................................................................................111CDROM.................................................................................................................................111

Abrir e fechar a gaveta do CDROM...................................................................................111Disquetes................................................................................................................................111

Formatando um Disquete...................................................................................................111Drive.......................................................................................................................................112

Ler propriedades de drives, pastas e arquivos....................................................................112Hard Disk...............................................................................................................................121

Saber o Número Serial do HD...........................................................................................121Impressoras............................................................................................................................122

Imprimindo Direto para a Impressora................................................................................122Selecionando a impressora que será usada na impressão...................................................122

Monitores...............................................................................................................................123Obter a resolução de tela....................................................................................................123Resolução do Monitor........................................................................................................123

Mouse.....................................................................................................................................123Capturar a Posição do Mouse.............................................................................................123

USANDO AS APIs GetCursorPos E WindowFromPoint.............................................124USANDO AS APIs SetCapture E ReleaseCapture........................................................124Verificando se o cursor do mouse está ou não sobre o Form........................................124Verificando se o cursor do mouse está ou não sobre um controle................................125

Como limitar a área de movimento do mouse....................................................................125Desativamento do mouse...................................................................................................126Inverter os botões do mouse...............................................................................................126Mudar a Posição do Mouse via Código (sem Move-lo).....................................................127

4

Page 5: Dicas de VB

Teclados.................................................................................................................................128Acionar o CAPS LOCK via código...................................................................................128

Internet.......................................................................................................................................129Acionar o navegador padrão em um URL específico............................................................129Acionar uma conexão Dial-Up pelo VB................................................................................129Capturar o nome da conexao Dial-Up....................................................................................130Criar um link para um e-mail.................................................................................................130Dar um Ping...........................................................................................................................131Desconectar da Internet Via Código no VB...........................................................................131Discar com o modem via API................................................................................................132Enviar E-mail pelo VB via MAPI..........................................................................................132Exibir um arquivo direto da Internet/Intranet num TextBox.................................................133Salvando uma Página HTML.................................................................................................133Transferência de arquivos via FTP.........................................................................................134Verificando se o Computador está Conectado à Internet.......................................................135

Multimídia..................................................................................................................................137Criando um CD Player...........................................................................................................137Criar tela de apresentação no CD-ROM................................................................................140Detectando se o Micro tem Placa de Som..............................................................................140Gravando uma Trilha do CD para um Arquivo Wave...........................................................141Rodando um Vídeo AVI........................................................................................................141Tocar Arquivos MIDI............................................................................................................142Tocar Arquivos WAVE..........................................................................................................143

Programação Inteligente.............................................................................................................144Cuidado com Variáveis Tipo Variant!!!.................................................................................144Eliminando o If...End If Quando Possível.............................................................................144Executar com Compilação Completa.....................................................................................145Faça amplo uso das constantes intrínsecas do VB.................................................................145Instanciando Objetos Corretamente.......................................................................................146Saber se o Objeto está Vazio..................................................................................................146Usando a Immediate Window................................................................................................147Usando o Auto Completar......................................................................................................147Usando o DoEvents................................................................................................................147Usando o Object Browser......................................................................................................148Use o With para Atribuir Valores à Propriedades de Objetos................................................148Verificando Valor da Propriedade de um Objeto Mais Rapdamente.....................................148REDES...................................................................................................................................150Buscar data e hora do servidor...............................................................................................150Devolve o nome do micro na rede.........................................................................................151Identificando uma unidade de CD em Rede...........................................................................151Mapeando uma Unidade de Rede...........................................................................................152Retornar o nome do usuário logado.......................................................................................152

VBA...........................................................................................................................................153Copiando Textos de Documentos do Word...........................................................................153Trocar dados com o Excel......................................................................................................153

Validações..................................................................................................................................155Função para Verificar se um Ano é Bissexto ou Não............................................................155Validar Cartão de Crédito......................................................................................................155Validar CGC...........................................................................................................................156Validar CPF............................................................................................................................157

5

Page 6: Dicas de VB

Validar Datas..........................................................................................................................157Validar E-Mail.......................................................................................................................160Validar Informações Fornecidas pelo Usuário.......................................................................162Validar Texto em MaskEditBox............................................................................................166Valor por Extenso..................................................................................................................166Verificar a Validade do PIS...................................................................................................168

Variados.....................................................................................................................................169Acionar um HTML Help pelo VB.........................................................................................169Acionar um Help (*.HLP) pelo VB.......................................................................................169Cancelando Processos Longos...............................................................................................169Carregando forms do VB4 no VB3........................................................................................170Confirmando o Termino do Programa...................................................................................170Como Registrar Uma HotKey................................................................................................171Convertendo Identificadores em Rótulos e Cabeçalhos.........................................................173Criando gráficos sem utilizar OCX nem DLL.......................................................................173

Caso 1 - Meta pré-definida.................................................................................................173Caso 2 - Meta relativa........................................................................................................174

Criando uma Animação no VB..............................................................................................174Dar uma Pausa em seu Programa...........................................................................................175Fazer um aplicativo ser acionado silenciosamente................................................................175MsgBox que não seja modal..................................................................................................175Programa que dá "Bom dia", "Boa tarde" e "Boa noite" nos Horários Corretos...................176Recebendo Parâmetros Externos num Programa feito em VB..............................................176Saber se um programa foi encerrado......................................................................................176Tecla ENTER Agindo como TAB.........................................................................................177Testar caminho da aplicação..................................................................................................178Usando as Setas de Movimento Para Mudar de Controle......................................................178Use o Code Profiler para depuração.......................................................................................178Uso racional do SendKeys.....................................................................................................179Verificar o Formato de Data Configurado no Windows........................................................179

Variáveis....................................................................................................................................181Apresentando Corretamente Números no Formato de Moeda...............................................181Atenção na Declaração de Variáveis!!!..................................................................................181Arredondamento numérico.....................................................................................................182Busca Binária.........................................................................................................................182Capturar o formato da Moeda................................................................................................182Classificar um array em ordem alfabética..............................................................................183Criar Arrays com Type definido pelo usuário........................................................................183Facilitando a Declaração de Variáveis...................................................................................184Fazendo Alterações em Strings com o Mid...........................................................................185Função para Tira Acentos de Strings.....................................................................................185Função que Inverte Nomes (Sobrenome, Nome)...................................................................186Função Replace para VB5.0...................................................................................................186Função Split para o VB5........................................................................................................187Primeiras Letras das Palavras de uma String em Maiusculo.................................................188Saber as variáveis do ambiente..............................................................................................188

Windows....................................................................................................................................190Abrir a janela propriedades do sistema..................................................................................190Abrir arquivo com o programa que o criou............................................................................190Capturar Tela e Salvar em Arquivo........................................................................................190

6

Page 7: Dicas de VB

Chamando o ScreenSaver Através de API.............................................................................190Chamando Telas Específicas do Painel de Controle..............................................................191Como associar uma extensão ao programa............................................................................194Como Fazer Logoff, Desligar ou Reiniciar o Computador pelo VB.....................................196Criar atalho para arquivo facilmente......................................................................................197Executar um programa DOS..................................................................................................197Impedir que o programa apareça nos processos do windows................................................197Impedir que o programa seja encerrado com Ctrl+Alt+Del...................................................197Limpando a Lixeira pelo VB Através de API........................................................................198Minimizar um Programa Para o System Tray........................................................................198Mudando a Resolução de vídeo.............................................................................................201Mudando o Papel de Parede pelo VB.....................................................................................202Mudar a definição de data do Windows.................................................................................202Ocultar/Mostrar a Barra de Tarefas do Windows..................................................................203Usando a Área de Transferencia............................................................................................203Usando a Caixa "Sobre" Padrão do Windows.......................................................................206Usando a Função Environ$....................................................................................................207Verificando se um array foi ou não inicializado....................................................................209

7

Page 8: Dicas de VB

ARQUIVOS

Carregando um arquivo texto para um ListBoxPrivate Sub AbreArquivo() Dim sArquivo As String, sLinha As String Dim iARQ As Integer sArquivo = App.Path & "MeuTexto.TXT" If Right$(App.Path, 1) <> "\" Then sArquivo = App.Path & "\MeuTexto.TXT" End If

'Verificando se o arquivo existe: If Dir$(sArquivo) = "" Then 'O arquivo NÃO existe. MsgBox "O arquivo não existe!", vbExclamation, _ "ATENÇÃO!!!" Exit Sub End If iARQ = FreeFile Open sArquivo For Input As iARQ

'Verificando se o arquivo está em branco: If LOF(iARQ) = 0 Then 'O arquivo está em branco. MsgBox "O arquivo está em branco!", vbExclamation, _ "ATENÇÃO!!!" 'Fecha o arquivo Close iARQ Exit Sub End If

'Limpa o ListBox: List1.Clear Do While Not EOF(iARQ) 'Enquanto ñ chegar ao fim do arq... 'Pega a linha atual: Line Input #iARQ, sLinha

'Adiciona-a no ListBox: List1.AddItem sLinha Loop

'Fecha o arquivo Close iARQEnd Sub

Detalhe, você deverá mudar "MeuTexto.TXT" para o nome do arquivo que você deseja abrir e "List1" para o nome do ListBox onde as linhas serão adicionadas.

Checando se um arquivo texto está em branco'Se o Arquivo ainda esta fechado use:If FileLen("NomeDoArquivo") = 0 Then Arquivo está em brancoElse Arquivo tem conteúdoEnd If

8

Page 9: Dicas de VB

'Se o Arquivo está aberto use:If LOF(ARQ) = 0 Then Arquivo está em brancoElse Arquivo tem conteúdoEnd If

Copiando ArquivosCopiando Arquivos Através de Comandos do VB:

'O comando p/ copiar arquivos é o FileCopy.'Sintaxe:FileCopy ArquivoOrigem, DiretórioDestino

'Exemplo:FileCopy "C:\Desenho.BMP", "C:\Windows\"

'Você também pode copiar este arquivo (p/ o mesmo, ou'outro diretório) mudando o nome deste arquivo. Exemplo:FileCopy "C:\Desenho.BMP", "C:\Windows\Imagem.BMP"

Copiando Arquivos Através de API:

'O problema do FileCopy do VB é q ele não mostra visualmente a'operação (barra de progresso e etc) com no Explorer. Ao invés'de copiar arquivos com o FileCopy, use a rotina API abaixo:

'Num módulo:Option ExplicitPublic Declare Function SHFileOperation Lib "shell32.dll" _ Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) _ As Long

Public Const FO_COPY As Long = &H2Public Const FOF_ALLOWUNDO As Long = &H40

Public Type SHFILEOPSTRUCT hWnd As Long wFunc As Long pFrom As String pTo As String fFlags As Integer fAnyOperationsAborted As Boolean hNameMappings As Long lpszProgressTitle As StringEnd Type

Public Sub CopiarArq(Origem As String, Destino As String) Dim RST As Long Dim FLOP As SHFILEOPSTRUCT

FLOP.hWnd = 0 FLOP.wFunc = FO_COPY

'Arquivo de origem: FLOP.pFrom = Origem & vbNullChar & vbNullChar

'Para copiar TODOS os arquivos, use:

9

Page 10: Dicas de VB

'FLOP.pFrom = "C:\*.*" & vbNullChar & vbNullChar

'Diretório ou arquivo de destino: FLOP.pTo = Destino & vbNullChar & vbNullChar

FLOP.fFlags = FOF_ALLOWUNDO RST = SHFileOperation(FLOP) If RST <> 0 Then 'Erro na cópia MsgBox Err.LastDllError, vbCritical Or vbOKOnly Else If FLOP.fAnyOperationsAborted <> 0 Then MsgBox "Falha na cópia!!!", vbCritical Or vbOKOnly End If End IfEnd Sub

'P/ copiar um arquivo, execute a rotina:CopiarArq ArquivoOrigem, DiretórioDestino

'Por exemplo:CopiarArq "C:\Desenho.BMP", "C:\Windows\"'Ou:CopiarArq "C:\Desenho.BMP", "C:\Windows\Imagem.BMP"

Criando um arquivo texto em brancoDim ARQ As IntegerARQ = FreeFile

'ATENÇÃO!!! Esta próxima linha abre o arquivo'e, se ele contiver algo, TUDO será apagado!Open "NomeDoArquivo" For Output As ARQ

'Faz o que tiver q ser feito com o arquivo

'Fecha o arquivoClose ARQ

Descobrindo e Alterando Atributos de Arquivos'Num módulo:Public Type Attrib Archive As Boolean Hidden As Boolean ReadOnly As Boolean System As BooleanEnd Type

Public Function MudaAtributo(ByVal sNomeArq As _ String, ByRef m_Attrib As Attrib) As Boolean Dim AtributoMudar As Integer

If m_Attrib.Archive = True Then AtributoMudar = AtributoMudar + vbArchive End If If m_Attrib.Hidden = True Then AtributoMudar = AtributoMudar + vbHidden End If

10

Page 11: Dicas de VB

If m_Attrib.ReadOnly = True Then AtributoMudar = AtributoMudar + vbReadOnly End If If m_Attrib.System = True Then AtributoMudar = AtributoMudar + vbSystem End If

If Dir(sNomeArq, vbReadOnly + vbArchive + _ vbSystem + vbHidden) = "" Then MudaAtributo = False Exit Function End If

On Error GoTo Erro SetAttr sNomeArq, AtributoMudar On Error GoTo 0 MudaAtributo = TrueExit FunctionErro: MudaAtributo = FalseEnd Function

Public Function PegaAtributo(ByVal sNomeArq As _ String, ByRef m_Attrib As Attrib) As Boolean Dim AtributoReceber As Integer

If Dir(sNomeArq, vbReadOnly + vbArchive + _ vbSystem + vbHidden) = "" Then PegaAtributo = False Exit Function End If

On Error GoTo Erro AtributoReceber = GetAttr(sNomeArq) On Error GoTo 0 m_Attrib.Archive = AtributoReceber And vbArchive m_Attrib.Hidden = AtributoReceber And vbHidden m_Attrib.ReadOnly = AtributoReceber And vbReadOnly m_Attrib.System = AtributoReceber And vbSystem PegaAtributo = TrueExit FunctionErro: PegaAtributo = FalseEnd Function

'P/ saber os atributos, proceda da seguinte maneira:Private Sub cmdPegar_Click() Dim ATR As Attrib

If Not PegaAtributo("C:\Cezar.BMP", ATR) Then Debug.Print "Erro ao Pegar" Exit Sub End If

MsgBox "Atrubutos do Arquivo: C:\Cezar.BMP" & _ vbCrLf & "A - " & ATR.Archive & vbCrLf & _ "H - " & ATR.Hidden & vbCrLf & _ "R - " & ATR.ReadOnly & vbCrLf & _ "S - " & ATR.SystemEnd Sub

11

Page 12: Dicas de VB

Ele retornará da seguinte forma:ATR.Archive => Atributo Archive (Arquivo)ATR.Hidden => Atributo Hidden (Oculto)ATR.ReadOnly => Atributo ReadOnly (Somente p/ Leitura)ATR.System => Atributo System (Arquivo de Sistema)

'P/ mudar os atributos, proceda da seguinte'maneira:Private Sub cmdMudar_Click() Dim ATR As Attrib ATR.Archive = True ATR.Hidden = False ATR.ReadOnly = False ATR.System = False If Not MudaAtributo("C:\Cezar.BMP", ATR) Then Debug.Print "Erro ao Pegar" Exit Sub End If Call cmdPegar_ClickEnd Sub

Então, após ele mudar os atributos, ele irá confirmar (chamando a Sub anterior) e lhe mostrará o resultado (os novos valores p/ os atributos...).

Detalhe, os parâmetros da função MudaAtributo são:ATR.Archive => Atributo Archive (Arquivo)ATR.Hidden => Atributo Hidden (Oculto)ATR.ReadOnly => Atributo ReadOnly (Somente p/ Leitura)ATR.System => Atributo System (Arquivo de Sistema)

Excluindo Arquivos

Excluindo Arquivos Através de Comandos do VB (SEM usar a Lixeira):

'O comando p/ excluir arquivos é o KILL.'Sintaxe:Kill Caminho\NomeDoArquivo.QualquerCoisa

'Exemplo:Kill "C:\Desenho.BMP"

Excluindo Arquivos Através de API (USANDO a Lixeira):

O comando KILL do VB apaga o arquivo SEM manda-lo p/ a Lixeira. Ou seja, o perdemos para sempre. O código a seguir nos ensina como deletar um arquivo enviando-o para a LIXEIRA do computador:

'Num módulo:Option ExplicitPublic Declare Function SHFileOperation Lib "shell32.dll" _ Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) _ As Long

Public Const FO_DELETE As Long = &H3Public Const FOF_ALLOWUNDO As Long = &H40

12

Page 13: Dicas de VB

Public Type SHFILEOPSTRUCT hWnd As Long wFunc As Long pFrom As String pTo As String fFlags As Integer fAnyOperationsAborted As Boolean hNameMappings As Long lpszProgressTitle As StringEnd Type

Public Sub ExcluirArq(ByVal FileName As String) Dim FLOP As SHFILEOPSTRUCT Dim RST As Long

FLOP.wFunc = FO_DELETE FLOP.pFrom = FileName FLOP.fFlags = FOF_ALLOWUNDO

'deletando o arquivo RST = SHFileOperation(FLOP)End Sub

'P/ excluir um arquivo, execute a rotina:ExcluirArq "C:\Desenho.BMP"

Função que Abre um Arquivo Texto e Retorna seu ConteúdoFunction AbreArquivo(sArquivo As String) As String Dim iARQ As Integer Dim sLinha As String Dim sResult As String

iARQ = FreeFile Open sArquivo For Input As iARQ Do While Not EOF(iARQ) 'Pega o conteúdo da linha Line Input #iARQ, sLinha

'Quebra a linha e concatena (soma) o resultado sResult = sResult + Chr(13) & Chr(10) + sLinha Loop

AbreArquivo = sResult

'Fecha o arquivo Close iARQEnd Function

'P/ usar:Text1.Text = AbreArquivo("C:\Texto.TXT")

Funçãos para Manipulação de Arquivos INI

Digamos que, por exemplo, você precise salvar certas configurações de seu programa em um arquivo INI. Digamos ainda que você tenha que salvar neste arquivo INI os seguintes parâmetros:

13

Page 14: Dicas de VB

* Parâmetro1 => Posição X do Form* Parâmetro2 => Posição Y do Form* Parâmetro3 => Nome do usuário* Parâmetro4 => Senha* Parâmetro5 => Uma opção qualquer.(Lembre-se que isto é apenas um exemplo!)Muito bem. Então, coloque as seguintes declarações e funções num módulo:

Public INI_Parametro1 As StringPublic INI_Parametro2 As StringPublic INI_Parametro3 As StringPublic INI_Parametro4 As StringPublic INI_Parametro5 As StringPublic Sub Ler_INI(ByVal sArquivoINI As String) Dim sLinha As String Dim iARQ As Integer

If Dir$(sArquivoINI) = "" Then 'O arquivo INI não existe MsgBox "O arquivo INI não existe!!!", vbCritical, _ "ATENÇAO!!!" Exit Sub End If

iARQ = FreeFile Open sArquivoINI For Input As iARQ

Do While Not EOF(iARQ) Line Input #iARQ, sLinha Select Case Separa_Parametro(sLinha) Case "Parâmetro1" INI_Parametro1 = Separa_Valor(sLinha) Case "Parâmetro2" INI_Parametro2 = Separa_Valor(sLinha) Case "Parâmetro3" INI_Parametro3 = Separa_Valor(sLinha) Case "Parâmetro4" INI_Parametro4 = Separa_Valor(sLinha) Case "Parâmetro5" INI_Parametro5 = Separa_Valor(sLinha) End Select Loop

Close iARQEnd Sub

Public Sub Salvar_INI(ByVal sArquivoINI As String) Dim iARQ As Integer

iARQ = FreeFile Open sArquivoINI For Output As iARQ

Print #iARQ, "[Geral]" Print #iARQ, "Parâmetro1 = " & INI_Parametro1 Print #iARQ, "Parâmetro2 = " & INI_Parametro2 Print #iARQ, "Parâmetro3 = " & INI_Parametro3 Print #iARQ, "Parâmetro4 = " & INI_Parametro4 Print #iARQ, "Parâmetro5 = " & INI_Parametro5

Close iARQEnd Sub

14

Page 15: Dicas de VB

Private Function Separa_Parametro(ByVal Texto _ As String) As String Dim i As Integer

For i = 1 To Len(Texto) If Mid$(Texto, i, 1) = "=" Then Separa_Parametro = Trim(Left$(Texto, i - 1)) Exit For End If Next iEnd Function

Private Function Separa_Valor(ByVal Texto As _ String) As String Dim i As Integer

For i = 1 To Len(Texto) If Mid$(Texto, i, 1) = "=" Then Separa_Valor = Trim(Right$(Texto,Len(Texto)-i)) Exit For End If Next iEnd Function

Lendo o Arquivo INI:P/ pegar o valor dos parâmetros gravado no arquivo INI:» Ler_INI("Caminho\NomeDoArquivo.INI")

Ele retornará cada parâmetro em sua variável. Veja:* A variável INI_Parametro1 conterá o valor do Parâmetro1* A variável INI_Parametro2 conterá o valor do Parâmetro2* A variável INI_Parametro3 conterá o valor do Parâmetro3* A variável INI_Parametro4 conterá o valor do Parâmetro4* A variável INI_Parametro5 conterá o valor do Parâmetro5

Gravando no Arquivo INI:P/ gravar o valor dos parâmetros no arquivo INI, preencha as variáveis, e:» Salvar_INI("Caminho\NomeDoArquivo.INI")

Ele gravará o conteúdo das variáveis em seus respectivos parâmetros. Veja:* Parâmetro1 = Gravará o conteúdo da variável INI_Parametro1* Parâmetro2 = Gravará o conteúdo da variável INI_Parametro2* Parâmetro3 = Gravará o conteúdo da variável INI_Parametro3* Parâmetro4 = Gravará o conteúdo da variável INI_Parametro4* Parâmetro5 = Gravará o conteúdo da variável INI_Parametro5

Você só deverá modificar os nomes das variáveis dos parâmetro que serão recuperado/gravado no arquivo INI conforme a sua necessidade.

O nome dos parâmetros deverá ser modificado nas Subs Ler_INI (no Select Case) e Salvar_INI (no comando Print).

As modificações segem esta sintaxe:* Modificações no Select Case:Case "Nome_Do_Parâmetro"* Modificações no comando Print:Print #iARQ, "Nome_Do_Parâmetro = " & INI_Nome_Do_Parâmetro

O nome das variáveis deverão seguir a seguinte sintaxe:

15

Page 16: Dicas de VB

INI_Nome_Do_Parâmetro

ATENÇÃO!!! Caso algum parâmetro não tenha sido preenchido na hora de gravar, NADA SERÁ GRAVADO (ficará algo como "Parâmetro1 = ")!!!Caso, na hora de ler o arquivo INI, ele não encontre o valor de certo parâmetro (foi gravado algo como "Parâmetro1 = "), ele não avisará. Então, é bom verificar estas variáveis depois de preenchidas com a Sub Ler_INI.

Gravar cada informação em uma linha nova de um arquivo'Você deverá abrir o arquivo com a instrução Open e:Print #ARQ, "O que se deseja grava"'Depois é só fechar o arquivo:Close ARQ

Imprimindo Arquivos Texto pelo VB

O modo mais fácil de se imprimir um arquivo texto é este:

'Num módulo:Public Function ImprimeArq(ByVal sArq As String) As _ Boolean Dim lArq As Long Dim sTexto As String If Dir$(sArq) = "" Then 'O arquivo não existe ImprimeArq = False Exit Function End If iArq = FreeFile() Open sArq For Binary Access Read As iArq sTexto = Space$(LOF(iArq)) Get #iArq, , sTexto Close iArq Printer.Print sTexto Printer.EndDoc ImprimeArq = TrueEnd Function

'Aí, chame-a assim:Dim bRet As BooleanbRet = ImprimeArq("C:\Caminho\Do\Arq\NomeDoArq.TXT")

Procurar um arquivo em diretórios e subdiretóriosPrivate NumFiles%, FilesNames$()Private FilesDates() As Date, FilesSizes&()

Sub ScanPath(ByVal Path$, ByVal Files$) Dim i%, DirCount%, Buf$, DirName$, Dim FileName$, SubDir$() Const ATTR_DIRECTORY = 16 On Error Resume Next

'Le os arquivos locais FileName$ = Dir(Path$ + Files$) Do While FileName$ <> "" 'Esta inferior ou igual a data solicitada

16

Page 17: Dicas de VB

NumFiles% = NumFiles% + 1 ReDim Preserve FilesNames$(NumFiles%), _ FilesDates(NumFiles%), FilesSizes&(NumFiles%) FilesNames$(NumFiles% - 1) = LCase(Path$ + _ FileName$) FilesDates(NumFiles% - 1) = FileDateTime(Path$ + _ "\" + FileName$) FilesSizes&(NumFiles% - 1) = FileLen(Path$ + _ "\" + FileName$) FileName$ = Dir Loop

'Identifica os subdiretorios DirName$ = Dir(Path$ + "*.*", ATTR_DIRECTORY) DirCount% = 0 Do While DirName$ <> "" 'Ignora "." e ".." If DirName$ <> "." And DirName$ <> ".." Then 'E diretorio??? If (GetAttr(Path$ + DirName$) And _ ATTR_DIRECTORY) = ATTR_DIRECTORY Then 'Sim, adiciona DirCount% = DirCount% + 1 ReDim Preserve SubDir$(DirCount%) SubDir$(DirCount% - 1) = DirName$ End If End If DirName$ = Dir Loop For i% = 0 To DirCount% - 1 'Faz uma recursividade, varrendo subdiretorios 'deste diretorio Call ScanPath(Path$ + SubDir$(i%) + "\", Files$) NextEnd Sub

Salvando o conteúdo de um TextBox num Arquivo TextoPublic Sub SalvaArq(ByVal sArquivo As String, _ ByVal sTexto As String) Dim iARQ As Integer, iRet As Integer iARQ = FreeFile If Dir$(sArquivo) <> "" Then iRet = MsgBox("O arquivo já existe. Você " & _ "deseja sobrescreve-lo?", vbQuestion + _ vbYesNo, "ATENÇÃO!!!") If iRet = vbNo Then Exit Sub End If End If Open sArquivo For Output As iARQ Print #iARQ, sTexto Close iARQEnd Sub

'P/ usar, chame-a passando o nome do arquivo e'o texto. Veja:SalvaArq "C:\Texto.TXT", Text1.Text

17

Page 18: Dicas de VB

Verificando a Data da Última Alteração de um Arquivo'Num módulo:Public Function DataArq(ByVal sArq As _ String) As String If Dir$(sArq) <> "" Then DataArq = FileDateTime(sArq) Else DataArq = "ERRO" End IfEnd Function

'P/ chamar, no evento que você quizer:Private Sub Command1_Click() Dim sVar As String sVar = DataArq("C:\Quadrado 02.BMP") If sVar <> "ERRO" Then Text1.Text = sVar End IfEnd Sub

Verificando a existencia de um arquivoIf Dir$("X:\XXXX\XXXXX.XXX") <> "" Then 'O arquivo existe Else 'O arquivo não existe End If

18

Page 19: Dicas de VB

BANCO DE DADOS

Abrindo Bancos de Dados Externos - DAO & ADO

Caso você venha a ter a necessidade de abrir uma base de dados externa, como um arquivo do Excel (por exemplo), use uma chave de conexão com a base de dados externa. Veja este exemplo:

DAOSub DAOAbrirBDExterno() Dim DB As DAO.Database Set DB = DBEngine.OpenDatabase(App.Path & _ "\Plan.XLS", False, False, "Excel 5.0;") DB.CloseEnd Sub

ADOSub ADOAbrirBDExterno() Dim CNN As New ADODB.Connection CNN.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & App.Path & "\Plan.XLS;" & _ "Extended " & "Properties=Excel 5.0;" CNN.CloseEnd Sub

Veja nesta tabela, os principais tipos de chaves de conexão usadas.

Base de Dados Chave de Conexão (String)dBase III dBase III;dBase IV dBase IV;dBase 5 dBase 5.0;Paradox 5.x Paradox 5.x;Excel 5.0/Excel 95 Excel 5.0;Excel 97 Excel 97;Excel2000 Excel 8.0;HTML Import HTML Import;HTML Export HTML Export;Text Text;

ODBC

ODBC;DATABASE=database;UID=user;PWD=password;DSN=datasourcename;

Abrindo Relatórios do Access pelo VB

Para usar este código, é necessário fazer uma referência à biblioteca de automação do Access, em Project/References.

19

Page 20: Dicas de VB

'No evento desejado:Dim sCaminho As StringDim objAccess As Access.Application

'Cria uma instância do AccessSet objAccess = New Access.Application

'Caminho do arquivo de banco de dadossCaminho = App.Path & "\Banco.MDB"If Right$(App.Path,1) = "\" Then sCaminho = App.Path & "Banco.MDB"End If

With objAccess .Visible = False 'O Access firará invisível .OpenCurrentDatabase filepath:=sCaminho .DoCmd.OpenReport "Relatório", acViewNormalEnd With

Set objAccess = Nothing

ATENÇÃO!!! Para funcionar, a máquina onde você for instalar seu programa DEVE ter o Access instalado, pois este código "abre" o Access, mostrando o relatório (o Access em si fica invisível).

Abrir Banco de Dados com Senha - DAO & ADO

Caso você tenha definido uma senha para seu banco de dados, abra-o desta maneira:

DAOSub DAOAbrirBDProtegido() Dim DB As DAO.Database

'O parâmetro pwd (q é a senha - 4o parâmetro) é case 'sensitive (diferencia A de a) e - ao contrário do que 'diz a documentação do VB - os parâmetros exclusive e 'read-only (2o e 3o parâmetros) devem ser falsos. Set DB DBEngine.OpenDatabase(App.Path & "\SeuBD.MDB", _ False, False, ";pwd=senha") DB.CloseEnd Sub

ADOSub ADOAbrirBDProtegido() Dim CNN As New ADODB.Connection CNN.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & App.Path &"\SeuBD.MDB;Jet " & _ "OLEDB:Database Password=senha;" CNN.CloseEnd Sub

Onde "senha" é a sua senha. Quer dizer, subistitua "senha" pela senha do banco de dados.

20

Page 21: Dicas de VB

Compactar Banco de Dados - DAO & ADO

Antes de começar:Certifique-se que o banco de dados está fechado, pois se estiver aberto por algum usuário vai dar zebra. Certifique-se que não ha arquivo igual ao nome do arquivo temporário. Se houver, delete. Então vamos lá:

'Usando DAO:Private Sub DAO_CompactarDB() 'Iniciamos o tratamento de erros. 'Se algo der errado, vamos para a linha 'indicada. On Error Goto ErroCompactar

'Declaramos as variáveis Dim S_DbNome As String, S_DbTemp As String

'Descobrimos o caminho do Arquivo Original 'e do Arquivo Temp

S_DbNome = App.Path & "\Armarinho.mdb" S_DbTemp = App.Path & "\AdmTmp.mdb" If Right$(App.Path, 1) = "\" Then S_DbNome = App.Path & "Armarinho.mdb" S_DbTemp = App.Path & "AdmTmp.mdb" End If

'Descobrimos se o Arquivo Temp existe... If Dir$(S_DbTemp) <> "" Then 'Se existe, deletamos (vide *Kill lá em baixo) Call Kill(S_DbTemp) End If

'Compactamos o banco de dados com o 'nome de Arquivo Temp DBEngine.CompactDatabase S_DbNome, S_DbTemp

'Se Arquivo Original existir... If Dir$(S_DbNome) <> "" Then 'deleta Call Kill(S_DbNome) End If

'Aqui, vc poderia usar a instrução 'Name (vide *Name lá em baixo) DBEngine.CompactDatabase S_DbTemp, S_DbNome

Se na linha acima preferir usar a instrução Name, sua sintaxe seria como 'a linha aqui em baixo, portanto, a linha aqui em cima não existiria.Alternativa para a ultima linha acima>>> Name S_DbTemp As S_DbNome

'Se chegamos até aqui, avisa ao usuário que 'tudo correu bem... MsgBox "Compactação do Banco de Dados " & _ S_DbNome & " executada com sucesso.", _ vbOKOnly + vbInformation, "Compactação"Exit SubErroCompactar:

21

Page 22: Dicas de VB

'Se caiu aqui, é porque houve erro. Avise ao usuário. MsgBox "Houve um erro inesperado ao compactar o " & _ S_DbNome & " ." , vbOKOnly + vbInformation, _ "Compactação" 'Limpa o erro. Não é obrigatório mais é de bom 'costume fazer. Err.ClearEnd Sub

'Usando ADO:'Marque nas referências "Microsoft Jet and Replication'Objects 2.1 Library" e:Private Sub ADO_CompactarDB() 'Iniciamos o tratamento de erros. 'Se algo der errado, vamos para a linha indicada. On Error Goto ErroCompactar

'Declaramos as variáveis Dim JR As New JRO.JetEngine Dim S_DbNome As String, S_DbTemp As String

'Descobrimos o caminho do Arquivo Original 'e do Arquivo Temp S_DbNome = App.Path & "\Armarinho.mdb" S_DbTemp = App.Path & "\AdmTmp.mdb" If Right$(App.Path, 1) = "\" Then S_DbNome = App.Path & "Armarinho.mdb" S_DbTemp = App.Path & "AdmTmp.mdb" End If

'Descobrimos se o Arquivo Temp existe... If Dir$(S_DbTemp) <> "" Then 'Se existe, deletamos (vide *Kill lá em baixo) Call Kill(S_DbTemp) End If

'Compactamos o banco de dados com o 'nome de Arquivo Temp JR.CompactDatabase "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & S_DbNome & ";", _ "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & S_DbTemp & ";Jet." & _ "OLEDB:Engine Type = 4;" 'Este "Engine Type" no final indica a versão do Access que está 'sendo usada. Veja os valores e as versões correspondentes: '5 (Defaut) para Access 2000 '4 para Access 97 '3 para Access 95/6 '2 para Access 2 '1 para Access 1

'Se Arquivo Original existir... If Dir$(S_DbNome) <> "" Then 'deleta Call Kill(S_DbNome) End If

'Aqui, vc poderia usar a instrução 'Name (vide *Name lá em baixo) JR.CompactDatabase "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & S_DbTemp & ";", _

22

Page 23: Dicas de VB

"Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & S_DbNome & ";Jet." & _ "OLEDB:Engine Type = 4;"

'Se chegamos até aqui, avisa ao usuário que 'tudo correu bem... MsgBox "Compactação do Banco de Dados " & _ S_DbNome & " executada com sucesso.", _ vbOKOnly + vbInformation, "Compactação" Set JR = NothingExit SubErroCompactar: 'Se caiu aqui, é porque houve erro. Avise ao usuário. MsgBox "Houve um erro inesperado ao compactar o " & _ S_DbNome & " ." , vbOKOnly + vbInformation, _ "Compactação" 'Limpa o erro. Não é obrigatório mais é de bom 'costume fazer. Err.ClearEnd Sub

Kill >>> Esta expressão DELETA o arquivo especificado do HD, mais deve ser usada com cuidado. Este arquivo deletado NÃO será armazenado na lixeira. Para usa-la, vc deve se certificar que o arquivo realmente exista.

Name >>> A instrução Name, copia um arquivo para outro local com 'outro nome'. No lugar do segundo CompactDatabase, vc poderia usar a instrução Name. Isto é só uma questão de escolha. Eu coloquei assim como ilustração, mais os dois modos funcionam. Cuidado: como na instrução CompactDatabase, na instrução Name o arquivo que será copiado tem que existir, caso contrário dará erro.

Compactar banco de dados protegido por senha - DAO & ADO

Problema:Neste exemplo, vc tem um banco de dados que quer compactar e este banco de dados é protegido por senha

Solução:Ao usar a instrução "CompactDatabase", vc exclui os espaços vazios. Para isto, vc deve descobrir o nome e caminho do DB e sua respectiva 'senha'. Então, vc fornece um nome temporário para o DB, chama a instrução CompactDatabase com o nome temporario, o nome original e a senha (vide *Senha lá em baixo) e depois vc renomeia para o nome original.

Antes de começar:Certifique-se que o banco de dados está fechado, pois se estiver aberto por algum usuário vai dar zebra. Certifique-se que não ha arquivo igual ao nome do arquivo temporário. Se houver, delete. Então vamos lá:

'Usando DAO:Private Sub DAO_CompactarDB() 'Iniciamos o tratamento de erros. 'Se algo der errado, vamos para a linha indicada. On Error Goto ErroCompactar

23

Page 24: Dicas de VB

'Declaramos as variáveis Dim S_DbNome As String, S_DbTemp As String

'Descobrimos o caminho do Arquivo Original 'e do Arquivo Temp

S_DbNome = App.Path & "\Armarinho.mdb" S_DbTemp = App.Path & "\AdmTmp.mdb" If Right$(App.Path, 1) = "\" Then S_DbNome = App.Path & "Armarinho.mdb" S_DbTemp = App.Path & "AdmTmp.mdb" End If

'Descobrimos se o Arquivo Temp existe... If Dir$(S_DbTemp) <> "" Then 'Se existe, deletamos (vide *Kill lá em baixo) Call Kill(S_DbTemp) End If

'Compactamos o banco de dados com o 'nome de Arquivo Temp DBEngine.CompactDatabase S_DbNome, S_DbTemp, _ , , ";PWD=rosakom"

'Se Arquivo Original existir... If Dir$(S_DbNome) <> "" Then 'deleta Call Kill(S_DbNome) End If

'Aqui, vc poderia usar a instrução 'Name (vide *Name lá em baixo) DBEngine.CompactDatabase S_DbTemp, S_DbNome, _ , , ";PWD=rosakom"

Se na linha acima preferir usar a instrução Name, sua sintaxe seria como 'a linha aqui em baixo, portanto, a linha aqui em cima não existiria.Alternativa para a ultima linha acima>>> Name S_DbTemp As S_DbNome

'Se chegamos até aqui, avisa ao usuário que 'tudo correu bem... MsgBox "Compactação do Banco de Dados " & _ S_DbNome & " executada com sucesso.", _ vbOKOnly + vbInformation, "Compactação"Exit SubErroCompactar: 'Se caiu aqui, é porque houve erro. Avise ao usuário. MsgBox "Houve um erro inesperado ao compactar o " & _ S_DbNome & " ." , vbOKOnly + vbInformation, _ "Compactação" 'Limpa o erro. Não é obrigatório mais é de bom 'costume fazer. Err.ClearEnd Sub

'Usando ADO:'Marque nas referências "Microsoft Jet'and Replication Objects 2.1 Library" e:Private Sub ADO_CompactarDB() 'Iniciamos o tratamento de erros.

24

Page 25: Dicas de VB

'Se algo der errado, vamos para a linha indicada. On Error Goto ErroCompactar

'Declaramos as variáveis Dim JR As New JRO.JetEngine Dim S_DbNome As String, S_DbTemp As String

'Descobrimos o caminho do Arquivo Original 'e do Arquivo Temp S_DbNome = App.Path & "\Armarinho.mdb" S_DbTemp = App.Path & "\AdmTmp.mdb" If Right$(App.Path, 1) = "\" Then S_DbNome = App.Path & "Armarinho.mdb" S_DbTemp = App.Path & "AdmTmp.mdb" End If

'Descobrimos se o Arquivo Temp existe... If Dir$(S_DbTemp) <> "" Then 'Se existe, deletamos (vide *Kill lá em baixo) Call Kill(S_DbTemp) End If

'Compactamos o banco de dados com o 'nome de Arquivo Temp JR.CompactDatabase "Provider=Microsoft.Jet.OLEDB.4" & _ ".0;Data Source=" & S_DbNome & ";" & _ "Jet OLEDB:Database Password=rosakom;", _ "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & S_DbTemp & ";" & _ "Jet.OLEDB:Engine Type = 4;" 'Este "Engine Type" no final indica a versão do Access que está 'sendo usada. Veja os valores e as versões correspondentes: '5 (Defaut) para Access 2000 '4 para Access 97 '3 para Access 95/6 '2 para Access 2 '1 para Access 1

'Se Arquivo Original existir... If Dir$(S_DbNome) <> "" Then 'deleta Call Kill(S_DbNome) End If

'Aqui, vc poderia usar a instrução 'Name (vide *Name lá em baixo) JR.CompactDatabase "Provider=Microsoft.Jet.OLEDB.4" & _ ".0;Data Source=" & S_DbTemp & ";" & _ "Jet OLEDB:Database Password=rosakom;", _ "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & S_DbNome & ";" & _ "Jet.OLEDB:Engine Type = 4;"

'Se chegamos até aqui, avisa ao usuário que 'tudo correu bem... MsgBox "Compactação do Banco de Dados " & _ S_DbNome & " executada com sucesso.", _ vbOKOnly + vbInformation, "Compactação" Set JR = NothingExit SubErroCompactar:

25

Page 26: Dicas de VB

'Se caiu aqui, é porque houve erro. Avise ao usuário. MsgBox "Houve um erro inesperado ao compactar o " & _ S_DbNome & " ." , vbOKOnly + vbInformation, _ "Compactação" 'Limpa o erro. Não é obrigatório mais é de bom 'costume fazer. Err.ClearEnd Sub

Senha >>> No exemplo usamos uma senha qualquer. Então, onde está rosakom deve ser substituída por sua senha.

Kill >>> Esta expressão DELETA o arquivo especificado do HD, mais deve ser usada com cuidado. Este arquivo deletado NÃO será armazenado na lixeira. Para usa-la, vc deve se certificar que o arquivo realmente exista.

Name >>> A instrução Name, copia um arquivo para outro local com 'outro nome'. No lugar do segundo CompactDatabase, vc poderia usar a instrução Name. Isto é só uma questão de escolha. Eu coloquei assim como ilustração, mais os dois modos funcionam. Cuidado: como na instrução CompactDatabase, na instrução Name o arquivo que será copiado tem que existir, caso contrário dará erro.

Criando Banco de Dados com Tabelas e Índices via VB - DAO

1º - A criação de um banco de dados via código é bastante simples:

Dim WRK As WorkspaceDim DB As DatabaseSet WRK = DBEngine.Workspaces(0)'Cria o banco de dados:Set DB = WRK.CreateDatabaseE("Banco.MDB", _ dbLangGeneral)'Feche o banco de dados e o Workspace:DB.CloseWRK.Closeset DB = Nothingset WRK = Nothing

2º - Para se criar uma tabela você terá que criar seus campos, expecificando o valor de certas propriedades. Neste exemplo, criaremos uma tabela contendo 3 campos: Código, Nome e DataNasc. Veja o código a seguir:

Dim WRK As WorkspaceDim DB As DatabaseDim TB As New TableDefDim Campo1 As New FieldDim Campo2 As New FieldDim Campo3 As New FieldSet WRK = DBEngine.Workspaces(0)'Abre o banco de dados:Set DB = WRK.OpenDatabase("Banco.MDB")'Atribui nome e utras propriedades à tabela'e aos campos:TB.Name = "Tabela"Campo1.Name = "Código"Campo1.Type = dbIntegerCampo2.Name = "Nome"

26

Page 27: Dicas de VB

Campo2.Type = dbTextCampo2.Size = 60Campo3.Name = "DataNasc"Campo3.Type = dbDate'Cria os campos na tabelaTB.Fields.Append Campo1TB.Fields.Append Campo2TB.Fields.Append Campo3'Cria a tabela:DB.TableDefs.Append TB'Feche o banco de dados, a tabela e o Workspace:TB.CloseDB.CloseWRK.CloseSet TB = Nothingset DB = Nothingset WRK = Nothing

3º - Criando Índices:

Os índices são muito úteis em rotinas de procura de dados em tabelas, pois, além de serem mais rápidos, eles requerem menos código para realizar estas buscas. Veja como criar um índice em um campo de uma tabela já existente:

Dim WRK As WorkspaceDim DB as Database Dim TB as Table Dim Index1 as New Index Dim Index2 as New Index Set WRK = DBEngine.Workspaces(0)'Abre o banco de dados e a tabela:set DB = WRK.OpenDatabase("Banco.MDB")Set TB = DB.OpenTable("Tabela")'Atribui nome e utras propriedades aos'índices:Index1.Name = "Cód"Index1.Fields = "Código"Index1.Unique = TrueIndex1.Primary = TrueIndex1.Name = "Nom"Index2.Fields = "Nome"Index2.Unique = FalseIndex2.Primary = False'Cria os indices na tabela:TB.Indexes.Append Index1TB.Indexes.Append Index2'Feche o banco de dados, a tabela e o Workspace:TB.CloseDB.CloseWRK.CloseSet TB = Nothingset DB = Nothingset WRK = Nothing

Filtrar Recordset já aberto - DAOJá tentou usar o método FILTER? Ex:

Sub FilterX() Dim dbsNorthwind As Database

27

Page 28: Dicas de VB

Dim rstPedidos As Recordset Dim intPedidos As Integer Dim strPaís As String Dim rstPedidosPaís As Recordset Dim strMessage As String

Set dbsNorthwind = OpenDatabase("Northwind.mdb") Set rstPedidos = dbsNorthwind.OpenRecordset("Pedidos", _ dbOpenSnapshot)

'Preenche o Recordset. rstPedidos.MoveLast intPedidos = rstPedidos.RecordCount

'Obtém a entrada do usuário. strPaís = Trim(InputBox("Digite um " & _ "país para filtrar em:"))

If strPaís <> "" Then 'Abre um objeto Recordset filtrado. Set rstPedidosPaís = FilterField(rstPedidos, _ "PaísDeDestino", strPaís) With rstPedidosPaís 'Verifica RecordCount antes de preencher o Recordset; 'caso contrário, um erro pode ser gerado. If .RecordCount <> 0 Then .MoveLast

'Imprime o número de registros do objeto Recordset 'original e do objeto Recordset filtrado. strMessage = "Pedidos no conjunto de registros " & _ "original: " & vbCr & intPedidos & vbCr & _ "Pedidos no conjunto de registros " & _ "filtrado (País = '" & strPaís & "'): " & _ vbCr & .RecordCount MsgBox strMessage .Close End With End If rstPedidos.Close dbsNorthwind.CloseEnd Sub

Function FilterField(rstTemp As Recordset, strField As _ String, strFilter As String) As Recordset 'Define um filtro no objeto Recordset especificado e em 'seguida abre um novo objeto Recordset. rstTemp.Filter = strField & " = '" & strFilter & "'" Set FilterField = rstTemp.OpenRecordsetEnd Function

Observação Para ver os efeitos de filtrar rstPedidos, você deve definir sua propriedade Filter e, em seguida, abrir um segundo objeto Recordset baseado em rstPedidos.Observação: Quando você conhece os dados que deseja selecionar, em geral é mais eficiente criar um Recordset com uma instrução SQL. Este exemplo mostra como você pode criar apenas um Recordset e obter os registros de um país específico.

Sub FilterX2() Dim dbsNorthwind As Database Dim rstPedidos As Recordset

28

Page 29: Dicas de VB

Set dbsNorthwind = OpenDatabase("Northwind.mdb")

'Abre um objeto Recordset que seleciona registros de 'uma tabela baseada no país da remessa. Set rstPedidos = dbsNorthwind.OpenRecordset("SELECT * " & _ "FROM Pedidos WHERE PaísDeDestino = " & _ "'USA'", dbOpenSnapshot) rstPedidos.Close dbsNorthwind.CloseEnd Function

Função que Cria a Clausula Where para Você'Num módulo, coloque a função Plic e esta'seguinte:Public Sub CreateSQL(ByRef SQL As String, _ ByVal sFldCriteria As String, ByVal _ Value As Variant, Optional ByVal _ sAMais As String) Select Case VarType(Value) Case vbString If Value <> vbNullString Then If sAMais <> vbNullString Then Value = Left(sAMais, 1) & Value & _ Right(sAMais, 1) Value = Trim$(Value) End If If SQL = vbNullStrin Then SQL = " Where " & sFldCriteria & _ Plic(Value) Else SQL = SQL & " AND " & sFldCriteria & _ Plic(Value) End If End If Case vbCurrency, vbSingle, vbDecimal, _ vbDouble, vbInteger, vbByte, vbLong If SQL = vbNullStrin Then SQL = " Where " & sFldCriteria & _ Str(Value) Else SQL = SQL & " AND " & sFldCriteria & _ Str(Value) End If Case vbDate If SQL = vbNullStrin Then SQL = " Where " & sFldCriteria & _ Format$(Value, "\#yyyy/mm/dd hh:nn:ss\#") Else SQL = SQL & " AND " & sFldCriteria & _ Format$(Value, "\#yyyy/mm/dd hh:nn:ss\#") End If Case vbBoolean If SQL = vbNullStrin Then SQL = " Where " & sFldCriteria & _ CStr(Value) Else SQL = SQL & " AND " & sFldCriteria & _ CStr(Value)

29

Page 30: Dicas de VB

End If End SelectEnd Sub

'Exempos de uso:

Dim sMySQL as String

sMySQL = vbNullStringCreateSQL sMySQL, "Campo1 = ", Text1.TextCreateSQL sMySQL, "Campo2 > ", Text2.Text.....rs.Open "SELECT * FROM Tabela" & sMySQL, cnn, ........

Neste caso, quando o programa chegar na linha rs.Open, sMySQL conterá o seguinte: " Where Campo1 = 'Conteúdo de Text1.Text' And Campo2 > 'Conteúdo de Text2.Text'"

Se você precisar usar o comando Like, use assim:

sMySQL = vbNullStringCreateSQL sMySQL, "Campo1 Like ", Text1.Text, "%%"

Ele retornará: " Where Campo1 Like '%Conteúdo de Text1.Text%'

Vantagens: não precisa ficar fazendo testes a cada montagem do SQL, a função testa se tem algo e monta a clausula Where direitinho.

Listando o Nome de Todas as Tabelas de um BD - ADO & DAO*** Usando ADO ***

'No evento que você desejar: Dim ADOXCat As New ADOX.Catalog ADOXCat.ActiveConnection = "PROVIDER=Microsoft.Jet." & _ "OLEDB.4.0;Data Source=" & _ "C:\Banco.MDB;" For i = 0 To ADOXCat.Tables.Count - 1 Debug.Print ADOXCat.Tables.Item(i).Name Next i

Depois desta rotina ter sido executada, o nome de TODAS as tabelas do banco de dados estará na janela Immediate Windows...

*** Usando DAO ***

'No evento que você desejar: Dim DB As DAO.Database Dim i As Integer Set DB = Workspaces(0).OpenDatabese("C:\Banco.MDB") For i = 0 To DB.TableDefs.Count - 1 If (DB.TableDefs(i).Attributes And _ dbSystemObject) <> dbSystemObject Then Print DB.TableDefs(i).Name End If Next

30

Page 31: Dicas de VB

Passar parametro para SQL armazenada em DB - ADOSub ADOExecuteParamQuery() Dim cnn As New ADODB.Connection Dim cat As New ADOX.Catalog Dim cmd As ADODB.Command Dim rst As New ADODB.Recordset Dim fld As ADODB.Field 'Open the connection cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\nwind.mdb;"

'Open the catalog cat.ActiveConnection = cnn

'Get the Command object from the Procedure Set cmd = cat.Procedures("Sales by Year").Command

'Specify the parameter values cmd.Parameters("Forms!Sales by Year Dialog!" & _ "BeginningDate")=#8/1/1993# cmd.Parameters("Forms!Sales by Year Dialog!" & _ "EndingDate")=#8/31/1993# 'Open the recordset rst.Open cmd, , adOpenForwardOnly, adLockReadOnly, adCmdStoredProc

'Display the records in the debug window While Not rst.EOF For Each fld In rst.Fields Debug.Print fld.Value & ";"; Next Debug.Print rst.MoveNext Wend

'Close the recordset rst.Close

'Apesar da documentação não fazê-lo, *EU acrescento*... '(chato 8^)) né?) Set rst = Nothing cmd.Close Set cmd = Nothing

'cat.Close '<< Não achei no Doc, referência ao .Close Set cat = Nothing '<< Só ACHEI Nothing cnn.Close Set cnn = Nothing 'Fim do *EU Acrescento*End Sub

Procurando no Banco de Dados (Find - FindFirst - FindNext) - DAO & ADO

(DAO)

No DAO, exite o comando FindFirst que faz a procura a partir do início da tabela, achando a primeira ocorrencia daquilo a que está sendo procurado.

'Abre o Recordset e então:

31

Page 32: Dicas de VB

Dim sArg as StringsArg = InputBox ("Por favor, digite o Nome do " &_ "Cliente:", "Localizar Nome")'P/ procurar EXATAMENTE o que foi digitado:RS.FindFirst "NomeCliente = '" & sArg & "'"

'P/ procurar algum nome que COMECE com o que'foi digitado:RS.FindFirst "NomeCliente like '" & sArg & "*'"

'P/ procurar algum nome que TERMINE com o que'foi digitado:RS.FindFirst "NomeCliente like '*" & sArg & "'"

'P/ procurar algum nome que tenha o que foi'digitado em qualquer parte (inicio/meio/fim):RS.FindFirst "NomeCliente like '*" & sArg & "*'"

If RS.NoMatch then 'Nenhum registro foi encontrado.Else 'Foi encontrado um registro.Endif

Bom, se algum registro tiver sido encontrado, você poderá pesquizar a próxima ocorrencia (próximo registro que contenha aquele valor procurado no campo que se está sendo feita a pesquiza), usando o comando FindNext:

RS.FindNext "NomeCliente = '" & sArg & "'"'Ou:RS.FindNext "NomeCliente like '" & sArg & "*'"'Ou:RS.FindNext "NomeCliente like '*" & sArg & "'"'Ou:RS.FindNext "NomeCliente like '*" & sArg & "*'"

If RS.NoMatch then 'Nenhum registro foi encontrado.Else 'Foi encontrado um registro.Endif

Bem, a única coisa que você precisa saber para usar os comandos FindFirst, FindLast, FindNext e FindPrevious, é que o FindFirst faz a procura SEMPRE a partir do início da tabela, que o FindLast faz a procura SEMPRE a partir do fim da tabela e os outros dois (FindNext e FindPrevious) fazem a procura SEMPRE a partir do ponto da tabela em que estão.

(ADO)

No ADO não existe os comandos FindFirst, FindLast, FindNext e FindPrevious, mas existe o comando Find. Usando este comando (Find) você não poderá usar o RS.NoMatch, pois ele não trabalha desta forma. Mas como eu posso fazer procuras do tipo "achar a primeira ocorrencia", "achar a próxima ocorrencia" e etc na minha tabela, sendo que eu só tenho o comando Find??? Bem, veja a sintaxe que você irá entender:

RS.Find "[Campo] = [Valor]", [SkipRows], [Tipo]

32

Page 33: Dicas de VB

Partes da sintaxe:[Campo] => Campo do banco de dados. O nome deve ser IDENTICO ao que está no banco de dados.[Valor] => Aquilo que se está procurando.[SkipRows] => Valor entre 0 e 1. Depende do tipo de procura que está sendo feita.[Tipo] => Constante que indica como a procura deverá ser feita.

Veja esta tabela para saber o que colocar em [SkipRows] e em[Tipo] conforme a sua procura:

Método DAOADO-SkipRowsADO - Search direction

FindFirst 0

adScarchForward (se não estiver posicionado no primeiro registro, execute o MoveFirst antes do Find)

FindLast 0

adScarchBackward (se não estiver posicionado no último registro, execute o MoveLast antes do Find)

FindNext 1 adScarchForward FindPrevious 1 adScarchBackward

Veja um exemplo de FindFirst no ADO usando o comando Find:

'Abre o Recordset e então:Dim sArg as StringRS.MoveFirst '<<<- MUITO importante!!!sArg = InputBox ("Por favor, digite o Nome do " &_ "Cliente:", "Localizar Nome")'P/ procurar EXATAMENTE o que foi digitado:RS.Find "NomeCliente = '" & sArg & "'", adSearchForward

'P/ procurar algum nome que COMECE com o que'foi digitado:RS.Find "NomeCliente like '" & sArg & "*'", adSearchForward

'P/ procurar algum nome que TERMINE com o que'foi digitado:RS.Find "NomeCliente like '*" & sArg & "'", adSearchForward

'P/ procurar algum nome que tenha o que foi'digitado em qualquer parte (inicio/meio/fim):RS.Find "NomeCliente like '*" & sArg & "*'", adSearchForward

If RS.EOF Then 'Nenhum registro foi encontrado.Else 'Foi encontrado um registro.Endif

Bem, seguindo essa filosofia, veja:

'FindLast:RS.Find "NomeCliente like '" & sArg & "'", adScarchBackward

'FindNext:RS.Find "NomeCliente like '" & sArg & "'", 1, adSearchForward

'FindPrevious:

33

Page 34: Dicas de VB

RS.Find "NomeCliente like '" & sArg & "'", 1, adScarchBackward

Reparar Banco de Dados - DAO'Reparar banco de dadosDim PERGPERG = MsgBox("Deseja reparar o banco de dados agora?", _ vbQuestion + vbYesNo, "Reparar DB?")If PERG = vbYes Then DBEngine.RepairDatabase "C:\agenda.mdb" MsgBox "Operação realizada com sucesso!", vbInformation, _ "DB Reparado!"Else MsgBox "Operação cancelada", vbInformation, _ "DB não Reparado!"End If

Salvar informações do Access para dBase - DAO

DB.EXECUTE "INSERT INTO Tabela IN 'C:\TEMP' 'dBase III;' SELECT * FROM Tabela"

Solução para a Aspa Simples (') em Strings de SQLPublic Function Plic(ByVal sTexto As String) As _ String If InStr(sTexto, Chr(39)) Then Plic = Chr(39) & Replace(sTexto, _ Chr(39), Chr(39) & Chr(39)) & _ Chr(39) Else Plic = Chr(39) & sTexto & Chr(39) End IfEnd Function

'P/ usar, por exemplo:Text1.Text = Plic(Text1.Text)

'No caso, se for p/ passar p/ uma string SQL, veja:Dim MySQL As StringMySQL = "Select * From Clientes Where Nome = " & _ Plic(Text1.Text)(...)

ATENÇÃO!!! Se você estiver usando o VB5.0 (ou mais antigo), nele NÃO tem a função Replace. P/ corrigir isto veja a dica Função Replace para VB5.0.

Trabalhando com Recordsets Desconectados - ADO

Digamos que você faça uma tela de pesquiza do seu cadastro (com um Grid e etc), e goste de abrir e fechar a conexão/Recordset quando necessário (ou seja, programação direcionada a multipos usuários - rede).

34

Page 35: Dicas de VB

Nesse caso, você pode abrir o Recordset e desconecta-lo da conexão,ou seja, do banco de dados. Para isso, proceda da seguinte forma:

'Sete o CursorLocation do Recordset como adUseClient:RS.CursorLocation = adUseClient

'Abra o Recordset com AdLockBatchOptimistic:RS.Open etc etc etc, AdLockBatchOptimistic

'Desconecta o Recordset:Set RS.ActiveConnection = Nothing

'Agora sim você pode fechar a conexão e tudo mais...

'P/ setar este Recordset p/ um Grid, por exemplo:Set Grid.DataSource = RS

Trabalhando com Recordsets Dinâmicos - ADO

Digamos que em um programa qualquer você precise usar um recordset para guardar dados em memória... Dados que não serão salvos num banco de dados, ou que poderão vir a ser salvos mais tarde ou não.

Um exemplo disso seria num cadastro de vendas. Enquanto a venda não é salva, os produtos que estão sendo vendidos nessa venda não serão cadastrados. Quando a venda for salva, aí sim isto seria salvo numa tabela de produtos da venda, a qual guarda também o código da venda.

Então veja como fazer:

'No declarations do Form:Dim RS As ADODB.Recordset

No evento Form_Load:Private Sub Form_Load() Set RS = New ADODB.Recordset 'Cria os campos necessários With RS.Fields .Append "Campo1", AdInteger, 100 .Append "Campo2", adVarChar, 100 End With 'No caso, o nome dos campos são "Campo1" e '"Campo2". '"Campo1" é do tipo numérico inteiro e '"Campo1" é do tipo caracter de 100 espaços...

RS.OpenEnd Sub

Bom, depois disso você poderá navegar por este Recordset (RS.MoveFirst, RS.MovePrevious, RS.MoveNext, RS.MoveLast), fazer procuras nele com o Find, com o Seek, apagar, adiciona e atualizar registros. Veja:

RS.AddNewRS![Campo1] = Text1.TextRS![Campo2] = Text1.TextRS.Update

35

Page 36: Dicas de VB

Você pode até salvar esse Recordset num arquivo e depois abri-lo novamente, veja:

'SalvandoRS.Save "c:\temp\arq.dat"

Usando o IIF em Consultas SQL

Digamos que você precise atribuir um determinado valor a uma variável, dependendo do conteúdo de outra (inseri um valor ou outro). Neste caso, pode-se utilizar o comando IIF.

Syntaxe:IIF([Condição], [Valor Verdadeiro], [Valor Falso]).

Este comando retornará [Valor Verdadeiro] no caso da [Condição] ser verdadeira ou [Valor Falso] no caso da [Condição] ser falsa.

Ex:Dim iX As Integer, sRet As StringiX = 3sRet = IIF(X > 1, "X é maior que 1", _ "X é menor ou igual a 1")

Depois disso, sRet conterá a String "X é maior que 1".

Você pode usar o IIF fácilmente numa consulta SQL. Digamos que você precise fazer uma consulta SQL, onde tenha que testar o conteúdo de um campo e retornar valores diferentes conforme o conteúdo deste campo. Num caso como este, pode-se utilizar o comando IIF. Por exemplo, digamos que você fará uma consulta na tabela de alunos e você quer criar um campo onde, se a média do aluno for maior ou igual a 5, ele seja preenchido com o texto "Aprovado", ou então "Reprovado". Veja como ficaria:

SELECT Nome, Média, IIF(Média>=5,"Aprovado","Reprovado") AS Status FROM Alunos

Utilizando o ADO - [Básico]

Esta dica mostra os passos básicos p/ se usar o ADO ao invés do DAO.

A. Abertura de Banco de Dados e de Tabelas

'1º - Criar uma ConexãoDim Conexão As ADODB.ConnectionSet Conexão = New ADODB.Connection'2º - Criar uma RecordsetDim Tabela As ADODB.RecordsetSet Tabela = New ADODB.Recordset'3º - Criar uma Variável para SQLDim SQLString As String'4º - Abrir o Banco de Dados (Definir o SGBD a ser Utilizado)Conexão.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _ App.Path & "\Banco.MDB"

36

Page 37: Dicas de VB

'5º - Definir o Valor Inicial para a Variável de SQLSQLString = "Select * From Tabela"'6º - Abrir o Recordset (Tabela)Tabela.Open SQLString, Conexão, [CursorType], [LockType]

Explicações:

[CursorType]: Opcional. Um valor CursorTypeEnum que determina o tipo de cursor que o provedor deve usar ao abrir o Recordset. Pode ser uma das seguintes constantes:

Constante Descrição

adOpenForwardOnly

Cursor somente progressivo. Padrão. Idêntico ao cursor estático exceto pelo fato de que é possível somente efetuar rolagem progressiva pelos registros.

Isso melhora o desempenho em situações em que é necessária somente uma passagem pelo recordset.

adOpenKeyset

Cursor do conjunto de teclas. Como um cursor dinâmico, exceto pelo fato de que não é possível

consultar os registros que outros usuário adicionaram, embora os registros excluídos por outros usuários sejam inacessíveis a partir do recordset. As

alterações nos dados feitas por outros usuários permanecem visíveis.

adOpenDynamic

Cursor dinâmico. Adições, alterações e exclusões feitas por outros usuários são visíveis e todos os tipos de movimentos pelo recordset são permitidos, exceto indicadores, se o provedor não der suporte a

eles.

adOpenStatic

Cursor estático. Uma cópia estática de um recordset que pode ser usada para localizar dados ou gerar

relatórios. Adições, alterações ou exclusões feitas por outros usuários não são visíveis.

[LockType]: Opcional. Um valor LockTypeEnum que determina qual tipo de bloqueio (simultaneidade) o provedor deve usar ao abrir o Recordset. Pode ser uma das seguintes constantes:

Constante Descrição

adLockReadOnly Padrão. Somente leitura - não é possível alterar os dados.

adLockPessimistic

Bloqueio pessimista, registro por registro - o provedor faz o que for necessário para garantir o

êxito da edição dos registros, em geral, bloqueando-os na fonte de dados imediatamente acima de uma

edição.

adLockOptimisticBloqueio otimista, registro por registro - o provedor

usa o bloqueio otimista, bloqueando os registros somente quando o método Update for chamado.

adLockBatchOptimisticAtualizações em lotes otimistas - necessárias para o modo de atualização em lotes em oposição ao modo de

atualização imediata.

B. Manipulação de Dados

A manipulação continua idem ao do DAO, com a diferença de não existir mais o metodo Edit.

37

Page 38: Dicas de VB

Veja os exemplos:

Adicionando um Registro:Tabela.AddNewTabela![Campo1] = Valor1Tabela![Campo2] = Valor2Tabela![Campo3] = Valor3Tabela![Campo4] = Valor4Tabela.Update

Alterando um Registro:Tabela![Campo1] = NovoValor1Tabela![Campo2] = NovoValor2Tabela![Campo3] = NovoValor3Tabela![Campo4] = NovoValor4Tabela.Update

Excluindo um Registro:Dim RESRES = MsgBox("Deseja excluir o registro atual?", _ 48 + vbYesNo, "Excluir???")If RES = vbYes Then Tabela.Delete If Not Tabela.EOF Then Tabela.MoveFirst 'Sub que joga os valores dos campos da 'tabela p/ os TextBoxes MostraDados End IfEnd If

Movendo entre Registros:Coloque 4 botões no Form, com Captions "|<", "<", ">" e ">|", todos com o nome cmdMove, formando assim um array de botões de indices 0 à 3.

No evento Click deste array de botões, coloque o seguinte código:

Private Sub cmdMove_Click(Index As Integer) Select Case Index Case 0 Tabela.MoveFirst Case 1 If Not Tabela.BOF Then Tabela.MovePrevious If Tabela.BOF Then Tabela.MoveFirst End If Case 2 If Not Tabela.EOF Then Tabela.MoveNext If Tabela.EOF Then adoPrimaryRS.MoveLast End If Case 3 Tabela.MoveLast End SelectEnd Sub

Utilizar algum programa que compacte os DBsOption Explicit

38

Page 39: Dicas de VB

Private WinZipPath$Private Data_Path$, Data_BaseName$, Data_BaseExt$

Private Type STARTUPINFO cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Long hStdInput As Long hStdOutput As Long hStdError As LongEnd Type

Private Type PROCESS_INFORMATION hProcess As Long hThread As Long dwProcessID As Long dwThreadID As LongEnd Type

Private Declare Function WaitForSingleObject Lib _ "Kernel32" (ByVal hHandle As Long, ByVal _ dwMilliseconds As Long) As LongPrivate Declare Function CreateProcessA Lib _ "Kernel32" (ByVal lpApplicationName As _ Long, ByVal lpCommandLine As String, ByVal _ lpProcessAttributes As Long, ByVal _ lpThreadAttributes As Long, ByVal _ bInheritHandles As Long, ByVal _ dwCreationFlags As Long, ByVal _ lpEnvironment As Long, ByVal _ lpCurrentDirectory As Long, lpStartupInfo _ As STARTUPINFO, lpProcessInformation As _ PROCESS_INFORMATION) As LongPrivate Declare Function CloseHandle Lib "Kernel32" _ (ByVal hObject As Long) As LongPrivate Declare Function GetDiskFreeSpace Lib _ "Kernel32" Alias "GetDiskFreeSpaceA" ( _ ByVal lpRootPathName As String, _ lpSectorsPerCluster As Long, lpBytesPerSector _ As Long, lpNumberOfFreeClusters As Long, _ lpTtoalNumberOfClusters As Long) As Long

Private Const NORMAL_PRIORITY_CLASS = &H20&Private Const INFINITE = -1&Private Const SW_NORMAL = 1Private Const SW_HIDE = 0Private Const SW_SHOW = 5Private Const SW_SHOWMINNOACTIVE = 7Private Const SW_SHOWNA = 8

39

Page 40: Dicas de VB

Private Const STARTF_USESHOWWINDOW = 1&

Private Sub mnu_UtilitariosBaseDadosCompac_Click() Dim SourceFile$, OutFile$, OutExt$ On Error Resume Next 'With FormMsgBox ' .Label1.Visible = False ' Set .Label2.Font = .Label1.Font ' .Label2.Caption = "Copactando Base de Dados." ' .Label3.Visible = True ' .Label3.Caption = "Aguarde!" ' .pnl_Flood.Visible = False ' .Show ' .Refresh 'End With SourceFile$ = CompressBD(OutFile$,OutExt$) If SourceFile$<>Data_Path$+"\"+OutFile$+OutExt$ Then Err.Clear Kill Data_Path$+"\"+Data_BaseName$+".bak" Name Data_Path$+"\"+Data_BaseName$+Data_BaseExt$ As _ Data_Path$+"\"+Data_BaseName$+".bak" Name Data_Path$+"\"+OutFile$+OutExt$ As _ Data_Path$+"\"+Data_BaseName$+Data_BaseExt$ End If

'Unload FormMsgBox Call AbreDataBaseEnd Sub

Private Sub mnu_UtilitariosEnviarDisquete_Click() Dim i%, SourceFile$,OutFile$,OutExt$,RetErrNbr&,RetErrDesc$ On Error Resume Next 'With FormMsgBox ' .Label1.Visible = False ' Set .Label2.Font = .Label1.Font ' .Label2.Caption = "Copactando Base de Dados." ' .Label3.Visible = True ' .Label3.Caption = "Aguarde!" ' .pnl_Flood.Visible = False ' .Show ' .Refresh 'End With SourceFile$ = CompressBD(OutFile$,OutExt$) 'FormMsgBox.Label2.Caption = "Zipando Base copiada." 'FormMsgBox.Refresh Call ZipCopyFile(SourceFile$, "a:", OutFile$, OutExt$, _ RetErrNbr&, RetErrDesc$)

'Unload FormMsgBox If RetErrNbr& <> 0 Then Kill "a:\" & OutFile$ & OutExt$ MsgBox RetErrDesc$, vbInformation Else MsgBox "Arquivo '" & OutFile$ & OutExt$ & _ "' copiado para o disquete.", vbInformation End If Call AbreDataBaseEnd Sub

Function CompressBD$(OutFile$, OutExt$) Dim i%

40

Page 41: Dicas de VB

On Error Resume Next If FileDateTime(Data_Path$+"\"+Data_BaseName$ + _ Data_BaseExt$)>FileDateTime(Data_Path$+"\COMPAC" + _ Data_BaseExt$) Then ' For i% = Forms.Count - 1 To 0 Step -1 ' If Forms(i%).Name <> "MDIForm" And _ ' Forms(i%).Name <> "FormMsgBox" And _ ' Forms(i%).Name <> "FormFlyOver" Then ' Unload Forms(i%) ' End If ' DoEvents: DoEvents ' Next Call CloseDataBase Screen.MousePointer = vbHourglass Err.Clear ChDir Data_Path$ If "COMPAC" <> Data_BaseName$ Then Kill "COMPAC" + Data_BaseExt$ End If CompactDatabase Data_Path$ + "\" + Data_BaseName$ + _ Data_BaseExt$, Data_Path$ + "\COMPAC" + Data_BaseExt$ End If OutFile$ = "COMPAC" OutExt$ = Data_BaseExt$ If Err.Number = 0 Then CompressBD = Data_Path$+"\COMPAC"+Data_BaseExt$ Else CompressBD = Data_Path$+"\"+Data_BaseName$+Data_BaseExt$ End If Screen.MousePointer = vbNormalEnd FunctionFunction ZipCopyFile(ByVal InFile$, OutPath$, OutFile$, _ OutExt$, ErrNumber&, ErrDesc$) As Boolean Dim i%, FreeSpace&, szCommandLine$ Dim lDiskFree&, lRet&, lBytes&, lSect&, lClust&, lTot& Dim ProcInfo As PROCESS_INFORMATION Dim StartProc As STARTUPINFO On Error Resume Next ErrNumber& = -1 ErrDesc$ = "Erro desconhecido." Err.Clear If WinZipPath$ <> "" Then Screen.MousePointer = vbHourglass szCommandLine$ = Aspas(WinZipPath$) & " -a " & _ Aspas(OutPath$ + "\" + OutFile$) & " " & _ Aspas(InFile$) StartProc.cb = Len(StartProc) If CreateProcessA(0&, szCommandLine$, 0&, 0&, 1&, _ NORMAL_PRIORITY_CLASS, 0&, 0&, StartProc, _ ProcInfo) Then lRet& = WaitForSingleObject(ProcInfo.hProcess, INFINITE) CloseHandle (ProcInfo.hThread) CloseHandle (ProcInfo.hProcess) If FileDateTime(InFile$) > FileDateTime(OutPath$ + "\" + _ OutFile$ + ".zip") Then GoTo ZipStartErro End If Else GoTo ZipStartErro End If Screen.MousePointer = vbNormal

41

Page 42: Dicas de VB

If Err.Number = 0 Then OutExt$ = ".zip" ErrNumber& = 0 ErrDesc$ = "" ZipCopyFile = True Else GoTo ZipStartErro End If Else ZipStartErro: Screen.MousePointer = vbHourglass If Mid(OutPath$, 2, 1) = ":" Then lRet = GetDiskFreeSpace(Left(OutPath$, 2) + "\", lSect, lBytes, lClust, lTot) lDiskFree = (lBytes * lSect) * lClust If Err.Number <> 0 Then lDiskFree = 2147483647 Err.Clear If FileLen(InFile$) > lDiskFree Then ErrNumber& = 0 ErrDesc$ = "Disco cheio." ZipCopyFile = False Exit Function End If End If Err.Clear FileCopy InFile$, OutPath$ & OutFile$ & OutExt$ Screen.MousePointer = vbNormal ZipCopyFile = (Err.Number = 0) ErrNumber& = Err.Number ErrDesc$ = Err.Description End IfEnd Function

Public Sub AbreDataBase() 'Abro a base de dadosEnd SubPublic Sub CloseDataBase() 'Fecho as tabelas, recorsets e a basededados/conexãoEnd Sub

Public Function Aspas$(ByVal Value) If InStr(Value, """") Then Aspas = "'" & Trim(Value) & "'" Else Aspas = """" & Trim(Value) & """" End IfEnd Function

42

Page 43: Dicas de VB

CÁLCULOS

Calcula a idade em anos entre duas datasPublic Function Age(Bdate As Date, DateToday _ As Date) As Integer If Month(DateToday) < Month(Bdate) Or _ (Month(DateToday) = Month(Bdate) And _ Day(DateToday)<Day(Bdate)) Then Age = Year(DateToday) - Year(Bdate) - 1 Else Age = Year(DateToday) - Year(Bdate) End IfEnd Function

Calcula a Raiz Quadrada de um Número

Para fazer o calculo da raiz quadrada de qualquer número, é só usar a função Sqr. Veja este exemplo:

Dim iNum As IntegeriNum = Sqr(25)

Depois desta operação, iNum conterá o número 5. 8^)

By Tamanhoni - ValewZAÇO!!! 8^)))

Calculando a Diferença entre Duas Datas em DiasEste cálculo é bem simples de ser feito. Veja o código:

Private Sub Calcula_DT() Dim dData As Date, sMsg As String dData = InputBox("Digite uma data:") sMsg = "Dias até a data escolhida: "& _ DateDiff("d", Now, dData) Msgbox sMsgEnd Sub

Calculo de Mensalidades

Digamos que você precise gerar 4 datas a partir de uma data digitada pelo usuário (para um controle de parcelas, por exemplo. No caso, seriam 5 parcelas). Veja:

Para isso usaremos a função DateAdd() que tem a seguinte sintáxe:

DateAdd(Intervalo,Numero,Data)

Intervalos:"d" - Dias

43

Page 44: Dicas de VB

"m" - Meses"y" - Anos

Então ficaria:

Dim MyArray(4) As DateDim i As IntegerMyArray(0) = "14/05/2000"For i = 1 To 4 MyArray(i) = DateAdd("m", i, "14/05/2000")Next

By Maximiliano Damian Rodrigues - ValewZAÇO!!! 8^))

Contas corretas com ponto fluante

Alguém já notou que o Visual Basic não é muito bom em matemática? Tente fazer 18.51 + (-17.59) e você irá receber .9200000000000002.

Isso ocorre, porque no Visual Basic, os valores com ponto flutuante são armazenados no formato padrão IEEE. A representação da máquina sobre valores numéricos é em binário. Qualquer valor inteiro pode ser representado "EXATAMENTE" na forma binária, mas nos casos de valores com ponto flutuante, isso não acontece.

Por exemplo, o decimal 0.0001 não pode ser representado exatamente em binário (0.0001 é uma fração repetitiva com um período de 104 bits!). Então, os valores com ponto flutuante são aproximados para o próximo valor que pode ser representado em binário. Logo, eles tendem a causar algum erro nos calculos quando são utilizados. No nosso exemplo, ambos 18.51 e 17.59 não podem ser representados exatamente pelo padrão de ponto flutuante. A soma deles incluirá um pequeno erro. Observe que o erro é bastante pequeno e essencialmente a soma (quando vista em uma precisão de 14/15 pontos decimais usando a função Format$) é correta.

Para exibir o resultado exato para o usuário, faça o seguinte:

Format$(18.51 + (-17.59), "###.#####")

Dias úteis entre duas datasFunction DiasUteis(dtInicio As Variant, _ dtFinal As Variant) As Integer Dim intSemanas As Integer Dim varDataCont As Variant Dim intFimDias As Integer

dtInicio = DateValue(dtInicio) dtFinal = DateValue(dtFinal) intSemanas = DateDiff("w",dtInicio,dtFinal) varDataCont = DateAdd("ww",intSemanas,dtInicio) intFimDias = 0

Do While varDataCont < dtFinal If Format(varDataCont,"ddd") <> "Sun" And _ Format(varDataCont,"ddd") <> "Sat" Then

44

Page 45: Dicas de VB

intFimDias = intFimDias + 1 End If varDataCont = DateAdd("d", 1, varDataCont) Loop

DiasUteis = intSemanas * 5 + intFimDiasEnd Function

Descobrindo Dias no Ano* Primeiro Dia do Ano

Data = Now() - Datepart("y", Now()) + 1 'Now() pode ser substituído por algo como '#04/06/1996#, ou #16/08/2000#, etc...

* Ultimo Dia do Ano

Data = Dateadd("yyyy", 1, Now() - _ Datepart("y", Now())) 'Now() pode ser substituído por algo como '#04/06/1996#, ou #16/08/2000#, etc...

* Número de Dias até o Fim do Ano

Data = Dateadd("yyyy", 1, Now() - _ Datepart("y", Now())) - Now() 'Now() pode ser substituído por algo como '#04/06/1996#, ou #16/08/2000#, etc...

* Número de Dias até o Natal

Data = Dateadd("yyyy", 1, Now() - _ Datepart("y", Now())) - Now() - 7 'Now() pode ser substituído por algo como '#04/06/1996#, ou #16/08/2000#, etc...

* Número de Dias no Ano

Data = Dateadd("yyyy", 1, Now() - _ Datepart("y", Now())) - (Now() - Datepart("y", Now())) 'Now() pode ser substituído por algo como '#04/06/1996#, ou #16/08/2000#, etc...

Obs.: Esses números (2000 - ano, 5 - mês) podem ser modificados, claro...

Descobrindo Dias no Mês* Primeiro Dia do Mês: Data = DateSerial(2000, 5, 1)

* Último Dia do Mes: Data = DateSerial(2000, 5 + 1, 0)

* Número de Dias no Mes Data = Datepart("d", DateSerial(2000, _ 5 + 1, 0))

Nesses exemplos, 2000 é o ano e 5 é o mês...

45

Page 46: Dicas de VB

Recomendo uma olhada BEM de perto na função DateSerial(Ano, Mes, Dia). Ela faz muito mais coisas.

Trabalhando com Data Juliana'Converte para Data JulianaPublic Function CDate2Julian(MyDate As Date) _ As String CDate2Julian = Format$(MyDate - _ DateSerial(Year(MyDate) - _ 1, 12, 31), "000")End Function

'Converte de Data Juliana para DataPublic Function CJulian2Date(JulDay As _ Integer, Optional YYYY) As Date If IsMissing(YYYY) Then YYYY = Year(Date) If Not IsNumeric(YYYY) Or _ YYYY \ 1 <> YYYY Or YYYY < 100 Or _ YYYY > 9999 Then Exit Function If JulDay > 0 And JulDay < 366 Or _ JulDay = 366 And YYYY Mod 4 = 0 And _ YYYY Mod 100 <> 0 Or _ YYYY Mod 400 = 0 Then CJulian2Date = DateSerial(YYYY, 1, JulDay) End IfEnd Function

46

Page 47: Dicas de VB

CONTROLES

Alterando Propriedades de Controles (não Array) em um Loop

Digamos que você tenha 5 TextBoxes, cada um com um nome diferente (quer dizer, NÃO estaria formando um array). Então, vamos dizer que você presice desabilitar (.Enabled = False) todos eles. Como você faria?

'Você faria assim?:Text1.Enabled = FalseText2.Enabled = FalseText3.Enabled = FalseText4.Enabled = FalseText5.Enabled = False

Deste modo até funcionaria, mas tem um modo mais fácil de se fazer isso... Veja:

Dim cObjeto As ControlFor Each cObjeto In Controls If TypeOf cObjeto Is TextBox Then cObjeto.Enabled = False End IfNext

A vantagem de se usar este método é que, caso você tenha MUITOS TextBoxes, o código ficaria, sem dúvida, menor. Com este método NÃO IMPORTA quantos nem quais são os nomes dos TextBoxes! Ele irá, no caso, desabilitar TODOS eles!

Alterando Propriedades de um Array de Controles em um Loop

Digamos que você tenha 5 TextBoxes com um mesmo nome (quer dizer, um array de TextBoxes - Text1(0), Text1(1), Text1(2), Text1(3), Text1(4)). Então, vamos dizer que você presice desabilitar (.Enabled = False) todos eles. Como você faria?

'Você faria assim?:Text1(0).Enabled = FalseText1(1).Enabled = FalseText1(2).Enabled = FalseText1(3).Enabled = FalseText1(4).Enabled = False

Deste modo até funcionaria, mas tem um modo mais fácil de se fazer isso... Veja:

Dim iNum As IntegerFor iNum = 0 To 4 Text1(iNum).Enabled = FalseNext

A vantagem de se usar este método é que, caso você tenha MUITOS TextBoxes, o código ficaria, sem dúvida, menor.

Agora, digamos que você queira fazer isto sem expecificar a quantidade de TextBoxes (0 até 4 seriam 5 TextBoxes). Como você faria, usando o 1º

47

Page 48: Dicas de VB

exemplo??? Meio complicado, né? Então veja como fazer isso usando o 2º exemplo:

Dim iNum As IntegerFor iNum = 0 To Text1.Count - 1 Text1(iNum).Enabled = FalseNext

Coordenadas do controle em relaçao a area de trabalhoPublic Type RECT Left As Long Top As Long Right As Long Bottom As LongEnd Type

Public Declare Function GetWindowRect Lib "user32" Alias _ "GetWindowRect" (ByVal hwnd As Long, lpRect As RECT _ ) As Long

' Uso:

Dim R As RECTGetWindowRect(Controle.hWnd, R)

"R" retornará com as coordenadas do controle (ou qq coisa que tenha hWnd)na tela. Cuidado que é em Pixel!!!

Criando Objetos em Run Time (VB6.0)

Neste exemplo criaremos uma ScrollBar. Para podermos usar seus eventos (Click, Change e etc), precisaremos declarar a variável com a palavra chave WithEvents. Veja:

Private WithEvents MyHSBar As HScrollBarPrivate Sub Form_Load() 'Cria a instancia da ScrollBar Set MyHSBar = Form1.Controls.Add("VB.HScrollBar", _ "HScroll1") 'Agora precisamos alterar algumas propriedades 'para a ScrollBar poder ficar visível. With MyHSBar .Top = 0 .Left = 0 .Height = 255 .Width = Me.ScaleWidth .Visible = True End With 'Pronto. A ScrollBar já está instanciada e 'visível no Form.End SubPrivate Sub MyHSBar_Change() 'Podemos até usar os eventos da ScrollBar, como 'já foi comentado antes. MsgBox "HEI!!! Você me clicou!!!", vbCriticalEnd Sub

48

Page 49: Dicas de VB

Agora coloque este código num Form e teste! 8^)

P.S.: Só funciona no VB6.0...

Determinando a classe de qualquer objeto'Esta rotina imprime informações específicas de objetos

Public Sub PrintObjectInfo (YourObject As Object) If TypeOf YourObject Is CDesk then Print "Object Type: Mesa" Print "Número de pernas: " & YourObject.NumberOfLegs ElseIf TypeOf YourObject Is CHouse Then Print "Object Type: Casa" Print "Número de portas: " & YourObject.NumberOfDoors End If 'impressão das propriedades de mesmo nome Print "Data de Venda: " & YourObject.Date Print "Preço de Venda: " & YourObject.Price '...End Sub

Determinando se um objeto foi definido (Set)

VB providencia uma série de novas capacidades de uso de objetos. Porém, um objeto deve ser "setado" (definido) antes de ser referenciado. Existem formas de verificar se um objeto já foi definido é através do código de erro (91).

Por exemplo:

Public Function IsSomething (ob As Object) As Long Dim J as Long Err.Clear On Error Resume Next If TypeOf ob Is TextBox Then J = 1 End If Select Case Err.Number Case 91 'error 91 = object not set IsSomethig = false Case 0 IsSomething = true Case Else '... outro erro ocorreu End Select On Error GoTo 0End Function

' Outra maneira simples seria apenas:

If Not MeuObjeto Is Nothing Then ' Se chegou aqui é pq foi definido.....Else ' O objeto não foi definido.....End If

49

Page 50: Dicas de VB

Manipulando Controles num Form Usando-se o Teclado

Se você preferir usar o teclado ao invés do mouse para mover ou alterar o tamanho dos controles num Form, você pode usar as combinações de teclas abaixo durante a criação de suas telas:

Para alterar o tamanho dos controles use a tecla Shift e as teclas de setas como segue:

Shift+Seta p/ Direita => Aumenta a largura do controle (Width)Shift+Seta p/ Esquerda => Diminue a largura do controle (Width)Shift+Seta p/ Baixo => Aumeta a altura do controle (Height)Shift+Seta p/ Cima => Diminue a altura do controle (Height)

Para mover os controles use a tecla Ctrl e as teclas de setas como segue:

Ctrl+Seta p/ Direita => Move o controle para a direita.Ctrl+Seta p/ Esquerda => Move o controle para a esquerda.Ctrl+Seta p/ Baixo => Move o controle para baixo.Ctrl+Seta p/ Cima => Move o controle para cima.

Se você selecionar mais de um controle, as operações acima afetarão todos eles.

Testar se um controle existePrivate Sub Command1_Click() On Error GoTo SaiComErro

If Me("Label1").Name <> vbNullString Then MsgBox "Sim" End IfExit SubSaiComErro: MsgBox "Nao"End Sub

ToolTipText personalizado

Este código transforma um formulário retangular em um quadrado de cantos arredondados. Ponha um Label no formulário para exibir o que você quiser, e no evento Deactivate do Form, ou Click, MouseMove, ou qualquer outro, de um Unload no Form, para ele sumir.

Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As _ Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As LongPrivate Declare Function CreateRoundRectRgn Lib "gdi32" (ByVal X1 _ As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As _ Long, ByVal X3 As Long, ByVal Y3 As Long) As Long

Private Sub Form_Load() Dim RoundRect As Long Me.Move 0, 0 RoundRect = CreateRoundRectRgn((Me.Left + 60) / Screen.TwipsPerPixelX, _ (Me.Top + 400) / Screen.TwipsPerPixelY, _ (Me.Left + 2600) / Screen.TwipsPerPixelX, _ (Me.Top + 1500) / Screen.TwipsPerPixelY, 20, 20)

50

Page 51: Dicas de VB

SetWindowRgn Me.hwnd, RoundRect, True Me.Move (Screen.Width - 2550) / 2, (Screen.Height - 1100) / 2End Sub

Verificar se um controle está com o focoIf Screen.ActiveControl.Name = "txtContrato" ThenEnd If

If TypeOf Screen.ActiveControl Is TextBox Then Debug.Print , "É um TextBox"Else Debug.Print , "Não é um TextBox"End If

51

Page 52: Dicas de VB

Criação de AtiveXs

Colocando as Tecla de Atalho para Funcionar num OCXs

Este código será muito útil quando você estiver criando um OCX de um botão, de uma espécie de Label ou qqr outro tipo de controle que contenha Caption.

Antes de mais nada, tenho que explicar-lhe o como esta propriedade funcionará, quer dizer, qual será sua ação conforme a propriedade CanGetFocus do UserControl estiver setada:* True - Ele dá um clique no UserControl;* False - NADA. A menos que você coloque a propriedade ForwardFocus como True (neste caso, ele jogará o foco p/ o próximo controle na lista do TabIndex - assim como faz o Label).

Então vamos ao código:

'Num Módulo:Public Function SelectKeys(ByVal sTexto As _ String) As String Dim iNum As Integer If sTexto <> "" And InStr(sTexto, "&") <> 0 Then For iNum = 1 To Len(sTexto) If Mid(sTexto, iNum, 1) = "&" And _ Mid(sTexto, iNum - 1, 1) <> "&" And _ Mid(sTexto, iNum + 1, 1) <> "&" And _ iNum <> Len(sTexto) Then SelectKeys = SelectKeys & Mid(sTexto, iNum + 1, 1) End If Next Else SelectKeys = "" End IfEnd Function

'No local onde você "PINTA" o texto no'UserControl, logo após pinta-lo, coloque'esta linha de código:UserControl.AccessKeys = SelectKeys(VarDoCaption)

P.S.: Eu recomendo que você pinte o UserControl TODO no evento UserControl_Paint, chamando-o das funções que recebem valores para as propriedades, pois assim ficará mais fácil de fazer-se um controle sobre todo este processo.

Manipulando Propriedades do Form onde seu OCX Está

É muito fácil de se verificar propriedades do Form onde seu UserControl está. Digamos que você precise verificar se a propriedade KeyPreview do Form está setada como True ou como False. Para isto, bastaria o seguinte código:

If UserControl.Extender.Parent.KeyPreview Then MsgBox "A propriedade KeyPreview do Form " & _ "está setada como True!!!"Else MsgBox "A propriedade KeyPreview do Form " & _ "está setada como False!!!"

52

Page 53: Dicas de VB

End If

Também é muito fácil de se modificar propriedades do Form onde seu UserControl está. Digamos que você precise modificar a propriedade AutoRedraw do Form para True ou como False. Para isto, bastaria o seguinte código:

UserControl.Extender.Parent.AutoRedraw = True'OuUserControl.Extender.Parent.AutoRedraw = False

Observação: Tome cuidado quando for alterar propriedades do Form, pois assim você poderá estar alterando personalizações feitas pelo programador que está usando seu OCX.

O Projeto está em Run ou Design Time?

Para saber isto é muito simples. Basta um If:

If Ambient.UserMode Then 'O projeto está em Run-Time, ou seja, 'ele está sendo executado.Else 'O projeto está em Design-Time.End If

Pegando o hWnd do Verdadeiro Container

Digamos que você queira pegar o hWnd do Form onde seu UserControl está. Bem, como eu expliquei na dica "Manipulando Propriedades do Form onde seu OCX está", bastaria usar isto:

Dim m_hWnd As Longm_hWnd = UserControl.Parent.hWnd

Ok. Mas você concorda que o usuário do seu UserControl pode coloca-lo dentro de um controle container (um PictureBox, por exemplo)? Pois é. Acontece que se você usar o código anterior, ele SEMPRE vai retornar o hWnd do Form. NUNCA do controle container (caso haja um).

Para resolver isto basta usar a API GetParent, como demonstro a seguir:

'Num módulo:Public Declare Function GetParent Lib _ "user32" (ByVal hWnd As Long) _ As Long

'No seu código:Dim m_hWnd As Longm_hWnd = GetParent(UserControl.hWnd)

Só finalizando, caso não haja um controle container, quer dizer, o UserControl está colocado diretamente no Form, o hWnd retornado pela API GetParent será do Form. Pronto.

53

Page 54: Dicas de VB

Qual tipo de Compatibilidade devo Usar?

A compatibilidade binaria é muito útil em ActiveXs, pois permite que, caso você altere seus ActiveXs, não precise refazer as telas de seus programas que o usamvam. Mas para isto você deve ter alguns cuidados:

1º - Quando você compilar o projeto a primeira vez usa a opção "Project Compatibility" e deixa a caixa de referencia em branco.

2º - Depois de compilado, (compile sempre pro diretorio do Windows\System), copie a ActiveX gerada para o diretorio dos fontes ou em um sub-diretorio (por exemplo para o subdiretório "Versoes"). Depois abra o projeto, mude para a opção "Binary Compatibility" e na caixa de referencia digite o diretorio/nome da ActiveX que é a "COPIA" (não aquela que está no diretorio do Windows\System - que é para onde você compilará novamente). Grave tudo e feche o projeto. Detalhe, usar a opção "Binary Compatibility" significa que o CLSID, o IID e LIBID serao mantidos entre as versoes.

3º - Na proxima vez que você chamar o projeto, o VB irá olhar para a ActiveX que você referenciou para deixar a proxima compilação "binariamente compativel" (isso significa que a interface publica da ActiveX continuará igual e o usuario da ActiveX não precisará compilar novamente o projeto que a usa). Ai então você pode compilar quantas vezes quiser (sempre no diretorio do Windows\System).

Não esqueça que qualquer alteração que você fizer na interface pública da ActiveX irá resultar na "incompatibilidade" mesmo que você esteja usando a opção dentro do VB. Em quase todos os casos o proprio VB irá mostrar uma mensagem enorme explicando que você está mudando a interface e bla bla bla...

Você também não pode incluir novas propriedades/metodos/eventos na ActiveX, porque vai dar problema...

Registrando e Desregistrando ActiveX via Código VB

Esta dica descreve como os controles de ActiveX podem ser registados e desregistrados diretamente do VB. Cada controle ActiveX contém duas funções que, quando chamadas o registram ou desregistram no sistema. Estas funções são DLLRegisterServer e DLLUnregisterServer. O seguinte código demonstra como registar e desregistrados os controles Microsoft Common Controls OCX, ComCtl32.OCX.

'Num módulo:Public Declare Function RegComCtl32 Lib _ "ComCtl32.OCX" Alias _ "DllRegisterServer" () As Long

Public Declare Function UnRegComCtl32 Lib _ "ComCtl32.OCX" Alias _ "DllUnregisterServer" () As Long

Const ERROR_SUCCESS = &H0

'Num Form coloque dois botões e insira'este código:Private Sub Command1_Click() 'P/ Registrar: If RegComCtl32 = ERROR_SUCCESS Then

54

Page 55: Dicas de VB

MsgBox "Registration Successful" Else MsgBox "Registration Unsuccessful" End IfEnd Sub

Private Sub Command2_Click() 'P/ DESregistrar: If UnRegComCtl32 = ERROR_SUCCESS Then MsgBox "UnRegistration Successful" Else MsgBox "UnRegistration Unsuccessful" End IfEnd Sub

Nota: Cada chamada a essa função do ActiveX pode levar um tempo de até 5 segundos.

55

Page 56: Dicas de VB

FlexGrid

Deixando um FlexGrid Zebrado (com 2 Cores Intercaladas)Function EImpar(ByVal iNum As Long) As Boolean 'Verifica se o número é impar 'Se for impar a função retorna True. 'Se for par a função retorna False. EImpar = (iNum Mod 2)End Function

Sub FlexCores(lCorPar As Long, lCorImpar As Long) Dim iLinha As Integer SeuMSFlexGrid.FillStyle = flexFillRepeat For iLinha = 1 To SeuMSFlexGrid.Rows - 1 With SeuMSFlexGrid .Row = iLinha If EImpar(iLinha) Then 'Se a linha for impar: 'Seleciona a partir da primeira coluna .Col = 1 'Seleciona até a última coluna .ColSel = .Cols - 1 'Aplica a cor .CellBackColor = lCorImpar Else 'Se a linha for par: 'Seleciona a partir da primeira coluna .Col = 1 'Seleciona até a última coluna .ColSel = .Cols - 1 'Aplica a cor .CellBackColor = lCorPar End If End With Next SeuMSFlexGrid.FillStyle = flexFillSingleEnd Sub

'Sintaxe:FlexCores(Cor das linhas pares, Cor das linhas impares)'Exemplo:FlexCores(&HFFFFFF, &HC0FFFF)

Exportar dados de FlexGrid para ExcelSub CopyToExcel(InFlexGrid As MSFlexGrid, Nome$, _ ByVal TextoAdicional$) Dim R%, c%, Buf$, LstRow%, LstCol% Dim FormatMoney As Boolean Dim MyExcel As Excel.Application Dim wbExcel As Excel.Workbook Dim shExcel As Excel.Worksheet On Error Resume Next

Set MyExcel = GetObject(, "Excel.Application") If Err.Number <> 0 Then Set MyExcel = CreateObject("Excel.Application") End If Set wbExcel = MyExcel.Workbooks.Add Set shExcel = wbExcel.Worksheets.Add

56

Page 57: Dicas de VB

shExcel.Name = Nome$ shExcel.Activate LstCol% = 0 For c% = 0 To InFlexGrid.Cols - 1 InFlexGrid.Col = c% LstRow% = 0 shExcel.Columns(Chr(Asc("A")+c%)).ColumnWidth=InFlexGrid.ColWidth(c%)/72 For R% = 0 To InFlexGrid.Rows - 1 InFlexGrid.Row = R% Err.Clear Buf$ = InFlexGrid.TextMatrix(R%, c%) If Buf$ <> "" Then FormatMoney = False If InStr(Buf$, vbCrLf) Then Buf$ = StrTran(Buf$, vbCrLf, vbLf) Do While Right(Buf$, 1) = vbLf Buf$ = Left(Buf$, Len(Buf$) - 1) Loop shExcel.Range(Chr(Asc("A") + c%)).WrapText = True ElseIf Format(CDbl(Buf$),csFormatMoneyZero)=Buf$ Then If Err.Number = 0 Then Buf$ = Str(CDbl(Buf$)) FormatMoney = True End If End If If Buf$ <> "" Then If InFlexGrid.MergeRow(R%) Then For LstCol% = c% To 1 Step -1 If InFlexGrid.TextMatrix(R%,LstCol%-1)<>InFlexGrid.TextMatrix(R%,c%) Then Exit For End If Next If LstCol% <> c% Then shExcel.Range(Chr(Asc("A")+LstCol%) & (R%+1), _ Chr(Asc("A")+c%) & (R%+1)).MergeCells=True shExcel.Range(Chr(Asc("A")+LstCol%) & (R%+1), _ Chr(Asc("A")+c%) & (R%+1)).BorderAround End If End If If InFlexGrid.MergeCol(c%) And LstRow% <> R% Then If InFlexGrid.TextMatrix(LstRow%,c%)=InFlexGrid.TextMatrix(R%,c%)Then shExcel.Range(Chr(Asc("A")+c%) & (LstRow%+1), _ Chr(Asc("A")+c%) & (R%+1)).MergeCells=True shExcel.Range(Chr(Asc("A")+c%) & (LstRow%+1), _ Chr(Asc("A")+c%) & (R%+1)).BorderAround Else LstRow% = R% End If End If shExcel.Range(Chr(Asc("A")+c%) & _ (R%+1)).Font.Color=InFlexGrid.CellForeColor If R%<InFlexGrid.FixedRows Or c%<InFlexGrid.FixedCols Then shExcel.Range(Chr(Asc("A")+c%) & _ (R%+1)).Font.Bold=True ' shExcel.Range(Chr(Asc("A")+c%) & _ ' (r%+1)).Font.BackColor = 40 End If shExcel.Range(Chr(Asc("A")+c%) & (R%+1)).Value=Buf$ If FormatMoney Then

57

Page 58: Dicas de VB

shExcel.Range(Chr(Asc("A")+c%) & _ (R%+1)).NumberFormat="#,##0.00;#,##0.00;#,##0.00" End If End If End If Next Next If TextoAdicional$ <> "" Then ' shExcel.Rows(Str(r%+2)).Delete (xlShiftUp) Do While Right(TextoAdicional$, 1) = vbLf TextoAdicional$ = Left(TextoAdicional$, _ Len(TextoAdicional$) - 1) Loop shExcel.Range("A" & (R% + 2)).Value = TextoAdicional$ End If MyExcel.Visible = True Set shExcel = Nothing Set wbExcel = Nothing Set MyExcel = NothingEnd Sub

Para imprimir o conteudo de um FlexGridDim intTamanho as IntegerintTamanho = MSFlexGrid.WidthMSFlexGrid.Width = Printer.WidthPrinter.PaintPicture MSFlexGrid.Picture, 0, 0Printer.EndDocMSFlexGrid.Width = intTamanho

58

Page 59: Dicas de VB

ComboBox

Abrir um ComboBox assim que receber o focoPrivate Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ lParam As Long) As Long

Private Sub Combo1_GotFocus() Const CB_SHOWDROPDOWN As Long = &H14F Dim Tmp As Long Tmp = SendMessage(Combo1.hwnd,CB_SHOWDROPDOWN,1,ByVal 0&)End SubOu no evento GotFocusPrivate Sub Combo1_GotFocus() SendKeys "%" & "{DOWN}"End Sub

Ajustando a Largura do Drop-Down de um ComboBox

Descobrindo a largura atual do Drop-Down

'Coloque este código num módulo:Private Const CB_GETDROPPEDWIDTH As Long = &H15FPrivate Const CB_ERR As Long = -1

Private Declare Function SendMessage Lib "USER32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal Msg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As Long

Public Function GetDropdownWidth(cbohWnd As _ Long) As Long Dim lRetVal As Long

'Descobrindo a largura atual do Drop Down: lRetVal = SendMessage(cbohWnd, _ CB_GETDROPPEDWIDTH, 0&, 0&) If lRetVal <> CB_ERR Then 'Ele retornará a largura do Drop Down 'em pixels. GetDropdownWidth = lRetVal Else GetDropdownWidth = 0 End IfEnd Function

'P/ chamar use assim:Dim iLargura As IntegeriLargura = GetDropdownWidth(Combo1.hWnd)

'Pronto. A variável iLargura conterá a'largura do Drop Down em pixels.

59

Page 60: Dicas de VB

Adicionando itens ao ComboBox em Run-Time

Você pode adicionar itens e atualizar a largura do Drop Down automaticamente. Veja como:

'Coloque este código num módulo:Option Explicit

Private Const CB_GETDROPPEDWIDTH As Long = &H15FPrivate Const CB_SETDROPPEDWIDTH As Long = &H160Private Const CB_ERR As Long = -1Private Const DT_CALCRECT As Long = &H400

Public Type Rect Left As Long Top As Long Right As Long Bottom As LongEnd Type

Private Declare Function DrawText Lib "user32" _ Alias "DrawTextA" (ByVal hDC As Long, _ ByVal lpStr As String, ByVal nCount As _ Long, lpRect As Rect, ByVal wFormat As _ Long) As LongPrivate Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ ByVal lParam As Any) As Long

Public Function cboAdiciona(ByRef ctl As Control, _ ByVal sNewItem As String, Optional ByVal _ dwNewItemData As Variant) As Long Dim RC As Rect Dim newWidth As Long Dim currWidth As Long Dim sysScrollWidth As Long Dim OldFont As StdFont If ctl.Tag <> "" Then currWidth = CLng(ctl.Tag) End If Set OldFont = ctl.Parent.Font Set ctl.Parent.Font = ctl.Font Call DrawText(ctl.Parent.hDC, sNewItem, -1&, _ RC, DT_CALCRECT) newWidth = RC.Right + 5 Set ctl.Parent.Font = OldFont

If newWidth > currWidth Then Call SendMessage(ctl.hwnd, CB_SETDROPPEDWIDTH, _ newWidth, 0&) ctl.Tag = newWidth End If ctl.AddItem sNewItem If Not IsMissing(dwNewItemData) Then If IsNumeric(dwNewItemData) Then ctl.ItemData(ctl.NewIndex) = dwNewItemData End If

60

Page 61: Dicas de VB

End If cboAdiciona = ctl.NewIndexEnd Function

'P/ usar, adicione os itens desta maneira (se'você usar com Combo1.AddItem NÃO FUNCIONARÁ!):Call cboAdiciona(Combo1, "Texto")

'Esta função retorna o valor do ListIndex do'novo item. Então, você pode usar esta função'recebemdo o valor do ListIndex p/ usa-lo de'alguma forma. Veja como fazer isto:

Dim NovoIndex As LongNovoIndex = cboAdiciona(Combo1, "Texto")MsgBox "O Item " & NovoIndex & " foi adicionado!"

Adicionando itens ao ComboBox em Design-Time

Se você quizer adicionar os itens em Design-Time e atualizar a largura do Drop Down Run-Time, faça da seguinte maneira:

'Coloque este código num módulo:Private Const CB_SETDROPPEDWIDTH As Long = &H160Private Const CB_ERR As Long = -1

Private Declare Function SendMessage Lib "USER32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal Msg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As LongPublic Function SetDropdownWidth(cboHwnd As Long, _ NewWidthPixel As Long) As Boolean Dim lRetVal As Long 'Ajustando a largura do Drop-Down: lRetVal = SendMessage(cboHwnd, _ CB_SETDROPPEDWIDTH, NewWidthPixel, 0) If lRetVal <> CB_ERR Then SetDropdownWidth = True Else SetDropdownWidth = False End IfEnd Function

'No Form, coloque:Private Sub Form_Load() Dim iLar1 As Integer, iLar2 As Integer Dim iNum As Integer, OldFont As StdFont iLar2 = 0 OldFont = Me.Font Me.Font = Combo1.Font Me.ScaleMode = 3 For iNum = 0 To Combo1.ListCount - 1 Combo1.ListIndex = iNum iLar1 = Me.TextWidth (Combo1.Text) If iLar1 > iLar2 Then iLar2 = iLar1 End If Next iLar2 = iLar2 + 5

61

Page 62: Dicas de VB

Call SetDropdownWidth(Combo1.hWnd, iLar2) Me.Font = OldFontEnd Sub

Auto preenche o ComboBox de acordo com o texto encontrado

Duas rotinas, a Combo1_Change() que auto preenche o combo de acordo com o texto encontrado e uma outra Combo1_LostFocus() que impede que o Compo perca o focus se o texto digitado não existir...

PS: Declare as variaveis... OK?

Private Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ lParam As Any) As Long

Const CB_FINDSTRING As Long = &H14CConst CB_ERR As Long = (-1)

Private Sub Combo1_Change() With Combo1 'Procura pelo texto já digitado strPartial = .Text I = SendMessage(.hwnd,CB_FINDSTRING,-1, _ ByVal strPartial)

'Se achou, adiciona o resto do Texto If I <> CB_ERR Then 'Pega o texto inteiro strTotal = .List(I)

'Compute number of unmatched characters j = Len(strTotal) - Len(strPartial) If j <> 0 Then 'Adiciona o resto da string encontrada m_bEditFromCode = True .SelText = Right$(strTotal, j)

'Marca os caracteres adicionados .SelStart = Len(strPartial) .SelLength = j End If End If End WithEnd Sub

Private Sub Combo1_LostFocus() With Combo1 if Len(.Text) then 'Procura pelo texto digitado strPartial = .Text I = SendMessage(.hwnd,CB_FINDSTRING,-1,ByVal strPartial) 'Se não achou, retorna o focus para o Combo If I = CB_ERR Then .SetFocus End if End WithEnd Sub

62

Page 63: Dicas de VB

Preenchendo um ComboBox com os Registros de um Banco de Dados

Bom, primeiro você deve abrir o Recordset (tanto faz se isso é feito em DAO ou ADO) e, depois disso feito, execute esta rotina:

'Abre o Recordset... RS.MoveFirst Do While Not RS.EOF Combo1.AddItem RS![Nome do Campo] RS.MoveNext Loop

Uma dica interessante seria, por exemplo, exibir na ComboBox o campo Nome e guardar na própria ComboBox o valor do campo Código. Veja como fazer isto:

'Abre o Recordset... RS.MoveFirst Do While Not RS.EOF Combo1.AddItem RS![Nome] Combo1.ItemData(Combo1.NewIndex) = RS![Código] RS.MoveNext Loop

Então, digamos que você queira jogar na variável sNom o Nome selecionado na ComboBox e na variável iCod o código correspondente a este nome selecionado. Para isso, proceda da seguinte forma:

'No evento que você quizer, coloque isto: Dim sNom As String, iCod As Integer If Combo1.ListIndex <> -1 Then iCod = Combo1.ItemData(Combo1.ListIndex) sNom = Combo1.Text End If

63

Page 64: Dicas de VB

DbGrid

Auto Ajustar Colunas no DBGridPrivate Sub DBGrid1_ColResize(ByVal ColIndex As Integer, _ Cancel As Integer) Dim DB As Database, RS As Recordset, FL As Field Dim Tamanho As Double 'Cada caracter corresponde a 120 twips na horizontal Tamanho = Len(DBGrid1.Columns(ColIndex).Caption) * 120

Set DB = OpenDatabase("C:\Dir Do VB\Biblio.mdb") Set RS = DB.OpenRecordset("Authors") Set FL = RS.Fields(DBGrid1.Columns(ColIndex).DataField)

Do While Not RS.EOF 'Verifica o tamanho de cada valor do campo On Error Resume Next If Tamanho < Me.TextWidth(FL.Value) Then Tamanho = Me.TextWidth(FL.Value) End If RS.MoveNext Loop DBGrid1.Columns(ColIndex).Width = TamanhoEnd Sub

Destacando uma linha em um DBGrid

Para destacar uma linha no controle DBGrid, adicione o registro corrente à SellBookmarks Collection:

Private Sub DBGrid_RowColChange (LatRow _ As Variant, ByVal LasRow As Integer) If Data1.RecordSet.RecordCount Then DBGrid.SelBookmarks.Add _ Data1.RecordSet.Bookmark End IfEnd Sub

Mudar de Coluna no DBGrid com TABÉ bem simples fazer isto. Basta você mudar algumas propriedades do DBGrid:- Mude a propriedade TabAction p/ "2-Grid Navigation";- Mude a propriedade WrapCellPointer para True.E é só usar!

64

Page 65: Dicas de VB

Preenchendo o DBGrid via Código

Para preencher um DBGRID dentro de um código, basta referenciara coluna e a linha e passar o valor desejado.Por exemplo, se você quiser preencher a célula da linha 2,coluna 3, defina a propriedade ROW=2 e Col=3. Depois, defina apropriedade Text com o valor desejado.

Ex.:

'Limpa TODO o conteúdo do DBGrid1DBGrid1.Cls'Seleciona a linha 2DBGrid1.Row = 2'Seleciona a coluna 3DBGrid1.Col = 3'Atribui o textoDBGrid1.Text = "Texto a ser inserido"

65

Page 66: Dicas de VB

DriveListBox

Códigos Erro do DriveListBoxPrivate Sub Dir1_Change() 'Faz com que os arquivos que irão aparecer no 'FileListBox serão os do diretório selecionado 'no DirListBox File1.Path = Dir1.PathEnd Sub

Private Sub Drive1_Change() 'tratamento de erro On Error GoTo ErrorDRV 'Indica que os diretórios que irão aparecer no 'DriveListBox serão o da unidade selecionada Dir1.Path = Drive1.DriveExit SubErrorDRV: MsgBox "Não há disco nesta unidade !", vbCriticalEnd Sub

66

Page 67: Dicas de VB

Form

Animando a Barra de Título de um Form

Para criar uma animação na barra de título do Form (tipo Marquee), basta você colocar no Form o código abaixo.

'Será usado p/ parar a animação quando o Form'for fechado. Coloque no Declarations do Form:Dim bFechado As Boolean

Private Sub Form_Activate() Dim iTempo As Single, bDiminui As Boolean Dim iNum As Integer, iLarg As Integer Dim iLargT As Integer, Texto As String iTempo = Timer Do While Not bFechado If Timer > iTempo + 0.01 Then iTempo = Timer Select Case bDiminui Case False iNum = iNum + 1 Texto = String(iNum, " ") & _ "Mensagem do Marquee" iLargT = TextWidth(Texto) iLarg = ScaleWidth - 1110 If iLargT >= iLarg Then iNum = iNum - 2 bDiminui = True Texto = String(iNum, " ") & _ "Mensagem do Marquee" End If Case Else iNum = iNum - 1 If iNum < 1 Then iNum = 1 Texto = "Mensagem do Marquee" bDiminui = False Else Texto = String(iNum, " ") & _ "Mensagem do Marquee" End If End Select Caption = Texto End If DoEvents LoopEnd Sub

Private Sub Form_Unload(Cancel As Integer) bFechado = TrueEnd Sub

Detalhe, modifique as linhas onde aparece "Mensagem do Marquee" pelo texto que você quizer que apareça.

67

Page 68: Dicas de VB

Arrastar um controle ou Formulário sem Título'Na parte geral do Form:Private Declare Function SendMessage Lib _ "user32" Alias "SendMessageA" (ByVal _ hWnd As Long, ByVal wMsg As Long, _ ByVal wParam As Long, lParam As Any) _ As LongPrivate Declare Function ReleaseCapture Lib _ "user32" () As Long

'No evento Mouse_DownDim rec&If Button And 1 Then ReleaseCapture rec& = SendMessage(Me.hwnd, &HA1, 2, 0&)End IF

'OBS.: Esta dica pode também ser usada para arrastar controles (Legal!!!).

Carregar Várias Instancias do Mesmo FormulárioDim Formulario As Form1Set Formulario = New Form1Load FormularioFormulario.Show

Centralizar um Form MDIChild

Para centralizar um Form MDIChild ou colocá-lo em qualquer lugar da tela utilize a seguinte rotina no evento Load:

'P/ centralizar:Private Sub Form_Load() Me.Left = (MDIForm1.ScaleHeight - Me.Height) / 2 Me.Top = (MDIForm1.ScaleWidth - Me.Width) / 2End Sub

'Ou, p/ ele aparecer em um ponto qualquer (que'você tenha escolhido):Private Sub Form_Load() Me.Left = Valor Me.Top = ValorEnd Sub

Criando forms de formatos especiais

Esta é uma das mais interessantes. Você pode criar forms de formatos especiais facilmente. Experimente o exemplo abaixo e veja que efeito interessante:

' Declare estas duas APIs na seção General Declarations do form:

Private Declare Function CreateEllipticRgn Lib _ "gdi32" (ByVal X1 As Long, ByVal Y1 As _

68

Page 69: Dicas de VB

Long, ByVal X2 As Long, ByVal Y2 As Long) _ As LongPrivate Declare Function SetWindowRgn Lib "user32" _ (ByVal hWnd As Long, ByVal hRgn As Long, _ ByVal bRedraw As Boolean) As Long

Private Sub Form_Load() Show 'o form! SetWindowRgn hWnd,CreateEllipticRgn(0,0,300,200),TrueEnd Sub

Criando um Form Circular'No Declarations do form: Private Declare Function CreateEllipticRgn Lib "gdi32" _ (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As _ Long, ByVal Y2 As Long) As Long Private Declare Function SetWindowRgn Lib "user32" (ByVal _ hWnd As Long, ByVal hRgn As Long, ByVal bRedraw _ As Boolean) As Long

'No Form_Load: Private Sub Form_Load() Dim hr&, dl& Dim usew&, useh& usew& = me.Width / Screen.TwipsPerPixelX useh& = me.Height / Screen.TwipsPerPixelY x = 0 'Deixa o Form ficar em forma círcular hr& = CreateEllipticRgn(0, 0, usew, useh) dl& = SetWindowRgn(me.hWnd, hr, True)End Sub

Crinado um Form com Cantos Arredondados

Você pode criar facilmente Forms ou controles usando o código a seguir:

'Coloque num Form coloque um CommandButton'chamado Command1.

'No Declarations:Private Declare Function CreateRoundRectRgn Lib _ "gdi32" (ByVal X1 As Long, ByVal Y1 As _ Long, ByVal X2 As Long, ByVal Y2 As Long, _ ByVal X3 As Long, ByVal Y3 As Long) As LongPrivate Declare Function SetWindowRgn Lib "user32" _ (ByVal hwnd As Long, ByVal hRgn As Long, _ ByVal bRedraw As Boolean) As LongPrivate Declare Function GetClientRect Lib "user32" _ (ByVal hWnd As Long, lpRect As Rect) As LongPrivate Type Rect Left As Long Top As Long Right As Long Bottom As LongEnd Type

Sub Retangulo(m_hWnd As Long, Fator As Byte)

69

Page 70: Dicas de VB

Dim RGN As Long Dim RC as Rect Call GetClientRect(m_hWnd, RC) RGN = CreateRoundRectRgn(RC.Left, RC.Top, RC.Right, _ RC.Bottom, Fator, Fator) SetWindowRgn m_hWnd, RGN, TrueEnd Sub'Fator é a distância da curvatura do canto arredondado

'No evento click do CommandButton:Private Sub Command1_Click() Me.BackColor = &H808080 'Apenas para destacar a cor 'Coloca o formulário com os cantos arredondados 'e fator 80 de área Retangulo Me.hWnd, 80 Retangulo Command1.hWnd, 30End Sub

Criando um Form Elíptico

Poucos programas utilizam esse recurso do Windows 95 que cria Forms e até mesmmo outros objetos em forma elíptica.

'Coloque num Form coloque um CommandButton'chamado Command1.

'No Declarations:Private Declare Function CreateEllipticRgn Lib _ "gdi32" (ByVal X1 As Long, ByVal Y1 As _ Long, ByVal X2 As Long, ByVal Y2 As Long) _ As LongPrivate Declare Function SetWindowRgn Lib "user32" _ (ByVal hwnd As Long, ByVal hRgn As Long, _ ByVal bRedraw As Boolean) As LongPrivate Declare Function GetClientRect Lib "user32" _ (ByVal hWnd As Long, lpRect As Rect) As Long

Private Type Rect Left As Long Top As Long Right As Long Bottom As LongEnd Type

Sub Eliptico(m_hWnd As Long) Dim RGN As Long Dim RC as Rect Call GetClientRect(m_hWnd, RC) RGN = CreateEllipticRgn(RC.Left, RC.Top, RC.Right, _ RC.Bottom) SetWindowRgn m_hWnd, RGN, TrueEnd Sub

'No evento click do CommandButton:Private Sub Command1_Click() Me.BackColor = &H808080 'Apenas para destacar a cor Eliptico Me.hWnd 'O formulário fica Elíptico Eliptico Command1.hWnd 'O botão fica Elíptico

70

Page 71: Dicas de VB

End Sub

Criando um Form em forma de Estrela (Polígono)

Essa API possibilita a criação de um Form de qualquer forma poligonal. Até hoje eu só vi o 4 programas com formulários diferentes: O Vibe MP3player 3D, Norton CrashGuard, Norton Utilities 3 e o RomSoft Photo Collection 10000. O uso de polígonos é mais complexo que os outros métodos de criação de Forms citados anteriormente. Veja o Exemplo, que cria um formulário na forma de uma estrela de quatro pontas:

'No Declarations:Option Base 1Private Declare Function CreatePolygonRgn Lib _ "gdi32" (lpPoint As POINTAPI, ByVal nCount _ As Long, ByVal nPolyFillMode As Long) _ As LongPrivate Declare Function SetWindowRgn Lib "user32" _ (ByVal hwnd As Long, ByVal hRgn As Long, _ ByVal bRedraw As Boolean) As Long

Private Type POINTAPI X As Long Y As LongEnd Type

'No evento Form_Load:

Private Sub Form_Load() Dim Pontos(8) As POINTAPI 'Cria uma matriz de 8 Pontos Dim RGN As Long Me.Width = 1500 Me.Height = 1500 'Determina as oito coordenadas de uma estrela de 'quatro pontas (em Pixel) Pontos(1).X = 0 Pontos(1).Y = 0 Pontos(2).X = 50 Pontos(2).Y = 25 Pontos(3).X = 100 Pontos(3).Y = 0 Pontos(4).X = 75 Pontos(4).Y = 50 Pontos(5).X = 100 Pontos(5).Y = 100 Pontos(6).X = 50 Pontos(6).Y = 75 Pontos(7).X = 0 Pontos(7).Y = 100 Pontos(8).X = 25 Pontos(8).Y = 50 RGN = CreatePolygonRgn(Pontos(1), 8, 0) SetWindowRgn Me.hwnd, RGN, TrueEnd Sub

A API CreatePolygonRgn possui os seguintes parâmetros* Pontos(1) => Primeiro elemento da matriz* 8 => Número de vértices do polígono (Elementos da matriz)* 0 => Como ficaria o polígono se as suas linhas se sobrepossem (0 ou 1)

71

Page 72: Dicas de VB

Criando um Form em forma de Triângulo'Coloque este código num Form:Option ExplicitPrivate Type POINTAPI x As Long y As LongEnd Type

Private Type tP P(1 To 3) As POINTAPIEnd Type

Private Declare Function CreatePolygonRgn Lib _ "gdi32" (lpPoint As POINTAPI, ByVal _ nCount As Long, ByVal nPolyFillMode _ As Long) As LongPrivate Declare Function SetWindowRgn Lib _ "user32" (ByVal hWnd As Long, ByVal _ hRgn As Long, ByVal bRedraw As Boolean) _ As Long

Private Sub Form_Load() Dim z As tP Me.ScaleMode = vbPixels z.P(1).x = ((Me.ScaleHeight - Me.ScaleLeft) / _ 2) + 13 z.P(1).y = 26 z.P(2).x = 26 z.P(2).y = Me.ScaleHeight - Me.ScaleLeft z.P(3).x = Me.ScaleHeight - Me.ScaleLeft z.P(3).y = Me.ScaleHeight - Me.ScaleLeft SetWindowRgn hWnd, CreatePolygonRgn(z.P(1), _ 3, 3), TrueEnd Sub

Criando um Form com forma do Logotipo do Windows'Coloque o seguinte código no form:Private Type RECT Left As Long Top As Long Right As Long Bottom As LongEnd TypePrivate Declare Function BeginPath Lib "gdi32" _ (ByVal hdc As Long) As LongPrivate Declare Function TextOut Lib "gdi32" _ Alias "TextOutA" (ByVal hdc As Long, _ ByVal X As Long, ByVal Y As Long, ByVal _ lpString As String, ByVal nCount As _ Long) As LongPrivate Declare Function EndPath Lib "gdi32" _ (ByVal hdc As Long) As LongPrivate Declare Function PathToRegion Lib _ "gdi32" (ByVal hdc As Long) As LongPrivate Declare Function GetRgnBox Lib "gdi32" _ (ByVal hRgn As Long, lpRect As RECT) _ As LongPrivate Declare Function CreateRectRgnIndirect _ Lib "gdi32" (lpRect As RECT) As LongPrivate Declare Function CombineRgn Lib "gdi32" _

72

Page 73: Dicas de VB

(ByVal hDestRgn As Long, ByVal hSrcRgn1 _ As Long, ByVal hSrcRgn2 As Long, ByVal _ nCombineMode As Long) As LongPrivate Declare Function DeleteObject Lib "gdi32" _ (ByVal hObject As Long) As LongPrivate Declare Function SetWindowRgn Lib "user32" _ (ByVal hwnd As Long, ByVal hRgn As Long, _ ByVal bRedraw As Boolean) As LongPrivate Declare Function ReleaseCapture Lib _ "user32" () As LongPrivate Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ lParam As Any) As Long

Private Const RGN_AND As Long = 1Private Const WM_NCLBUTTONDOWN As Long = &HA1Private Const HTCAPTION As Long = 2

Private Function GetTextRgn() As Long Dim hRgn1 As Long, hRgn2 As Long Dim rct As RECT BeginPath hdc TextOut hdc, 10, 10, Chr$(255), 1 EndPath hdc hRgn1 = PathToRegion(hdc) GetRgnBox hRgn1, rct hRgn2 = CreateRectRgnIndirect(rct) CombineRgn hRgn2, hRgn2, hRgn1, GN_AND DeleteObject hRgn1 GetTextRgn = hRgn2End FunctionPrivate Sub Form_DblClick() Unload MeEnd SubPrivate Sub Form_Load() Dim hRgn As Long Me.Font.Name = "Wingdings" Me.Font.Size = 200 hRgn = GetTextRgn() SetWindowRgn hwnd, hRgn, 1End SubPrivate Sub Form_MouseDown(Button As Integer, Shift _ As Integer, X As Single, Y As Single) ReleaseCapture SendMessage hwnd, WM_NCLBUTTONDOWN, HTCAPTION, _ ByVal 0&End Sub

'Depois é só executar q o Form ficará no formato do'logotipo do Windows!!!

Criando um Form no Formato da Imagem Desejada'No módulo:Public Declare Function SetWindowRgn Lib "user32" _ (ByVal hwnd As Long, ByVal hRgn As Long, _ ByVal bRedraw As Boolean) As LongPublic Declare Function DeleteObject Lib "gdi32" _

73

Page 74: Dicas de VB

(ByVal hObject As Long) As LongPublic Declare Function ReleaseCapture Lib _ "user32" () As LongPublic Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ lParam As Any) As LongPrivate Declare Function CreateCompatibleDC Lib _ "gdi32" (ByVal hdc As Long) As LongPrivate Declare Function SelectObject Lib _ "gdi32" (ByVal hdc As Long, ByVal hObject _ As Long) As LongPrivate Declare Function GetObject Lib "gdi32" _ Alias "GetObjectA" (ByVal hObject As _ Long, ByVal nCount As Long, lpObject As _ Any) As LongPrivate Declare Function CreateRectRgn Lib _ "gdi32" (ByVal X1 As Long, ByVal Y1 As _ Long, ByVal X2 As Long, ByVal Y2 As Long) _ As LongPrivate Declare Function CombineRgn Lib "gdi32" _ (ByVal hDestRgn As Long, ByVal hSrcRgn1 _ As Long, ByVal hSrcRgn2 As Long, ByVal _ nCombineMode As Long) As LongPrivate Declare Function DeleteDC Lib "gdi32" _ (ByVal hdc As Long) As LongPrivate Declare Function GetPixel Lib "gdi32" _ (ByVal hdc As Long, ByVal X As Long, _ ByVal Y As Long) As Long

Public Const WM_NCLBUTTONDOWN As Long = &HA1Public Const HTCAPTION As Long = 2

Private Type BITMAP bmType As Long bmWidth As Long bmHeight As Long bmWidthBytes As Long bmPlanes As Integer bmBitsPixel As Integer bmBits As LongEnd Type

Public Function GetBitmapRegion(cPicture As _ StdPicture, cTransparent As Long) Dim hRgn As Long, tRgn As Long Dim X As Integer, Y As Integer, X0 As Integer Dim hdc As Long, BM As BITMAP 'Cria um novo DC, então procuramos a imagem hdc = CreateCompatibleDC(0) If hdc Then 'Coloca o novo DC na Imagem SelectObject hdc, cPicture 'Pega as dimensões e cria uma nova região 'de retangulo GetObject cPicture, Len(BM), BM hRgn = CreateRectRgn(0, 0, BM.bmWidth, BM._ bmHeight) 'Inicia procurando a imagem de cima para 'baixo For Y = 0 To BM.bmHeight

74

Page 75: Dicas de VB

For X = 0 To BM.bmWidth 'Procura uma linha de píxeis não 'transparentes While X <= BM.bmWidth And GetPixel(hdc, _ X, Y) <> cTransparent X = X + 1 Wend 'Marca o Início da linha de píxeis não 'transparentes X0 = X 'Procura uma linha com Píxeis 'transparentes While X <= BM.bmWidth And GetPixel(hdc, _ X, Y) = cTransparent X = X + 1 Wend 'Cria uma nova região que corresponda à 'linha dos píxeis transparentes e então 'remove ele da região principal If X0 < X Then tRgn = CreateRectRgn(X0, Y, X, Y + 1) CombineRgn hRgn, hRgn, tRgn, 4 'Libera a memória usada para a nova 'região temporária DeleteObject tRgn End If Next X Next Y 'Volta ao endereço de memória da imagem pronta GetBitmapRegion = hRgn 'Libera memória apagando a imagem DeleteObject SelectObject(hdc, cPicture) End If 'Libera memória apagando o DC criado DeleteDC hdcEnd Function

A função GetBitmapRegion pede dois parâmetros: a figura e uma cor a ser apagada. Se o fundo da sua figura for preto, você pode usar a constante vbBlack e apagar toda a cor preta da figura. Lembrando que se a cor estiver dentro da figura, ela será apagada também, deixando o form transparente naquele lugar.

'Coloque a imagem na propriedade Picture do Form'e, no Form_Load:Private Sub Form_Load() Dim hRgn As Long If hRgn Then DeleteObject hRgn hRgn = GetBitmapRegion(Me.Picture, vbBlack) SetWindowRgn Me.hwnd, hRgn, TrueEnd Sub

Criando uma Tela de Splash para seu Programa

Para ter uma tela de splash (aquela que aparece enquanto o programa está sendo carregado) em seu programa, siga os seguintes passos:

75

Page 76: Dicas de VB

1º - Coloque em seu projeto um novo Form e configure-o conforme o seu gosto para que ele seja sua tela de splash.

2º - Abra a tela de propriedades do seu projeto e selecione este form que você acaba de criar em "Startup Object:" (para que ele seja o 1º form a aparecer quando seu programa for executado).

3º - Coloque este código nesse form:

Private Sub Form_Activate() Screen.MousePointer = 11 DoEvents

'Troque este "frmPrincipal" pelo nome do 'principal form de seu programa. frmPrincipal.Show

'Esta linha é uma chamada de API. 'Para saber mais sobre ela veja a 'dica Dar uma Pausa em seu Programa Sleep (1000) Unload Me Screen.MousePointer = 0End SubPrivate Sub Form_Load() 'Esta linha é uma chamada de API. 'Para saber mais sobre ela veja a 'dica Formulário ficar por cima de todos Call SetWindowPos(frmSplash.hWnd, -1, 150, _ 130, 0, 0, &H1)End Sub

O uso do DoEvents nesse caso é para permitir que o primeiro Form (o frmSplash) apareça sobreposto atraves da chamada da API SetWindowPos. Se não for colocado o DoEventes o SetWindowsPos não funcionará.

Degradê em Forms'Degradê se faz utilizando a variação de cores:'Ex: para fazer num Form (tons de azul)

Dim k as integerForm1.AutoRedraw=TrueForm1.ScaleWidth = 255Form1.DrawWidth = 2For k = 0 to 255 Form.line (k, 0)-(k+1,Form1.height),rgb(0,0,k)Next

Fazer um form maior que a tela

Faça um form com o tamanho da tela. Insira um picturebox no form. Finalmente, via código, aumente o tamanho do picture e ajuste os valores da barra de rolagem.

Scroll.Max = (Picture1.Height - Me.Height) / 10

76

Page 77: Dicas de VB

'P/ rolar a barra:Sub Scroll_Change() Picture1.Top= -1 * Picture1.Top + Scroll.ValueEnd Sub

Fechando todos os Forms Abertos'Crie a seguinte função:

Public Function Fechar() Dim FRM As Integer FRM = Forms.Count Do While FRM > 0 Unload Forms(FRM-1) If FRM = Forms.Count Then Exit Do End If FRM = FRM - 1 LoopEnd Function

'Então, qdo quizer que seu programa seja finalizado,'ao invés de usar o comando "End", chame esta função:Fechar

Formulário ficar por cima de todos'Na seção geral do módulo:Public Declare Function SetWindowPos Lib _ "user32" (ByVal hwnd As Long, ByVal _ hWndInsertAfter As Long, ByVal x As _ Long, ByVal y As Long, ByVal cx As _ Long, ByVal cy As Long, ByVal wFlags _ As Long) As Long

'No evento Form_Load do formulário.Call SetWindowPos(Me.hwnd,-1,0,0,0,0,&H1 Or &H2)

Passe nothing aos forms com cautela

'Use esta função para dar Nothing em seus forms

Private Sub Form_Unload (Cancel As Integer) Dim Form As Form For Each Form In Forms If Form Is Me Then Set Form = Nothing Exit For End If Next FormEnd Sub

77

Page 78: Dicas de VB

Pintar um local do formulario com a cor escolhidaPrivate Declare Function FloodFill Lib _ "gdi32" (ByVal hDC As Long, ByVal _ X As Long, ByVal Y As Long, ByVal _ crColor As Long) As Long

Private Sub Form_Click() ScaleMode = vbPixels 'Windows draws in pixels. ForeColor = vbBlack 'Set draw line to black. Line (100, 50)-(300, 50) 'Draw a triangle. Line -(200, 200) Line -(100, 50)

FillStyle = vbFSSolid 'Set FillStyle to solid. FillColor = RGB(128, 128, 255) 'Set FillColor.

'Call Windows API to fill. FloodFill hDC,200,100,ForeColorEnd Sub

Removendo o move

Em alguns casos, é interessante impedir o usuário de mover um form. No VB isto pode ser implementado com APIs:

Declare Function GetMenu% Lib "User" _ (ByVal hWnd%)Declare Function RemoveMenu% Lib "User" _ (ByVal hWnd%, ByVal nPosition%, _ ByVal wFlags%)'...Dim Res%Res = RemoveMenu(GetMenu(Form.hWnd), _ SC_MOVE, MF_BYPOSITION)

Removendo os Botões MIN-MAX de Forms MDI'Coloque o seguinte código num módulo:

Private Declare Function SetWindowLong Lib "user32" _ Alias "SetWindowLongA" (ByVal hwnd As Long, _ ByVal nIndex As Long, ByVal dwNewLong As _ Long) As LongPrivate Declare Function GetWindowLong Lib "user32" _ Alias "GetWindowLongA" (ByVal hwnd As Long, _ ByVal nIndex As Long) As Long

Private Const WS_MINIMIZEBOX As Long = &H20000Private Const WS_MAXIMIZEBOX As Long = &H10000Private Const GWL_STYLE As Long = (-16)

'No evento MDIForm_Load do MDIForm:

Sub MDIForm_Load() Dim lWnd as Long lWnd = GetWindowLong(Me.hWnd, GWL_STYLE)

78

Page 79: Dicas de VB

'Tira o botão de minimizar lWnd = lWnd And Not (WS_MINIMIZEBOX)

'Tira o botão de maximizar lWnd = lWnd And Not (WS_MAXIMIZEBOX)

lWnd = SetWindowLong(Me.hWnd, GWL_STYLE, lWnd)End Sub

Saber se um form está abertodim v as IntegerFor v = 0 To Forms.Count if Forms(v).Name = "NomeDoForm" Then msgbox "Está aberto!" Exit For End IfNext

79

Page 80: Dicas de VB

Grid

Digitação em Grid

O controle Grid é uma tabela de exibição de dados, que não permite a digitação direta de valores em suas células (não estou falando do DBGrid). É possível "simular" a aceitação de teclas através de código. Basta um clique de mouse na célula e digitar. O programador deve ter incluído as rotinas abaixo nos eventos KeyDown e KeyPress.

Sub Grid1_KeyDown (KeyCode As Integer, Shift As Integer) Select Case KeyCode Case &H8 'BACKSPACE If Len(Grid1.Text) > 0 Then Grid1.Text = Left(Grid1.Text, (Len(Grid1.Text) - 1)) End If Case &H2E 'DEL Grid1.Text = "" End SelectEnd Sub

Sub Grid1_KeyPress (keyascii As Integer) Select Case keyascii Case Is <> 8, 9, 10, 13'não imprimíveis Grid1.Text = Grid1.Text & Chr(keyascii) End SelectEnd Sub

No evento KeyPress todos os caracteres imprimíveis são acrescentados ao texto da célula ativa do Grid. O evento KeyDown apaga o último caracter com BACKSPACE ou o texto inteiro com a tecla DEL.

80

Page 81: Dicas de VB

ImageList

Alterando o Conteúdo da ImageList sem Desvincula-la da ToolBar

Para fazer isto, em disign-time, recorte a Toolbar (selecione-a e Ctrl+X) e altere o conteúdo da ImageList (adicionar imagens, excluir imaens e etc). Então, cole a Toolbar novamente (selecione o Form e Ctrl+V).

ATENÇÃO!!! Isso PODE não ser útil se houver mudanças nos índices dos botões.

81

Page 82: Dicas de VB

ListBox

Achar uma palavra num ListBoxPublic Const LB_FINDSTRING As Long = &H18FPublic Const LB_FINDSTRINGEXACT As Long = &H1A2

Public Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ lParam As Any) As Long

Private Sub Text1_Change() ListBox1.ListIndex = Sendmessage(ListBox1.hWnd, _ LB_FINDSTRING, -1, _ Byval Text1.Text)End Sub

Colocando ScrollBar Horizontal num ListBox'Coloque o seguinte código num módulo:Option Explicit

Private Const LB_GETHORIZONTALEXTENT As Long = &H193Private Const LB_SETHORIZONTALEXTENT As Long = &H194Private Const DT_CALCRECT As Long = &H400Private Const SM_CXVSCROLL As Long = 2

Public Type Rect Left As Long Top As Long Right As Long Bottom As LongEnd Type

Private Declare Function DrawText Lib "user32" _ Alias "DrawTextA" (ByVal hDC As Long, _ ByVal lpStr As String, ByVal nCount As _ Long, lpRect As Rect, ByVal wFormat As _ Long) As LongPrivate Declare Function GetSystemMetrics Lib _ "user32" (ByVal nIndex As Long) As LongPrivate Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ lParam As Any) As Long

Public Function AdicionaItem(ByRef ctl As Control, _ ByVal sNewItem As String, Optional ByVal _ dwNewItemData As Variant) As Long Dim RC As Rect Dim newWidth As Long Dim currWidth As Long Dim sysScrollWidth As Long Dim OldFont As StdFont If ctl.Tag <> "" Then currWidth = CLng(ctl.Tag) End If

82

Page 83: Dicas de VB

Set OldFont = ctl.Parent.Font Set ctl.Parent.Font = ctl.Font Call DrawText(ctl.Parent.hDC, sNewItem, -1&, _ RC, DT_CALCRECT) Set ctl.Parent.Font = OldFont sysScrollWidth = GetSystemMetrics(SM_CXVSCROLL) newWidth = RC.Right + sysScrollWidth

If newWidth > currWidth Then Call SendMessage(ctl.hwnd, _ LB_SETHORIZONTALEXTENT, newWidth, _ ByVal 0&) ctl.Tag = newWidth End If ctl.AddItem sNewItem If Not IsMissing(dwNewItemData) Then If IsNumeric(dwNewItemData) Then ctl.ItemData(ctl.newIndex) = dwNewItemData End If End If AdicionaItem = ctl.newIndexEnd Function

'No form:Private Sub Form_Load() 'Detalhe, NÃO use o List1.AddItem!!! 'Veja como adiciona algumas linhas... Call AdicionaItem(List1, "Coloque o texto que será adicionado aqui") Call AdicionaItem(List1, "Não se preocupe se o texto for muito grande") Call AdicionaItem(List1, "Ele será exibido, seja como for!!!")End Sub

Uma dica legal é usar a propriedade TopIndex. Veja o exemplo:

Dim NovoIndex As Long NovoIndex = AdicionaItem(List1, "Texto") List1.TopIndex = NovoIndex

O resultado isso é que ele irá posicionar a barra de rolagem vertical da ListBox para que este item recem-adicionado possa ficar visível..

Desmarcar todos os itens de uma lista

Uma forma rápida de retirar qualquer seleção de uma listbox é:

list1.selected (-1) = False

Isto não funciona em VB4.

Movendo itens em uma ListBox

Para, através do mouse, mover a localização de um item numa ListBox, use o código abaixo.

'declarations:

83

Page 84: Dicas de VB

Dim Tmp_Text As StringDim Old_index As IntegerDim New_index As Integer

'mouse events:Sub List1_MouseDown (Button As Integer, Shift As _ Integer, X As Single, Y As Single) Old_index = List1.ListIndex Tmp_text = List1.textEnd Sub

Sub List1_MouseUp (Button As Integer, Shift As _ Integer, X As Single, Y As Single) New_index = List1.ListIndex If Old_index <> New_index Then List1.RemoveItem Old_Index List1.AddItem TmpText, NewIndex End IfEnd Sub

Multiplas Colunas em um ListBox'Num módulo:Private Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ lParam As Any) As Long

Private Const LB_SETTABSTOPS = &H192

Public Sub ListColumns(lListHandle As Long) Dim iNumColumns As Long 'Coloque o nº de colunas que o ListBox 'terá -1 no array a seguir: Dim iListTabs(1) As Long Dim Ret As Long 'O ListBox terá 2 colunas iNumColumns = 2 'A 1º coluna terá 24 caracteres e a 2º 48 '24 caracteres * 4 = 96 iListTabs(0) = 96 ' 96/4 = 24 caracteres '48 caracteres * 4 = 192 iListTabs(1) = 192 ' 192/4 = 48 caracteres Ret = SendMessage(lListHandle, _ LB_SETTABSTOPS, iNumColumns, iListTabs(0))End Sub

'No Form_Load:Private Sub Form_Load() 'lListHandle é o handle da ListBox Call ListColumns(lstLista.hwnd)End Sub

P/ adicionar os ítens faça da seguinte maneira:Lista.AddItem "Coluna 1" & vbTab & "Coluna 2"Por exemplo (seguindo o nome da ListBox passado p/ a função no Form_Load):

84

Page 85: Dicas de VB

lstLista.AddItem "Coluna 1 data1" & vbTab & _ "Coluna 02 data1"lstLista.AddItem "Coluna 01 data2" & vbTab & _ "Coluna 02 data2"lstLista.AddItem "Coluna 001 data3" & vbTab & _ "Coluna 02 data3"lstLista.AddItem "Coluna 0001 data4" & vbTab & _ "Coluna 02 data4"

85

Page 86: Dicas de VB

ListView

Ordenando Colunas da ListView

Dê ao seu controle ListView (32 bits) a funcionalidade de ordenação do Windows 95 Explorer. Este código ordena a lista por qualquer coluna. Se a lista já estiver ordenada por esta coluna, a ordem será invertida.

Private Sub ListView1_ColumnClick (ByBal _ ColumnHeader As ColumnHeader) Whith ListView1 If (ColumnHeader.Index -1) = .SortKey Then .SortOrder = (.SortOrder + 1) Mod 2 Else .Sorted = False .SortOrder = 0 .SortKey = ColumnHeader - 1 .Sorted = True End If End WithEnd Sub

86

Page 87: Dicas de VB

Masked Edit Box

Limpar o controle Masked Edit Box

O controle MS MaskedEditBox apenas aceita entrada de dados dentro da máscara formatada (mask). Isto impede o programador de limpar a text do controle diretamente (masked1.text = ""), pois o caracter espaço (ou nulo) pode não se encaixar no formato da máscara. Por exemplo, algumas possuem o formato # (aceitam somente números). Logo, o "" não seria aceito. Este problema é resolvido por este código:

Removendo a máscara é possível limpar o texto. Depois, basta devolver a máscara original ao controle. Uso isto no evento Data1_ValidationError quando adiciono um novo registro.

vTemp = MaskEd1.MaskMaskEd1.Mask = ""MaskEd1.Text = ""MaskEd.Mask = vTemp

87

Page 88: Dicas de VB

Menús

Colocando bitmaps em menus

Com esta dica você poderá dar um incremento visual em seus programas, incluindo bitmaps nos ítens de menu.

Coloque o código a seguir em um módulo:Declare Function GetMenu Lib "user32" (ByVal _ hWnd As Long) As LongDeclare Function GetSubMenu Lib "user32" (ByVal _ hMenu As Long, ByVal nPos As Long) As LongDeclare Function GetMenuItemID Lib "user32" _ (ByVal hMenu As Long, ByVal nPos As _ Long) As LongDeclare Function SetMenuItemBitmaps Lib "user32" _ (ByVal hMenu As Long, ByVal nPosition _ As Long, ByVal wFlags As Long, ByVal _ hBitmapUnchecked As Long, ByVal _ hBitmapChecked As Long) As Long

Public Const MF_BITMAP As Long = &H4&

Type MENUITEMINFO cbSize As Long fMask As Long fType As Long fState As Long wID As Long hSubMenu As Long hbmpChecked As Long hbmpUnchecked As Long dwItemData As Long dwTypeData As String cch As LongEnd Type

Declare Function GetMenuItemCount Lib "user32" _ (ByVal hMenu As Long) As LongDeclare Function GetMenuItemInfo Lib "user32" _ Alias "GetMenuItemInfoA" (ByVal hMenu As _ Long, ByVal un As Long, ByVal b As Boolean, _ lpMenuItemInfo As MENUITEMINFO) As Boolean

Public Const MIIM_ID As Long = &H2Public Const MIIM_TYPE As Long = &H10Public Const MFT_STRING As Long = &H0&

Agora crie um formulário, coloque nele uma picture box (autosize=true) com um bitmap de tamanho máximo 13x13 e adicione o seguinte código em um botão:

Private Sub Command1_Click() 'Recupera o handle do menu formulário hMenu& = GetMenu(Form1.hwnd)

'Recupera o handle do 1º menu hSubMenu& = GetSubMenu(hMenu&, 0)

88

Page 89: Dicas de VB

'Pega o menuId do 1º submenu hID& = GetMenuItemID(hSubMenu&, 0)

'Adiciona o bitmap ao submenu SetMenuItemBitmaps hMenu&, hID&, MF_BITMAP, _ Picture1.Picture, Picture1.Picture

'Você pode colocar dois bitmaps no menu 'Uma para o estado selecionado, e outro 'para o não selecionado.End Sub

Menus popup em caixa de Texto

Se você quiser mostrar um menu popup para um texto, um menu de sistema (default) será mostrado primeiro e o seu menu só aparecerá quando o menu default for fechado. Para contornar este problema:

Private Sub Text1_MouseDown(Button As Integer, Shift _ As Integer, X As Single, Y as Single) If Button = 2 Then Text1.Enabled = False PopupMenu myMenu Text1.Enabled = True End IfEnd Sub

89

Page 90: Dicas de VB

Microsoft Comm Control

Trabalhando com Microsoft Comm Control

Defina Settings, Porta e tudo mais do do MsComm1, e:

'P/ abra a porta:MSComm1.PortOpen = True

'P/ receber dados:While MSComm1.PortOpen = True If MSComm1.InBufferCount > 0 Then Text1= Text1& MSComm1.Input End If DoEventsWend

'P/ enviar dados:MSComm1.Output = Text2

'P/ fechar a conexão:MSComm1.PortOpen = False

90

Page 91: Dicas de VB

PictureBox

Carregando figuras em Pictures

Em qualquer objeto que tenha a propriedade PICTURE, é possível defini-la em tempo de desenho, informando o arquivo (BMP, ICO, DIB, WMF) que contém a imagem. Salvando o form com texto(FRM), as imagens são salvas como binárias em arquivos FRX.

'COPIAR DE OUTRO OBJETOMe.Picture = Picture1.Picture

'COPIAR A FIGURA DA ÁREA DE TRANSFERENCIA (COLAR)Me.Picture =ClipBoard.GetData()

'ABRIR FIGURA DE UM ARQUIVOMe.Picture = LoadPicture("C:\Windows\Winlogo.bmp")

'LIMPANDO FIGURAMe.Picture = LoadPicture()

Dimensões de um bitmap

Você pode utilizar o controle PictureBox com a propriedade AutoSize=True. Carregue o bitmap no PictureBox, usando a função LoadPicture. O controle irá ajustar o seu tamanho automaticamente, para que o bitmap caiba nele. As propriedades Height e Width deste controle contém as dimensões do bitmap. Note que os valores destas propriedades estão em Twips.

Uma outra forma, é utilizar a API GetObject. Esta função retorna a estrutura do Bitmap em dois membros, bmWidth e bmHeight representando as dimensões do bitmap em pixels. Veja o exemplo abaixo:

Coloque o seguinte código em um módulo:

Type BITMAP '14 bytes bmType As Integer bmWidth As Integer bmHeight As Integer bmWidthBytes As Integer bmPlanes As String * 1 bmBitsPixel As String * 1 bmBits As Long End Type

Declare Function GetObjectAPI% Lib "GDI" Alias _ "GetObject"(ByVal hObject%, ByVal nCount%, _ lpObject As Any)

Coloque o seguinte código aonde você quer obter as dimensões do bitmap. (O Bitmap deve ser carregado em um PictureBox chamado Picture1):

Dim bmp As BITMAP, ret%ret = GetObjectAPI(picture1.Picture, Len(bmp), bmp)Print "Width = " & Str$(bmp.bmWidth) & ", Height = " & _Str$(bmp.bmHeight)

91

Page 92: Dicas de VB

Rolando textos em PictureBox'Num módulo:Public Function MostrarTexto() Static Count As Integer Static Texto As String

If Len(Texto) = 0 Then Count = 1 Texto = "Rolando texto numa Picture Box!" End If

Picture1.Cls Picture1.Print Mid$(Texto, Count); Texto; Count = Count + 1

If Count > Len(Texto) Then Count = 1 End IfEnd Function

'No Form:'Coloque uma PictureBox e um Timer com interval=1000.Private Sub Timer1_Timer() MostrarTextoEnd Sub

Salvando e Pintando em cima de figuras

A propriedade IMAGE permite pintar com os métodos (PRINT, PSET, LINE e CIRCLE) em tempo de execução. Para imcorporar uma imagem à picture, basta fazer:

Picture1.Picture = Picture1.image

Esta linha de comando atribui o resultado dos gráficos à imagem principal. No exemplo abaixo, serve para riscar um arquivo:

Dim X As IntegerDim Y As IntegerPicture1.Picture = LoarPicture("C:\Windows\Logo.ico")X = Picture1.ScaleWidthY = Picture1.ScaleHeightPicture1.Line (0, 0)-(X, Y), RGB(255, 0, 0)Picture1.Picture = Picture1.ImageSavePicture Picture1, "C:\Windows\Logo.bmp"

No exemplo acima, a picture somente converte o traço após receber a image.Detalhe: independente do formato da imagem contida em picture, a propriedade image contém sempre um bitmap. Assim, o truque acima é uma ótima forma de converter ICO e WMF em BMP.

Ícones e metafiles podem possuir um fundo transparente. Quando transformamos em bitmaps incorporam os pontos (e a cor) de fundo. Veja o exemplo:

92

Page 93: Dicas de VB

'*** CONVERTENDO ICO EM BMP ***

Picture1.Picture = LoadPicture("C:\Icons\Mylogo.ico")

'ATRIBUINDO COR DE FUNDOPicture1.BackColor = RGB(255, 255, 255)Picture1.Picture = Picture1.Image

'CONVERTENDO EM BMP SavePicture Picture1, "C:\Windows\Mylogo.bmp"

93

Page 94: Dicas de VB

RichTextBox

Imprimindo o Conteúdo de um RichTextBox

Para imprimir o conteúdo de um RichTextBox, basta você passar a ele o hDC da impressora. Veja:

'No evnto que você desejar:RichTextBox1.SelPrint Printer.hDC

Mas e para imprimir numa impressora selecionada num CommonDialog??? Também é simples. Veja o exemplo:

'No evnto que você desejar: 'Seleciona as Flags necessárias CommonDialog1.Flags = cdlPDReturnDC + _ cdlPDNoPageNums If RichTextBox1.SelLength = 0 Then CommonDialog1.Flags = cdlFontes.Flags + _ cdlPDAllPages Else CommonDialog1.Flags = cdlFontes.Flags + _ cdlPDSelection End If 'Abre o CommonDialog para seleção/configuração 'de impressoras CommonDialog1.ShowPrinter 'Manda imprimir o conteúdo do RichTextBox na 'impressora selecionada no CommonDialog RichTextBox1.SelPrint CommonDialog1.hDC

Localizando um Texto num RichTextBox

Isto é muito simples de ser feito. Veja o código a seguir:

'No declarations do Form:Public sFind As String

'No evento onde você deseja localizar um determinado'Texto no RichTextBox: sFind = InputBox("Localizar o que?", "Procura", sFind) If sFind = "" Then Exit Sub RichTextBox1.Find sFind

'Para localizar a próxima ocorrencia do mesmo texto: RichTextBox1.SelStart = RichTextBox1.SelStart + _ RichTextBox1.SelLength + 1 RichTextBox1.Find sFind, , Len(RichTextBox1)

Pronto. Se o texto digitado existir no RichTextBox, ele será selecionado.

Uso Geral do Controle RichTextBox'Para abrir um arquivo: CommonDialog1.ShowOpen RichTextBox1.LoadFile (CommonDialog1.FileName)

94

Page 95: Dicas de VB

'Para salvar um arquivo: CommonDialog1.ShowSave RichTextBox1.SaveFile (CommonDialog1.FileName)

'Para mudar a fonte usada (muda apenas p/ o pedaço'de texto selecionado, ou para todo o texto que vier'a ser digitado apartir daquele ponto): CommonDialog1.Flags = cdlCFBoth + cdlCFEffects CommonDialog1.ShowFont With RichTextBox1 .SelFontName = CommonDialog1.FontName .SelFontSize = CommonDialog1.FontSize .SelBold = CommonDialog1.FontBold .SelItalic = CommonDialog1.FontItalic .SelStrikeThru = CommonDialog1.FontStrikethru .SelUnderline = CommonDialog1.FontUnderline End With

95

Page 96: Dicas de VB

TextBox

Apenas Números num TexBox'Coloque num form um TextBox e um CommandButton.

'No Declarations ponha:Option ExplicitPrivate Declare Function GetWindowLong& Lib "user32" _ Alias "GetWindowLongA" (ByVal hwnd As Long, _ ByVal nIndex As Long)Private Declare Function SetWindowLong& Lib "user32" _ Alias "SetWindowLongA" (ByVal hwnd As Long, _ ByVal nIndex As Long, ByVal dwNewLong As Long)

Private Const ES_NUMBER As Long = &H2000&Private Const GWL_STYLE As Long = (-16)

'No Click do CommandButton ponha:Private Sub Command1_Click() Dim tmpValue& Dim fAlignment& Dim ret& fAlignment& = ES_NUMBER tmpValue& = GetWindowLong&(Text1.hwnd, GWL_STYLE) ret& = SetWindowLong&(Text1.hwnd, GWL_STYLE, tmpValue& Or fAlignment&) Text1.RefreshEnd Sub

Quando você executar perceberá que o TextBox permite que você digite QUALQUER coisa, mas quando você precionar o CommandButton ele SÓ receberá números. Ele não aceitará nem mesmo o ponto (.) e a virgula (,).

Bloqueando funções Copiar e Colar em caixas de texto

Bloqueando funções Copiar e Colar em caixas de texto as funções Copiar (CTRL+C) e Colar (CTRL+V) estão sempre disponíveis para TextBoxes, mas e se você não desejar que estas funções funcionem? Você deve supor que o evento KeyDown consegue detectar CTR+C e CTRL+V, mas não detecta. No evento KeyPress, estas teclas podem ser capturadas:

Sub Text1_KeyPress (KeyAscii As Integer) If KeyAscii = 3 Or KeyAscii = 22 Then KeyAscii = 0 'CTRL+C = 3 e CTRL+V = 22, valores não constantes na tabela ANSI, 'geram estas combinações. Recurso não documentadoEnd Sub

Forçando Caracteres Maiúsculos ou Minúsculos

Para facilitar a digitação de caracteres maiúsculos ou minúsculos, independente do pressionamento de Caps Lock ou do Shift, converta cada caracter no evento KeyPress.

Private Sub Controle_KeyPress (KeyAscII as Integer) 'Converter p/ maiúsculos KeyAscII = Asc(UCase(Chr(KeyAscII)))

96

Page 97: Dicas de VB

'Converter p/ maiúsculos KeyAscII = Asc(LCase(Chr(KeyAscII)))End Sub

Para que esta rotina funcione para todos os campos do form, altere a propriedade KeyPreview do mesmo para True e coloque o código no evento Form_KeyPress.

O Caracter ENTER

Ele nunca aparece, mas existe. No Word é representado por um , nas caixas de texto do VB aparece um y (caracter não imprimível). Mas como aceitar e gerar este caracter?

1) No evento KeyPress, o caracter digitado (parâmetro KeyAscii) vale 10 ou 13 (os dois valores do ENTER na tabela de caracteres ANSI).

2) Em quaisquer consistências (como TextBox_Change ou análise de variáveis string) a função Asc retornará 10 ou 13.

Texto = Left(Texto, (Len(Texto) - 1)) If Asc(texto) = 10 or Asc(texto) = 13 then msgbox "Foi digitado um ENTER"

3) Numa textbox, é preciso gerar (via função chr) o caracter 10 mais o caracter 13.

text1.Text = "linha 1" text1.Text = text1.Text & Chr$(13) & Chr$(10) & "linha 2" text1.Text = text1.Text & Chr$(13) & Chr$(10) text1.Text = text1.Text & Chr$(13) & Chr$(10) & "linha 4"

4) Numa MsgBox, basta gerar o caracter 13.

Dim vmsg As String vmsg = "linha 1" vmsg = vmsg & Chr$(13) & "linha 2" vmsg = vmsg & Chr$(13) vmsg = vmsg & Chr$(13) & "linha 4" MsgBox vmsg, 0, "texto 2

Procurando Strings em um TextBox'No Declarations do Form:Private iLast As IntegerPrivate iFirst As IntegerPrivate sFind As StringPrivate Sub Text1_GotFocus() 'Valor Default p/ as variaveis iLast = 1 iFirst = 1End Sub

Private Sub Text1_KeyUp(KeyCode As Integer, _ Shift As Integer) Dim sMensagem As String, sTitulo As String

97

Page 98: Dicas de VB

Dim sDefault As String, bCtrlDown As Boolean Dim bProcura As Boolean, iNum As Integer Dim iPos As Integer, iPos_Fim As Integer

bCtrlDown = (Shift And vbCtrlMask) > 0 bProcura = False If KeyCode = vbKeyF And bCtrlDown Then 'A Tecla Ctrl+F foi pressionada

sMensagem = "Entre com o Texto a ser procurado!" sTitulo = "Procura" sDefault = "" sFind = InputBox(Mensagem, Titulo, Default) If sFind = "" Then Exit Sub

'Marca como a tecla F3 tivesse sido pressionada. KeyCode = 114 'Forca a passagem pela Busca End If

'As rotinas abaixo verificam se a tecla apertada é 'F3. A primeira coisa a ser feita é verificar se 'realmente existe em algum ponto do TextBox a string 'informada no InputBox. 'Existindo a string, entao é verificado se a busca 'será feita "para baixo" (F3) ou "para cima" (Shift+F3) If KeyCode = 114 Then If InStr(Text1.Text, sFind) = 0 Then MsgBox "Texto não encontrado!", vbInformation Exit Sub End If If Shift = 1 Then If iFirst = 0 Or InStr(Mid(Text1.Text, 1, _ iFirst), sFind) = 0 Then iFirst = Len(Text1.Text) End If For iNum = (iFirst - 1) To 1 Step -1 If Mid(Text1.Text, i%, _ Len(Find_String)) = Find_String Then iPos = iNum Exit For End If DoEvents Next For iNum = (iFirst - 1) To 1 Step -1 If Mid(Text1.Text, iNum, _ Len(sFind)) = sFind Then iPos_Fim = Len(sFind) + iNum Exit For End If DoEvents Next iLast = iPos_Fim iFirst = iPos Text1.SelStart = iPos - 1 Text1.SelLength = iPos_Fim - iPos Else iPos = InStr(iLast, Text1.Text, sFind) iFirst = iPos If iPos = 0 Then iLast = 1 iPos = InStr(iLast, Text1.Text, sFind)

98

Page 99: Dicas de VB

End If iPos_Fim = Len(sFind) + iPos iLast_Pos = iPos_Fim Text1.SelStart = iPos - 1 Text1.SelLength = iPos_Fim - Pos End If End IfEnd Sub

Selecionando Texto do TextBox ao Receber Foco'Basta colocar no evento GotFocus do TextBox,'por exemplo Text1, a seguinte rotina:Private Sub Text1_GotFocus() Text1.SelStart = 0 Text1.SelLength = Len(Text1.Text) End Sub

Rolar um TextBox linha a linhaPublic Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _ lParam As Any) As Long

SendMessage(SuaText.hWnd, EM_LINESCROLL, 0, 5&)

' Onde o IParam é o numero de linhas a ser rolado.

99

Page 100: Dicas de VB

ToolBar

Deixando a ToolBar (do VB5) no Estilo Flat'Num módulo:Private Declare Function FindWindowEx Lib "user32" _ Alias "FindWindowExA" (ByVal hWnd1 As Long, _ ByVal hWnd2 As Long, ByVal lpsz1 As String, _ ByVal lpsz2 As String) As LongPrivate Declare Function SendTBMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, ByVal wParam As Integer, _ ByVal lParam As Any) As Long

Private Const WM_USER As Long = &H400Private Const TBSTYLE_FLAT As Long = &H800Private Const TBSTYLE_TRANSPARENT As Long = &H8000Private Const TB_SETSTYLE As Long = (WM_USER + 56)Private Const TB_GETSTYLE As Long = (WM_USER + 57)

Public Sub MakeToolbarFlat(theToolbar As Control) Dim Res As Long Dim Style As Long Style = SendTBMessage(FindWindowEx(theToolbar.hwnd, _ 0&, "ToolbarWindow32", vbNullString), _ TB_GETSTYLE, 0&, 0&) Style = Style Or TBSTYLE_FLAT Or TBSTYLE_TRANSPARENT Res = SendTBMessage(FindWindowEx(theToolbar.hwnd, 0&, _ "ToolbarWindow32", vbNullString), TB_SETSTYLE, _ 0, Style) theToolbar.RefreshEnd Sub

'P/ chamar, no evento Form_Load (por exemplo) coloque:Private Sub Form_Load() Call MakeToolbarFlat(Toolbar1)End Sub

True DbGrid

Como ligar o True DbGrid a um Array

O True DbGrid é um controle completo. Você pode, por exemplo, querer ligá-lo a um array ao invés de um banco de dados (ou seja, os dados ficarão na memória). Para isso, siga os passos:

1 - Insira o True DbGrid em seu Form;2 - Altere a propriedade DataMode dele p/ 4 - Storage;3 - Em Project/References, adicione a biblioteca "APEX XArray Object", própria dele.

Então, use o código a seguir:

'No declarations do Form:Dim MeuArray As New XArray'Então, no evento Form_Load:

Private Sub Form_Load()

100

Page 101: Dicas de VB

'Redimensiona o array p/ ter 5 linhas (1 à 5) 'e 2 colunas (0 à 1): 'Array.ReDim 1, nº de linhas, 0, nº de colunas -1 MeuArray.ReDim 1, 5, 0, 1 'Inseri dados no array: MeuArray.Value(1, 0) = "Linha 1, Coluna 0" MeuArray.Value(1, 1) = "Linha 1, Coluna 1" MeuArray.Value(2, 0) = "Linha 2, Coluna 0" MeuArray.Value(2, 1) = "Linha 2, Coluna 1" MeuArray.Value(3, 0) = "Linha 3, Coluna 0" MeuArray.Value(3, 1) = "Linha 3, Coluna 1" MeuArray.Value(4, 0) = "Linha 4, Coluna 0" MeuArray.Value(4, 1) = "Linha 4, Coluna 1" MeuArray.Value(5, 0) = "Linha 5, Coluna 0" MeuArray.Value(5, 1) = "Linha 5, Coluna 1" 'Atribui o array ao True DBGrid: Set TDBGrid1.Array = MeuArrayEnd Sub

Deixando um True DBGrid Zebrado (com 2 Cores Intercaladas)'No evento Form_Load:Private Sub Form_Load() TDBGrid1.EvenRowStyle.BackColor = &HC0FFFF TDBGrid1.OddRowStyle.BackColor = &HFFFFFF TDBGrid1.AlternatingRowStyle = TrueEnd Sub

Parece ser simples de mais para ser verdade, não é? Pois é, mas funciona!!! Eu não tinha o True DBGrid em meu micro, então fiz o download só p/ testar e funcionou!!!

Detectar a Linha Selecionada num True DBGrid

Digamos que você esteja criando um programa, onde tenha um Form de pesquizas. Nesse Form teria um um TrueGrid, onde seriam exibidos dados de um cadastro de clientes, por exemplo.

Uma coisa bastante interessante seria permitir que o usuário desse um duplo clique em uma linha do True DBGrid para abrir um outro Form com detalhes daquele registro.

Isto é possível de ser feito, usando-se o evento DblClick do True DBGrid, bastando então criar uma sub-rotina que detecte a linha selecionada e abra o Form de detalhes. Se o programador quiser criar também um botão Detalhes, basta associar essa sub-rotina ao evento Click do botão.

Veja o exemplo:

Private Sub TDBGrid1_DblClick() Call VerDetalhesEnd SubPrivate Sub cmdDetalhes_Click() Call VerDetalhesEnd SubPrivate Sub VerDetalhes() 'Passa para o Form frmDetalhes o conteúdo da

101

Page 102: Dicas de VB

'coluna 0 (zero) da linha que estiver 'selecionada (Código do cliente, por exemplo...) frmDetalhes.Texto = TDBGrid1.Columns(0).Text 'Abre o Form frmDetalhes... frmDetalhes.Show vbModalEnd Sub

Navegação de Linha no True DBGrid

Digamos que você criou uma tela de pesquisa de um cadastro qualquer no seu programa (usando string de SQL e etc) e queira exibir isto num Grid, mas NÃO quer que o usuário possa selecionar mais de um registro (uma coluna inteira, por exemplo). Neste caso o ideal seria que, quando o usuário selecionasse um registro, o Grid selecionasse a linha toda do Grid...

Para fazer isto, usando o True DBGrid, coloque o seguinte código no seu Form:

Private Sub Form_Load() With TDBGrid1 .AllowUpdate = False .EditDropDown = False .InsertMode = False .AllowColSelect = False .MultiSelect = 0 .MarqueeStyle = 3 .HighlightRowStyle.BackColor = vbHighlight .HighlightRowStyle.ForeColor = vbHighlightText End WithEnd Sub

102

Page 103: Dicas de VB

DIRETÓRIOS

Capturar o caminho DOS de um arquivoPublic Declare Function GetShortPathName Lib _ "kernel32" Alias "GetShortPathNameA" _ (ByVal lpszLongPath As String, ByVal _ lpszShortPath As String, ByVal cchBuffer _ As Long) As Long

Public Const MAX_PATH As Long = 260

Dim sDirLong As StringDim sDirDOS As String

Call GetShortPathname(sDirLong, sDirDOS, MAX_PATH)

Criando múltiplos níveis de diretórios

Programas de instalação ou outras aplicações podem solicitar ao usuário para que informe onde deseja instalar arquivos ou efetuar alguma operação. Se o diretório não existir, será criado. Mas, o usuário poderá informar vários subníveis de diretórios inexistentes que devem ser criados. A rotina abaixo cria qualquer diretório, em todos os níveis. Basta informar o drive (como C:) e o caminho (como \MYAPP\MYDIR\SUBDIR) a ser criado (se não existir). Podem ser criados diretórios de nomes longos em VB4 32 bits, mas, em 16 bits (inclusive VB3), os nomes serão truncados para a convenção 8.3. Você poderá adicionar seu próprio código de manipulação de erros, conforme sua necessidade.Abaixo temos um exemplo simples da criação de vários níveis de diretórios:

Sub CreateLongDir(sDrive as String, sDir as String) Dim sBuild As String While Instr(2, sDir, "\") > 1 sBuild = sBuild & Left(sDir, Instr(2, sDir, "\") - 1) sDir = Mid$(sDir, InStr (2, sDir, "\")) If Dir$(sDrive & Sbuild, 16) = "" Then MkDir sDrive & sBuild End If WendEnd Sub

Sub Test() Call CreateLongDir ("C:\", "Test\MyApp\MyDir\Long " & _ "Directory Name\")End Sub

Como interceptar mudanças em um diretório

Claro que apos a ocorrer a mudanca essa funcao nao vai retornar qual o arquivo modificado. O ideal (tem outro jeito?) é manter uma lista do status dos arquivos na pasta (e se for o caso, subpastas) em uma coleção ou array.

Depois de receber uma notificacao criar uma nova lista e comparar com a antiga pra descobrir o que mudou.

103

Page 104: Dicas de VB

Have fun!

'Declaracoes:

Public Declare Function FindFirstChangeNotification Lib _ "kernel32" Alias "FindFirstChangeNotificationA" _ (ByVal lpPathName As String, ByVal bWatchSubtree _ As Long, ByVal dwNotifyFilter As Long) As LongPublic Declare Function FindCloseChangeNotification Lib _ "kernel32" (ByVal hChangeHandle As Long) As LongPublic Declare Function FindNextChangeNotification Lib _ "kernel32" (ByVal hChangeHandle As Long) As Long

Public Const FILE_NOTIFY_CHANGE_ATTRIBUTES As Long = &H4Public Const FILE_NOTIFY_CHANGE_DIR_NAME As Long = &H2Public Const FILE_NOTIFY_CHANGE_FILE_NAME As Long = &H1Public Const FILE_NOTIFY_CHANGE_SECURITY As Long = &H100Public Const FILE_NOTIFY_CHANGE_LAST_WRITE As Long = &H10Public Const FILE_NOTIFY_CHANGE_SIZE As Long = &H8Public Const WAIT_FAILED As Long = &HFFFFFFFFPublic Const WAIT_OBJECT_0 As Long = &H0Public Const WAIT_ABANDONED As Long = &H80Public Const WAIT_ABANDONED_0 As Long = &H80Public Const WAIT_TIMEOUT As Long = &H102Public Const WAIT_IO_COMPLETION As Long = &HC0

Public Declare Function WaitForSingleObject Lib _ "kernel32" (ByVal hHandle As Long, ByVal _ dwMilliseconds As Long) As Long

' Public Declare Function WaitForSingleObjectEx Lib _' "kernel32" (ByVal hHandle As Long, ByVal _' dwMilliseconds As Long, ByVal bAlertable As _' Long) As Long

Public Declare Function GetShortPathName Lib _ "kernel32" Alias "GetShortPathNameA" (ByVal _ lpszLongPath As String, ByVal lpszShortPath _ As String, ByVal cchBuffer As Long) As Long

Public Const MAX_PATH As Long = 260

'Em um Form: Option Explicit

Private hFind As LongPrivate bParar As Boolean

' Dois command button com captions "Assistir" e "Parar"' Uma caixa de texto txtDir para conter o Path a ser monitorado' Uma listbox List1 para mostrar o que esta acontecendo :-)

Private Sub Command1_Click() Dim hEvento As Long Dim sPathParaApi As String * MAX_PATH Dim sPathLongo As String

bParar = False

'

104

Page 105: Dicas de VB

' Nao sei se a funcao FindFirstChangeNotification aceita ' diretórios longos entao estou convertendo antes de mandar ' sPathParaApi = String(MAX_PATH, Chr(0)) sPathLongo = txtDir.Text

If GetShortPathName(sPathLongo,sPathParaApi,MAX_PATH) Then If hFind <> 0 Then Call FindCloseChangeNotification(hFind) hFind = 0 End If ' Atenção nisso ' FindFirstChangeNotification(Path, _ ' Deseja monitorar os subdiretorios?, _ ' Tipo de monitoracao) ' ' Tipos possiveis ' FILE_NOTIFY_CHANGE_ATTRIBUTES - Notifica se houve ' mudança nos atributos ' FILE_NOTIFY_CHANGE_DIR_NAME - Notifica se houve ' mudança no nome dos ' diretorios ' FILE_NOTIFY_CHANGE_FILE_NAME - Mudança no nome dos arqs, ' criação ou exclusao ' FILE_NOTIFY_CHANGE_SECURITY - Mudança de permissão ' FILE_NOTIFY_CHANGE_LAST_WRITE - Mudança na data de ultima ' gravação ' FILE_NOTIFY_CHANGE_SIZE - Mudança de tamanho ' ' Combinacoes são possivel com OR

hFind = FindFirstChangeNotification(sPathParaApi, False, _ FILE_NOTIFY_CHANGE_FILE_NAME)

If hFind = 0 Then MsgBox "Ops... Nao foi possivel inicializar", vbInformation, _ "Erro" End If

Do ' Estou usando TimeOut pra dar tempo do usuario clicar ' em PARAR e poder sair desse Loop ' mas não é obrigatório.... ' PS.: Lembre se q WaitForSingleObject irá travar o ' thread até acontecer alguma coisa :-)

hEvento = WaitForSingleObject(hFind, 200) Select Case hEvento Case WAIT_FAILED List1.AddItem "WAIT_FAILED" Call FindCloseChangeNotification(hFind) hFind = 0 Exit Do Case WAIT_ABANDONED List1.AddItem "WAIT_ABANDONED" Call FindCloseChangeNotification(hFind) hFind = 0 Exit Do Case WAIT_ABANDONED_0 List1.AddItem "WAIT_ABANDONED_0" Call FindCloseChangeNotification(hFind)

105

Page 106: Dicas de VB

hFind = 0 Exit Do Case WAIT_OBJECT_0 List1.AddItem "WAIT_OBJECT_0" ' ' Essa é a notificacao que algo aconteceu.... ' ' Executa ações ' ' blah blah blah.... ' Case WAIT_IO_COMPLETION List1.AddItem "WAIT_IO_COMPLETION" Call FindCloseChangeNotification(hFind) hFind = 0 Exit Do Case WAIT_TIMEOUT DoEvents If bParar Then List1.AddItem "Stopped" Call FindCloseChangeNotification(hFind) hFind = 0 Exit Do End If

If FindNextChangeNotification(hFind) = 0 Then List1.AddItem "Problemas..." Call FindCloseChangeNotification(hFind) hFind = 0 Exit Do End If End Select Loop Else MsgBox "Erro ao converter diretório.", vbInformation, _ "Erro" End IfEnd Sub

Private Sub Command2_Click() bParar = TrueEnd Sub

Private Sub Form_Load() ' Setei um default, mas isso vc pode mudar txtDir.Text = "C:\WINNT\Profiles\User\Desktop"End Sub

Diretório onde o Programa foi Instalado

Para saber qual o diretório onde está o executalvel (arquivo *.EXE) de seu programa proceda da seguinte forma:

'No evendo que você quizer: Dim MeuDir as String MeuDir = App.Path If Right$(App.Path) = "\" Then MeuDir = App.Path & "\" End If

106

Page 107: Dicas de VB

MsgBox MeuDir

Então, se, por exemplo, seu progama tiver sido instalado no diretório "C:\Arquivos de Programas\Meu Programa" ele mostrará na mensagem o seguinte texto:

"C:\Arquivos de Programas\Meu Programa\"

Esta última barra (\) é necessária no caso de você querer concatenar (somar) à essa variável o nome de um banco de dados. Veja:

MeuDir = MeuDir & "BancoDeDados.MDB"

Nesse caso a variável MeuDir passará a conter:

"C:\Arquivos de Programas\Meu Programa\BancoDeDados.MDB".

CASO o endereço não tenha essa última barra, o resultado seria "C:\Arquivos de Programas\Meu ProgramaBancoDeDados.MDB". Isto COM CERTEZA causaria um erro na hora de abrir o banco de dados. Mas, se é assim, POR QUE não fazer "SIMPLESMENTE" assim: MeuDir = App.Path & "\BancoDeDados.MDB"??? Porque o App.Path pode vir a já conter essa barra. Por isso eu fiz assim:

'Joga p/ MeuDir o conteúdo de App.Path MeuDir = App.Path 'Verifica a existencia da barra If Right$(App.Path) = "\" Then 'CASO App.Path NÃO contenha a última barra, 'soma-a à variável MeuDir MeuDir = App.Path & "\" End If

Função para Unir um Diretório a um Subdiretório'Coloque esta função num módulo ou mesmo no form:Public Function Junta_Dirs(ByVal sDir1 As String, _ ByVal sDir1 As String) If Right$(Dir1, 1) = "\" Then If Left$(Dir2, 1) = "\" Then Junta_Dirs = Left$(Dir1, Len(Dir1) - 1) & Dir2 Else Junta_Dirs = Dir1 & Dir2 End If Else If Left$(Dir2, 1) = "\" Then Junta_Dirs = Dir1 & Dir2 Else Junta_Dirs = Dir1 & "\" & Dir2 End If End If If Right$(Junta_Dirs, 1) <> "\" Then Junta_Dirs = Junta_Dirs & "\" End IfEnd Function

'P/ chamar:Dim Dir As String

107

Page 108: Dicas de VB

Dir = Junta_Dirs(App.Path,"\BMPs\")&"Desenho.BMP"'OU:Dir = Junta_Dirs(App.Path, "\BMPs")&"Desenho.BMP"'OU:Dir = Junta_Dirs(App.Path, "BMPs\")&"Desenho.BMP"'OU:Dir = Junta_Dirs(App.Path, "BMPs")&"Desenho.BMP"

'TODAS as anteriores irão funcionar. Só NÃO use assim:Dir = Junta_Dirs(App.Path, "BMPs")&"\Desenho.BMP"'Pois não irá funcionar.

Pegar o Diretório de Arquivos Temporários (Windows\Temp)'NUM MÓDULO:Private Const MAX_PATH As Long = 260Private Declare Function GetTempPath Lib "kernel32" _ Alias "GetTempPathA" (ByVal nBufferLenght _ As Long, ByVal lpBuffer As String) As Long

Public Function GetTempDir() As String Dim strFolder As String Dim lngResult As Long strFolder = String(MAX_PATH, 0) lngResult = GetTempPath(MAX_PATH, strFolder) If lngResult <> 0 Then If Right(Left(strFolder, lngResult), 1) = "\" Then GetTempDir = Left(strFolder, lngResult) Else GetTempDir = Left(strFolder, lngResult) & "\" End If Else GetTempDir = "" End IfEnd Function

'P/ CHAMAR:MsgBox "O Diretório System do Windows é: " & GetTempDir, _ vbOKOnly + 64, "Local do Diretório System do Windows"

Pegar o Diretório do System'NUM MÓDULO:Private Const MAX_PATH As Long = 260Private Declare Function GetSystemDirectory Lib _ "kernel32" Alias "GetSystemDirectoryA" _ (ByVal lpBuffer As String, ByVal nSize _ As Long) As Long

Public Function GetSysDir() As String Dim strFolder As String Dim lngResult As Long strFolder = String(MAX_PATH, 0) lngResult = GetSystemDirectory(strFolder, MAX_PATH) If lngResult <> 0 Then If Right(Left(strFolder, lngResult), 1) = "\" Then GetSysDir = Left(strFolder, lngResult) Else GetSysDir = Left(strFolder, lngResult) & "\"

108

Page 109: Dicas de VB

End If Else GetSysDir = "" End IfEnd Function

'P/ CHAMAR:MsgBox "O Diretório System do Windows é: " & GetSysDir, _ vbOKOnly + 64, "Local do Diretório System do Windows"

Pegar o Diretório do Windows'NUM MÓDULO:Private Const MAX_PATH As Long = 260Private Declare Function GetWindowsDirectory Lib _ "kernel32" Alias "GetWindowsDirectoryA" _ (ByVal lpBuffer As String, ByVal nSize As _ Long) As Long

Public Function GetWinDir() As String Dim strFolder As String Dim lngResult As Long strFolder = String(MAX_PATH, 0) lngResult = GetWindowsDirectory(strFolder, MAX_PATH) If lngResult <> 0 Then If Right(Left(strFolder, lngResult), 1) = "\" Then GetWinDir = Left(strFolder, lngResult) Else GetWinDir = Left(strFolder, lngResult) & "\" End If Else GetWinPath = "" End IfEnd Function

'P/ CHAMAR:MsgBox "O Diretório do Windows é: " & GetWinDir, _ vbOKOnly + 64, "Local do Diretório do Windows"

109

Page 110: Dicas de VB

110

Page 111: Dicas de VB

HARDWARE

CDROM

Abrir e fechar a gaveta do CDROMPrivate Declare Function mciSendString Lib "winmm.dll" _ Alias "mciSendStringA" (ByVal lpstrCommand As _ String, ByVal lpstrReturnString As String, _ ByVal uReturnLength As Long, ByVal hwndCallback _ As Long) As Long

'PARA ABRIRCall mciSendString("Set CDAudio Door Open Wait", 0&, _ 0&, 0&)

'PARA FECHARCall mciSendString("Set CDAudio Door Closed Wait", 0&, _ 0&, 0&)

Disquetes

Formatando um Disquete

Este exemplo chama a caixa de diálogo Formatar Disquete do Windows Explorer.

Coloque um botão num Form e coloque o seguinte código:

'Num módulo:Option Explicit

Private Declare Function SHFormatDrive Lib _ "shell32" (ByVal hwnd As Long, ByVal _ Drive As Long, ByVal fmtID As Long, _ ByVal options As Long) As LongPrivate Declare Function GetDriveType Lib _ "kernel32" Alias "GetDriveTypeA" _ (ByVal nDrive As String) As Long

Public Const DRIVE_CDROM = 5Public Const DRIVE_FIXED = 3Public Const DRIVE_RAMDISK = 6Public Const DRIVE_REMOTE = 4Public Const DRIVE_REMOVABLE = 2Public Const SHFMT_ID_DEFAULT = &HFFFFPublic Const SHFMT_OPT_FULL = 1Public Const SHFMT_OPT_SYSONLY = 2

Public Sub FormatFloppy(hWndOwner As _ Long, ByVal DriveLetter As String) Dim DriveNum As Long, DriveType As Long Dim ret As Long DriveLetter = Left(DriveLetter, 1) & ":\" DriveNum = Asc(UCase(DriveLetter)) - Asc("A") DriveType = GetDriveType(DriveLetter) If DriveType = DRIVE_REMOVABLE Then

111

Page 112: Dicas de VB

ret = SHFormatDrive(hWndOwner, _ DriveNum, SHFMT_ID_DEFAULT, _ SHFMT_OPT_FULL) Else MsgBox "O drive informado não é um " & _ "drive de discos removíveis", _ vbExclamation, "Formatar Disquete" End IfEnd Sub

'No evento click do botao:

Private Sub Command1_Click() FormatFloppy Me.hwnd, "A" 'Neste caso, estaria mandando formatar o drive A:.End Sub

Drive

Ler propriedades de drives, pastas e arquivos'Ação:'- Lê propriedades de drives, pastas e arquivos'- Modifica data e hora em arquivos

Private Declare Function GetDiskFreeSpace Lib "kernel32" _ Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName _ As String, lpSectorsPerCluster As Long, _ lpBytesPerSector As Long, lpNumberOfFreeClusters _ As Long, lpTotalNumberOfClusters As Long) As Long

Private Declare Function GetDriveType Lib "kernel32" Alias _ "GetDriveTypeA" (ByVal nDrive As String) As Long

Private Type FILETIME dwLowDateTime As Long dwHighDateTime As LongEnd Type

Private Type SYSTEMTIME wYear As Integer wMonth As Integer wDayOfWeek As Integer wDay As Integer wHour As Integer wMinute As Integer wSecond As Integer wMilliseconds As IntegerEnd Type

Private Const GENERIC_WRITE As Long = &H40000000Private Const OPEN_EXISTING As Long = 3Private Const FILE_SHARE_READ As Long = &H1Private Const FILE_SHARE_WRITE As Long = &H2

Private Declare Function SetFileTimeWrite Lib "kernel32" _ Alias "SetFileTime" (ByVal hFile As Long, ByVal _ MullP As Long, ByVal NullP2 As Long, lpLastWriteTime _ As FILETIME) As Long

112

Page 113: Dicas de VB

Private Declare Function SystemTimeToFileTime _ Lib "kernel32" (lpSystemTime As SYSTEMTIME, _ lpFileTime As FILETIME) As Long

Private Declare Function CreateFile Lib "kernel32" Alias _ "CreateFileA" (ByVal lpFileName As String, ByVal _ dwDesiredAccess As Long, ByVal dwShareMode As Long, _ ByVal lpSecurityAttributes As Long, ByVal _ dwCreationDisposition As Long, ByVal _ dwFlagsAndAttributes As Long, ByVal hTemplateFile _ As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal _ hObject As Long) As Long

Private Declare Function LocalFileTimeToFileTime Lib _ "kernel32" (lpLocalFileTime As FILETIME, lpFileTime _ As FILETIME) As Long

Private Const Tit As String = "Data & Hora"Dim arqAtual As StringDim blnDrvDir As Boolean

Private Sub cmdAjuda_Click() ' Mensagem de ajuda Dim m$ m$ = "Este programa lhe permite visualizar informações " m$ = m$ & "sobre drives, pastas e arquivos. Além disso, " m$ = m$ & "altera data e hora de um, vários ou todos os " m$ = m$ & "arquivos de um diretório. Os arquivos para " m$ = m$ & "modificação devem ser selecionados na caixa " m$ = m$ & "Arquivos. A data (dd/mm/aaaa) e a hora (hh:mm:ss) " m$ = m$ & "são indicadas, respectivamente, nos campos Nova " m$ = m$ & "Data e Nova Hora. Clique na etiqueta Atributos para " m$ = m$ & "mais informações sobre os tipos de arquivos. Os " m$ = m$ & "tamanhos de drives e arquivos são sempre expressos " m$ = m$ & "em bytes. O botão Atualizar renova as informações " m$ = m$ & "na lista de arquivos. Use-o, por exemplo, depois de " m$ = m$ & " trocar um disco no drive A." & vbCrLf & vbCrLf m$ = m$ & "Data & Hora © 1996-1999 Carlos Machado" MsgBox m$, vbOKOnly, TitEnd Sub

Private Sub cmdAlterar_Click() ' Dispara a alteração de data e hora On Error GoTo cmdAlterar_Click_Err Dim i As Integer Dim s As String Dim nomePath As String Dim Ano As Integer, Mes As Integer Dim Dia As Integer, Hora As Integer Dim Minuto As Integer, Segundo As Integer Dim DataeHora As Variant Dim sArquivo As String Dim x As Integer Dim sData As String Dim sHora As String Dim sReadOnly As String

sData = Text1

113

Page 114: Dicas de VB

Ano = Year(sData)

' Checa se é CD-ROM If Label2(1) = "CD-ROM " Then MsgBox "Arquivos em CD-ROM não podem ser alterados.",vbCritical,Tit Text1.SetFocus Exit Sub End If

' Checa validade da data digitada If Not IsDate(sData) Then MsgBox "Data inválida.", vbCritical, Tit Text1.SetFocus: Exit Sub Else If Ano < 1980 Then MsgBox "O sistema de arquivos não suporta " & _ "datas anteriores a 1980.", vbCritical , Tit Text1.SetFocus: Exit Sub End If End If

' Se data é válida, segue (a hora já é) s = "Tem certeza de que deseja alterar o(s) arquivo(s) indicado(s)?"

i = MsgBox(s, vbYesNo + vbQuestion + vbDefaultButton2, Tit) If i <> vbYes Then Exit Sub

' Liga a ampulheta: a operação pode demorar Screen.MousePointer = vbHourglass

Mes = Month(sData) Dia = Day(sData) Hora = Val(labHora) Minuto = Val(labMinuto) Segundo = Val(labSegundo) DataeHora = DateSerial(Ano, Mes, Dia) + TimeSerial(Hora,Minuto,Segundo)

' Ajusta Path nomePath = Dir1.Path If Len(nomePath) > 3 Then nomePath = nomePath & "\" End If

' Define arquivo, data e hora: File1 é Seleção múltipla (3) sReadOnly = "" For i = 0 To File1.ListCount - 1 If File1.Selected(i) Then sArquivo = nomePath & File1.List(i) If GetAttr(sArquivo) And vbReadOnly Then ' Lista de arquivos ready-only = não alterados sReadOnly = sReadOnly & File1.List(i) & vbCrLf End If x = AlterarDataHora(sArquivo, DataeHora) End If Next i

' Atualiza lista de arquivos cmdAtualizar_Click

' Desliga ampulheta Screen.MousePointer = vbDefault

114

Page 115: Dicas de VB

' Exibe mensagem ao usuário s = "Alterações realizadas com êxito." If sReadOnly <> "" Then s = s & vbCrLf & vbCrLf s = s & "Atenção: os arquivos abaixo são do tipo " s = s & vbCrLf & "somente leitura e não foram " s = s & "alterados:" & vbCrLf & vbCrLf s = s & sReadOnly End If MsgBox s, vbInformation, Tit

cmdAlterar_Click_Fim:Exit SubcmdAlterar_Click_Err: MsgBox Error$(Err) Resume cmdAlterar_Click_FimEnd Sub

Private Sub cmdAtualizar_Click() ' Força renovação da lista de arquivos On Error GoTo cmdAtualizar_Click_Err Dir1.Refresh File1.Refresh If File1.ListCount > 0 Then File1.SetFocus File1.Selected(0) = True End If

cmdAtualizar_Click_Fim:Exit SubcmdAtualizar_Click_Err: MsgBox Error$(Err) Resume cmdAtualizar_Click_FimEnd Sub

Private Sub cmdFechar_Click() EndEnd Sub

Private Sub Dir1_Change() ' Atualiza lista de arquivos On Error GoTo Dir1_Change_Err File1.Path = Dir1.Path blnDrvDir = True DefineArquivo

Dir1_Change_Fim:Exit SubDir1_Change_Err: MsgBox Error$(Err) Resume Dir1_Change_FimEnd Sub

Private Sub Drive1_Change() On Error GoTo DRChange_Err Err = False Dim m$

' Atualiza diretório Dir1.Path = Drive1.Drive

115

Page 116: Dicas de VB

InfoDisco blnDrvDir = True DefineArquivo

DRChange_Fim:Exit SubDRChange_Err: ' Erros e avisos If (Err = 71) Or (Err = 68) Then Beep '71: sem disco; 68: disco inexiste m$ = "Não há disco no drive " & UCase$(Drive1.Drive) MsgBox m$, vbCritical, Tit

' Volta ao drive anterior ao erro Drive1.Drive = Dir1.Path Else m$ = "Erro número" & Str$(Err) & ", não previsto no programa: " & Error$ MsgBox m$, vbCritical, Tit End If ResumeEnd Sub

Private Sub File1_Click() ' Define arquivo ativo ' quando o usuário clica DefineArquivoEnd Sub

Private Sub Form_Load() ' Força um drive/dir inicial Drive1.Drive = "c:\"

' blnDrvDir avisa que o chamado de DefineArquivo ' é interno. Desse modo, o arquivo 0 da lista ' é selecionado, se houver. Evita que quando o ' usuário clique num arquivo, a seleção do ' arquivo 0 também seja feita, desselecionando ' o arquivo apontado pelo usuário. blnDrvDir = True

' Mostra atributos do arquivo 0 (se houver). DefineArquivo

' Disco InfoDisco

' Defaults: data atual, 12:00:00 Text1 = Format(Date, "dd/mm/yyyy") VScroll1.Value = 12End Sub

Private Sub DefineArquivo() ' Checa se o diretório contém arquivos ' Seleciona arquivo 0 ' Exibe atributos Dim nomePath As String Dim TemArquivo As Boolean nomePath = Dir1.Path

If File1.ListCount > 0 Then 'Tem arquivo If blnDrvDir Then File1.Selected(0) = True

116

Page 117: Dicas de VB

blnDrvDir = False End If If Len(nomePath) > 3 Then Label2(8) = " " & nomePath & "\" & File1.Filename Else Label2(8) = " " & nomePath & File1.Filename End If arqAtual = Trim$(Label2(8)) TemArquivo = True Else 'Não tem arquivo Label2(8) = "" TemArquivo = False End If

Call InfoAtributos(TemArquivo)End Sub

Private Sub Label2_Click(Index As Integer) ' Exibe mensagem que esclarece conteúdo ' de alguns campos de informação Dim m$

If Index = 4 Then ' Ajuda/atributos m$ = "Atributos de arquivos:" & vbCrLf m$ = m$ & " A archive (arquivo)" & vbCrLf m$ = m$ & " H hidden (oculto)" & vbCrLf m$ = m$ & " R read-only (somente leitura)" & vbCrLf m$ = m$ & " S system (sistema)" MsgBox m$, vbOKOnly, Tit ElseIf Index = 2 Or Index = 3 Or Index = 5 Then m$ = "Valor em bytes." & vbCrLf MsgBox m$, vbOKOnly, Tit Else End IfEnd Sub

Private Sub Text1_GotFocus() ' Seleciona o texto Text1.SelStart = 0 Text1.SelLength = Len(Text1.Text)End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer) ' Só aceita números (48-56) ou / (47) If (KeyAscii < 47 Or KeyAscii > 56) And KeyAscii <> 8 Then KeyAscii = 0End Sub

Private Sub InfoAtributos(blnTemArquivo As Boolean) On Error GoTo InfoAt_Err Dim i As Integer

If blnTemArquivo Then ' Se tem arquivo, mostra ' Atributos Label2(4) = "" Label2(4) = LeAtributos()

' Tamanho, data, hora If blnTemArquivo Then Label2(5) = Format$(FileLen(arqAtual), "##,##0 ") Call LeDataHora End If

117

Page 118: Dicas de VB

Else ' Arquivo não existe, limpa labels For i = 4 To 7 Label2(i) = "" Next End If

InfoAt_Fim:Exit SubInfoAt_Err: MsgBox Error$(Err) Resume InfoAt_FimEnd Sub

Private Sub LeDataHora() ' Lê e exibe data e hora do arquivo On Error GoTo LeDataHora_Err Dim vDataHora As Variant Dim sDataHora As String Dim iLen As Integer Dim sData As String, sHora As String

' 1. Garante data no formato dd/mm/yyyy ' 2. Hora 00:00:00 retorna nulo; corrige vDataHora = FileDateTime(arqAtual) sDataHora = CStr(vDataHora) iLen = Len(sDataHora) Select Case iLen Case 8 'dd/mm/yy sData = Format$(sDataHora, "dd/mm/yyyy ") sHora = "00:00:00 " Case 10 'dd/mm/yyyy sData = sDataHora & " " sHora = "00:00:00 " Case 17 'dd/mm/yy hh:mm:ss sData = Format$(Left$(sDataHora, 8), "dd/mm/yyyy ") sHora = Right$(sDataHora, 8) & " " Case 19 'dd/mm/yyyy hh:mm:ss sData = Left$(sDataHora, 10) & " " sHora = Right$(sDataHora, 8) & " " Case Else sData = "" sHora = "" End Select

Label2(6) = sData Label2(7) = sHora

LeDataHora_Fim:Exit SubLeDataHora_Err: MsgBox Error$(Err) Resume LeDataHora_FimEnd Sub

Private Function LeAtributos() As String ' Fornece lista de atributos do arquivo On Error GoTo LeAttr_Err Dim atribs As String

' Limpa os atributos

118

Page 119: Dicas de VB

atribs = ""

' Lê e mostra atributos If GetAttr(arqAtual) And vbNormal Then atribs = atribs & "N" If GetAttr(arqAtual) And vbAlias Then atribs = atribs & "L" If GetAttr(arqAtual) And vbArchive Then atribs = atribs & "A" If GetAttr(arqAtual) And vbDirectory Then atribs = atribs & "D" If GetAttr(arqAtual) And vbHidden Then atribs = atribs & "H" If GetAttr(arqAtual) And vbReadOnly Then atribs = atribs & "R" If GetAttr(arqAtual) And vbSystem Then atribs = atribs & "S" If GetAttr(arqAtual) And vbVolume Then atribs = atribs & "V"

atribs = atribs & " " LeAtributos = atribs

LeAttr_Fim:Exit FunctionLeAttr_Err: LeAtributos = "" MsgBox Error$(Err) Resume LeAttr_FimEnd Function

Private Sub InfoDisco() ' Obtém e mostra informações sobre o disco On Error GoTo InfoDisco_Err

Label2(0) = "" Label2(0) = Dir$(Left$(arqAtual, 2), vbVolume) & " " LeTipoDeDrive TamanhoDoDrive

InfoDisco_Fim:Exit SubInfoDisco_Err: MsgBox Error$(Err) Resume InfoDisco_FimEnd Sub

Public Sub TamanhoDoDrive() ' Obtém tamanho do drive On Error GoTo TamDrive_Err Dim SectorsPerCluster&, BytesPerSector& Dim NumberOfFreeClusters&, TotalNumberOfClusters& Dim BytesFree&, BytesTotal&, PercentFree& Dim dl&, s$, spaceloc% Dim FreeBytes&, TotalBytes&

s$ = Drive1.Drive ' Se há um espaço, elimina volume label spaceloc = InStr(s$, " ") If spaceloc > 0 Then s$ = Left$(s$, spaceloc - 1) End If If Right$(s$, 1) <> "\" Then s$ = s$ & "\" dl& = GetDiskFreeSpace(s$, SectorsPerCluster, BytesPerSector, _ NumberOfFreeClusters, TotalNumberOfClusters) TotalBytes = TotalNumberOfClusters * SectorsPerCluster * BytesPerSector Label2(2) = Format(TotalBytes, "#,0 ") FreeBytes = NumberOfFreeClusters * SectorsPerCluster * BytesPerSector Label2(3) = Format(FreeBytes, "#,0 ")

119

Page 120: Dicas de VB

TamDrive_Fim:Exit SubTamDrive_Err: MsgBox Error$(Err) Resume TamDrive_FimEnd Sub

Private Sub LeTipoDeDrive() ' Obtém o tipo de drive On Error GoTo LeTipoDeDrive_Err

Const DRIVE_UNKNOWN = 0 Const DRIVE_NO_ROOT_DIR = 1 Const DRIVE_REMOVABLE = 2 Const DRIVE_FIXED = 3 Const DRIVE_REMOTE = 4 Const DRIVE_CDROM = 5 Const DRIVE_RAMDISK = 6

Dim tipo As String Dim nDrive As String Dim drvType As Long

' O drive para a função deve ser "c:\" nDrive = Drive1.Drive If Len(nDrive) > 2 Then nDrive = Left$(nDrive, 2) End If nDrive = nDrive & "\"

' Chama a função da API e traduz resultado drvType = GetDriveType(nDrive) Select Case drvType Case DRIVE_UNKNOWN: tipo = "Indeterminado " Case DRIVE_NO_ROOT_DIR: tipo = "Não reconhecido " Case DRIVE_REMOVABLE: tipo = "Removível " Case DRIVE_FIXED: tipo = "Fixo " Case DRIVE_REMOTE: tipo = "Rede " Case DRIVE_CDROM: tipo = "CD-ROM " Case DRIVE_RAMDISK: tipo = "RAM Disk " End Select Label2(1) = tipo

LeTipoDeDrive_Fim:Exit SubLeTipoDeDrive_Err: MsgBox Error$(Err) Resume LeTipoDeDrive_FimEnd Sub

Function AlterarDataHora(Filename As String, TimeStamp As Variant) As Integer On Error GoTo AlterarDataHora_Err Dim x As Long Dim Handle As Long Dim System_Time As SYSTEMTIME Dim File_Time As FILETIME Dim Local_Time As FILETIME

'Define a estrutura System_Time System_Time.wYear = Year(TimeStamp)

120

Page 121: Dicas de VB

System_Time.wMonth = Month(TimeStamp) System_Time.wDay = Day(TimeStamp) System_Time.wDayOfWeek = Weekday(TimeStamp) - 1 System_Time.wHour = Hour(TimeStamp) System_Time.wMinute = Minute(TimeStamp) System_Time.wSecond = Second(TimeStamp) System_Time.wMilliseconds = 0

' Converte system_time para file_time x = SystemTimeToFileTime(System_Time, Local_Time)

' Converte local_file_time para file_time (UTC) x = LocalFileTimeToFileTime(Local_Time, File_Time)

' Abre o arquivo para capturar o handle dele Handle = CreateFile(Filename, GENERIC_WRITE, FILE_SHARE_READ _ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, 0, 0)

' Modifica data e hora do arquivo x = SetFileTimeWrite(Handle, ByVal 0&, ByVal 0&, File_Time) CloseHandle Handle x = AlterarDataHora

AlterarDataHora_Fim:Exit FunctionAlterarDataHora_Err: MsgBox Error$(Err) Resume AlterarDataHora_FimEnd Function

Private Sub VScroll1_Change() labHora = Format$(VScroll1.Value, "0#")End Sub

Private Sub VScroll2_Change() labMinuto = Format$(VScroll2.Value, "0#")End Sub

Private Sub VScroll3_Change() labSegundo = Format$(VScroll3.Value, "0#")End Sub

Hard Disk

Saber o Número Serial do HD'Num módulo:

Private Declare Function GetVolumeInformation Lib _ "kernel32" Alias "GetVolumeInformationA" _ (ByVal lpRootPathName As String, ByVal _ lpVolumeNameBuffer As String, ByVal _ nVolumeNameSize As Long, _ lpVolumeSerialNumber As Long, _ lpMaximumComponentLength As Long, _ lpFileSystemFlags As Long, ByVal _ lpFileSystemNameBuffer As String, ByVal _ nFileSystemNameSize As Long) As Long

121

Page 122: Dicas de VB

Public Function DriveSerial(ByVal Drive As _ String) As Long 'Valor que retornará o serial do HD Dim RetVal As Long

Dim HDNameBuffer As String * 256 'Nome do HD Dim FSBuffer As String * 256 'FS do HD Dim a As Long 'auxiliar Dim b As Long 'auxiliar

Call GetVolumeInformation(Drive, HDNameBuffer, _ 256, RetVal, a, b, FSBuffer, 256)

DriveSerial = RetValEnd Function

'P/ usar (no evento que você quizer):Dim lNSerial As LonglNSerial = DriveSerial("C:\")MsgBox "O número seirial do HD é: " & lNSerial

Impressoras

Imprimindo Direto para a Impressora

Para imprimir direto para a impressora (em modo draft - ideal para emissão de Notas Fiscais e Boletos), voce deve abrir a impressora com o comando Open e utilizar o Print para realizar a impressão:

Open "Lpt1" For Output As #1

Usando o Print direto na impressora, voce poderá enviar os caracteres especias para imprimir condensado ou mudar o passo da impressora. Exemplo:

Print #1, Chr(27) & "0" ' Muda o passo p/ 8 LPPPrint #1, Chr(15) ' CondensadoPrint #1, Chr(27) & "E" ' NegritoPrint #1, "" ' Salta uma linha

Bom, existem outros comandos para cada impressora. Assim que eu conseguir algo, coloco aqui!!!

Selecionando a impressora que será usada na impressão'Num móduloPublic Function SelectPrinter(byVal Nome as String) As Boolean Dim X as Printer For each X in Printers If Ucase(Mid(X.DeviceName,1,8))=UCase(Mid(Nome,1,8)) then Set Printer=X SelectPrinter = True Exit For End If Next SelectPrinter = FalseEnd Function

122

Page 123: Dicas de VB

'P/ chamar:Dim RET As BooleanRET = SelectPrinter("Epson LX-300")If RET = True Then 'A impressora foi encontrada e selecionada.Else 'A impressora NÃO foi encontrada.End If

A função definirá esta impressora ("Epson LX-300", como no exemplo) como padrão para a impressão a ser realizada.

ATENÇÃO!!!! Para que essa função funcione, você necessitará ter o Service Pack 3 do Visual Basic instalado em sua máquina para corrigir um bug do VB.

Monitores

Obter a resolução de telaPrivate Sub Obtem() Dim xTwips%, yTwips%, xPixels#, YPixels# xTwips = Screen.TwipsPerPixelX yTwips = Screen.TwipsPerPixelY YPixels = Screen.Height / yTwips xPixels = Screen.Width / xTwips Debug.print "A Resolução é: " & Str$(xPixels) + _ " por " + Str$(YPixels)End Sub

Resolução do Monitor

Há uma forma simples de se obter a resolução de um monitor de vídeo usando uma API.

Declare Function GetSystemMetrics Lib "User" _ (ByVal nIndex As Integer) As Integer'...

Sub Form_Resize() dim xRes As Integer dim yRes As Integer xRes = GetSystemMetrics(0) yRes = GetSystemMetrics(1) If xRes < 1024 and yRes < 768 Then 'adicione seu código conforme queira End IfEnd Sub

Mouse

Capturar a Posição do Mouse

Para saber se o mouse está sobre um objeto ou não, podemos usar de duas formas:

123

Page 124: Dicas de VB

USANDO AS APIs GetCursorPos E WindowFromPoint

'Use um Timer e proceda da seguinte forma:

'No DeclarationsPrivate Declare Function GetCursorPos Lib "user32" _ (lpPoint As POINTAPI) As LongPrivate Declare Function WindowFromPoint Lib _ "user32" (ByVal xPoint As Long, ByVal _ yPoint As Long) As Long

Private Type POINTAPI X As Long Y As LongEnd Type

Private Controle_MouseMove(...) Timer1.Enabled = True 'O mouse está sobre o controleEnd Sub

Private Sub Timer1_Timer() Dim P as POINT If GetCursorPos(P) Then If WindowFromPoint(P.X, P.Y) <> Controle.hWnd then Timer1.Enabled = False 'O mouse NÃO está mais sobre o controle End If End IfEnd Sub

USANDO AS APIs SetCapture E ReleaseCapture

Verificando se o cursor do mouse está ou não sobre o Form 'Coloque num form um CommandButton e dois Labels.

'No DeclarationsPrivate Declare Function SetCapture Lib "user32" _ Alias "SetCapture" (ByVal hwnd As Long) _ As LongPrivate Declare Function ReleaseCapture Lib _ "user32" Alias "ReleaseCapture" () As Long

Private Sub Form_Load() SetCapture Me.HwndEnd Sub

Private Sub Command1_Click() ReleaseCaptureEnd Sub

Private Sub Form_MouseMove(Button As Integer, Shift _ As Integer, X As Single, Y As Single) Label1.Caption = X Label2.Caption = YEnd Sub

124

Page 125: Dicas de VB

Quando você executar, perceberá que, mesmo que o mouse não esteja sobre o Form, os Labels serão atualizados com as posições X e Y do mouse quando você o mover.Quando você clicar no CommandButton ele irá parar de detectar o mouse quando ele estiver fora do Form (o ReleaseCapture "desliga" o SetCapture).

Verificando se o cursor do mouse está ou não sobre um controle'Coloque num form um CommandButton, dois Labels e'um PictureBox.

'No DeclarationsPrivate Declare Function SetCapture Lib "user32" _ Alias "SetCapture" (ByVal hwnd As Long) _ As LongPrivate Declare Function ReleaseCapture Lib _ "user32" Alias "ReleaseCapture" () As Long

Private Sub Form_Load() SetCapture Picture1.HwndEnd Sub

Private Sub Command1_Click() 'Para de detectar o mouse no form todo. ReleaseCaptureEnd Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift _ As Integer, X As Single, Y As Single) If X > -1 And X < Picture1.Width And Y > -1 And Y < _ Picture1.Height Then Picture1.BackColor = vbRed Else Picture1.BackColor = vbBlack EndIfEnd Sub

Quando você executar, perceberá que, quando o mouse estiver sobre o PictureBox ele ficará vermelho e quando não estiver ficará preto.Quando você clicar no CommandButton ele irá parar de detectar o mouse quando ele estiver fora do PictureBox (o ReleaseCapture "desliga" o SetCapture). Então, ele não ficará mais preto, pois o VB não detectará mais quando o mouse "sair" do PictureBox...

Como limitar a área de movimento do mouse

Digamos que, por um motivo qualquer, você precise "limitar" a área de movimentação do mouse. Para isso use a seguinte função:

'Num módulo:Private Declare Function ClipCursor Lib "user32" _ (lpRect As Any) As Long

Private Type RECT Left As Long Top As Long Right As Long Bottom As LongEnd Type

125

Page 126: Dicas de VB

Public Function LimitaArea(X1 As Integer, Y1 As _ Integer, X2 As Integer, _ Y2 As Integer) As Long Dim RC As RECT RC.Left = X1 RC.Top = Y1 RC.Right = X2 RC.Bottom = Y2 ClipCursor RCEnd Function

'No evento Form_Load, chame a função passando os'pontos aos quais o mouse ficará limitado:Private Sub Form_Load() LimitaArea 50,100, 300,200 'POR EXEMPLOEnd Sub

'No evento Form_Unload, volte ao normal da seguinte'forma:Private Sub Form_Unload(Cancel As Integer) 'Volta ao estado Normal LimitaMouse 0, 0, Screen.Width / Screen.TwipsPerPixelX, _ Screen.Height / Screen.TwipsPerPixelYEnd Sub

'ATENÇÃO!!! Estas cordenadas devem ser passadas em pixeis!!!

Desativamento do mouse1. Declare a API que oculta/exibe o mouse (no módulo): Declare Function ShowCursor Lib "user32" Alias _ "ShowCursor" (ByVal bShow as Long) as Long

2. Chame-a no form_load: ShowCursor False 'oculta o mouse

3. No form_unload, re-exiba o mouse: ShowCursor True

4. Crie uma rotina Form_Mouse e Form_KeyDown. Se houver movimento e teclas pressionadas, finalize o programa.

Unload Me 'descarrega o form e devolve o mouse End 'garante o fechamento do programa

Inverter os botões do mouse'No Declarations:Declare Function SwapMouseButton(ByVal bSwap as _ Long) As Long

'Para inverter os botões do mouse:SwapMouseButton(1)

'Para voltar ao normal:SwapMouseButton(0)

126

Page 127: Dicas de VB

Mudar a Posição do Mouse via Código (sem Move-lo)

Esse recurso é muito útil para posicionar o ponteiro sobre botões e outros objetos sem mover o mouse, usando a API SetCursorPos.

'No Declarations:Private Declare Function SetCursorPos Lib _ "user32" (ByVal X As Long, ByVal Y _ As Long) As Long

'P/ colocar o cursor do mouse em qualquer parte'do vídeo use o comando:SetCursorPos PosiçãoX, PosiçãoY'Onde PosiçãoX e PosiçãoY são valores inteiros'(Integer) e são as coordenadas da posição em'Pixel da tela p/ onde o mouse irá.

'Por exemplo:SetCursorPos 200, 250

'Use esta Sub para centralizar o ponteiro do'mouse sobre um objeto no Form:Sub Posiciona(Controle As Control) Dim SX As Integer, SY As Integer SX = Screen.TwipsPerPixelX SY = Screen.TwipsPerPixelY SetCursorPos Me.Left / SX + Controle.Left / _ SX + (Controle.Width / SX / 2), _ Me.Top / SY + Controle.Top / SY + _ (Controle.Height / SY / 2) + 20End Sub

Obs: A última linha da Sub é que faz com que o ponteiro do mouse se mova para a nova poisição da tela, conforme o resultado do calculo:Posição do Form no vídeo + Posição do controle no Form + largura do controle /2Veja que no final existe uma soma (+20) que foi feita para compensar a barra de título que não é contada no formulário.

'P/ testar, coloque dois CommandButton no Form e,'em seus respectivos eventos, coloque:Private Sub Command1_Click() Posiciona Command2 'Centraliza o ponteiro no Command2End Sub

Private Sub Command2_Click() Posiciona Command1 'Devolve o ponteiro no Command1End Sub

127

Page 128: Dicas de VB

Teclados

Acionar o CAPS LOCK via código

*** 1) Crie Uma Classe, Chame-a de Teclado, Copie o código abaixo e cole na respectiva janela de código:

Option ExplicitPrivate Declare Function GetKeyboardState Lib "user32" _ (pbKeyState As Any) As LongPrivate Declare Function SetKeyboardState Lib "user32" _ (lppbKeyState As Any) As Long

Privatr Const KeyCaps = 20Dim MatrizDoTeclado(128) As Integer

Public Property Get CapsLock() As Boolean GetKeyboardState MatrizDoTeclado(0) If MatrizDoTeclado(KeyCaps / 2) Then CapsLock = True Else CapsLock = False End IfEnd Property

Public Property Let CapsLock(ATiva As Boolean) GetKeyboardState MatrizDoTeclado(0)

'Em C, True representa 1 e nao -1 If ATiva Then MatrizDoTeclado(KeyCaps / 2) = 1 Else MatrizDoTeclado(KeyCaps / 2) = 0 End If SetKeyboardState MatrizDoTeclado(0)End Property

*** 2) Feito ? Agora experimente: a) . Tecle Ctrl+G para trazer a janela Depurar b) . Digite: Set X = New Teclado <Enter> X.CapsLock = True <Enter> '(A luz do Caps Lock Acende) X.CapsLock = False <Enter> '(A luz do Caps Lock Apaga)

128

Page 129: Dicas de VB

INTERNET

Acionar o navegador padrão em um URL específico>> Dica 1

'Na seção de declarações coloque:Private Declare Function ShellExecute Lib _ "shell32.dll" Alias "ShellExecuteA" _ (ByVal hwnd As Long, ByVal lpOperation _ As String, ByVal lpFile As String, _ ByVal lpParameters As String, ByVal _ lpDirectory As String, ByVal nShowCmd _ As Long) As Long

Private Const SW_SHOWNORMAL As Long = 1

'Coloque um botão em um form e adicione o código:

Private Sub Command1_Click() Dim i As Long i = ShellExecute (hwnd,"open", _ "http://www.silicio.com.br/index.html", _ "", "", SW_SHOWNORMAL)End Sub

>> Dica 2

'Clique em Project - References e selecione Microsoft internet Controls e então experimente o código a seguir:

Private Sub Command1_Click() On Error GoTo Err_IE Dim objIE4 As SHDocVw.InternetExplorer Set objIE4 = New SHDocVw.InternetExplorer With objIE4 .Navigate2 "www.silicio.com.br" .Visible = True End With Set objIE4 = NothingExit SubErr_IE: Set objIE4 = NothingEnd Sub

>> Dica 3

Ou então experimente este código (NÃO funca em Win NT):Shell "start.exe http://www.silicio.com.br", vbHide

Acionar uma conexão Dial-Up pelo VB

Use o código a seguir para chamar uma conexão DialUp previamente criada no seu computador.

129

Page 130: Dicas de VB

Primeiro crie a rotina ChamarDialUp e depois coloque num evento de sua preferência a chamada a esta rotina.

Private Sub ChamarDialUp(ByVal sConect As String) Dim X As Long X = Shell("C:\Windows\rundll32.exe rnaui.dll,RnaDial " & _ sConect, 1) AppActivate X SendKeys "{enter}" DoEventsEnd Sub

'No evento que você desejar: Call ChamarDialUp("Minha Conexão")

Substitua "Minha Conexão" pelo nome da conexão que você deseja ativar.

Detalhe: Esta conexão deve existir em seu computador.

Capturar o nome da conexao Dial-UpGetSettingString(HKEY_CURRENT_USER,"RemoteAccess", _ "Default",vbNullString)

Vai lhe retornar o nome da conexao default. Daívocê usa...

HKEY_CURRENT_USER, "RemoteAccess\Profile\" & _ <nome da Default>, ....

Criar um link para um e-mail

Coloque num Form um TextBox onde o usuário vai digitar o endereço de e-mail. Presumindo-se que este TextBox terá o nome de Text1, texte esse código:

>> Dica 1

'Na seção de declarações coloque:Private Declare Function ShellExecute Lib _ "shell32.dll" Alias "ShellExecuteA" _ (ByVal hwnd As Long, ByVal lpOperation _ As String, ByVal lpFile As String, _ ByVal lpParameters As String, ByVal _ lpDirectory As String, ByVal nShowCmd _ As Long) As Long

Private Const SW_SHOWNORMAL As Long = 1

'No evento que você desejar: Call ShellExecute(0&, vbNullString, "mailto:" & _ Text1.Text, vbNullString, vbNullString, _ SW_SHOWNORMAL)

>> Dica 2 (NÃO funciona no Win NT)Shell "start.exe mailto:" & Text1.text, vbHide

130

Page 131: Dicas de VB

Dar um Ping

Crie um .BAT, por exemplo, para o Ping, no diretório do seu pgm e ative-o com um simples:

Shell App.Path & "\Ping.Bat " & Nome_do_Arq_de_Destino

Lá no Ping.Bat, Escreva:@echo offPing >> %1

Após sua execução, poderás ter o resultado no respectivo arquivo TXT.

Desconectar da Internet Via Código no VB'Num módulo:Public Const RAS_MAXENTRYNAME As Integer = 256Public Const RAS_MAXDEVICETYPE As Integer = 16Public Const RAS_MAXDEVICENAME As Integer = 128Public Const RAS_RASCONNSIZE As Integer = 412Public Const ERROR_SUCCESS As Long = 0&

Public Type RasEntryName dwSize As Long szEntryName(RAS_MAXENTRYNAME) As ByteEnd Type

Public Type RasConn dwSize As Long hRasConn As Long szEntryName(RAS_MAXENTRYNAME) As Byte szDeviceType(RAS_MAXDEVICETYPE) As Byte szDeviceName(RAS_MAXDEVICENAME) As ByteEnd Type

Public Declare Function RasEnumConnections Lib _ "rasapi32.dll" Alias "RasEnumConnectionsA" _ (lpRasConn As Any, lpcb As Long, _ lpcConnections As Long) As Long

Public Declare Function RasHangUp Lib _ "rasapi32.dll" Alias "RasHangUpA" _ (ByVal hRasConn As Long) As Long

Public gstrISPName As StringPublic ReturnCode As Long

Public Sub HangUp() Dim i As Long Dim lpRasConn(255) As RasConn Dim lpcb As Long Dim lpcConnections As Long Dim hRasConn As Long lpRasConn(0).dwSize = RAS_RASCONNSIZE lpcb = RAS_MAXENTRYNAME * lpRasConn(0).dwSize lpcConnections = 0 ReturnCode = RasEnumConnections(lpRasConn(0), _ lpcb, lpcConnections) If ReturnCode = ERROR_SUCCESS Then For i = 0 To lpcConnections - 1

131

Page 132: Dicas de VB

If Trim(ByteToString(lpRasConn(i).szEntryName)) _ = Trim(gstrISPName) Then hRasConn = lpRasConn(i).hRasConn ReturnCode = RasHangUp(ByVal hRasConn) End If Next i End IfEnd Sub

Public Function ByteToString(bytString() As _ Byte) As String Dim i As Integer ByteToString = "" i = 0 While bytString(i) = 0& ByteToString = ByteToString & Chr(bytString(i)) i = i + 1 WendEnd Function

'P/ usar:Call HangUp

Discar com o modem via APIPublic Declare Function tapiRequestMakeCall _ Lib "TAPI32.DLL" (ByVal Dest As String, _ ByVal AppName As String, ByVal _ CalledParty As String, ByVal Comment _ As String) As Long

Public Sub PhoneCall(sNumber As String, sName As String) Dim lRetVal As Long lRetVal = tapiRequestMakeCall(sNumber, _ App.Title, sName, "") If lRetVal <> 0 Then 'Erro qualquer ou não conseguiu! End IfEnd Sub

Crie um controle com um textbox e uma imagem de um telefone ao lado. Quando o Text tem algo, se o usuário clicar na imagem a função é executada.

Enviar E-mail pelo VB via MAPI'Coloque este código no evento que você quizer:Dim objSession As ObjectDim objMessage As Object

Set objSession = CreateObject("MAPI.SESSION")Set objMessage = objSession.Inbox.Messages.Add

objSession.Logon "Your Profile Name", , _ False, FalseobjMessage.Subject = "Assunto do e-mail..."objMessage.Text = "Texto do e-mail..."

'Aqui você deve colocar o caminho COMPLETO'do arquivo que irá em anexo:objMessage.Attachments.Add "Anexo", , , _

132

Page 133: Dicas de VB

"C:\anexo.XLS"

'Se for mais de um destinatário, separe'os endereçod de e-mail por virgulas (,)'ou ponto e virgula (;).objMessage.Recipients.Add _ "Endereços de e-mail do(s) destinatário(s)"

objMessage.Recipients.ResolveobjMessage.Send

Exibir um arquivo direto da Internet/Intranet num TextBox

Digamos que você precise exibir num TextBox um arquivo .TXT que está num servidor da Internet. Parece coisa do "outro mundo", não é? Pois bem, com esta dica você vai ver que é até simples de se fazer isto.

Para realizar esta tarefa, coloque num Form dois TextBox, um CommandButton, o componente Microsoft Internet Transfer Control e escreva o código à seguir no evento Click do CommandButton:

'Text1 é o TextBox onde o arquivo texto será'exibido. Por tanto deverá ter a propriedade'MultiLine = True.'txtURL é o TextBox onde o usuário deverá'digitar o endereço do texto na Internet.Private Sub Command1_Click() Dim sTxt As String, bVet() As Byte Dim iNum As Integer

On Error GoTo Erro Command1.Enabled = False

'txtURL.Text deverá conter o endereço 'do arquivo texto na Internet. Ex.: 'http://www.site.com/texto.txt bVet() = Inet1.OpenURL(txtURL.Text, 1) sTxt = ""

For iNum = 0 To UBound(bVet) - 1 sTxt = sTxt + Chr(bVet(iNum)) Next

Text1.Text = sTxt Command1.Enabled = TrueExit SubErro: MsgBox "O documento requerido não foi " & _ "encontrado.", vbCriticalEnd Sub

Salvando uma Página HTML

Coloque num Form um Winsock (Winsock1), um CommandButton (cmdDownload), um TextBox (txtSource) e colole nele este código:

133

Page 134: Dicas de VB

Private Sub Winsock1.Connect() Dim cCommand as String Dim cPage as String cPage = "http://fybra/index.html" cCommand = "GET " & cPage & " HTTP/1.0" & _ vbCrLf cCommand = cCommand & "Accept: */*" & vbCrLf cCommand = cCommand & "Accept: text/html" & _ vbCrLf cCommand = cCommand & vbCrLf Winsock1.SendData cCommandEnd Sub

Private Sub Winsock1_DataArrival(ByVal _ bytesTotal As Long) Dim cWebData As String Winsock1.GetData cWebData, vbString txtSource.Text = txtSource.Text & webDataEnd Sub

Private Sub cmdDownload_Click() 'Winsock1.RemoteHost = "fybra/" Winsock1.RemotePort = 80 Winsock1.ConnectEnd Sub

Depois é só salvar o conteúdo de txtSource para um arquivo .HTML...

Transferência de arquivos via FTP'Crie o controle no seu forms e um botão de'comando com o seguinte:'***************************** Dim strURL As String Dim bData() As Byte Dim intFile As Integer strURL = "ftp://aaaaa:[email protected]" & _ "/home/user/mercur/usuario.txt" intFile = FreeFile() bData() = Inet1.OpenURL(strURL, icByteArray) Open "C:\usuario.txt" For Binary Access Write As #intFile Put #intFile, , bData() Close #intFile'*****************************

'Além disso, crie no inet1:

'(Esse procedimento faz com que o arquivo'seja copiado integralmente.)'*****************************Private Sub Inet1_StateChanged(ByVal State As Integer) On Error GoTo fim_anormal2 Select Case State Case icError, icDisconnected MsgBox "Erro na comunicação --> " & Err.Description GoTo Fim_a Case icResponseReceived ' 12 Dim vtData As Variant ' Data variable. Dim strData As String: strData = "" Dim bDone As Boolean: bDone = False vtData = Inet1.GetChunk(1024, icString)

134

Page 135: Dicas de VB

Do While Not bDone strData = Data & vtData vtData = Inet1.GetChunk(1024, icString) If Len(vtData) = 0 Then bDone = True End If Me.Text1 = Me.Text1 + 1 If Me.Text1 > 100 Then Me.Text1 = 1 End If ProgressBar1.Value = Me.Text1 Dim TempoDePausa, Início, Fim, TempoTotal TempoDePausa = 1 ' Define a duração. Início = Timer ' Define a hora inicial. Do While Timer < Início + TempoDePausa DoEvents ' Submete-se a outros processos. Loop Fim = Timer ' Define a hora final. TempoTotal = Fim - Início ' Calcula o tempo total. Loop End Select GoTo Fim_a fim_anormal2: Dim a a = MsgBox("Erro de copia! " & Err.Description, vbCritical, "Erro") Fim_a:End sub

Verificando se o Computador está Conectado à Internet'Num módulo:

Private Const ERROR_SUCCESS = 0&Private Const APINULL = 0&Private Const HKEY_LOCAL_MACHINE = &H80000002Private ReturnCode As Long

Private Declare Function RegCloseKey Lib _ "advapi32.dll" (ByVal hKey As Long) _ As LongPrivate Declare Function RegOpenKey Lib _ "advapi32.dll" Alias "RegOpenKeyA" _ (ByVal hKey As Long, ByVal _ lpSubKey As String, phkResult As _ Long) As LongPrivate Declare Function RegQueryValueEx _ Lib "advapi32.dll" Alias _ "RegQueryValueExA" (ByVal hKey As _ Long, ByVal lpValueName As String, _ ByVal lpReserved As Long, lpType _ As Long, lpData As Any, lpcbData _ As Long) As Long

Public Function EstaConectado() As Boolean Dim hKey As Long Dim lpSubKey As String Dim phkResult As Long Dim lpValueName As String Dim lpReserved As Long

135

Page 136: Dicas de VB

Dim lpType As Long Dim lpData As Long Dim lpcbData As Long ActiveConnection = False lpSubKey = "System\CurrentControlSet\" & _ "Services\RemoteAccess"

ReturnCode = RegOpenKey(HKEY_LOCAL_MACHINE, _ lpSubKey, phkResult)

If ReturnCode = ERROR_SUCCESS Then hKey = phkResult lpValueName = "Remote Connection" lpReserved = APINULL lpType = APINULL lpData = APINULL lpcbData = APINULL

ReturnCode = RegQueryValueEx(hKey, _ lpValueName, lpReserved, _ lpType, ByVal lpData, lpcbData)

lpcbData = Len(lpData)

ReturnCode = RegQueryValueEx(hKey, _ lpValueName, lpReserved, _ lpType, lpData, lpcbData)

If ReturnCode = ERROR_SUCCESS Then If lpData = 0 Then ActiveConnection = False Else ActiveConnection = True End If End If RegCloseKey (hKey) End IfEnd Function

'P/ chamar a função, no evento que você quizer: If EstaConectado = True Then 'Está conectado Else 'NÃO Está conectado End If

136

Page 137: Dicas de VB

MULTIMÍDIA

Criando um CD Player

Coloque um textBox e cinco botoes no form. Insira um Class module, mude seu nome para CDAudio e codifique:

Private Declare Function mciGetErrorString Lib _ "winmm.dll" Alias "mciGetErrorStringA" _ (ByVal dwError As Long, ByVal lpstrBuffer _ As String, ByVal uLength As Long) As LongPrivate Declare Function mciSendString Lib _ "winmm.dll" Alias "mciSendStringA" _ (ByVal lpstrCommand As String, ByVal _ lpstrReturnString As String, ByVal _ uReturnLength As Long, ByVal _ hwndCallback As Long) As Long

Function StartPlay() mciSendString "play cd", 0, 0, 0End Function

Function SetTrack(Track As String) mciSendString "seek cd to " & Str(Track), 0, _ 0, 0End Function

Function StopPlay() mciSendString "stop cd wait", 0, 0, 0End Function

Function PausePlay() mciSendString "pause cd", 0, 0, 0End Function

Function EjectCD() mciSendString "set cd door open", 0, 0, 0End Function

Function CloseCD() mciSendString "set cd door closed", 0, 0, 0End Function

Function UnloadAll() mciSendString "close all", 0, 0, 0End Function

Function SetCDPlayerReady() mciSendString "open cdaudio alias cd wait " & _ shareable", 0, 0, 0End Function

Function SetFormat_tmsf() mciSendString "set cd time format tmsf wait", _ 0, 0, 0End Function

Function SetFormat_milliseconds() mciSendString "set cd time format " & _

137

Page 138: Dicas de VB

milliseconds", 0, 0, 0End Function

Function CheckCD() As Integer Dim s As String * 30 mciSendString "status cd media present", s, _ Len(s), 0 CheckCD = CInt(s)End Function

Function GetNumTracks() As Integer Dim s As String * 30 mciSendString "status cd number of tracks " & _ wait", s, Len(s), 0 GetNumTracks = CInt(Mid$(s, 1, 2))End Function

Function GetCDLength() As String Dim s As String * 30 mciSendString "status cd length wait", s, _ Len(s), 0 GetCDLength = sEnd Function

Function GetTrackLength(TrackNum As Integer) As _ String Dim s As String * 30 mciSendString "status cd length track " & _ TrackNum, s, Len(s), 0 GetTrackLength = sEnd Function

Sub GetCDPosition(ByRef Track As Integer, ByRef _ Min As Integer, ByRef Sec As Integer) Dim s As String * 30 mciSendString "status cd position", s, Len(s), 0 Track = CInt(Mid$(s, 1, 2)) Min = CInt(Mid$(s, 4, 2)) Sec = CInt(Mid$(s, 7, 2))End Sub

Function CheckIfPlaying() As Integer CheckIfPlaying = 0 Dim s As String * 30 mciSendString "status cd mode", s, Len(s), 0 If Mid$(s, 1, 7) = "playing" Then CheckIfPlaying = 1 End IfEnd Function

Function SeekCDtoX(Track As Integer) StopPlay SetTrack Track StartPlayEnd Function

Function ReadyDevice() UnloadAll SetCDPlayerReady SetFormat_tmsfEnd Function

138

Page 139: Dicas de VB

Function FastForward(Spd As Integer) Dim s As String * 40, Ply As Integer SetFormat_milliseconds mciSendString "status cd position wait", s, _ Len(s), 0 Ply = CheckIfPlaying If Ply = 1 Then mciSendString "play cd from " & _ CStr(CLng(s) + Spd), 0, 0, 0 Else mciSendString "seek cd to " & _ CStr(CLng(s) + Spd), 0, 0, 0 End If SetFormat_tmsfEnd Function

Function ReWind(Spd As Integer) Dim s As String * 40, Ply As Integer SetFormat_milliseconds mciSendString "status cd position wait", s, _ Len(s), 0 Ply = CheckIfPlaying If Ply = 1 Then mciSendString "play cd from " & _ CStr(CLng(s) - Spd), 0, 0, 0 Else mciSendString "seek cd to " & _ CStr(CLng(s) - Spd), 0, 0, 0 End If SetFormat_tmsfEnd Function

'No form coloque:Dim Snd As CDAudio

Private Sub Command1_Click() Snd.SeekCDtoX Val(Text1)End Sub

Private Sub Command2_Click() Dim s As String s = Snd.GetCDLength MsgBox "Total de minutos do CD: " & s, , _ "CD len"End Sub

Private Sub Command3_Click() Snd.CloseCDEnd Sub

Private Sub Command4_Click() Snd.EjectCDEnd Sub

Private Sub Command5_Click() Snd.StopPlayEnd Sub

Private Sub Form_Load() Set Snd = New CDAudio

139

Page 140: Dicas de VB

Snd.ReadyDeviceEnd Sub

Private Sub Form_Unload(Cancel As Integer) Snd.StopPlay Snd.UnloadAll Set Snd = NothingEnd Sub

Criar tela de apresentação no CD-ROM

- Crie um programa VB SEM USAR NENHUMA OCX QUE NÃO FAÇA PARTE DO 'PACOTE' PADRÃO. Não inclua nenhum componente na palete, trabalhe com os que aparecem originalmente;- Compile o programa e crie o EXE;- Coloque o EXE no CD e, NO MESMO DIRETÓRIO, coloque o arquivo MSVBVM50.DLL, que se encontra no diretório \windows\system (ele é instalado junto ao VB).

AUTO-RUN Se quiser que o seu programa seja executado automaticamente quando a pessoa inserir o CD no drive (e o sistema estiver configurado para isso, é claro), é só criar, no diretório raiz do CD, um arquivo chamado AUTORUN.INF, com o conteúdo:

[Autorun]OPEN=PROGRAM.EXEICON=CDICON.ICO

Onde você deve substituir PROGRAM.EXE pelo nome do seu executável (com path completo, mas normalmente esse tipo de arquivo deve ser colocado na raiz do CD) e CDICON.ICO é opcional, e indica um arquivo ICO com o ícone que você deseja que apareça no lugar do ícone padrão para o CD-ROM.

Detectando se o Micro tem Placa de Som'Num módulo:Private Declare Function waveOutGetNumDevs Lib _ "winmm.dll" Alias "waveOutGetNumDevs" () _ As LongPublic Function HaveSoundCard() As Boolean Dim i As Integer i = waveOutGetNumDevs() If i > 0 Then HaveSoundCard = True Else HaveSoundCard = False End IfEnd Function

'P/ usar:If HaveSoundCard Then MsgBox "Seu micro tem placa de som!", _ vbInformation, "Sound Card Test" Else MsgBox "Seu micro NÃO tem placa de som!", _ vbInformation, "Sound Card Test"End If

140

Page 141: Dicas de VB

Gravando uma Trilha do CD para um Arquivo Wave

Esta função usa o multimedia control interface (MCI) para controlar o drive de CD.

'Num módulo:Private Declare Function mciSendString Lib _ "winmm.dll" Alias "mciSendStringA" _ (ByVal lpstrCommand As String, ByVal _ lpstrReturnString As String, ByVal _ uReturnLength As Long, ByVal _ hwndCallback As Long) As LongPublic Sub RecordWave(TrackNum As Integer, _ Filename As String) ' Tracknum: Trilha a ser gravada ' Filename: Arquivo Wave a ser gerado On Local Error Resume Next Dim i As Long, RS As String, cb As Long, t# RS = Space$(128) i = mciSendString("stop cdaudio", RS, 128, cb) i = mciSendString("close cdaudio", RS, 128, cb) Kill filename RS = Space$(128) i = mciSendString("status cdaudio position track " & TrackNum, RS, 128, cb) i = mciSendString("open cdaudio", RS, 128, cb) i = mciSendString("set cdaudio time format milliseconds", RS, 128, cb) i = mciSendString("play cdaudio", RS, 128, cb) i = mciSendString("open new type waveaudio alias capture", RS, 128, cb) i = mciSendString("record capture", RS, 128, cb) t# = Timer + 1: Do Until Timer > t#: DoEvents: Loop i = mciSendString("save capture " & filename, RS, 128, cb) i = mciSendString("stop cdaudio", RS, 128, cb) i = mciSendString("close cdaudio", RS, 128, cb)End Sub

O método é bastante simples. Veja o que ele faz:

1º - Para o CD (caso ele esteja tocando, claro);2º - Toca a trilha selecionada;3º - Grava um novo arquivo wave com a informação do CD (obs: isso tambem grava MIDI e sons do microfone, na verdade qualquer coisa que saia pelos alto falantes)4º - Salva o som Wave;5º - Para o CD novamente.

Rodando um Vídeo AVI

Esta dica demonstra como tocar um vídeo AVI sem usar o Multimedia (MCI) Control.

'Num módulo:

Public Declare Function mciSendString Lib _ "winmm.dll" Alias "mciSendStringA" _ (ByVal lpstrCommand As String, ByVal _ lpstrReturnString As String, ByVal _ uReturnLength As Long, ByVal _ hwndCallback As Long) As Long

141

Page 142: Dicas de VB

'Num Form, adicione dois botões e coloque este'código:

Dim returnstring As String, erg As LongPrivate Sub Command1_Click() 'Este código abre o vídeo AVI Dim FileName As String FileName As String returnstring = Space(127) 'Arquivo AVI a ser tocado. FileName = "C:\Videos\Sei Lá\Welcome1.avi" erg = mciSendString("open " & Chr$(34) & _ FileName & Chr$(34) & _ " type avivideo alias video", _ returnstring, 127, 0) erg = mciSendString("set video time format ms", _ returnstring, 127, 0) erg = mciSendString("play video from 0", _ returnstring, 127, 0)End Sub

Private Sub Command1_Click() 'Este código fecha o vídeo AVI erg = mciSendString("close video", _ returnstring, 127, 0)End Sub

Tocar Arquivos MIDI'Num módulo:Public Declare Function mciExecute Lib "winmm.dll" _ (ByVal lpstrCommand As String) As Long

Public Sub TocarMID(File As String, Optional Wait _ As Boolean) If File = "" Then Call mciExecute("close Musica") Else Call mciExecute("open " & File & " type " & _ "sequencer alias Musica") If Wait Then Call mciExecute("play Musica wait") Else Call mciExecute("play Musica") End If End IfEnd Sub

'P/ abrir a música MIDI (já tocando-o):TocarMID "C:\Musica.MID"

'P/ dar uma pausa:TocarMID "C:\Musica.MID", True

'P/ voltar a tocar a música MIDI:TocarMID "C:\Musica.MID", False

'P/ fechar a música:TocarMID ""

142

Page 143: Dicas de VB

Tocar Arquivos WAVEPublic Declare Function sndPlaySound Lib "winmm.dll" _ Alias "sndPlaySoundA" (ByVal lpszSoundName As _ String, ByVal uFlags As Long) As Long

Public Enum SndPlayFlags SND_SYNC = &H0 SND_ASYNC = &H1 SND_NODEFAULT = &H2 SND_MEMORY = &H4 SND_LOOP = &H8 SND_NOSTOP = &H10End Enum

Public Sub PlaySound(File As String, Optional Flags _ As SndPlayFlags) If File = "" Then Call sndPlaySound(0&, 0) Else Call sndPlaySound(File, Flags) End IfEnd Sub

'P/ tocar o som, utilize:PlaySound "C:\Som.WAV"'P/ parar o som, utilize:PlaySound ""

P.S.: Quando for tocar um som, você pode passar alguma opção no parâmetro Flags. As opções são:* SND_SYNC => Toca o WAVE sincronizado (default).* SND_ASYNC => Toca o WAVE sem sincronismo.* SND_NODEFAULT => Não usa o som padrão.* SND_MEMORY => Direciona o IpszSoundName para o lugar de um arquivo na memória.* SND_LOOP => Toca o WAVE em looping. Até q você mande-o parar.* SND_NOSTOP => Não para o som que estiver tocando.

143

Page 144: Dicas de VB

PROGRAMAÇÃO INTELIGENTE

Cuidado com Variáveis Tipo Variant!!!

Evite usar as variáveis do tipo Variant a todo custo, pois elas consomem MUITO mais memória. Para se ter uma idéia, enquanto uma variável String requisita 1 byte, uma Integer requisita 2bytes, uma Long requisita 4 bytes e uma Double ou Date requisita 8 bytes, uma Variant requisita, no mínimo, 16 bytes + 1 byte por caracter, ou seja, o dobro do maior valor requisitado dos outros tipos. Até mesmo um objeto de OLE requisita apenas 4bytes!

O uso de uma variável Variant sacrifica um pouco o desempenho do programa exatamente pela requisição mais acentuada da memória e pelo fato do consumo mínimo da estrutura (16 bytes para variants com números e 22 bytes mais o comprimento da string para variants com strings).

Seu uso quase que só é aprovado em funçoes onde você não tem como antecipar o tipo de variável que irá receber... Pode ver que várias declarações de APIs usão parâmetros Variant.

O uso de variants como variáveis globais ou estáticas deve ser evitado a todo custo e nem deve ser empregada em qualquer tipo de loop (o desperdício e a queda de desempenho seria multiplicado por cada passagem pela referência.)

O motivo disso tudo é que o tipo Variant tem que ter, internamente, todos os métodos e tratamentos dos outros tipos de dados. Veja que as conversões são feitas automaticamente.

Também tem o detalhe de este tipo de variável não faz validação de nenhum tipo. Por exemplo, se você colocar numa variável Variant uma data e concatenar (somar) uma string ela aceita sem dar NENHUM tipo de erro.

A única vantagem das variáveis tipo Variant é que elas pode conter valores especiais, como Null, Error e Empty.

Eliminando o If...End If Quando Possível'Ao invés de:If sDados = "S" then bVar = TrueElse bVar = FalseEnd If

'Use:Dim bVar As BooleanbVar = (sDados = "S")

Outra coisa que alguns programadores usam e é TOTALMENTE desnecessário são verificações como esta:

Dim bVar As Boolean'...'Comandos'...If bVar = True Then '...

144

Page 145: Dicas de VB

'Comandos '...Else '... 'Comandos '...End If

Eu digo que é desnecessário, pois você pode usar SIMPLESMENTE não colocando o " = True". Veja:

Dim bVar As Boolean'...'Comandos'...If bVar Then 'bVar é igual a True.Else 'bVar é igual a False.End If

Executar com Compilação Completa

Quando você executa um programa pela IDE do VB, clicando no botão "Start" da ToolBar do VB, precionando F5 ou clicando no menu "Run"/"Start", o compilador verifica seus erros de programação a medida que os comandos vão sendo executados. Com a Compilação Completa, se houver algum erro em qualquer parte de seu programa, ele será detectado.

Para facilitar, você pode criar na barra de ferramentas do VB um botão com a opção do menu "Run"/"Start With Full Compile". Ele ficará com uma imagem como a do Run, porém com 2 setas.

Você também pode simplesmente precionar Ctrl+F5, pois dá na mesma...

Faça amplo uso das constantes intrínsecas do VB

Quando for necessário, procure usar as constantes intrínsecas do VB, como vbNull, vbNullString, vbCrLf. Para MsgBoxes, por exemplo, temos vbInformation + vbYesNo, vbYes. E uma paulada de outras (verifique-as no Object Browser - F2).

Além de tornar seu código mais legível (até pra você), não estarás redundando a declaração do que já existe e está disponível.

Já fiz o teste (repitam por favor). Substituam todos os seus "" por vbNullString e outros penduricalhos repetitivos como Chr(10)+Chr(13) por vbCrLf, etc ... e comparem o tamanho final do EXE.

Ps: Declare também suas próprias constantes (num módulo .BAS)

Public Const vbDbName = "NomeDoDB.MDB" 'O path adiciona depoisPublic Const vbCPFMask = "###,###,###\-##"Public Const vbCGCMask = "##,###,###\/####\-##"Public Const vbNumViado = 24

145

Page 146: Dicas de VB

Public DataVazia As Date 'Só use para comparação

Instanciando Objetos Corretamente

Evite fazer declarações de objetos com "New", pois quando você faz isso o VB NÃO está criando uma referencia. Ele só irá instanciar (criar a referencia) quando você referencia-lo pela 1º vez (usar um método ou alterar uma propriedade deste objeto). O problema disto é que a cada vez que você referenciar este objeto, o VB irá verificar se ele já foi instanciado ou não. Quer dizer, gera uma lentidão neste processo...

Confuso? Veja:

Dim varObj As New Objeto'O VB não instanciou o objeto.

varObj.Propriedade = 7'Aqui o VB verificou se o objeto já estava instanciado. Como ele'notou que nao, ele instanciou

varObj.Metodo 100'Aqui o VB também verificou se o objeto ja estava instanciado.'Isto causa lentidão!

'E o pior:Set varObj = Nothing'Descarregou-o da memóriaIf varObj Is Nothing Then Msgbox "Objeto destruído!"End If

Ele NÃO vai mostrar a mensagem "Objeto destruído!", pois o objeto não será totalmente descarregado da memória!!!

Para evitar tudo isso, declare apenas como "Objeto".

'Forma correta (recomendada):Dim varObj As ObjetoSet varObj = New Objeto

Não esqueça de liberar sua memória após usar o objeto. P/ isso use Nothing:Set varObj = Nothing

Saber se o Objeto está Vazio

Não é possível comparar um objeto (como Form ou outro controle) com IsEmpty para saber se ele possui um valor ou não. Entretando, é possível usar uma estrutura condicional usando o "Is Nothing". Veja:

If Not frmMenu Is Nothing Then 'NÃO Está vazioElse 'ESTÁ vazioEnd If

146

Page 147: Dicas de VB

Usando a Immediate Window

Durante um BreakPoint de execução (Pausa) [CTRL+{Break}], use a Immediate Window para obter informações sobre suas variáveis e o ambiente do VB. P/ faze-la aparecer é só prescionar [CTRL+G].

Na janela, experimente:

? Nome_da_sua_variável (não esqueça do escopo)

? Seu_Recordset!Nome_do_Campo

? Err.description

Usando o Auto Completar

O recurso de Auto Completar [CTRL+{Espaço}] do VB é muito útil quando você quer digirar o MÍNIMO possível, ou se tem nomes longos de variáveis, por exemplo.

Experimente, com as seguintes variáveis...

Dim NomeDaVariavel As String, OutraVariavel As String

... digitar:

nomed + [CTRL+{Espaço}]

outr + [CTRL+{Espaço}]

Usando o DoEvents

Quando seu programa tiver a necessidade de realizar um processamento longo (utilizando loops como Do...Loop, For...Next,), seu programa (ou mesmo seu computador) poderá travar. Para evitar isto utilize SEMPRE a funçao DoEvents, que permite que o seu programa realize este processamento enquanto o usuário realiza outras tarefas. Além do que fica uma coisa deselegante o seu programa ficar travando a cada comando que o usuário manda executar.

'Utilize o DoEvents desta maneira:Do 'Entra no Loop DoEvents '<--- ... Outros comandos ...Loop

Outra utilidade do DoEvents é em uma tela de Splash, pois esta necessita ficar por cima de toda as outras janelas (e isto é conseguido com o uso da API SetWindowPos). O problema é que sem o DoEvents ela NÃO fica por cima das outras MESMO usando essa API.

147

Page 148: Dicas de VB

Usando o Object Browser

Tens dúvidas sobre que eventos/métodos/propriedades de determinado objeto já adicionado à seu projeto? Use-o. Basta prescionar [F2] que ele aparecerá.

Use o With para Atribuir Valores à Propriedades de Objetos

Digamos que você necessite mudar as propriedades de um objeto, um Label por exemplo. Então, veja:

'(01) Ao invéz de:Label1.AutoSize = TrueLabel1.Caption = "Blá, blá, blá..."Label1.Enabled = TrueLabel1.Visible = TrueLabel1.Refresh

'(02) Use:With Label1 .AutoSize = True .Caption = "Blá, blá, blá..." .Enabled = True .Visible = True .RefreshEnd With

Motivo: No exemplo 01, ele carrega na memória, uma instância do objeto para cada atribuição, no caso, cria 5 instâncias. Já na segunda, ele cria APENAS uma instância, ficando assim, mais rápido.

Verificando Valor da Propriedade de um Objeto Mais Rapdamente

Quando você cria um objeto (classe, ActiveX Control ou ActiveX DLL), você tem que criar duas funções para cada propriedade: uma usando "Property Get" e outra usando "Property Let" (ou "Property Set"). A função que usa "Property Get" é chamada quando você verifica o valor contido na propriedade e a função "Property Let" é chamada quando você atribui um novo valor a essa propriedade (a função "Property Set" é usada quando esta propriedade aceita um objeto - uma imagem, por exemplo - e não um valor).

Por este motivo, prefira acessar várias vezes uma variável do que uma propriedade.

'Então, ao invés de usar desta maneira:If txtOpção.Text = "Nada" Then ... Comandos ...ElseIf txtOpção.Text = "Tudo" And Var = "S" Then ... Comandos ...ElseIf txtOpção.Text = "Tudo" And Var = "N" Then ... Comandos ...End If

148

Page 149: Dicas de VB

'Use assim:Dim sTexto As StringsTexto = txtOpção.TextIf sTexto = "Nada" Then ... Comandos ...ElseIf sTexto = "Tudo" And Var = "S" Then ... Comandos ...ElseIf sTexto = "Tudo" And Var = "N" Then ... Comandos ...End If

149

Page 150: Dicas de VB

REDES

Buscar data e hora do servidor

Para chamar: Data = ServerTime("\\NomedaMaquina") ou Data = ServerTime("NomedaMaquina").

'Coloque isso em um módulo.

Private Declare Function NetRemoteTOD Lib _ "NETAPI32.DLL" (ByVal server As _ String, buffer As Any) As LongPrivate Declare Sub CopyMemory Lib "kernel32" _ Alias "RtlMoveMemory" (hpvDest As _ Any, hpvSource As Any, ByVal cbCopy _ As Long)Private Declare Function NetApiBufferFree Lib _ "NETAPI32.DLL" (buffer As Any) As Long

Private Type TIME_OF_DAY t_elapsedt As Long t_msecs As Long t_hours As Long t_mins As Long t_secs As Long t_hunds As Long t_timezone As Long t_tinterval As Long t_day As Long t_month As Long t_year As Long t_weekday As LongEnd Type

Public Function ServerTime(ByVal pServerName _ As String) As Variant Dim t As TIME_OF_DAY Dim tPtr As Long Dim Result As Long Dim szServer As String Dim ServDate As Date If Left(pServerName, 2) = "\\" Then szServer = StrConv(pServerName,vbUnicode) Else szServer = StrConv("\\" & pServerName, _ vbUnicode) End If Result = NetRemoteTOD(szServer, tPtr) If Result = 0 Then Call CopyMemory(t, ByVal tPtr, Len(t)) ServDate = DateSerial(70, 1, 1) + _ (t.t_elapsedt / 60 / 60 / 24) ServDate = ServDate - (t.t_timezone / 60 / 24) NetApiBufferFree (tPtr) ServerTime = ServDate Else 'erro End IfEnd Function

150

Page 151: Dicas de VB

Devolve o nome do micro na redePublic Declare Function GetComputerName Lib _ "kernel32" Alias "GetComputerNameA" _ (ByVal lpBuffer As String, nSize As _ Long) As Long

Public Function GetComputer() As String Dim Buffer As String Dim Size As Long Dim dl As Long Size = 199 Buffer = String$(200, 0) dl = GetComputerName(Buffer, Size) If dl <> 0 Then GetComputer = Left$(Buffer, Size) Else GetComputer = "" End IfEnd Function

'Vc chamada a função assim: Dim Var as String Var = GetComputer()

Identificando uma unidade de CD em Rede

A API de 32 bits é bem mais rica que a de 16 bits. Entretanto, a função GetDriveType mostra os Drives CDs em Rede, apenas como DRIVE_REMOTE (de rede). Isto é uma verdade, mas não completa. Combine a chamada a GetDriveType com uma chamada a GetVolumeInformation para determinar se o drive é, ao mesmo tempo, de rede e CD.

A chamada indica o sistema de arquivos: FAT, NTFS, HPFS ou CDFS (CD File System).

Declare Function GetVolumeInformation Lib "Kernel32" _ Alias "GetVolumeInformationA" (ByVal _ lPRootPathName as String ByVal lpVolumeNameBuffer _ As String ByVal nVolumeNameSize As Long ByVal _ lpVolumeSerialNumber As Long ByVal _ lpMaximumComponentLenght As Long ByVal _ lpFileSystemFlags As Long ByVal _ lpFileSystemNameSize As Long) As Long'...pstrRootPath = "E:\"pstrVolName = Space$(256)pstrSystemType = Space$(32)plngSysTypeSize = Clng(Len(pstr(SystemType))plnVolNameSize = Clng(Len(pstrVolName))plngRtn = GetVolumeInformation (pstrRoothPath, _ pstrVolName, plngVolNameSize, _ plngVolSerialNum, plngMaxFileNameLen, _ plngSysFlags, pstrSystemType, plngSysTypeSize)

151

Page 152: Dicas de VB

Mapeando uma Unidade de Rede'Num módulo:Public Declare Function WNetAddConnection Lib _ "mpr.dll" Alias "WNetAddConnectionA" _ (ByVal lpszNetPath As String, ByVal _ lpszPassword As String, ByVal _ lpszLocalName As String) As LongPublic Declare Function WNetGetConnection Lib _ "mpr.dll" Alias "WNetGetConnectionA" _ (ByVal lpszLocalName As String, ByVal _ lpszRemoteName As String, cbRemoteName _ As Long) As LongPublic Declare Function WNetCancelConnection _ Lib "mpr.dll" Alias _ "WNetCancelConnectionA" (ByVal lpszName As _ String, ByVal bForce As Long) As Long

'No evento desejado:Dim sCaminho As String, sUnidade as StringsCaminho = "\\Computador\Caminho"sUnidade = "I:"

'Realiza a conexãoWNetAddConnection sCaminho, _ "Se tiver senha, digite á aqui", _ sUnidade

'Consulta caminho de uma determinada conexão,'neste caso, na variável caminho será'armazenado o local do caminho atual referente'a unidadeWNetGetConnection sUnidade, sCaminho, 255)

'DesconectaWNetCancelConnection Unidade, True

Retornar o nome do usuário logadoPublic Declare Function GetUserName Lib _ "advapi32.dll" Alias "GetUserNameA" _ (ByVal lpbuffer As String, nSize _ As Long) As LongPublic Function sUserID() As String Dim sBuffer As String Dim lSize As Long sBuffer = Space$(255) lSize = Len(sBuffer) GetUserName sBuffer, lSize If lSize > 0 Then sUserID = Left$(sBuffer, lSize - 1) MsgBox sUserID End IfEnd Function

152

Page 153: Dicas de VB

VBA

Copiando Textos de Documentos do Word'No evento desejado:Dim Word As ObjectSet Word = CreateObject("Word.Application")

'Abre o documentoWord.Documents.Open "C:\Meus Documentos\" & _ "NomeDoDocumento.DOC"

'Seleciona o documento inteiroWord.Documents("NomeDoDocumento.DOC").Select

'Joga o conteúdo da seleção numa caixa de Texto.Text1.Text = Word.Selection.TextPesquise o VBA, pois utilizando-o é possível selecionar palavras, parágrafos, tabelas, etc. Ou seja, qualquer parte do documento.

Trocar dados com o ExcelSub Importa(strArquivo As String) 'Número do arq Dim lngArquivo As Long

'Dados da 1º coluna Dim strUm As String

'Dados da 2º coluna Dim strDois As String

'Dados da 3º coluna Dim strTres As String

'Usada na substituição do ponto Dim strDecimal As Variant

Range("A1").Select lngArquivo = FreeFile Open strArquivo For Input As lngArquivo Do While Not EOF(lngArquivo) Input #lngArquivo, strUm, strDois, strTres ActiveCell.Value = strUm ActiveCell.Offset(0, 1).Activate

'Obtem o ponto strDecimal = InStr(1, strDois, ".") If strDecimal <> 0 Then

153

Page 154: Dicas de VB

'Se houver valor de retorno

'Substitui o ponto por vírgula Mid(strDois, strDecimal, 1) = ","

'Converte para moeda ActiveCell.Value = CCur(strDois) Else 'Senão 'Não altera a string ActiveCell.Value = strDois End If ActiveCell.Offset(0, 1).Activate ActiveCell.Value = strTres If ActiveCell.Column = 3 Then 'Se coluna atual = 3(C)

'Muda de linha ActiveCell.Offset(rowOffset:=1, _ columnOffset:=-2).Activat End If Loop Close lngArquivo ThisWorkbook.SaveAs "c:\SeuArquivo.xls"End SubVocê pode usar a rotina dentro de um loop passando como parâmetro o nome do arquivo texto a ser aberto.

154

Page 155: Dicas de VB

VALIDAÇÕES

Função para Verificar se um Ano é Bissexto ou Não'Num módulo:Public Function IsBissexto(Year As Integer) _ As Boolean IsBissexto = (Month(DateSerial(Year, 2, _ 29)) = 2)End Function

'P/ usar:

Private Sub Command1_Click() Dim bRet As Boolean bRet = IsBissexto(txtAno) If bRet Then MsgBox "O Ano É Bissexto!!!" Else MsgBox "O Ano NÃO É Bissexto!!!" End IfEnd Sub

Validar Cartão de CréditoFunction CheckCard(CCNumber As String) As Boolean Dim Counter As Integer, TmpInt As Integer Dim Answer As Integer Counter = 1 TmpInt = 0 While Counter <= Len(CCNumber) If IsEven(Len(CCNumber)) Then TmpInt = Val(Mid$(CCNumber, Counter, 1)) If Not IsEven(Counter) Then TmpInt = TmpInt * 2 If TmpInt > 9 Then TmpInt = TmpInt - 9 End If Answer = Answer + TmpInt 'Debug.Print Counter, TmpInt, Answer Counter = Counter + 1 Else TmpInt = Val(Mid$(CCNumber, Counter, 1)) If IsEven(Counter) Then TmpInt = TmpInt * 2 If TmpInt > 9 Then TmpInt = TmpInt - 9 End If Answer = Answer + TmpInt 'Debug.Print Counter, TmpInt, Answer Counter = Counter + 1 End If Wend Answer = Answer Mod 10 If Answer = 0 Then CheckCard = TrueEnd Function

155

Page 156: Dicas de VB

Validar CGC'Num módulo:

Public Function FU_ValidaCGC(cgc As String) As Boolean Dim retorno, a, j, i, d1, d2 If Len(cgc) = 8 And Val(cgc) > 0 Then a = 0 j = 0 d1 = 0 For i = 1 To 7 a = Val(Mid(cgc, i, 1)) If (i Mod 2) <> 0 Then a = a * 2 End If If a > 9 Then j = j + Int(a / 10) + (a Mod 10) Else j = j + a End If Next i d1 = IIf((j Mod 10) <> 0, 10 - (j Mod 10), 0) If d1 = Val(Mid(cgc, 8, 1)) Then FU_ValidaCGC = True Else FU_ValidaCGC = False End If Else If Len(cgc) = 14 And Val(cgc) > 0 Then a = 0 i = 0 d1 = 0 d2 = 0 j = 5 For i = 1 To 12 Step 1 a = a + (Val(Mid(cgc, i, 1)) * j) j = IIf(j > 2, j - 1, 9) Next i a = a Mod 11 d1 = IIf(a > 1, 11 - a, 0) a = 0 i = 0 j = 6 For i = 1 To 13 Step 1 a = a + (Val(Mid(cgc, i, 1)) * j) j = IIf(j > 2, j - 1, 9) Next i a = a Mod 11 d2 = IIf(a > 1, 11 - a, 0) If (d1 = Val(Mid(cgc, 13, 1)) And d2 = Val(Mid(cgc, _ 14, 1))) Then FU_ValidaCGC = True Else FU_ValidaCGC = False End If Else FU_ValidaCGC = False End If End IfEnd Function

'P/ chamar:

156

Page 157: Dicas de VB

Dim RET as BooleanRET = FU_ValidaCGC "15.545.974/5489-28" 'É APENAS um Exemplo!If RET = True Then 'O CGC é válidoElse 'O CGC NÃO é válidoEnd If

Validar CPF'Num módulo:Public Function FU_ValidaCPF(CPF As String) As Boolean Dim soma As Integer Dim Resto As Integer Dim i As Integer 'Valida argumento If Len(CPF) <> 11 Then FU_ValidaCPF = False Exit Function End If soma = 0 For i = 1 To 9 soma = soma + Val(Mid$(CPF, i, 1)) * (11 - i) Next i Resto = 11 - (soma - (Int(soma / 11) * 11)) If Resto = 10 Or Resto = 11 Then Resto = 0 If Resto <> Val(Mid$(CPF, 10, 1)) Then FU_ValidaCPF = False Exit Function End If soma = 0 For i = 1 To 10 soma = soma + Val(Mid$(CPF, i, 1)) * (12 - i) Next i Resto = 11 - (soma - (Int(soma / 11) * 11)) If Resto = 10 Or Resto = 11 Then Resto = 0 If Resto <> Val(Mid$(CPF, 11, 1)) Then FU_ValidaCPF = False Exit Function End If FU_ValidaCPF = TrueEnd Function

'P/ chamar:Dim RET as BooleanRET = FU_ValidaCPF "518.284.565-28" 'É APENAS um Exemplo!If RET = True Then 'O CGC é válidoElse 'O CGC NÃO é válidoEnd If

Validar Datas'Num módulo:Public Function ValidaData(ByVal sData _ As String, Optional ByVal sFormato _ As String) As Boolean

157

Page 158: Dicas de VB

Dim Dia As Integer, Dia_Pos As Integer Dim Mes As Integer, Mes_Pos As Integer Dim Ano As Integer, Ano_Pos As Integer Dim DDOk As Integer, MMOk As Integer Dim YYOk As Integer, i As Integer Dim m As Integer, Temp As String Dim sBst As Boolean

If IsMissing(sFormato) Then sFormato = "DD/MM/YYYY" 'OU então, você pode pegar o formato 'que estiver configurado no Windows. End If

Temp = Replace(sData, "-", "/") sData = Temp Temp = Replace(sFormato, "-", "/") sFormato = Temp Temp = ""

DDOk = 0 MMOk = 0 YYOk = 0

For i = 1 To Len(sFormato) If UCase(Mid(sFormato, i, 1)) = "D" Then If DDOk > 2 Then ValidaData = False Exit Function Else DDOk = DDOk + 1 If Dia_Pos = 0 Then Dia_Pos = Mes_Pos + Ano_Pos + 1 End If End If ElseIf UCase(Mid(sFormato, i, 1)) = "M" Then If MMOk > 2 Then ValidaData = False Exit Function Else MMOk = MMOk + 1 If Mes_Pos = 0 Then Mes_Pos = Dia_Pos + Ano_Pos + 1 End If End If ElseIf UCase(Mid(sFormato, i, 1)) = "Y" Then If YYOk > 4 Then ValidaData = False Exit Function Else YYOk = YYOk + 1 If Ano_Pos = 0 Then Ano_Pos = Dia_Pos + Mes_Pos + 1 End If End If Else Select Case UCase(Mid(sFormato, i, 1)) Case "D", "M", "Y", "/" Case Else ValidaData = False Exit Function

158

Page 159: Dicas de VB

End Select End If Next i

If DDOk = 0 Or MMOk = 0 Then ValidaData = False Exit Function End If

If YYOk = 0 Or YYOk > 4 Then ValidaData = False Exit Function End If

If Not IsDate(sData) Then ValidaData = False Exit Function End If

m = 0 For i = 1 To Len(sData) If Mid(sData, i, 1) = "/" Or _ i = Len(sData) Then If i = Len(sData) Then Temp = Temp & Mid(sData, i, 1) End If m = m + 1 If m = 3 Then m = 4 If Dia_Pos = m Then Dia = Temp ElseIf Mes_Pos = m Then Mes = Temp ElseIf Ano_Pos = m Then Ano = Temp End If Temp = "" Else Temp = Temp & Mid(sData, i, 1) End If Next i

Select Case Mes Case 1, 3, 5, 7, 8, 10, 12 If Dia < 1 Or Dia > 31 Then ValidaData = False Exit Function End If Case 4, 6, 9, 11 If Dia < 1 Or Dia > 31 Then ValidaData = False Exit Function End If Case 2 If Dia < 1 Or Dia > 29 Then ValidaData = False Exit Function ElseIf Dia = 29 Then sBst = False If Ano = 0 Then sBst = True ElseIf Ano Mod 4 = 0 Then

159

Page 160: Dicas de VB

sBst = True If Ano Mod 100 = 0 Then sBst = False If Ano Mod 400 = 0 Then sBst = True End If End If Else sBst = False End If If sBst = False Then ValidaData = False Exit Function End If End If Case Else ValidaData = False Exit Function End Select ValidaData = TrueEnd Function

'P/ chamar, no evento desejado:VariávelBoolean = ValidaData(Data, Formato)

'Exemplo: Dim bRESP As Boolean bRESP = ValidaData("31/03/2000", "M/D/Y") If bRESP Then MsgBox "A data é válida!!!" Else MsgBox "A data NÃO é válida!!!" End If'Ele exibirá "A data é válida!!!"

Validar E-Mail'Num módulo:Public Function ValidEMail(sEMail As String) As Boolean Dim nCharacter As Integer Dim Count As Integer Dim sLetra As String 'Verifica se o e-mail tem no MÍNIMO 5 'caracteres ([email protected]) If Len(sEMail) < 5 Then 'O e-mail é inválido, pois tem menos 'de 5 caracteres ValidEMail = False MsgBox "O e-mail digitado tem menos de 5 " & _ "caracterec!!!" Exit Function End If 'Verificar a existencia de arrobas (@) no e-mail For nCharacter = 1 To Len(sEMail) If Mid(sEMail, nCharacter, 1) = "@" Then 'OPA!!! Achou uma arroba!!! 'Soma 1 ao contador Count = Count + 1 End If

160

Page 161: Dicas de VB

Next 'Verifica o número de arrobas. 'TEM que ter """UMA""" arroba If Count <> 1 Then 'O e-mail é inválido, pois tem 0 ou 'mais de 1 arroba ValidEMail = False MsgBox "O nº de arrobas (@) do e-mail é " & _ "inválido!!!" Exit Function Else 'O e-mail tem 1 arroba. 'Verificar a posição da arroba If InStr(sEMail, "@") = 1 Then 'O e-mail é inválido, pois começa 'com uma @ ValidEMail = False MsgBox "O e-mail foi iniciado com uma " & _ "arroba (@)!!!" Exit Function ElseIf InStr(sEMail, "@") = Len(sEMail) Then 'O e-mail é inválido, pois termina 'com uma @ ValidEMail = False MsgBox "O e-mail termina com uma arroba (@)!!!" Exit Function End If End If nCharacter = 0 Count = 0 'Verificar a existencia de pontos (.) no e-mail For nCharacter = 1 To Len(sEMail) If Mid(sEMail, nCharacter, 1) = "." Then 'OPA!!! Achou um ponto!!! 'Soma 1 ao contador Count = Count + 1 End If Next 'Verifica o número de pontos. 'TEM que ter PELO MENOS UM ponto. If Count < 1 Then 'O e-mail é inválido, pois não tem pontos. ValidEMail = False MsgBox "O e-mail é inválido, pois não contém " & _ "pontos (.)!!!" Exit Function Else 'O e-mail tem pelo menos 1 ponto. 'Verificar a posição do ponto: If InStr(sEMail, ".") = 1 Then 'O e-mail é inválido, pois começa 'com um ponto ValidEMail = False MsgBox "O e-mail foi iniciado com um ponto (.)!!!" Exit Function ElseIf InStr(sEMail, ".") = Len(sEMail) Then 'O e-mail é inválido, pois termina 'com um ponto. ValidEMail = False MsgBox "O e-mail termina com um ponto (.)!!!" Exit Function

161

Page 162: Dicas de VB

ElseIf InStr(InStr(sEMail,"@"),sEMail,".") = 0 Then 'O e-mail é inválido, pois termina 'com um ponto. ValidEMail = False MsgBox "O e-mail não tem nenhum ponto (.) após " & _ "a arroba (@)!!!" Exit Function End If End If nCharacter = 0 Count = 0 'Verifica se o e-mail não tem pontos 'consecutivos (..) após a arroba (@). If InStr(sEMail, "..") > InStr(sEMail, "@") Then 'O e-mail é inválido, tem pontos 'consecutivos após o @. ValidEMail = False MsgBox "O e-mail contém pontos consecutivos " & _ "(..) após o arroba (@)!!!" Exit Function End If 'Verifica se o e-mail tem caracteres 'inválidos For nCharacter = 1 To Len(sEMail) sLetra = Mid$(sEMail, nCharacter, 1) If Not (LCase(sLetra) Like "[a-z]" Or sLetra = _ "@" Or sLetra = "." Or sLetra = "-" Or _ sLetra = "_" Or IsNumeric(sLetra)) Then 'O e-mail é inválido, pois tem 'caracteres inválidos ValidEMail = False MsgBox "Foi digitado um caracter inválido " & _ "no e-mail!!!" Exit Function End If Next nCharacter = 0 'Bem, se a verificação chegou até aqui 'é porque o e-mail é válido, então... ValidEMail = TrueEnd Function

'P/ chamar a função: Dim VALID As Boolean VALID = ValidEMail(Text1.Text) If VALID = True Then MsgBox "Tudo Ok na verificação!!!" Else MsgBox "Houve algum problema na verificação!!!" End If

'Quando você for colocar esta função num programa você pode tirar as MsgBoxes, claro.

Validar Informações Fornecidas pelo Usuário

PARA GARANTIR A DIGITAÇÃO CORRETA

162

Page 163: Dicas de VB

Como validar informações fornecidas pelo usuário usando as Expressões Regulares do VBScript.

As expressões regulares mostradas fazem parte do VBScript, uma das linguagens que usam os serviços do Windows Script, disponível no Windows 98. Para experimentar os exemplos em sua máquina, você precisa fazer o download da versão atualizada do Windows Scripting Host, no endereço http://www.microsoft.com/scripting/downloads/ws/x86/ste50ptb.exe (676 KB). Mais informações sobre o tema podem ser encontradas no site dedicado ao Windows Scripting: http://msdn.microsoft.com/scripting.

Além de usar as expressões em arquivos texto do tipo VBS, do VBScript, você pode também usá-las no Visual Basic 5.0 ou 6.0 e nos ambientes de programação VBA, como nos aplicativos do Office 97 ou 2000. Nestes últimos, para ativar as expressões regulares, acione o comando Ferramentas/Referências e marque a opção Microsoft VBScript Regular Expressions.

O JOGO DA STRING E DO PADRÃO(por Andrew Camargo Francis)

Não importa se você está desenvolvendo para a Internet ou para uso local no Windows, uma das características mais importantes de um bom programa é a capacidade de lidar elegantemente com situações de erro. Em especial quando se trata de erros do usuário. Um aplicativo que formata o disco rígido e reinicia o micro toda vez que o usuário comete um erro certamente jamais receberia cinco estrelas do INFOLAB na categoria facilidade de uso. Para auxiliar os programadores nesta árdua tarefa, a nova versão 5.0 do VBScript traz um recurso conhecido como Expressões Regulares. Com elas é possível validar a entrada de dados feita pelo usuário de uma forma bastante prática.

Digamos que seu programa peça ao usuário que digite um número de telefone. Como saber se ele realmente forneceu um número de telefone ou apenas digitou "1234" no lugar? Poderíamos escrever uma rotina que percorresse a string verificando caractere a caractere se aquilo parece ser um número de telefone. Com a expressão regular correta, podemos fazer exatamente isso, quase sem nenhuma programação. Como?

Primeiro, vamos entender o que são as expressões regulares. Elas são simplesmente strings em que alguns caracteres (ou combinações de caracteres) têm um significado especial. Por exemplo, a combinação "\d" significa um dígito. Não algum dígito em particular mas qualquer um dos dez dígitos. Essas strings (mais conhecidas como padrões) são comparadas com outras strings comuns, de tal maneira que os caracteres especiais "batam" com aquilo que eles representam. Assim, se você comparar o padrão "\d" com a string "\d" irá obter um resultado False, mas se você o comparar com a string "6" irá obter True.

Muito bem, já conhecemos o suficiente para validar uma string como sendo um número de telefone ou não. Vamos combinar que um telefone válido tem 7 dígitos, ou seja, 3 dígitos seguidos por um traço, seguido por mais 4 dígitos. Montamos, então, o seguinte padrão:

"\d\d\d-\d\d\d\d"

Falta apenas um detalhe. Quando comparamos um padrão com uma string, na verdade estamos buscando o padrão dentro da string. Portanto, se aquele padrão existir em algum lugar dentro da string, a comparação será verdadeira. Não é o que queremos, pois "qwer555-1234zxcv" apesar de não ser um número válido seria "aceito" pelo padrão. Precisamos de mais alguns caracteres

163

Page 164: Dicas de VB

especiais. O "^" é usado para representar o começo da string e o "$" o seu fim. Assim, o padrão "^\d\d\d-\d\d\d\d$" resolve o nosso problema, pois não permite nenhum outro caractere entre o começo da string e o primeiro dígito (idem para o fim).

Ótimo, temos um padrão pronto. Só precisamos saber agora como usá-lo no VBScript. Para isso, existe o objeto RegExp. Neste primeiro momento, só precisamos de uma propriedade e um método desse objeto. A propriedade Pattern armazena o padrão que será usado na comparação e o método Test verifica se o padrão é encontrado na string fornecida. Podemos fazer um pequeno teste com o seguinte código:

Dim oExpr, resultadoSet oExpr = New RegExpoExpr.Pattern = "^\d\d\d-\d\d\d\d$"resultado = oExpr.Test("555-1234")MsgBox resultadoresultado = oExpr.Test("1234")MsgBox resultado

A primeira string é comparada com sucesso e a segunda não, exatamente como queríamos. Agora que já temos funcionando a versão 1.0 da nossa expressão regular, podemos acrescentar alguns recursos. O usuário pode ter um telefone de oito dígitos. Como fazemos para validar os dois tipos de números? O ponto de interrogação "?" funciona como uma espécie de "sufixo" dizendo que o caractere anterior (especial ou não) é opcional. Assim, podemos ter três ou quatro dígitos antes do traço:

"^\d?\d\d\d-\d\d\d\d$"

Essa seqüência muito grande de "\d"s torna a leitura (e compreensão) da expressão um pouco difícil. Podemos melhorar isso da seguinte forma:

"^\d{3,4}-\d{4}$"

Mudou tudo! Espero que para melhor. O sufixo "{n}" é parecido com o "?" mas permite que você diga quantas vezes o caractere anterior deve ser repetido (ou seja, n vezes). Já o "{3,4}" diz que o "\d" anterior deve se repetir no mínimo 3 e no máximo 4 vezes. Fácil, não?

Vamos supor agora que tenhamos de validar um endereço de e-mail em vez de um telefone. Para tanto, precisamos definir qual é a "cara" de um e-mail, como fizemos para o telefone. Novamente vamos combinar um padrão: uma seqüência de letras ou números, um "@" e mais outra seqüência de letras e números entremeada com pontos. Na primeira parte (antes do "@") precisamos do "\w" que representa qualquer letra maiúscula ou minúscula, qualquer dígito e também o "_". Como não sabemos quantos caracteres serão, vamos usar mais um sufixo. O "+" nos garante que haverá uma ou mais letras e números (pelo menos um é necessário):

"\w+"

A segunda parte é um pouco mais complicada. Precisamos garantir que seja algo como "infoexame.com.br". Em outras palavras:

- que haja uma seqüência de "\w" seguida por um ".";- que isso se repita quantas vezes forem necessárias;- e que no final tenhamos mais uma seqüência de "\w".

164

Page 165: Dicas de VB

Parece difícil? Veja como se faz:

"(\w+\.)+\w+"

Usamos os parênteses para agrupar a primeira seqüência e o "." e fazer com que isso se repita com o segundo "+". Se você prestou atenção, deve ter percebido um "\" a mais antes do ".". Para que isto? Acontece que o caractere "." também é especial. Ele representa qualquer caractere! Mas aqui queremos apenas o ponto final. Nestes casos usamos o prefixo "\" antes de um caractere especial quando queremos representar o próprio caractere e não o seu significado. Juntando as partes, obtemos:

"\w+@(\w+\.)+\w+"

Podemos testar o padrão com um código similar ao anterior:

Set oExpr = New RegExpoExpr.Pattern = "\w+@(\w+\.)+\w+"resultado = oExpr.Test ("[email protected]")MsgBox resultadoresultado = oExpr.Test ("asdf")MsgBox resultado

Novamente, o primeiro teste é verdadeiro e o segundo não. Se quisermos aceitar apenas endereços em que a primeira parte não contenha números, como fica o padrão correspondente? Uma possível solução usa o que se chama classe de caracteres. Uma classe é simplesmente uma forma de agrupar caracteres de maneira que o grupo represente qualquer caractere da classe. Criamos uma classe colocando colchetes em volta de uma seqüência de caracteres:

"[0123456789]"

Esse padrão representa qualquer dígito. O "\d" é apenas uma forma bem mais curta de dizer a mesma coisa! Podemos reescrever isso de uma maneira mais sintética:

"[0-9]"

Ou seja, criamos a classe dos caracteres de "0" até "9". Observe que o "-" só tem um significado especial quando se encontra entre colchetes. No exemplo do telefone, ele era um caractere normal. Portanto, a classe das letras (minúsculas e maiúsculas) ficaria assim:

"[a-zA-Z]"

Acrescentando essa classe ao nosso padrão temos:

"[a-zA-Z]+@(\w+\.)+\w+"

Como faríamos para validar apenas os endereços de pessoas chamadas "Rosa" ou "Pereira"? Poderíamos usar dois padrões diferentes:

"rosa@(\w+\.)+\w+" "pereira@(\w+\.)+\w+"

Também podemos usar o caractere "|" que permite separar duas coisas num padrão de maneira que uma das duas deva aparecer na string comparada:

165

Page 166: Dicas de VB

"(rosa|pereira)@(\w+\.)+\w+"

Até agora havíamos usado quase exclusivamente caracteres especiais, mas observe que os caracteres normais (representando a si mesmos) também são perfeitamente válidos num padrão.

O mais importante é que, nesses casos, geralmente desejamos que a comparação seja feita ignorando se as letras são maiúsculas ou minúsculas. Para isso, contamos com a propriedade IgnoreCase:

Set oExpr = New RegExpoExpr.Pattern = "(rosa|pereira)@(\w+\.)+\w+"oExpr.IgnoreCase = Trueresultado = oExpr.Test ("[email protected]")MsgBox resultadoresultado = oExpr.Test ("[email protected]")MsgBox resultado

Ambos os testes acima têm resultado True.

Há vários outros caracteres especiais das expressões regulares, bem como outras propriedades e métodos do objeto RegExp que não discutimos aqui. Além da validação, as expressões podem ser usadas para outros fins, como a busca e a substituição em textos. O importante é que, tendo dominado os seus fundamentos, o programador terá ao seu alcance uma poderosa ferramenta de manipulação de strings. Lembre-se de que muitas vezes há mais de um jeito de escrever a mesma coisa e que é sempre importante testar a expressão para garantir que ela faça exatamente o que você deseja. É muito fácil se perder em meio a tantas letras, barras e outros símbolos de significado pouco intuitivo. Mas, afinal, ninguém disse que elas eram bonitas -- as expressões regulares são apenas enxutas e práticas!

Validar Texto em MaskEditBoxPrivate Sub Mask1_Validate(Cancel as Boolean) Cancel = Not IsDate(Mask1.FormattedText)End Sub

Valor por Extenso'Num módulo:Public Function Extenso(ByVal Valor As _ Double, ByVal MoedaPlural As _ String, ByVal MoedaSingular As _ String) As String Dim StrValor As String, Negativo As Boolean Dim Buf As String, Parcial As Integer Dim Posicao As Integer, Unidades Dim Dezenas, Centenas, PotenciasSingular Dim PotenciasPlural

Negativo = (Valor < 0) Valor = Abs(CDec(Valor)) If Valor Then Unidades = Array(vbNullString, "Um", "Dois", _ "Três", "Quatro", "Cinco", _ "Seis", "Sete", "Oito", "Nove", _ "Dez", "Onze", "Doze", "Treze", _ "Quatorze", "Quinze", "Dezesseis", _

166

Page 167: Dicas de VB

"Dezessete", "Dezoito", "Dezenove") Dezenas = Array(vbNullString, vbNullString, _ "Vinte", "Trinta", "Quarenta", _ "Cinqüenta", "Sessenta", "Setenta", _ "Oitenta", "Noventa") Centenas = Array(vbNullString, "Cento", _ "Duzentos", "Trezentos", _ "Quatrocentos", "Quinhentos", _ "Seiscentos", "Setecentos", _ "Oitocentos", "Novecentos") PotenciasSingular = Array(vbNullString, " Mil", _ " Milhão", " Bilhão", _ " Trilhão", " Quatrilhão") PotenciasPlural = Array(vbNullString, " Mil", _ " Milhões", " Bilhões", _ " Trilhões", " Quatrilhões")

StrValor = Left(Format(Valor, String(18, "0") & _ ".000"), 18) For Posicao = 1 To 18 Step 3 Parcial = Val(Mid(StrValor, Posicao, 3)) If Parcial Then If Parcial = 1 Then Buf = "Um" & PotenciasSingular((18 - _ Posicao) \ 3) ElseIf Parcial = 100 Then Buf = "Cem" & PotenciasSingular((18 - _ Posicao) \ 3) Else Buf = Centenas(Parcial \ 100) Parcial = Parcial Mod 100 If Parcial <> 0 And Buf <> vbNullString Then Buf = Buf & " e " End If If Parcial < 20 Then Buf = Buf & Unidades(Parcial) Else Buf = Buf & Dezenas(Parcial \ 10) Parcial = Parcial Mod 10 If Parcial <> 0 And Buf <> vbNullString Then Buf = Buf & " e " End If Buf = Buf & Unidades(Parcial) End If Buf = Buf & PotenciasPlural((18 - Posicao) \ 3) End If If Buf <> vbNullString Then If Extenso <> vbNullString Then Parcial = Val(Mid(StrValor, Posicao, 3)) If Posicao = 16 And (Parcial < 100 Or _ (Parcial Mod 100) = 0) Then Extenso = Extenso & " e " Else Extenso = Extenso & ", " End If End If Extenso = Extenso & Buf End If End If Next If Extenso <> vbNullString Then

167

Page 168: Dicas de VB

If Negativo Then Extenso = "Menos " & Extenso End If If Int(Valor) = 1 Then Extenso = Extenso & " " & MoedaSingular Else Extenso = Extenso & " " & MoedaPlural End If End If Parcial = Int((Valor - Int(Valor)) * _ 100 + 0.1) If Parcial Then Buf = Extenso(Parcial, "Centavos", _ "Centavo") If Extenso <> vbNullString Then Extenso = Extenso & " e " End If Extenso = Extenso & Buf End If End IfEnd Function

'P/ chamar a função:Dim sRet As StringDim dValor As DoubledValor = 1500.50sRet = Extenso(dValor, "Reais", "Real")MsgBox sRet

Então, sRet conterá "Um Mil e Quinhentos Reais e Cinqüenta Centavos".

Verificar a Validade do PISPublic Function PISPASEP(Fcamp As String) Dim FTAP As String Dim TOT As Integer Dim I As Integer If Val(Fcamp) = 0 Then PISPASEP = False Exit Function End If If Len(Fcamp) <> 11 Then PISPASEP = False Exit Function End If FTAB = "3298765432" TOT = 0 For I = 1 To 10 TOT = TOT + Val(Mid(Fcamp, I, 1)) * Val(Mid(FTAB, I, 1)) Next I RESTO = Int(TOT Mod 11) If RESTO <> 0 Then RESTO = 11 - RESTO End If If RESTO <> Val(Mid(Fcamp, 11, 1)) Then PISPASEP = False Exit Function End If PISPASEP = TrueEnd Function

168

Page 169: Dicas de VB

VARIADOS

Acionar um HTML Help pelo VBPublic Declare Function HtmlHlp Lib "hhctrl.ocx" Alias _ "HtmlHelpA" (ByVal wHandle As Long, ByVal psfile _ As String, ByVal command As Integer, ByVal data _ As Long) As Long

lngRet = HtmlHlp(Me.hwnd, App.Path & "\help.chm", &HF, 1000)

Onde &HF significa sensível ao contexto e 1000 é uma âncora (id) que você cria dentro do HtmlHelp Workshop.

Acionar um Help (*.HLP) pelo VB'No Declarations do Form:Private Declare Function WinHelp Lib "user32" Alias _ "WinHelpA" (ByVal hwnd As Long, ByVal lpHelpFile _ As String, ByVal wCommand As Long, ByVal dwData _ As Long) As Long

Private Const HELP_CONTENTS As Long = &H3&Private Const HELP_QUIT As Long = &H2

'P/ chamar (no evento que você quizer):

Dim CONF As LongDim DIR As StringDIR = App.Path & "SeuHelp.HLP"If Right(App.Path,1) <> "\" Then DIR = App.Path & "\SeuHelp.HLP"CONF = WinHelp(hwnd, DIR, HELP_CONTENTS, CLng(0))

Cancelando Processos Longos

Quando você for trabalhar com processamentos longos (utilizando loops como Do...Loop, For...Next), procure criar um botão de cancelameno p/ este processo. Utilize SEMPRE também a função DoEvents, que permite que o usuário realize outras tarefas enquanto o processo é executado (clicar no botão "Cancelar", por exemplo), impedindo assim que o seu programa trave, ou trave seu computador.

É bastante simples de criar este botão de cancelamento. Veja:

'No Declarations:Dim bParar As Boolean

'Na Rotina onde irá utilizar o Loop:bParar = FalseDo DoEvents 'A linha a seguir força a saída do Loop 'quando o botão "Cancelar" for precionado: If bParar = True Then Exit Do 'Ou Exit Sub ... Outros comandos ...Loop

169

Page 170: Dicas de VB

'No botão Cancelar, mude o valor da variável'bParar p/ True:Private Sub Command1_Click() bParar = TrueEnd Sub

Então, por estar se usando o DoEvents, o usuário poderá clicar no botão "Cancelar" e, quando ele fizer isto, a variável bParar passara a ter o valor True, parando assim o processo.

Carregando forms do VB4 no VB3

Você não poderá ler um form do VB4 diretamente no VB3. A definição do form deve ser alterada em um editor de texto (ASCII).

VERSION 4.00

Mude a versão 4.00 para VERSION 2.00, remova todos os sufixos VB, o comando Begin Form, remova todas as declarações Attribute. Remova também a cláusula Private de algumas rotinas (eventos). Salve o arquivo e abra-o no VB3.

Begin VB.Form Form1

Caption = "Form1"ClientHeight = 5940'demais propriedadesEndAttribute VB_Name = "Form1"Attribute VB_Creatable = FalseAttribute VB_Exposed = FalseOption ExplicitPrivate Sub Form_Load()'...End Sub

Confirmando o Termino do Programa

Como faríamos para perguntar ao usuário se ele "realmente" deseja finalizar o programa? Colocaríamos um botão ou menu com o caption "Sair" e, se o usuário clicasse nele perguntaríamos? Mas e se o usuário clicasse no botão "X" q fica no lado direito da barra detítulos?Bem, para nossa sorte existe o evento QueryUnload em todo Form. Então, proceda da seguinte forma:

Private Sub Form_QueryUnload(Cancel As Integer, _ UnloadMode As Integer) Dim RES As VbMsgBoxResult 'Pergunta ao usuário se ele realmente deseja finalizar 'o programa RES = MsgBox("Você deseja finalizar o programa???", _ vbQuestion + vbYesNo, "Sair???") If RES = vbNo Then 'O usuário NÃO deseja finalizar o programa. Cancel = 1 Else 'O usuário DESEJA finalizar o programa.

170

Page 171: Dicas de VB

'Aqui coloque comandos, como salvar registros, 'por exemplo... End IfEnd Sub

Private Sub Form_Unload(Cancel As Integer) Set frmMenu = NothingEnd Sub

Como Registrar Uma HotKey'Num modulo:

Option ExplicitPrivate Const WM_HOTKEY = &H312

Public Declare Function RegisterHotKey Lib _ "user32" (ByVal hwnd As Long, ByVal _ id As Long, ByVal fsModifiers As _ Long, ByVal vk As Long) As Long'' Modificadores'Public Const MOD_ALT = &H1Public Const MOD_CONTROL = &H2Public Const MOD_SHIFT = &H4

' Tecla que será nossa hotkeyPublic Const VK_F2 = &H71

Public Declare Function DefWindowProc Lib _ "user32" Alias "DefWindowProcA" _ (ByVal hwnd As Long, ByVal wMsg As _ Long, ByVal wParam As Long, ByVal _ lParam As Long) As LongPublic Declare Function SendMessage Lib _ "user32" Alias "SendMessageA" _ (ByVal hwnd As Long, ByVal wMsg _ As Long, ByVal wParam As Long, _ lParam As Any) As Long

#If UNICODE Then Public Declare Function SetWindowLong Lib _ "user32" Alias "SetWindowLongW" _ (ByVal hwnd As Long, ByVal nIndex _ As Long, ByVal dwNewLong As Any) _ As Long Public Declare Function GetWindowLong Lib _ "user32" Alias "GetWindowLongW" _ (ByVal hwnd As Long, ByVal nIndex _ As Long) As Long#Else Public Declare Function SetWindowLong Lib _ "user32" Alias "SetWindowLongA" _ (ByVal hwnd As Long, ByVal nIndex _ As Long, ByVal dwNewLong As Any) _ As Long Public Declare Function GetWindowLong Lib _ "user32" Alias "GetWindowLongA" _

171

Page 172: Dicas de VB

(ByVal hwnd As Long, ByVal nIndex _ As Long) As Long#End IfPrivate Declare Function CallWindowProc Lib _ "user32" Alias "CallWindowProcA" _ (ByVal wndrpcPrev As Long, ByVal _ hwnd As Long, ByVal uMsg As Long, _ ByVal wParam As Long, lParam As _ Any) As LongPublic Const GWL_USERDATA = (-21)Public Const GWL_WNDPROC = -4

Public Function WindowProc(ByVal hwnd As _ Long, ByVal uMsg As Long, ByVal _ wParam As Long, ByVal lParam As _ Long) As Long On Error Resume Next If uMsg = WM_HOTKEY And wParam = 1 Then 'wParam informa o ID da hotkey Form1.BahMetodo WindowProc = 1 Exit Function End If If Form1.OldWndProc <> 0 Then WindowProc = CallWindowProc(Form1.OldWndProc, _ hwnd, uMsg, wParam, ByVal lParam) End IfEnd Function

'Agora em um Form chamado Form1:

Option ExplicitPublic OldWndProc As Long

Private Sub Form_Load() Dim Ret As Long 'Registra hotkey com ID 1 'Essa hotkey sera aciona com ALT + F2 'Se Ret <> 0 entao beleza, se = 0 já 'existe uma hotkey dessa definida Ret = RegisterHotKey(Me.hwnd, 1, MOD_ALT, _ VK_F2) ' 'Inicia subclassing ' OldWndProc = SetWindowLong(Me.hwnd, _ GWL_WNDPROC, AddressOf _ WindowProc)End Sub

Private Sub Form_Unload(Cancel As Integer) Cancel = False Call SetWindowLong(Me.hwnd, GWL_WNDPROC, _ OldWndProc)End Sub

'' Metodo chamado pela Hotkey'Public Sub BahMetodo() MsgBox "Opa !"

172

Page 173: Dicas de VB

End Sub

Rode o projeto, minimize a janela, clique em outra janela, esqueca da janela e impulsivamente pressione ALT + F2 ;-)

Convertendo Identificadores em Rótulos e Cabeçalhos

Programadores possuem o hábito de criar identificadores (nomes de variáveis, por exemplo) por fusão de palavras como SobreNome ou CargoAnterior. É possível usar alguns destes nomes para se criar labels (rótulos) e descrições diversas. A função abaixo insere espaços, "quebrando" os identificadores a cada inicial maiúscula. Assim, CargoAnterior será convertido para Cargo Anterior.

Function SpaceName (src As String) As String Dim i as Integer, tgt As String tgt = Left$(src,1) For i = 2 to Len(src) Select Case Mid$(src, i-1, 1 Case "a" to "z" Select Case Mid$ (src, i, 1) Case "A" to "Z" tgt = tgt & " " End Select End Select tgt = tgt & Mid$(src, i, 1) Next i SpaceName = tgtEnd Function

Criando gráficos sem utilizar OCX nem DLL

Um gráfico nada mas é que uma representação visual de um valor em relação a outros valores ou a uma meta pré-definida.

Para gerar esta representação o processo é bastante simples:

Caso 1 - Meta pré-definida:

Crie um projeto novo, Form1 será criado por padrão. Coloque o código abaixo em Form1 e execute o programa.

Private Sub Form_Load() AutoRedraw = True FillStyle = 0 ScaleMode = 3 'Dim Valor%(9) é o mesmo que 'Dim Valor(0 to 9) As Integer Dim Valor%(9), Item% Dim PosX!, PosY!, PosX1!, PosY1! Const ValorMaior% = 100 'traça o fundo do gráfico FillColor = &HFFFFFF Line (0, 0)-((UBound(Valor) + 1) * 20 + 10, ValorMaior% + 20), &H0&, B 'carrega valores aleatórios no gráfico For Item = 0 To UBound(Valor) Valor(Item) = (Rnd * ValorMaior%)

173

Page 174: Dicas de VB

Next 'traça o gráfico For Item = 0 To UBound(Valor) PosX = (Item * 10) + ((Item + 1) * 10) PosY = ValorMaior + 10 PosX1 = (Item * 10) + ((Item + 1) * 10) + 10 PosY1 = ValorMaior - Valor(Item) + 10 FillColor = Valor(Item) * (&HFFFFFF / ValorMaior) Line (PosX, PosY)-(PosX1, PosY1), &H0&, B NextEnd Sub

Este código irá gerar um gráfico de colunas baseado em valores aleatórios onde o valor limite é definido por ValorMaior e cada cor representa um nível de aproximação deste valor.

Caso 2 - Meta relativa:

Private Sub Form_Load() AutoRedraw = True FillStyle = 0 ScaleMode = 3 'Dim Valor%(9) é o mesmo que Dim Valor(0 to 9) As Integer Dim Valor%(9), Item%, ValorMaior% Dim PosX!, PosY!, PosX1!, PosY1! 'carrega valores aleatórios no gráfico e encontra o maior ValorMaior = 1 'Define o valor mínimo For Item = 0 To UBound(Valor) Valor(Item) = (Rnd * 100) ValorMaior = IIf(Valor(Item) > ValorMaior, Valor(Item), ValorMaior) Next 'traça o fundo do gráfico FillColor = &HFFFFFF Line (0, 0)-((UBound(Valor) + 1) * 20 + 10, ValorMaior% + 20), &H0&, B 'traça o gráfico For Item = 0 To UBound(Valor) PosX = (Item * 10) + ((Item + 1) * 10) PosY = ValorMaior + 10 PosX1 = (Item * 10) + ((Item + 1) * 10) + 10 PosY1 = ValorMaior - Valor(Item) + 10 FillColor = Valor(Item) * (&HFFFFFF / ValorMaior) Line (PosX, PosY)-(PosX1, PosY1), &H0&, B NextEnd Sub

Este código irá gerar um gráfico de colunas baseado em valores aleatórios onde o valor limite é o maior dos valores carregados, sendo que o limite mínimo é 1 e cada cor representa um nível de aproximação do maior valor ou de 1 caso todos os valores sejam nulos.

Criando uma Animação no VB

Crie um novo projeto, coloque no Form uma ImageList, um PictureBox (ou ImageBox, pois esta não recebe foco), um Timer (com Interval = 100, pelo menos) e coloque as figuras da animação na ImageList.

Então, coloque o seguinte código no Form:

Dim iAnim As Integer

174

Page 175: Dicas de VB

Private Sub Form_Load() iAnim = 1 Call Timer1_TimerEnd SubPrivate Sub Timer1_Timer() 'Img1 é a ImageBox e ImgLst1 é a ImageList. Set Img1.Picture = ImgLst1.ListImages(iAnim).Picture iAnim = iAnim + 1 If iAnim > ImageList1.ListImages.Count Then iAnim = 1 End IfEnd Sub

Dar uma Pausa em seu Programa'No declarations do Form onde você'deseja colocar essa "pausa":Private Declare Sub Sleep Lib "kernel32" _ (ByVal dwMilliseconds As Long)

'Então, no evento que você desejar, coloque'esta linha:Sleep (2000)

Pronto. Aí será dada uma pausa de 2000 milesegundos. Caso você queira que essa pausa seja de mais ou menos tempo, altere este 2000 pelo número que você quizer.

Detalhe: Cada 1000 milesegundos correspondem a 1 segundo.

Fazer um aplicativo ser acionado silenciosamente

Para fazer um aplicativo ser acionado silenciosamente na abertura do Windows, basta adicionar seu caminho na chave:

"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run"

À partir deste momento ele será acionado na abertura do Windows.

MsgBox que não seja modal

A função MsgBox do Visual Basic não contempla esta opção. Porém, é possível fazer usando a função API MessageBox. Declare e chame a API como segue (código VB 3.0):

Declare Function MessageBox% Lib "User" (ByVal _ hWnd%, ByVal lpText$, ByVal lpCaption$, _ ByVal wType%)

Const MB_OKCANCEL As Long = &H1Dim ret%ret = MessageBox(0, "I am a Modeless MessageBox", _ "Modeless MessageBox ", MB_OKCANCEL)

Obs.: É possível também criar um formulário com as mesmas características de um MessageBox e exibí-lo de forma não modal.

175

Page 176: Dicas de VB

Programa que dá "Bom dia", "Boa tarde" e "Boa noite" nos Horários Corretos'No evento Form_Load() do Form principal:Private Sub Form_Load() Me.Show If Time$ > "19:00:00" Then MsgBox "Boa noite e seja bem vindo!!!", _ vbInformation ElseIf Time$ > "12:00:00" Then MsgBox "Boa tarde e seja bem vindo!!!", _ vbInformation ElseIf Time$ > "00:00:00" Then MsgBox "Bom dia e seja bem vindo!!!", _ vbInformation End IfEnd Sub

Assim, ele lhe dirá:* "Bom dia e seja bem vindo!!!" - de manha* "Boa tarde e seja bem vindo!!!" - de tarde* "Boa noite e seja bem vindo!!!" - de noite

Recebendo Parâmetros Externos num Programa feito em VB

Para fazer com que um programa feito em VB receba parâmetros externos (como o %1, %2, etc dos arquivos .BAT), use a funcão "Command$" no evento Form_Load. Veja o código:

Private Sub Form_Load() Dim sParametro as String sParametro = Command$End Sub

Saber se um programa foi encerradoPrivate Type STARTUPINFO cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Long hStdInput As Long hStdOutput As Long hStdError As LongEnd Type

Private Type PROCESS_INFORMATION

176

Page 177: Dicas de VB

hProcess As Long hThread As Long dwProcessID As Long dwThreadID As LongEnd Type

Private Declare Function WaitForSingleObject Lib _ "Kernel32" (ByVal hHandle As Long, ByVal _ dwMilliseconds As Long) As LongPrivate Declare Function CreateProcessA Lib _ "Kernel32" (ByVal lpApplicationName As _ Long, ByVal lpCommandLine As String, _ ByVal lpProcessAttributes As Long, ByVal _ lpThreadAttributes As Long, ByVal _ bInheritHandles As Long, ByVal _ dwCreationFlags As Long, ByVal _ lpEnvironment As Long, ByVal _ lpCurrentDirectory As Long, lpStartupInfo _ As STARTUPINFO, lpProcessInformation As _ PROCESS_INFORMATION) As LongPrivate Declare Function CloseHandle Lib "Kernel32" _ (ByVal hObject As Long) As Long

Private Const NORMAL_PRIORITY_CLASS As Long = &H20&Private Const INFINITE As Long = -1&Private Const WAIT_FAILED As Long = &hFFFFFFFFPrivate Const WAIT_TIMEOUT As Long = &h102&Private Const STILL_ACTIVE As Long = &h103&

Private Sub Command1_Click() Dim lRet&, szCommandLine$ Dim ProcInfo As PROCESS_INFORMATION Dim StartProc As STARTUPINFO On Error Resume Next szCommandLine$ = "notepad.exe" StartProc.cb = Len(StartProc) If CreateProcessA(0&, szCommandLine$, 0&, 0&, 1&, _ NORMAL_PRIORITY_CLASS, 0&, 0&, StartProc, _ ProcInfo) Then 'Tá como INFINITE mas pode ser trocado para um 'valor em milisegundos e IRet& testado com WAIT_FAILED, 'WAIT_TIMEOUT e STILL_ACTIVE lRet& = WaitForSingleObject(ProcInfo.hProcess, INFINITE) CloseHandle (ProcInfo.hThread) CloseHandle (ProcInfo.hProcess) MsgBox "Deu Certo" Else MsgBox "Deu Erro" End IfEnd Sub

Tecla ENTER Agindo como TAB'No Form:

'Sete a propriedade KeyPreview do Form como true.'Coloque este código no evento KeyDown do form:

Private Sub Form_KeyDown(KeyCode As Integer, Shift _ As Integer)

177

Page 178: Dicas de VB

If KeyCode = vbKeyReturn then Sendkeys "{Tab}" KeyCode = 0 End IfEnd Sub

Testar caminho da aplicaçãoTestando se o caminho já inclui "\" ou não:

Private Sub Form_Load() Dim Teste As String Dim caminho As String Teste = App.Path If Right(Teste, 1) = "\" Then caminho = "Caminho" Else caminho = "\Caminho" End If Form1.Caption = App.Path & caminhoEnd Sub

Ou de uma forma mais "enxuta":

Private Sub Form_Load() Form1.Caption = App.Path & caminho If Right(App.Path, 1) <> "\" Then Form1.Caption = App.Path & "\" & caminho End IfEnd Sub

Usando as Setas de Movimento Para Mudar de Controle

Para usar as teclas de movimentação como a tecla TAB ou Shift+Tab, coloque a propriedade KeyPreview do Form como True e insira o seguinte código no evento KeyDown:

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) If KeyCode = vbKeyUp Then SendKeys "+{Tab}" KeyCode = 0 ElseIf KeyCode = vbKeyDown Then SendKeys "{Tab}" KeyCode = 0 End IfEnd Sub

Use o Code Profiler para depuração

Algumas vezes, um erro de execução se manifesta apenas após a criação de um EXE e não em tempo de debug. O add-in Code Profiler poderá ajudá-lo.

1) Faça uma cópia do seu fonte.2) Selecione o add-in Code Profiler.3) Selecione o(s) arquivo(s) de código a serem analisados.4) Selecione a opção Line Hit Count.

178

Page 179: Dicas de VB

5) Selecione o botão Add Profiler Code.6) Compile (make EXE) o programa (MYAPP.EXE).7) Execute o seu código com erro.8) Volte ao Code Profiler e selecione View Results

No menu File.

Veja a última linha que foi executada ao ocorrer o erro.Você terá que executar seu código em modo debug enquanto olha os resultados do Code Profiler.

Uso racional do SendKeys

A função SendKeys (que simula o aperto de teclas) adiciona ótimos recursos de "intervenção" do programador na operação do sistema. As teclas podem ser enviadas para um form ou controle (neste caso o controle deverá ter o foco). A rotina abaixo simplifica o processo.

Sub SendKeyTo (KeyValue as String, cCnt as Control) If cCnt.Enabled Then cCnt.SetFocus SendKeys KeyValueEnd Sub

Verificar o Formato de Data Configurado no Windows'Num módulo:Private Declare Function GetSystemDefaultLCID _ Lib "kernel32" () As LongPrivate Declare Function GetLocaleInfo Lib _ "kernel32" Alias "GetLocaleInfoA" ( _ ByVal Locale As Long, ByVal LCType _ As Long, ByVal lpLCData As String, _ ByVal cchData As Long ) As Long

Private Const LOCALE_SSHORTDATE = &H1F

Public Function GetShortDateFormat() As String 'usada como buffer da API Dim FormatString As String * 11

Dim ItWorked As Boolean 'retorno da api 'joga o separador decimal no buffer ItWorked = GetLocaleInfo(GetSystemDefaultLCID, _ LOCALE_SSHORTDATE, FormatString, 11)

'se conseguiu If ItWorked Then 'atribui o mesmo para função GetShortDateFormat = Left(FormatString, _ InStr(FormatString, _ Chr(0)) - 1) Else 'senão atribui vazio para a função GetShortDateFormat = "" End IfEnd Function

'P/ chamar, no evento que você desejar:

179

Page 180: Dicas de VB

txtRet.Text = GetShortDateFormat

Ele retornará algo como "dd/MM/yy".

180

Page 181: Dicas de VB

VARIÁVEIS

Apresentando Corretamente Números no Formato de Moeda

Digamos que você, por exemplo, precise exibir numa TextBox um campo de um banco de dados em formato moeda. Então, temos duas formas de fazer isto. Veja:

'1º Forma:Text1.Text = Format$(RS![Campo], "$###,##0.00;$ ###,##0.00;0;\n\u\l\o")

'2º Forma:Text1.Text = Format$(RS![Campo], "currency")

Atenção na Declaração de Variáveis!!!

Você já deve ter visto a declaração de variáveis da seguinte forma:

Dim Num1, Num2, Num3, Num4 As Integer

Pois bem, declarando desta forma teremos:Num1 => Variável do tipo VARIANT!!!Num2 => Variável do tipo VARIANT!!!Num3 => Variável do tipo VARIANT!!!Num4 => Variável do tipo Integer

As variáveis do tipo Variant aceitam QUALQUER tipo de dados. No entanto, com elas, seu programa perde performance (cerca de 40%! Vide dica "Cuidado com Variáveis Tipo Variant!!!").

Então, a maneira CORRETA de se vazer essa declaração seria:

Dim Num1 As Integer, Num2 As Integer, Num3 As Integer, Num4 As Integer

OU:

Dim Num1 As IntegerDim Num2 As IntegerDim Num3 As IntegerDim Num4 As Integer

By 3D Man®

-----

Outra dica é sempre declare suas variáveis com maiúsculas e minúsculas.

Dim NomeDaVariavel As String, OutraVariavel As String

Ao digitar seu programa, digite-as completamente em minúsculas (nomedavariavel e outravariavel). Após sair da linha alterada o VB automaticamente as transformará para a forma da declaração, lhe dando um input visual de que você escreveu-as corretamente.

181

Page 182: Dicas de VB

Arredondamento numéricoFunction Roun2 (X) Round2 = Int(X * 100 + ,5)/100End Function

Function RoundN (X As Interger, N As Interger) Dim Factor As Long Factor = 10 ^ N RoundN = Int(X * Factor + .5)/ FactorEnd Function

Busca BináriaPublic Function InArray(pArray As Variant, _ pValor As String, Optional pInicio _ As Integer = -1, Optional pFim As _ Integer = -1) As Long Dim intInicio As Integer, intFim As Integer Dim intMeio As Integer

If pInicio = -1 And pFim = -1 Then intInicio = LBound(pArray) intFim = UBound(pArray) Else intInicio = pInicio intFim = pFim End If intMeio = (intInicio + intFim) / 2

If pArray(intMeio) = Val(pValor) Or _ pArray(intInicio) = Val(pValor) Or _ pArray(intFim) = Val(pValor) Then InArray = intMeio Exit Function End If

If intMeio = intInicio Or intMeio = intFim Then InArray = -1 Exit Function End If

If pValor < pArray(intMeio) Then intFim = intMeio Else intInicio = intMeio + 1 End If

InArray = InArray(pArray, pValor, intInicio, _ intFim)End Function

Capturar o formato da Moeda------- OPÇÃO 1Private Declare Function GetLocaleInfo Lib _ "kernel32" Alias "GetLocaleInfoA" ( _ ByVal Locale As Long, ByVal LCType _ As Long, ByVal lpLCData As String, _ ByVal cchData As Long) As Long

182

Page 183: Dicas de VB

Const LOCALE_SCURRENCY As Long = &H14Const LOCALE_SYSTEM_DEFAULT As Long = 0

Private Sub Form_Click() CurrencyFormat$ = Space(100) i% = GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, _ LOCALE_SCURRENCY, CurrencyFormat$, 100) CurrencyFormat$ = Left(CurrencyFormat$, i% - 1) Debug.Print CurrencyFormat$End Sub

------- OPÇÃO 2

Private Sub Form_Click() CurrencyFormat$ = Format(1,"Currency") CurrencyFormat$ = Trim(Left(CurrencyFormat$, _ InStr(CurrencyFormat$,"1")-1))End Sub

Classificar um array em ordem alfabéticaSub OrdemAlfa(sArray(), ByVal ini, ByVal fim) Dim i, j, aux For i = ini to fim - 1 For j = i + 1 to fim If StrComp(sArray(i), sArray(j), 1) = 1 then aux = sArray(i) sArray(i) = sArray(j) sArray(j) = aux End if Next NextEnd Sub

Criar Arrays com Type definido pelo usuário'Na seção geral do formulário:Private Type Carro Pneus As Integer Cor As String Fabricante As String Preço As CurrencyEnd Type

'No procedimento: Dim iNum As Integer, Veiculo() As Carro For iNum = 0 To 10 Redim Preserve Veiculo(iNum) Veiculo(iNum).Pneus = iNum Veiculo(iNum).Cor = "Preto" Veiculo(iNum).Fabricante = "VW" Veiculo(iNum).Preço = iNum Next

183

Page 184: Dicas de VB

Facilitando a Declaração de Variáveis

Existe a instrução DefType q ajuda muito na declaração de variáveis. Essa instrução funciona a nível de módulo para definir o tipo de dados padrão para variáveis, argumentos passados a procedimentos e o tipo de retorno para os procedimentos (Function e Property Get) cujos nomes se iniciem pelos caracteres especificados.

Sintaxe:

DefType Letra, Letra ...

O argumento "Letra" (que é OBRIGATÓRIO) pode ser usado das seguintes formas:

DefType I, N <- Define que TODAS as variáveis iniciadas pelas letras

"I" e "N" serão de determinado tipo. DefType A-E <- Define que TODAS as variáveis iniciadas por letras entre

"A" e "E" serão de determinado tipo.

Veja como colocar o DefType p/ cada tipo de variável:

DefBool -> Tipo BooleanDefByte -> Tipo ByteDefInt -> Tipo IntegerDefLng -> Tipo LongDefCur -> Tipo CurrencyDefSng -> Tipo SingleDefDbl -> Tipo DoubleDefDate -> Tipo DateDefStr -> Tipo StringDefObj -> Tipo ObjectDefVar -> Tipo Variant

Exemplo:

DefInt IDefStr SDefBool BDim iNum, sTexto, bResposta, Acertos

Pois bem, declarando desta forma teremos:

iNum => Variável do tipo IntegersTexto => Variável do tipo StringbResposta => Variável do tipo BooleanAcertos => Variável do tipo Variant

Perceba que não é mais necessário usar o "As Type". Repare também que a variável "Acertos" foi declarada como Variant. Por que isso? Simples! Porque NÃO foi declarado um DefType p/ a letra "A". Então, se tivessemos declarado esta variável com o nome "iAcertos" ela seria declarada como Integer.

184

Page 185: Dicas de VB

Fazendo Alterações em Strings com o Mid

Você provavelmente já conhece a função e o comando Mid, que retorna uma substring com um número específico de caracteres, ou seja, uma parte da string usada como parâmetro.

Mas, você sabe como usar o Mid para substituir caracteres no meio de uma string?

O Mid é uma pequena excentricidade do VB, pois, altera um de seus próprios argumentos. Mas, isto economiza uma série de instruções de concatenação, observe:

Dim MyString As StringMyString = "Todo a Meu Texto"If Mid$(MyString, 6, 1) = "a" Then Mid$(MyString, 6, 1) = "o" 'Substituindo caracterEnd If

Bem, depois dessa rotina, a variável MyString conterá "Todo o Meu Texto" e não mais "Todo a Meu Texto".

Atenção!!!: Este comando só muda um certo número de caracteres pelo mesmo número de caracteres (ex.: se vc for mudar um caracter, como no exemplo anterior, você só poderá troca-lo por UM outro caracter...)!!!

Função para Tira Acentos de Strings'Coloque esta função num módulo ou mesmo no form:Public Function TiraAcentos(ByVal sTexto As String) As String Dim sAcentos(2, 8) As String Dim sCaracter As String Dim bAcentos As Boolean Dim i As Integer, j As Integer

sAcentos(1, 1) = "á" sAcentos(2, 1) = "a" sAcentos(1, 2) = "é" sAcentos(2, 2) = "e" sAcentos(1, 3) = "í" sAcentos(2, 3) = "i" sAcentos(1, 4) = "ó" sAcentos(2, 4) = "o" sAcentos(1, 5) = "ú" sAcentos(2, 5) = "u" sAcentos(1, 6) = "ê" sAcentos(2, 6) = "e" sAcentos(1, 7) = "ô" sAcentos(2, 7) = "o" sAcentos(1, 8) = "ã" sAcentos(2, 8) = "a"

TiraAcentos = sTexto 'Coloca o texto original como retorno

For i = 1 To Len(sTexto) sCaracter = Mid$(sTexto, i, 1) 'Testa cada caracter If Asc(sCaracter) >= 192 And Asc(sCaracter) <= 255 Then bAcentos = True 'Indica a presença de acentos Exit For

185

Page 186: Dicas de VB

End If Next

If bAcentos = True Then 'Comparamos cada caracter com os elementos da matriz For i = 1 To Len(sTexto) For j = 1 To 8 sCaracter = Mid$(sTexto, i, 1) If Asc(sCaracter) >= 192 And Asc(sCaracter) <= 255 Then If sCaracter = sAcentos(1, j) Then Mid$(sTexto, i, 1) = sAcentos(2, j) TiraAcentos = sTexto End If End If Next Next End IfEnd Function

'P/ chamar:Text1.Text = TiraAcentos(Text1.Text)

Função que Inverte Nomes (Sobrenome, Nome)'Num módulo:Public Function Inverte(ByVal sNome As _ String) As String Dim sNom As String Dim iPos As Integer Dim iNum As Integer sNome = Trim(sNome) For iNum = Len(sNome) To 1 Step -1 sNom2 = Mid(sNome, iNum, 1) If sNom2 = " " Then iPos = iNum Exit For End If Next sNom = Right(sNome, (Len(sNome) - _ iPos)) & ", " sNom = sNom + Left(sNome, (iPos - 1)) Inverte = sNomEnd Function

'P/ usar:Dim sResult As StringsResult = Inverte("José Carlos da Silva")

'Então, sResult conterá "Silva, José Carlos da"

Função Replace para VB5.0Private Function Replace(ByVal Texto _ As String, ByVal Isto As String, _ ByVal PorIsto As String) As String Dim i As Long

186

Page 187: Dicas de VB

If Len(Isto) < 1 Then Replace = Texto Exit Function End If

For i = 1 To Len(Texto) If Mid(Texto, i, Len(Isto)) = Isto Then Replace = Replace & PorIsto i = i + (Len(Isto) - 1) Else Replace = Replace & Mid(Texto, i, 1) End If Next iEnd Function

P/ usar, digamos que o TextBox Text1 contenha um texto como "Eu sei lá como isto funciona". Então, depois dessa linha:

Text1.Text Replace(Text1.Text, "sei lá", "não sei")

Text1 passará a conter "Eu não sei como isto funciona"

Detalhe: Neste replace, você pode fazer algo como Replace("Texto","-/-","*") que ele substituirá sem problemas!!!!!!!!

Função Split para o VB5'Num módulo coloque a seguinte função:Public Function Split(ByVal Texto, _ Optional ByVal SearchStr As _ String = " ") As Variant Dim Words() As String, i As Integer Dim j As Integer, k As Integer

If Len(Texto) Then k = 0 i = InStr(Texto, SearchStr) j = 1 Do While i ReDim Preserve Words(0 To k) Words(k) = Mid(Texto, j, i - j) k = k + 1 j = i + 1 i = InStr(j, Texto, SearchStr) Loop ReDim Preserve Words(0 To k) Words(k) = Mid(Texto, j, Len(Texto)) Else 'Fica compatível com o Split() do VB6, 'retornando Ubound() = -1 ReDim Words(-1 To -1) End If Split = WordsEnd Function

'P/ usar, por exemplo: Dim MeuArray As Variant, i As Integer MeuArray = Split("Sei lá|Blá1|Blá2|Blá3", "|") For i = 0 To UBound(MeuArray) txtDestino(i).Text = MeuArray(i)

187

Page 188: Dicas de VB

Primeiras Letras das Palavras de uma String em Maiusculo

Esta função converte o texto para Maiusculo/Minusculo, deixando as primeiras letras das palavras em maiusculo, respeitando as exceções da lingua portuguesa como: de, da, do, das, dos, a, e.

Public Function MMCase(Texto As String) As String Dim sPalavra As String, iPosIni As Integer Dim iPosFim As Integer, sResultado As String iPosIni = 1 Texto = LCase(Texto) & " "

Do Until InStr(iPosIni, Texto, " ") = 0 iPosFim = InStr(iPosIni, Texto, " ") sPalavra = Mid(Texto, iPosIni, iPosFim - iPosIni) iPosIni = iPosFim + 1 If sPalavra <> "de" And sPalavra <> "da" And _ sPalavra <> "do" And sPalavra <> "das" _ And sPalavra <> "dos" And sPalavra <> _ "a" And sPalavra <> "e" Then sPalavra = UCase(Left(sPalavra, 1)) & _ LCase(Mid(sPalavra, 2)) End If sResultado = sResultado & " " & sPalavra Loop MMCase = Trim(sResultado)End Function

'P/ usar:Dim sResult As StringsResult = MMCase("JOSÉ CARLOS DA SILVA")'Ou:sResult = MMCase("josé carlos da silva")'Ou:sResult = MMCase("jOSÉ cARLOS dA sILVA")

Enfim, com isso, sResult conterá "José Carlos da Silva"

Saber as variáveis do ambiente

Para saber as variáveis do ambiente, inclusive o caminho do Windows, use ENVIRON

MsgBox Environ("winbootdir")'Windows (*)MsgBox Environ("TMP")'Windows\TempMsgBox Environ("TEMP")'Windows\TempMsgBox Environ("PROMPT")'Prompt (**)MsgBox Environ("COMSPEC")'COMMAND.COM (***)MsgBox Environ("PATH")'OBJETO SELECIONADO (****)MsgBox Environ("CMDLINE")'WIN (*****)MsgBox Environ("windir")'Windows (*)

* = Caminho do Windows** = Configuração do Prompt*** = Command.com do Windows (ex.: C:\Windows\command.com)

188

Page 189: Dicas de VB

**** = Mouse, CDROM, etc.***** = Chamada do Windows pela linha de comando

>>>>> Se ENVIRON retornar "" é porque a variável do ambiente não foi encontrada.>>>>> ENVIRON pode ser chamada com argumento numérico por um FOR

Ex.: Dim VarAmbiente() As String, I_Num As Integer For I_Num = 1 To 10 If Environ(I_Num) <> "" Then Redim Preserve VarAmbiente(I_Num) VarAmbiente(I_Num) = Environ(I_Num) End If Next

189

Page 190: Dicas de VB

WINDOWS

Abrir a janela propriedades do sistema

Dim lngInfo As LonglngInfo = Shell("rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl, , 0")

Abrir arquivo com o programa que o criouPublic Const SW_SHOW As Long = 5Declare Function ShellExecute Lib "shell32.dll" Alias _ "ShellExecuteA" ( ByVal hwnd As Long, ByVal _ lpOperation As String, ByVal lpFile As String, _ ByVal lpParameters As String, ByVal lpDirectory _ As String, ByVal nShowCmd As Long) As Long

Private Sub Button_Click() dim i& i& = ShellExecute(0,"open",CaminhoArquivoWord,"","",SW_SHOW)End Sub

Capturar Tela e Salvar em Arquivo

Adicione num Form um PictureBox (Picture1) e dois CommandButtons (Command1 q vai capturar a tela e Command2 q vai salvar o conteúdo de Picture1 no arquivo "C:\Teste.BMP") e coloque este código:

Private Declare Sub keybd_event Lib "user32" _ (ByVal bVk As Byte, ByVal bScan As _ Byte, ByVal dwFlags As Long, ByVal _ dwExtraInfo As Long)

Private Sub Command1_Click() 'P/ capturar a tela: Picture1.AutoSize = True keybd_event vbKeySnapshot, 1, 0&, 0& DoEvents Picture1.Picture = Clipboard.GetData(vbCFBitmap)End Sub

Private Sub Command2_Click() 'P/ salvar a imagem: SavePicture Picture1.Image, "C:\Teste.BMP"

Chamando o ScreenSaver Através de API'Num módulo:

#If Win32 Then Private Declare Function SendMessage Lib _ "user32" Alias "SendMessageA" _ (ByVal hWnd As Long, ByVal wMsg _ As Long, ByVal wParam As Long, _ ByVal lParam As Long) As Long Const WM_SYSCOMMAND = &H112& Const SC_SCREENSAVE = &HF140&

190

Page 191: Dicas de VB

#Else Private Declare Function SendMessage Lib _ "User" (ByVal hWnd As Integer, _ ByVal wMsg As Integer, ByVal _ wParam As Integer, lParam As Any) _ As Long Const WM_SYSCOMMAND = &H112 Const SC_SCREENSAVE = &HF140&#End If

'Para chamar o ScreenSaver, use o código a'seguir:

Dim result As Longresult = SendMessage(Form1.hWnd, WM_SYSCOMMAND, _ SC_SCREENSAVE, 0&)

Chamando Telas Específicas do Painel de Controle

Para chamar qualquer tela do Painel de Controle não se usa necessariamente uma API, mas sim se executa o programa rundll32.exe. De acordo com os parâmetros cada tela é chamada. Veja as chamadas das principais telas:

'Para chamar a tela principal do Painel de Controle:Call Shell("rundll32.exe shell32.dll,Control_RunDLL", _ vbNormalFocus)

'Para chamar a tela Adicionar ou Remover Programas:Call Shell("rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,1", _ vbNormalFocus)

'Para chamar a tela Adicionar ou Remover Programas, na aba'Instalação do Windows:Call Shell("rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,2", _ vbNormalFocus)

'Para chamar a tela Adicionar ou Remover Programas, na aba'Disco de Inicialização:Call Shell("rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,3", _ vbNormalFocus)

'Para chamar a tela Vídeo, na aba Segundo Plano:Call Shell("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0", _ vbNormalFocus)

'Para chamar a tela Vídeo, na aba Proteção de Tela:Call Shell("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,1", _ vbNormalFocus)

'Para chamar a tela Vídeo, na aba Aparência:Call Shell("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,2", _ vbNormalFocus)

'Para chamar a tela Vídeo, na aba Configuração:Call Shell("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,3", _ vbNormalFocus)

'Para chamar a tela Configurações Regionais, na aba'Configurações Regionais:

191

Page 192: Dicas de VB

Call Shell("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,0", _ vbNormalFocus)

'Para chamar a tela Configurações Regionais, na aba'Número:Call Shell("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,1", _ vbNormalFocus)

'Para chamar a tela Configurações Regionais, na aba'Moeda:Call Shell("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,2", _ vbNormalFocus)

'Para chamar a tela Configurações Regionais, na aba'Hora:Call Shell("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,3", _ vbNormalFocus)

'Para chamar a tela Configurações Regionais, na aba'Data:Call Shell("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,4", _ vbNormalFocus)

'Para chamar a tela Joystick:Call Shell("rundll32.exe shell32.dll,Control_RunDLL joy.cpl", _ vbNormalFocus)

'Para chamar a tela Mouse:Call Shell("rundll32.exe shell32.dll,Control_RunDLL main.cpl @0", _ vbNormalFocus)

'Para chamar a tela Teclado:Call Shell("rundll32.exe shell32.dll,Control_RunDLL main.cpl @1", _ vbNormalFocus)

'Para chamar a tela Impressoras:Call Shell("rundll32.exe shell32.dll,Control_RunDLL main.cpl @2", _ vbNormalFocus)

'Para chamar a tela Fontes:Call Shell("rundll32.exe shell32.dll,Control_RunDLL main.cpl @3", _ vbNormalFocus)

'Para chamar a tela Mail e Fax:Call Shell("rundll32.exe shell32.dll,Control_RunDLL mlcfg32.cpl", _ vbNormalFocus)

'Para chamar a tela Multimídia, na aba Audio:Call Shell("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,0", _ vbNormalFocus)

'Para chamar a tela Multimídia, na aba Vídeo:Call Shell("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,1", _ vbNormalFocus)

'Para chamar a tela Multimídia, na aba MIDI:Call Shell("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,2", _ vbNormalFocus)

'Para chamar a tela Multimídia, na aba Música de CD:Call Shell("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,3", _

192

Page 193: Dicas de VB

vbNormalFocus)

'Para chamar a tela Multimídia, na aba Dispositivos:Call Shell("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,4", _ vbNormalFocus)

'Para chamar a tela Som:Call Shell("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl @1", _ vbNormalFocus)

'Para chamar a tela Modem:Call Shell("rundll32.exe shell32.dll,Control_RunDLL modem.cpl", _ vbNormalFocus)

'Para chamar a tela Rede:Call Shell("rundll32.exe shell32.dll,Control_RunDLL netcpl.cpl", _ vbNormalFocus)

'Para chamar a tela Senhas:Call Shell("rundll32.exe shell32.dll,Control_RunDLL password.cpl", _ vbNormalFocus)

'Para chamar a tela Sistema, na aba Geral:Call Shell("rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,0", _ vbNormalFocus)

'Para chamar a tela Sistema, na aba Gerenciador'de Dispositivos:Call Shell("rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,1", _ vbNormalFocus)

'Para chamar a tela Sistema, na aba Perfis deHardware:Call Shell("rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,2", _ vbNormalFocus)

'Para chamar a tela Sistema, na aba Performance:Call Shell("rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,3", _ vbNormalFocus)

'Para chamar a tela Opções de Acessibilidade, na aba'Teclado:Call Shell("rundll32.exe shell32.dll,Control_RunDLL access.cpl,,1", _ vbNormalFocus)

'Para chamar a tela Opções de Acessibilidade, na aba'Som:Call Shell("rundll32.exe shell32.dll,Control_RunDLL access.cpl,,2", _ vbNormalFocus)

'Para chamar a tela Opções de Acessibilidade, na aba'Vídeo:Call Shell("rundll32.exe shell32.dll,Control_RunDLL access.cpl,,3", _ vbNormalFocus)

'Para chamar a tela Opções de Acessibilidade, na aba'Mouse:Call Shell("rundll32.exe shell32.dll,Control_RunDLL access.cpl,,4", _ vbNormalFocus)

'Para chamar a tela Opções de Acessibilidade, na aba

193

Page 194: Dicas de VB

'Geral:Call Shell("rundll32.exe shell32.dll,Control_RunDLL access.cpl,,5", _ vbNormalFocus)

'Para chamar a tela do Assistente (Adicionar novo'Hardware):Call Shell("rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl @1", _ vbNormalFocus)

'Para chamar a tela Data e Hora:Call Shell("rundll32.exe shell32.dll,Control_RunDLL timedate.cpl", _ vbNormalFocus)

'Para chamar a tela DiskCopy:Call Shell("rundll32 diskcopy.dll,DiskCopyRunDll", _ vbNormalFocus)

Como associar uma extensão ao programa

'*** Sempre tome muito cuidado, pois estarás mechendo no Registro do Windows. ***'Coloque num Modulo

'General DeclarationsPublic Type mnuCommands Captions As New Collection Commands As New CollectionEnd Type

Public Type filetype Commands As mnuCommands Extension As String ProperName As String FullName As String ContentType As String IconPath As String IconIndex As IntegerEnd Type

Public Const REG_SZ As Long = 1Public Const HKEY_CLASSES_ROOT As Long = &H80000000

Public Declare Function RegCloseKey Lib "advapi32.dll" _ (ByVal hKey As Long) As LongPublic Declare Function RegCreateKey Lib "advapi32" _ Alias "RegCreateKeyA" (ByVal hKey As Long, ByVal _ lpszSubKey As String, phkResult As Long) As LongPublic Declare Function RegSetValueEx Lib "advapi32" _ Alias "RegSetValueExA" (ByVal hKey As Long, _ ByVal lpszValueName As String, ByVal dwReserved _ As Long, ByVal fdwType As Long, lpbData As Any, _ ByVal cbData As Long) As Long

'Código do Módulo:Public Sub CreateExtension(newfiletype As filetype) Dim IconString As String Dim Result As Long, Result2 As Long, ResultX As Long Dim ReturnValue As Long, HKeyX As Long

194

Page 195: Dicas de VB

Dim cmdloop As Integer IconString = newfiletype.IconPath & "," & _ newfiletype.IconIndex If Left$(newfiletype.Extension, 1) <> "." Then newfiletype.Extension = "." & _ newfiletype.Extension End If RegCreateKey HKEY_CLASSES_ROOT,newfiletype.Extension,Result ReturnValue = RegSetValueEx(Result, "", 0, REG_SZ, _ ByVal newfiletype.ProperName, _ LenB(StrConv(newfiletype.ProperName, _ vbFromUnicode)))

' Acertando o conteúdo If newfiletype.ContentType <> "" Then ReturnValue = RegSetValueEx(Result, "Content Type", 0, _ REG_SZ, ByVal CStr(newfiletype.ContentType), _ LenB(StrConv(newfiletype.ContentType, _ vbFromUnicode))) End If RegCreateKey HKEY_CLASSES_ROOT,newfiletype.ProperName,Result If Not IconString = ",0" Then RegCreateKey Result, "DefaultIcon", Result2

'Cria a chave do "ProperName\DefaultIcon" ReturnValue = RegSetValueEx(Result2, "", 0, REG_SZ, _ ByVal IconString, LenB(StrConv(IconString, _ vbFromUnicode))) End If

'Atribuir o valor padrão para a chave ReturnValue = RegSetValueEx(Result, "", 0, REG_SZ, ByVal _ newfiletype.FullName,LenB(StrConv(newfiletype.FullName, _ vbFromUnicode))) RegCreateKey Result, ByVal "Shell", ResultX

' Criando as subkeys necessárias para cada comando For cmdloop = 1 To newfiletype.Commands.Captions.Count RegCreateKey ResultX, ByVal newfiletype.Commands.Captions(cmdloop), _ Result RegCreateKey Result, ByVal "Command", Result2

Dim CurrentCommand$ CurrentCommand = newfiletype.Commands.Commands(cmdloop) ReturnValue = RegSetValueEx(Result2, "", 0, REG_SZ, _ ByVal CurrentCommand$, LenB(StrConv(CurrentCommand$, _ vbFromUnicode))) RegCloseKey Result RegCloseKey Result2 Next RegCloseKey Result2End Sub

'Então, para associar a Extensão ".MEX" ao Notepad.exe utilize o segunite código: Dim myfiletype As filetype myfiletype.ProperName = "MeuArquivo" myfiletype.FullName = "Meu Arquivo" myfiletype.ContentType = "AlgumTipoMIME" myfiletype.Extension = ".MEX" '<< Sua Extensão myfiletype.Commands.Captions.Add "Open"

195

Page 196: Dicas de VB

myfiletype.Commands.Commands.Add "c:\windows\notepad.exe ""%1""" myfiletype.Commands.Captions.Add "Print" myfiletype.Commands.Commands.Add "c:\windows\notepad.exe ""%1"" /P" CreateExtension myfiletype

'Extension contem a extensão que se deseja associar; 'Propername é o nome do tipo, que você se referenciará '(não use espaços) 'FullName é a descrição do Tipo

'ContentType é a descrição que verás em seu browser, caso 'estivesse para fazer o download de um arquivo deste tipo.

'Você pode pensar na extensão como um "atalho", o '"proper name" como o "nome" mesmo e o "fullname" como 'o "título" ou "caption" da exensão.

'Esses "Commands" contêm os "verbos" para o seu tipo. Quando 'você clica com o direito sobre este tipo de arquivo, você 'verá estas opção (verbos). O "Open" foi atribuido como "verbo" 'padrão, assim quando der um duplo clique sobre o arquivo, ele 'executará o comando associado ao "Open".

Como Fazer Logoff, Desligar ou Reiniciar o Computador pelo VB'Num módulo:Public Declare Function ExitWindowsEx Lib "user32" _ Alias "ExitWindowsEx" (ByVal uFlags As Long, _ ByVal dwReserved As Long) As Long

Public Const EWX_LOGOFF As Long = 0 'Faz Logoff do usuário.Public Const EWX_SHUTDOWN As Long = 1 'Desligar o compitador.Public Const EWX_REBOOT As Long = 2 'Reiniciar o computador.Public Const EWX_FORCE As Long = 4 'Força a ação desejada.

'No evento que você desejar:Dim RET as Long'P/ fazer logoff do usuário:RET = ExitWindowsEx(EWX_LOGOFF, 0)'P/ desligar o computador:RET = ExitWindowsEx(EWX_SHUTDOWN, 0)'P/ reiniciar o computadorRET = ExitWindowsEx(EWX_REBOOT, 0)

'Se você quizer "forçar" a ação a ser executada, faça'da seguinte maneira:

'P/ fazer logon com outro usuário:RET = ExitWindowsEx(EWX_FORCE Or EWX_LOGOFF, 0)'P/ desligar o computador:RET = ExitWindowsEx(EWX_FORCE Or EWX_SHUTDOWN, 0)'P/ reiniciar o computadorRET = ExitWindowsEx(EWX_FORCE Or EWX_REBOOT, 0)'P/ reiniciar o computadorRET = ExitWindowsEx(EWX_FORCE Or EWX_REBOOT, 0)

196

Page 197: Dicas de VB

Criar atalho para arquivo facilmentetxtCamNormal.LinkTopic = "Progman|Progman"txtCamNormal.LinkMode = 2txtCamNormal.LinkExecute "[CreateGroup(Iniciar, 1)] " & _ "[AddItem(c:\windows\calc.exe, " & _ "Calculadora criada via DDE)]"

Executar um programa DOSShell ("Command.com /C MeuProgramaDOS.exe", vbHide)

O /C fecha a janela DOS após o aplicativo rodar e o vbHide mantem a janela oculta durante a execução.

Impedir que o programa apareça nos processos do windows

1 - Coloque para false a propriedade ShowInTaskbar do Form

2 - Em um módulo declare:

Public Declare Function ShowWindow Lib "user32" _ Alias "ShowWindow" (ByVal hwnd As Long, _ ByVal nCmdShow As Long) As Long Public Const SW_HIDE As Long = 0

3 - No Form_Load adicione:

Dim RetValue as Long RetValue = ShowWindow(Me.hWnd, SW_HIDE)

Impedir que o programa seja encerrado com Ctrl+Alt+Del'Declara o seguinte em um Módulo:

Public Declare Function GetCurrentProcessId Lib _ "kernel32" () As LongPublic Declare Function GetCurrentProcess Lib _ "kernel32" () As LongPublic Declare Function RegisterServiceProcess _ Lib "kernel32" (ByVal dwProcessID As Long, _ ByVal dwType As Long) As Long

Public Const RSP_SIMPLE_SERVICE As Long = 1Public Const RSP_UNREGISTER_SERVICE As Long = 0

'Crie a seguinte Sub:Public Sub MakeMeService() Dim pid As Long Dim reserv As Long pid = GetCurrentProcessId() reserv = RegisterServiceProcess(pid,RSP_SIMPLE_SERVICE)End Sub

'Depois coloque o seguinte no FORM_LOAD:Private Form_Load() MakeMeServiceEnd Sub

197

Page 198: Dicas de VB

Limpando a Lixeira pelo VB Através de API'Num módulo:

Private Declare Function SHEmptyRecycleBin _ Lib "shell32.dll" Alias _ "SHEmptyRecycleBinA" (ByVal hwnd As _ Long, ByVal pszRootPath As String, _ ByVal dwFlags As Long) As Long'Execução normalPrivate Const SHERB_NORMAL = &H0'Executar sem confirmaçãoPrivate Const SHERB_NOCONFIRMATION = &H1'Executar sem mostrar o progressoPrivate Const SHERB_NOPROGRESSUI = &H2'Execução sem somPrivate Const SHERB_NOSOUND = &H4Private Const SHERB_NOALL = (SHERB_NOCONFIRMATION _ And SHERB_NOPROGRESSUI _ And SHERB_NOSOUND)Dim RetVal As Long

Public Sub EmpRecBin() RetVal = SHEmptyRecycleBin(0&, _ vbNullString, SHERB_NORMAL)End Sub

Você pode alterar esta função, trocando a constante SHERB_NORMAL, que é passada à API SHEmptyRecycleBin, pelas outras, conforme sua necessidade.

Minimizar um Programa Para o System Tray'Num Módulo:

Public Declare Function Shell_NotifyIcon Lib _ "shell32.dll" Alias "Shell_NotifyIconA" _ (ByVal dwMessage As Long, lpData As _ NOTIFYICONDATA) As Long

Public Type NOTIFYICONDATA cbSize As Long Hwnd As Long uID As Long uFlags As Long uCallbackMessage As Long hIcon As Long szTip As String * 64End Type

Public Const WM_LBUTTONDOWN = &H201Public Const WM_LBUTTONDBLCLK = &H203Public Const WM_RBUTTONDOWN = &H204Public Const WM_RBUTTONDBLCLK = &H206

Public Const NIM_ADD = &H0Public Const NIM_DELETE = &H2Public Const NIM_MODIFY = &H1Public Const NIF_ICON = &H2Public Const NIF_MESSAGE = &H1Public Const NIF_TIP = &H4

198

Page 199: Dicas de VB

Public Enum Actions TrayAdd = &H0 TrayModify = &H1 TrayDelete = &H2End Enum

Public Sub SysTray(Action As Actions, Hwnd As _ Long, ToolTip As String, Icon As _ StdPicture) Dim STray As NOTIFYICONDATA STray.uID = vbNull STray.uCallbackMessage = &H200 STray.Hwnd = Hwnd STray.hIcon = Icon STray.szTip = ToolTip & vbNullChar STray.uFlags = NIF_MESSAGE Or NIF_ICON Or _ NIF_TIP STray.cbSize = Len(STray) Select Case Action Case NIM_ADD Call Shell_NotifyIcon(NIM_ADD, STray) Case NIM_MODIFY Call Shell_NotifyIcon(NIM_MODIFY, STray) Case NIM_DELETE Call Shell_NotifyIcon(NIM_DELETE, STray) End SelectEnd Sub

'No Form, coloque o seguinte código:

Private Sub Form_Resize() If Me.WindowState = 1 Then Call SysTray(TrayAdd, Me.Hwnd, Me.Caption, _ Me.Icon) End IfEnd Sub

Private Sub Form_MouseMove(Button As Integer, _ Shift As Integer, X As Single, Y As _ Single) Dim Msg As Long If (Button + Shift + Y) = 0 Then Msg = X / Screen.TwipsPerPixelX Select Case Msg Case WM_LBUTTONDOWN 'Coloque aqui a rotina a ser executada 'quando ocorrer um clique com o botão 'esquerdo no icon do System Tray. Case WM_LBUTTONDBLCLK 'Coloque aqui a rotina a ser executada 'quando ocorrer um duplo clique com o 'botão esquerdo no icon do System Tray. 'Neste exemplo, a janela será restaurada 'e o ícone retirado so System Tray. Me.WindowState = 0 Call SysTray(TrayDelete, Me.Hwnd, _ Me.Caption, Me.Icon) Me.SetFocus Case WM_RBUTTONDOWN 'Coloque aqui a rotina a ser executada 'quando ocorrer um clique com o botão

199

Page 200: Dicas de VB

'direito do rato no icon do System Tray. Case WM_RBUTTONDBLCLK 'Coloque aqui a rotina a ser executada 'quando ocorrer um duplo clique com o 'botão direito do rato no icon do System 'Tray. End Select End If'Se você precisar colocar algum outro código neste'evento, pode coloca-lo aqui sem maiores problemas.End Sub

PRONTO!!!!! Agora é só executar!!! 8^)

Detalhe, você também pode adicionar este ícone ao System Tray quando o seu programa iniciar e só retira-lo quando o programa terminar. Neste caso, proceda da seguinte forma:

Private Sub Form_Load() Call SysTray(TrayAdd, Me.Hwnd, Me.Caption, Me.Icon)End Sub

Private Sub Form_QueryUnload(Cancel As Integer, _ UnloadMode As Integer) Call SysTray(TrayDelete, Me.Hwnd, Me.Caption, _ Me.Icon)End Sub

Private Sub Form_MouseMove(Button As Integer, _ Shift As Integer, X As Single, Y As _ Single) Dim Msg As Long If (Button + Shift + Y) = 0 Then Msg = X / Screen.TwipsPerPixelX Select Case Msg Case WM_LBUTTONDOWN 'Coloque aqui a rotina a ser executada 'quando ocorrer um clique com o botão 'esquerdo no icon do System Tray. Case WM_LBUTTONDBLCLK 'Coloque aqui a rotina a ser executada 'quando ocorrer um duplo clique com o 'botão esquerdo no icon do System Tray. 'Neste exemplo, a janela será restaurada 'e o ícone retirado so System Tray. Me.WindowState = 0 Me.SetFocus Case WM_RBUTTONDOWN 'Coloque aqui a rotina a ser executada 'quando ocorrer um clique com o botão 'direito do rato no icon do System Tray. Case WM_RBUTTONDBLCLK 'Coloque aqui a rotina a ser executada 'quando ocorrer um duplo clique com o 'botão direito do rato no icon do System 'Tray. End Select End If'Se você precisar colocar algum outro código neste'evento, pode coloca-lo aqui sem maiores problemas.

200

Page 201: Dicas de VB

End Sub

Mudando a Resolução de vídeo'Num módulo:

Private Declare Function EnumDisplaySettings Lib _ "user32" Alias "EnumDisplaySettingsA" _ (ByVal lpszDeviceName As Long, ByVal _ iModeNum As Long, lpDevMode As Any) As _ Boolean

Private Declare Function ChangeDisplaySettings Lib _ "user32" Alias "ChangeDisplaySettingsA" _ (lpDevMode As Any, ByVal dwflags As Long) _ As Long

Private Const CCDEVICENAME = 32Private Const CCFORMNAME = 32Private Const DM_PELSWIDTH = &H80000Private Const DM_PELSHEIGHT = &H100000

Private Type DEVMODE dmDeviceName As String * CCDEVICENAME dmSpecVersion As Integer dmDriverVersion As Integer dmSize As Integer dmDriverExtra As Integer dmFields As Long dmOrientation As Integer dmPaperSize As Integer dmPaperLength As Integer dmPaperWidth As Integer dmScale As Integer dmCopies As Integer dmDefaultSource As Integer dmPrintQuality As Integer dmColor As Integer dmDuplex As Integer dmYResolution As Integer dmTTOption As Integer dmCollate As Integer dmFormName As String * CCFORMNAME dmUnusedPadding As Integer dmBitsPerPel As Integer dmPelsWidth As Long dmPelsHeight As Long dmDisplayFlags As Long dmDisplayFrequency As LongEnd Type

Public Sub ChangeRes(iWidth As Single, iHeight _ As Single) Dim DevM As DEVMODE Dim a As Boolean Dim i As Long Dim b As Long i = 0 Do

201

Page 202: Dicas de VB

a = EnumDisplaySettings(0&, i&, DevM) i = i + 1 Loop Until (a = False) DevM.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT DevM.dmPelsWidth = iWidth DevM.dmPelsHeight = iHeight b = ChangeDisplaySettings(DevM, 0)End Sub

'P/ fazer a chamada:

Call ChangeRes(800, 600)

Só coloque resoluçoes q o monitor suporta, senão alguns arquivos poderão ser corrompidos...

Mudando o Papel de Parede pelo VB'Coloque isto num modulo

Private Declare Function SystemParametersInfo Lib _ "User32" Alias "SystemParametersInfoA" _ (ByVal uAction As Long, ByVal uParam As _ Long, ByVal lpvParam As String, ByVal _ fuWinIni As Long) As Long

Public Const SPIF_UPDATEINIFILE As Long = &H1Public Const SPI_SETDESKWALLPAPER As Long = 20Public Const SPIF_SENDWININICHANGE As Long = &H2

Public Sub SetWallpaper(ByVal sArquivo As String) Dim RT as long RT = SystemParametersInfo(SPI_SETDESKWALLPAPER, _ 0&, sArquivo, SPIF_UPDATEINIFILE Or _ SPIF_SENDWININICHANGE)End Sub

'P/ chamar:Call SetWallpaper NomeDoArquivo'ATENÇÃO!!! Passe o nome do arquivo com o caminho'completo!'Exemplo:Call SetWallpaper "C:\Windows\Desenho.BMP"

Mudar a definição de data do WindowsPrivate Declare Function SetLocaleInfo Lib "kernel32" _ Alias "SetLocaleInfoA" (ByVal Locale As Long, _ ByVal LCType As Long, ByVal lpLCData As String) _ As BooleanPrivate Declare Function PostMessage Lib "user32" Alias _ "PostMessageA" (ByVal hwnd As Long, ByVal wMsg _ As Long, ByVal wParam As Long, ByVal lParam As _ Long) As LongPrivate Declare Function GetSystemDefaultLCID Lib _ "kernel32" () As Long

Private Const LOCALE_SSHORTDATE As Long = &H1FPrivate Const WM_SETTINGCHANGE As Long = &H1APrivate Const HWND_BROADCAST As Long = &HFFFF&

202

Page 203: Dicas de VB

Private Sub Command1_Click() Dim dwLCID As Long

dwLCID = GetSystemDefaultLCID() If SetLocaleInfo(dwLCID,LOCALE_SSHORTDATE,"dd/mmm/yyyy")=False Then MsgBox "Erro na definição da data." Exit Sub End If PostMessage HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0

Ocultar/Mostrar a Barra de Tarefas do Windows'Num módulo:Option ExplicitPublic Declare Function FindWindow Lib _ "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, _ ByVal lpWindowName As String) _ As LongPublic Declare Function SetWindowPos _ Lib "user32" (ByVal hwnd As _ Long, ByVal hWndInsertAfter As _ Long, ByVal x As Long, ByVal y _ As Long, ByVal cx As Long, _ ByVal cy As Long, ByVal wFlags _ As Long) As LongPublic Const SWP_HIDEWINDOW As Long = &H80Public Const SWP_SHOWWINDOW As Long = &H40Public lRet As Long

'Insira o cogigo abaixo num Form:

Private Sub Form_Load( ) lRet = FindWindow("Shell_traywnd", "") 'Esconde a barra de tarefas Call SetWindowPos(lRet, 0, 0, 0, 0, 0, _ SWP_HIDEWINDOW)End Sub

Private Sub Form_Unload(Cancel As Integer) 'Como a variável lRet foi declarada como 'Public e já contém o Handle da barra de 'tarefas do Windows, não será necessário 'usar a API FindWindows de novo...

'Restaura a barra de tarefas Call SetWindowPos(lRet, 0, 0, 0, 0, 0, _ SWP_SHOWWINDOW)End Sub

Quando você iniciar o seu programa, ele esconderá a barra de tarefas do Windows e, quando você finaliza-lo, ele irá exibi-la novamente.

203

Page 204: Dicas de VB

Usando a Área de Transferencia

O objeto Clipboard tem algumas funções p/ copiar algo p/ a área de transferencia, como também funções p/ se recuperar o que tem nela.Vejamos então quais são estas funções:

Comando:Clear <- Limpa o conteúdo da área de transferencia.

Sintaxe:Clipboard.Clear

Comando:GetFormat <- Retorna True se um item na área de transferencia corresponde ao formato especificado. Caso contrário, ele retorna False.

Sintaxe:Clipboard.GetFormat (format)

Parametro format: OBRIGATÓRIO. Uma constante ou valor que especifique um dos formatos de elementos reconhecidos pelo VB. Esta constante ou valor deve estar entre parênteses.Constantes do Parametro format:

Constante Valor DescriçãovbCFLink &HBF00 Informações de conversação DDEvbCFText 1 TextovbCFBitmap 2 Bitmap (arquivos .BMP)vbCFMetafile 3 Metarquivo (arquivos .WMF)vbCFDIB 8 Bitmap independente de dispositivo (DIB)vbCFPalette 9 Paleta de cores

Exemplo:

If Clipboard.GetFormat(vbCFText) Then Text1.Text = "A área de transferencia contém um texto"EndIfIf Clipboard.GetFormat(vbCFBitmap) Then Text1.Text = "A área de transferencia contém uma imagem Bitmap"EndIf

Comando:GetData <- Retorna um objeto gráfico (imagem) da área de transferencia.

Sintaxe:Clipboard.GetData (format)

Parametro format: OPCIONAL. Uma constante ou valor que especifiqueum dos formatos de elementos gráficos reconhecidospelo VB. Se format for 0 ou omitido, GetData usaautomaticamente o formato adequado. A constanteou valor deve estar entre parêntesesConstantes do Parametro format:

Constante Valor DescriçãovbCFBitmap 2 Bitmap (arquivos .BMP)vbCFMetafile 3 Metarquivo (arquivos .WMF)

204

Page 205: Dicas de VB

vbCFDIB 8 Bitmap independente de dispositivo (DIB)vbCFPalette 9 Paleta de cores

Observações: Caso não exista nenhum elemento gráfico na área de transferencia corresponde ao formato especificado, nada será retornado. Se, na área de transferencia, estiver presente somente uma paleta de cores um DIB de tamanho mínimo (1 x 1) será criado.

Exemplo:Set Pricture1.Picture = Clipboard.GetData()

Comando:GetText <- Retorna um texto a partir da área de transferencia.

Sintaxe:Clipboard.GetText (format)

Parametro format: OPICIONAL. Um valor ou constante que especifica um dos formatos reconhecidos pelo VB. O valor ou constante deve estar entre parênteses.Constantes do Parametro format:

Constante Valor DescriçãovbCFLink &HBF00 Informações de conversação DDEvbCFRTF &HBF01 RichText Format (arquivo .RTF)vbCFText 1 (Padrão) texto

Observações: Caso não exista nenhum texto na área de transferencia corresponde ao formato especificado, será retornada um texto de comprimento zero ("").

Exemplo:Text1.Text = Clipboard.GetText(vbCFText)

Comando:SetData <- Coloca uma figura na área de transferencia usando o formato gráfico especificado.

Sintaxe:Clipboard.SetData data, format

Parametro data: OBRIGATÓRIO. Imagem a ser copiada.Parametro format: OPCIONAL. Uma constante ou valor que especifique um dos formatos de elementos gráficos reconhecidos pelo VB. Caso format for omitido, SetDatadetermina automaticamente o formato.Constantes do Parametro format:

Constante Valor DescriçãovbCFBitmap 2 Bitmap (arquivos .BMP)vbCFMetafile 3 Metarquivo (arquivos .WMF)vbCFDIB 8 Bitmap independente de dispositivo (DIB)vbCFPalette 9 Paleta de cores

Exemplo:Clipboard.SetData Picture1.Picture, vbCFBitmap

205

Page 206: Dicas de VB

Comando:SetText <- Copia um texto p/ a área de transferencia.

Sintaxe:Clipboard.SetText data, format

Parametro data: OBRIGATÓRIO. Texto a ser copiado.Parametro format: OPCIONAL. Uma constante ou valor que especifique um dos formatos reconhecidos pelo VB.Constantes do Parametro format:

Constante Valor DescriçãovbCFLink &HBF00 Informações de conversação DDEvbCFRTF &HBF01 RichText Format (arquivo .RTF)vbCFText 1 (Padrão) texto

Exemplo:Clipboard.SetText Text1.Text, vbCFText

Atenção:* Quando você quizer copiar algo p/ a área de transferencia, ANTES da cópia, limpe-a.* Quando você for recuperar algo da área de transferencia com o comando GetData ou SetData, ANTES verifique qual o formato do conteúdo da área de transferencia com o comando GetFormat.

Usando a Caixa "Sobre" Padrão do Windows'Num módulo:Private Declare Function ShellAbout Lib _ "shell32.dll" Alias "ShellAboutA" _ (ByVal hwnd As Long, ByVal szApp _ As String, ByVal szOtherStuff As _ String, ByVal hIcon As Long) As Long

Private Function WinAbout(ByVal l_hWnd _ As Long, ByRef pIcon As _ StdPicture, Optional ByVal _ sCopyright As String) As Boolean Dim lRet As Long lRet = ShellAbout(l_hWnd, App.ProductName & _ " ", sCopyright, pIcon) WinAbout = lRetEnd Function

'No evento que você desejar chamar a tela'de About: Dim bRET As Boolean bRET = WinAbout(Me.hwnd, Me.Icon, _ "MinhaMarca Ltda.") If bRET = True Then MsgBox "A tela de About foi exibida " & _ "sem problemas.", vbInformation Else MsgBox "Houve algum erro e a tela de " & _ "About não foi exibida.", _ vbInformation End If

206

Page 207: Dicas de VB

Detalhe: Para que esta função exiba o nome do programa, preencha o campo "Product Name" na aba "Make" da tela de propriedades do projeto.

Usando a Função Environ$

Um exemplo de uso desta função seria p/ recuperar o diretório do Windows (sem API). Veja:

'No evento que você queira: Dim WinDir As String WinDir = Environ$("WinDir")

Ele retorna algo como "C:\WINDOWS".

A função Environ$() retorna uma string associada a uma variável de ambiente do Windows.

Sintaxe:

Environ$({EnvString | Number})

EnvString - É a string q vc vai chamar pra descobrir o seu valor (no exemplo anterior era "WinDir", pra descobrir o diretório do Windows.Number - é o número (índice) da variável de ambiente.

Se você quizer saber todas as variáveis de ambiente e seus respectivos valores, é só criar um Form e colar esse código dentro dele; as variáveis serão listadas na janela de debug (Immediate).

Private Sub Form_Load() Dim EnvString As String Dim Indx As Byte Indx = 1 Do Debug.Print Indx & " - " & EnvString EnvString = Environ(Indx) Indx = Indx + 1 Loop Until EnvString = ""End Sub

Usando o Registro do Windows (Registry)

Quando nós ouvimos falar em "Registro do Windows" ou "Windows Registry", logo imaginamos que seja algo "de outro mundo"... Mas não é. Na verdade, é muito simples de se usar o Registro do Windows.Para facilitar na manutenção desses registros, o VB tem 3 funções:

Função(ões)Ação

SaveSettingSalvar configurações de programa.

GetSetting, GetAllSettings Ler configurações de programa.

DeleteSettingExcluir configurações de programa.

207

Page 208: Dicas de VB

Então, vejamos como funcionam essas funções:

SaveSetting:============Salva informações no registro do Windows seguindo alguns parâmetros.

Sintaxe:SaveSetting [Nome do Aplicativo], [Seção], [Chave], [Valor]

Vejamos a descrição dos parâmetros:

[Nome do Aplicativo]: Obrigatório. Nome do aplicativo ou do projeto ao qual se aplica a definição.[Seção] : Obrigatório. Nome da seção em que a definição da chave está sendo salva.[Chave] : Obrigatório. Nome da definição de chave sendo salva.[Valor] : Obrigatório. Valor com que será armazenado.

Exemplos:SaveSetting appname := "MeuProg", _ section := "Inicialização", _ key := "Superior", setting := 75'OuSaveSetting "MeuProg", "Inicialização", _ "Superior", 75

GetSetting:===========Recupera o valor de uma chave salva no registro do Windows.

Sintaxe:GetSetting([Nome do Aplicativo], [Seção], [Chave], [Valor Padrão])

Vejamos a descrição dos parâmetros:

[Nome do Aplicativo]: Obrigatório. Nome do aplicativo ou do projeto cuja definição de chave é solicitada.[Seção] : Obrigatório. Nome da seção onde se encontra a definição de chave.[Chave] : Obrigatório. Nome da definição de chave a ser retornada.[Valor Padrão] : Opcional. Valor a retornar se nenhum valor for definido na definição da chave. Se for omitido, default será assumido como uma string vazia ("").

Exemplo:Dim sRet As StringsRet = GetSetting(appname := "MeuProg", _ section := "Inicialização", _ key := "Esquerda", _ default := "25")

GetAllSettings:===============Retorna TODAS as chaves e TODOS os valores salvos de determinado programa/seção.

Sintaxe:GetAllSettings([Nome do Aplicativo], [Seção])

208

Page 209: Dicas de VB

Vejamos a descrição dos parâmetros:

[Nome do Aplicativo]: Obrigatório. Nome do aplicativo ou projeto cujas definições de chave são solicitadas.[Seção] : Obrigatório. Nome da seção cujas definições de chave são solicitadas.

Obs.: GetAllSettings retorna um Variant cujo conteúdo é uma matriz bidimensional de seqüências de caracters contendo todas as definições de chave da seção especificada e seus valores correspondentes.

Exemplo:Dim vRet As Variant, iDef As IntegervRet = GetAllSettings(appname := "MeuProg", _ section := "Inicialização")For iDef = LBound(vRet, 1) To UBound(vRet, 1) Debug.Print vRet(iDef, 0), vRet(iDef, 1)Next

DeleteSetting:==============Apaga (deleta) uma ou mais chaves de determinado registro...

Sintaxe:DeleteSetting [Nome do Aplicativo], [Seção], [Chave]

Vejamos a descrição dos parâmetros:

[Nome do Aplicativo]: Obrigatório. Nome do aplicativo ou projeto ao qual se aplica a seção ou a definição de chave.[Seção] : Obrigatório. Nome da seção da qual a definição da chave está sendo excluída. Se forem fornecidos somente [Nome do Aplicativo] e [Seção], a seção especificada será excluída juntamente com todas as definições de chave relacionadas.[Chave] : Opcional. Nome da definição da chave sendo excluída.

Exemplo:'Deletar APENAS uma chave da seção:DeleteSetting "MeuProg", "Inicialização", _ "Superior"

'Deletar seção INTEIRA (e TODAS as'chave da mesma):DeleteSetting "MeuProg", "Inicialização"

Verificando se um array foi ou não inicializado

Private Sub Command1_Click()Dim lista() As Integer, Teste As Boolean

‘Experimente este código usando Redim Preserve e depois não usando‘ReDim Preserve lista(0)

209

Page 210: Dicas de VB

Teste = FoiIncializado(lista)End Sub

Private Function FoiIncializado(ByRef mVetor() As Integer) As Boolean If ((Not mVetor) = -1) Then FoiIncializado = False Else FoiIncializado = True End IfEnd Function

210