VB - Criando uma aplicação do tipo Console


O VB é uma das ferramentas mais usadas para criar aplicações Windows , e , uma aplicação padrão Windows supõe a presença de pelo menos um formulário. Mas vamos supor que você seja do contra e que queira criar uma aplicação VB que interaja com o usuário sem usar formulários...uma aplicação do tipo console. E então ? dá ou não dá para fazer usando o VB ?

O VB é uma ferramenta que usamos para realizar tarefas de programação , é uma ótima ferramenta , mas nem sempre é a ferramenta ideal . Isto não quer dizer que você não possa fazer qualquer tarefa usando o VB , eu acho que até pode , o problema será a eficiência e o esforço dispendido para alcançar o objetivo. Por exemplo , se você tem um alicate e precisa pregar um prego na parede , embora o alicate não seja a ferramenta adequada para fazer a tarefa , você pode pregar o prego usando o alicate. Com o VB é mais ou menos assim , você tem que estar disposto a pagar o preço que a tarefa vai lhe exigir...

Então podemos dizer que não é impossível criar uma aplicação do tipo console no VB , mas você vai ter que pagar o preço para fazer isto. Vai ter que usar as API´s ...

Dica : Voce pode fazer o download do ApiWiewer 2002 para facilitar a usar as API´s !!

Por onde vamos começar ?? Que tal iniciar o VB e escolher a criação de um projeto padrão ? Então façamos isto... A primeira coisa que vai surgir é um projeto com um formulário padrão ( olha ele ai...) O que fazemos com ele ? Ora , você não quer criar uma aplicação sem formulários ? Então , tá esperando o que ??? Remova o formulário do projeto !!!!

Vamos dar uma espiada no projeto : Nada animador não é mesmo ???

Como eu disse vamos ter que usar as API´s do Windows para fazer este serviço. Então ao trabalho...

A primeira coisa a fazer é incluir um módulo no seu projeto : Menu Project | Add Module

Todo o nosso código será escrito no módulo inserido. O primeira ação será solicitar ao windows que aloque um console fazemos isto através da API :

Declare Function AllocConsole Lib "kernel32" () As Long

com isto estaremos criando uma janela console onde iremos trabalhar enviar e receber mensagens , tudo controlado pelo Windows. Para encerrar o processo usamos a seguinte API :

Declare Function FreeConsole Lib "kernel32" () As Long

Vamos agora declarar um subrotina Main() que irá invocar as API´s declaradas. Nosso código ficará assim :

Se executarmos o código agora , o sistema irá alocar a janela console e em seguida irá destruir o processo encerrando a janela console. Tudo rapidinho , mas já é um começo...

Nossa próxima etapa será obter um identificador para a janela console que vamos usar. Se você acha isto estranho, saiba que toda a janela gerada por um formulário tem um identificador ou handle , e, se você usar API´s para interagir com um formulário sempre terá um identificador hWnd.

Uma janela console possui um identificador para a entrada , saida e para erros. Podemos obter um identificador usando a seguinte API GetStdHandle :

Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long

o argumento nStdHandle é quem determina qual identificador será retornado. As constantes nos dão três possibilidades :

  1. Private Const STD_INPUT_HANDLE = -10&
  2. Private Const STD_OUTPUT_HANDLE = -11&
  3. Private Const STD_ERROR_HANDLE = -12&

Vamos avançar um pouco mais no nosso projeto , vamos agora escrever no Console. Para escrever no console vamos usar a API WriteConsole :

Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" (ByVal hConsoleOutput As Long, lpBuffer As Any, ByVal nNumberOfCharsToWrite As Long, lpNumberOfCharsWritten As Long, lpReserved As Any) As Long

Vamos usar esta API para escrever no console , mas antes vamos ver como definir o título da janela console. Fazemos isto usando a API SetConsoleTitle :

Declare Function SetConsoleTitle Lib "kernel32" Alias "SetConsoleTitleA" (ByVal lpConsoleTitle As String) As Long

Para usar a API apenas passamos uma string com o título da janela console e pronto.

Vamos agora finalmente usar a API WriteConsole para escrever na janela console , antes , vamos dar um toque de para tornar o trabalho mais colorido. Para podermos imprimir na janela console usando cores usaremos a API SetConsoleTextAttribute :

Declare Function SetConsoleTextAttribute Lib "kernel32" (ByVal hConsoleOutput As Long, ByVal wAttributes As Long) As Long

as cores são passadas pelo argumento wAttributes , assim :

  1. Private Const FOREGROUND_BLUE = &H1
  2. Private Const FOREGROUND_GREEN = &H2
  3. Private Const FOREGROUND_RED = &H4
  4. Private Const FOREGROUND_INTENSITY = &H8
  5. Private Const BACKGROUND_BLUE = &H10
  6. Private Const BACKGROUND_GREEN = &H20
  7. Private Const BACKGROUND_RED = &H40
  8. Private Const BACKGROUND_INTENSITY = &H80

e ainda podemos combinar os valores assim :

Private Const FOREGROUND_YELLOW = FOREGROUND_RED OR FOREGROUND_GREEN

Vou tocar em outro ponto muito importante antes de entrarmos na reta final do nosso aplicativo console : como obter a resposta do usuário e exibí-la na janela console ? A API ReadConsole é usada para ler o buffer da janela do console e dar conta do recado:

Declare Function ReadConsole Lib "kernel32" Alias "ReadConsoleA" (ByVal hConsoleInput As Long, lpBuffer As Any, ByVal nNumberOfCharsToRead As Long, lpNumberOfCharsRead As Long, lpReserved As Any) As Long

a API ReadConsole somente irá responder depois que o usuário pressionar ENTER.

Por isto vamos precisar de mais duas API´s ( calma que ja estou acabando...) . A primeira para definir o modo do buffer de entrada , a API : SetConsoleMode :

Declare Function SetConsoleMode Lib "kernel32" (ByVal hConsoleHandle As Long, ByVal dwMode As Long) As Long

passamos para esta API o identificador para a entrada e uma valor indicando qual tipo de entrada será gravada. Dependendo do modo usado podemos ter:

- input

  1. Private Const ENABLE_LINE_INPUT = &H2
  2. Private Const ENABLE_ECHO_INPUT = &H4
  3. Private Const ENABLE_MOUSE_INPUT = &H10
  4. Private Const ENABLE_PROCESSED_INPUT = &H1
  5. Private Const ENABLE_WINDOW_INPUT = &H8

- output

  1. Private Const ENABLE_PROCESSED_OUTPUT = &H1

Agora que ja temos uma visão geral do processo vamos juntar todas as partes e criar a aplicação console: Para você testar o código abaixo , copie e cole o código no módulo inserido no projeto.

'--------------------------------------------------------
'(C) Copyright 1999 by Scott Lloyd. All Rights Reserved.
'Scott Lloyd

Option Explicit

Private Declare Function AllocConsole Lib "kernel32" () As Long

Private Declare Function FreeConsole Lib "kernel32" () As Long

Private Declare Function GetStdHandle Lib "kernel32" _
(ByVal nStdHandle As Long) As Long

Private Declare Function ReadConsole Lib "kernel32" Alias _
"ReadConsoleA" (ByVal hConsoleInput As Long, _
ByVal lpBuffer As String, ByVal nNumberOfCharsToRead As Long, _
lpNumberOfCharsRead As Long, lpReserved As Any) As Long

Private Declare Function SetConsoleMode Lib "kernel32" (ByVal _
hConsoleOutput As Long, dwMode As Long) As Long

Private Declare Function SetConsoleTextAttribute Lib _
"kernel32" (ByVal hConsoleOutput As Long, ByVal _
wAttributes As Long) As Long

Private Declare Function SetConsoleTitle Lib "kernel32" Alias _
"SetConsoleTitleA" (ByVal lpConsoleTitle As String) As Long

Private Declare Function WriteConsole Lib "kernel32" Alias _
"WriteConsoleA" (ByVal hConsoleOutput As Long, _
ByVal lpBuffer As Any, ByVal nNumberOfCharsToWrite As Long, _
lpNumberOfCharsWritten As Long, lpReserved As Any) As Long

''''C O N S T A N T E S'''''''''''''''''''''''''''''''''''''
Private Const STD_INPUT_HANDLE = -10&
Private Const STD_OUTPUT_HANDLE = -11&
Private Const STD_ERROR_HANDLE = -12&

'CONSTANTES PARA CORES USADAS EM SetConsoleTextAttribute.
Private Const FOREGROUND_BLUE = &H1
Private Const FOREGROUND_GREEN = &H2
Private Const FOREGROUND_RED = &H4
Private Const FOREGROUND_INTENSITY = &H8
Private Const BACKGROUND_BLUE = &H10
Private Const BACKGROUND_GREEN = &H20
Private Const BACKGROUND_RED = &H40
Private Const BACKGROUND_INTENSITY = &H80

'SetConsoleMode (input)
Private Const ENABLE_LINE_INPUT = &H2
Private Const ENABLE_ECHO_INPUT = &H4
Private Const ENABLE_MOUSE_INPUT = &H10
Private Const ENABLE_PROCESSED_INPUT = &H1
Private Const ENABLE_WINDOW_INPUT = &H8
'SetConsoleMode (output)
Private Const ENABLE_PROCESSED_OUTPUT = &H1
Private Const ENABLE_WRAP_AT_EOL_OUTPUT = &H2

Private hConsoleIn As Long
Private hConsoleOut As Long
Private hConsoleErr As Long

Private Sub Main()
Dim szUserInput As String

AllocConsole 'Cria uma instancia para o console

SetConsoleTitle "Criando uma aplicação Console no VB" 'define o titulo da janela console

'pega o identificador do console
hConsoleIn = GetStdHandle(STD_INPUT_HANDLE)
hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE)
hConsoleErr = GetStdHandle(STD_ERROR_HANDLE)

'imprime o prompt do usuario.
SetConsoleTextAttribute hConsoleOut, _
FOREGROUND_RED Or FOREGROUND_GREEN _
Or FOREGROUND_BLUE Or FOREGROUND_INTENSITY _
Or BACKGROUND_BLUE

ConsolePrint "Criando uma aplicação Console no VB" & vbCrLf
SetConsoleTextAttribute hConsoleOut, _
FOREGROUND_RED Or FOREGROUND_GREEN _
Or FOREGROUND_BLUE
ConsolePrint "Qual o seu nome --> "

'Pega o nome do usuario
szUserInput = ConsoleRead()
If Not szUserInput = vbNullString Then
  ConsolePrint "Olá, " & szUserInput & "!" & vbCrLf
Else
   ConsolePrint "Olá, como vai !" & vbCrLf
End If

'termina o programa
ConsolePrint "tecle ENTER para sair"
Call ConsoleRead

FreeConsole 'Destroi o console
End Sub

Private Sub ConsolePrint(szOut As String)
   WriteConsole hConsoleOut, szOut, Len(szOut), vbNull, vbNull
End Sub
Private Function ConsoleRead() As String
 Dim sUserInput As String * 256

 Call ReadConsole(hConsoleIn, sUserInput, Len(sUserInput), vbNull, vbNull)
 ConsoleRead = Left$(sUserInput, InStr(sUserInput, Chr$(0)) - 3)

End Function

Executando o projeto teremos :

Este artigo foi baseado ( praticamente traduzido) no artigo de Scott Lloyd.

Espero que gostem , tchau...


José Carlos Macoratti