Editorial EDITORIAL. Olá amigos,



Documentos relacionados
Adicionando Propriedades e Funcionalidades aos Componentes Parte II

INSTALAÇÃO DO SISTEMA CONTROLGÁS

AMBIENTE. FORMULÁRIO: é a janela do aplicativo apresentada ao usuário. Considere o formulário como a sua prancheta de trabalho.

Procedimentos para Reinstalação do Sisloc

Inserindo Dados no Banco de Dados Paradox.

Procedimentos para Instalação do Sisloc

Listando itens em ComboBox e gravando os dados no Banco de Dados MySQL.

Despachante Express - Software para o despachante documentalista veicular DESPACHANTE EXPRESS MANUAL DO USUÁRIO VERSÃO 1.1

Dicas para usar melhor o Word 2007

Manual Captura S_Line

Memória Flash. PdP. Autor: Tiago Lone Nível: Básico Criação: 11/12/2005 Última versão: 18/12/2006. Pesquisa e Desenvolvimento de Produtos

ETEC DR. EMÍLIO HENRNANDEZ AGUILAR PROGRAMAÇÃO DE COMPUTADORES I PROFESSOR RAFAEL BARRETO

Iniciação à Informática

Sumário 1. SOBRE O NFGoiana DESKTOP Apresentação Informações do sistema Acessando o NFGoiana Desktop

TUTORIAL: MANTENDO O BANCO DE DADOS DE SEU SITE DENTRO DO DOMÍNIO DA USP USANDO O SSH!

Esse manual é um conjunto de perguntas e respostas para usuários(as) do Joomla! 1.5.

Manual do Google agenda. criação e compartilhamento de agendas

Microsoft Office Outlook Web Access ABYARAIMOVEIS.COM.BR

Novell. Novell Teaming 1.0. novdocx (pt-br) 6 April 2007 EXPLORAR O PORTLET BEM-VINDO DESCUBRA SEU CAMINHO USANDO O NOVELL TEAMING NAVIGATOR

INTRODUÇÃO AO WINDOWS

Atualizaça o do Maker

Interface para Regras de Negócios em Multi-Banco

OneDrive: saiba como usar a nuvem da Microsoft

Sistema Protocolo, Tramitação e Arquivamento de Processos Manual do Usuário

Manual Integra S_Line

GUIA MUDANÇA E FORMATAÇÃO DE SERVIDOR - MILLENNIUM

Data Transformation Services (DTS) por Anderson Ferreira Souza

Portaria Express 3.0

Procedimentos para Instalação do SISLOC

Vamos criar uma nova Página chamada Serviços. Clique em Adicionar Nova.

FAQ Perguntas Frequentes

GUIA MUDANÇA E FORMATAÇÃO DE SERVIDOR - SLIM

Bem- Vindo ao manual de instruções do ECO Editor de COnteúdo.

Revisão: Introdução. - Integração com o AutoManager; 1 Atualização de versão do banco de dados PostgreSQL

WF Processos. Manual de Instruções

Gerenciamento de Arquivos e Pastas. Professor: Jeferson Machado Cordini jmcordini@hotmail.com

Manual de Publicaça o no Blog da Aça o TRIBOS nas Trilhas da Cidadania

02 - Usando o SiteMaster - Informações importantes

Instalando o Internet Information Services no Windows XP

Neste capítulo discutiremos o que é uma DLL, seus aspectos e tipos e ainda, porquê é tão importante para as aplicações Windows

Como atualizar os preços da ABCFarma.

ETEC DR. EMÍLIO HENRNANDEZ AGUILAR PROGRAMAÇÃO DE COMPUTADORES II PROFESSOR RAFAEL BARRETO DELPHI FORMULÁRIO COM ABAS E BUSCAS DE REGISTROS

MANUAL DE UTILIZAÇÃO SISTEMA DE CADASTRO INTRANET

ArpPrintServer. Sistema de Gerenciamento de Impressão By Netsource Rev: 02

b 1 Copyright In9 Mídia Soluções Digitais Inc. All rights reserved.

Configurando DDNS no Stand Alone

Noções de. Microsoft SQL Server. Microsoft SQL Server

Aplicativo da Manifestação do Destinatário. Manual

AP_ Conta Aplicativo para digitação e envio de contas médicas no padrão TISS

MANUAL DE NAVEGAÇÃO DO MILLENNIUM BUSINESS

3. No painel da direita, dê um clique com o botão direito do mouse em qualquer espaço livre (área em branco).

Google Drive: Acesse e organize seus arquivos

FERRAMENTAS DE COLABORAÇÃO CORPORATIVA

BACKUP ONLINE PASSOS PARA CONFIGURAÇÃO INICIAL DO PRODUTO

ROTINAS PADRÕES DO SISTEMAS

Criando Banco de Dados, Tabelas e Campos através do HeidiSQL. Prof. Vitor H. Migoto de Gouvêa Colégio IDESA 2011

MANUAL EXPORTAÇÃO IMPORTAÇÃO

MANUAL DE INSTALAÇÃO DO ODONTO TECHNOLOGY

Guia de Início Rápido

Delphi 7 Aula 01 Área do Triângulo

Manual AGENDA DE BACKUP

Instalando o Sysloc versão manualmente

O programa Mysql acompanha o pacote de instalação padrão e será instalado juntamente com a execução do instalador.

Está apto a utilizar o sistema, o usuário que tenha conhecimentos básicos de informática e navegação na internet.

Como incluir artigos:

MANUAL DO USUÁRIO SORE Sistema Online de Reservas de Equipamento. Toledo PR. Versão Atualização 26/01/2009 Depto de TI - FASUL Página 1

Programa EndNote. Download para teste no site: (Atualmente o EndNote está na versão 5x)

BH PARK Software de Estacionamento

Manual de Instalação

1 REQUISITOS BÁSICOS PARA INSTALAR O SMS PC REMOTO

Manual das funcionalidades Webmail AASP

Instalando software MÉDICO Online no servidor

Universidade Federal do Mato Grosso - STI-CAE. Índice

Instalação e utilização do Document Distributor

Sistema de Chamados Protega

MANUAL DE UTILIZAÇÃO

WIN + D WIN + M SHIFT + WIN + M WIN + R WIN + E WIN + PAUSE BREAK

Usar Atalhos para a Rede. Logar na Rede

MANUAL DE INSTALAÇÃO 1) ORACLE VIRTUALBOX ; 2) MICROSOFT WINDOWS ; 3) SUMÁRIOS GENEPLUS.

SCIM 1.0. Guia Rápido. Instalando, Parametrizando e Utilizando o Sistema de Controle Interno Municipal. Introdução

Manual Vivo Sync. Manual do Usuário. Versão Copyright Vivo

Google Drive. Passos. Configurando o Google Drive

CONFIGURAÇÃO MINIMA EXIGIDA:

Delphi IDE. Jocélio Passos Delphi - IDE. Integrad Development Enviroment Ambiente de Desenvolvimento Integrado

Manual de Utilização

Manual de Instalação. SafeSign Standard (Para MAC OS 10.7)

Podemos agora ver no IDE do Morfik os objetos que já incorporamos ao nosso projeto :

Manual Sistema de Autorização Online GW

CRIANDO BANCOS DE DADOS NO SQL SERVER 2008 R2 COM O SQL SERVER MANAGEMENT STUDIO

Instalação do ByYou ESB. Guia de Instalação e Atualização do ByYou ESB

Manual AGENDA DE BACKUP

Tutorial do módulo Carteira Nacional de Militante

Instalando servidor Apache com MySQL e as linguagens ColdFusion e PHP. XAMPP (xampp-win installer.exe), veja aqui.

Roteiro de Uso do InstallShield

NetBeans. Conhecendo um pouco da IDE

Manual Xerox capture EMBRATEL

Tutorial Gerar arquivo PDF. Gerando um documento pdf com várias imagens 1- Inserir imagem no Word

Área de Trabalho. Encontramos: Ìcones Botão Iniciar Barra de Tarefas

Transcrição:

EDITORIAL Editorial Olá amigos, THE CLUB Av. Profº Celso Ferreira da Silva, 190 Jd. Europa - Aé - SP - CEP 18.707-150 Informações: (14) 3732-3689 Suporte: (14) 3733-1588 - Fax: (14) 3732-0987 Internet http://www.theclub.com.br Cadastro: cadastro@theclub.com.br Suporte: suporte@theclub.com.br Informações: info@theclub.com.br Dúvidas Correspondência ou fax com dúvidas devem ser enviados ao - THE CLUB, indicando "Suporte". Opinião Se você quer dar a sua opinião sobre o clube em geral, mande a sua correspondência para a seção "Tire sua dúvida". Reprodução A utilização, reprodução, apropriação, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criações intelectuais em cada publicação da revista The Club Megazine são terminantemente proibidos sem autorização escrita dos titulares dos direitos autorais. Impressão e acabamento: GRAFILAR Tel.: (14) 3841-2587 - Fax: (14) 3841-3346 Rua Cel. Amando Simôes, 779 Cep 18.650-000 - São Manuel - SP Tiragem: 5.000 exemplares Estamos começando mais um ano e gostaríamos desejar a todos vocês um excelente 2006 com muita saúde e sucesso. Também gostaríamos de dar as boas vindas ao nosso mais novo colaborador, Alexandre Tarifa. Ele é MVP (Most Valuable Professional), MCAD (Microsoft Certified Application Developer) e MCT (Microsoft Certified Trainer). Bacharel pela UMESP e pósgraduando pela Universidade Federal de São Carlos em Ciência da Computação. Analista de Sistemas. A partir deste mês estaremos publicando seus artigos. Nesta primeira edição de 2006 estamos começando com a nossa sessão Perguntas & Respostas com algumas das solicitações atendidas neste mês. Estamos trazendo também diversas dicas sobre o Delphi 7 que com certeza irão lhe auxiliar muito no seu dia a dia. E finalizando estamos trazendo mais novidades sobre o Delphi 2006. Um grande abraço a todos e boa leitura. Copyright The Club Megazine 2006 Diretor Técnico Mauro Sant Anna Colaboradores Marcelo Nogueira, Mário Bohm, Aguinaldo P. Silva, Alexandre Tarifa Delphi é marca registrada da Borland International, as demais marcas citadas são registradas pelos seus respectivos proprietários. Editorial... 03 Perguntas & Respostas... 04 Winforms - Expandindo controles... 09 Validando controles com Error Provider... 12 Dicas rápidas para Delphi 7... 16 Novas características do Delphi 2006... 27 3

Perguntas & Respostas Pergunta: Preciso enviar via email um relatório que vou gerar via QUICKREPORT, de preferência, no formato que aparece no PREVIEW. Resposta: O QuickReport gera um arquivo.qrp com o relatório. Para sal em arquivo faça da seguinte forma: QuickRep1.QRPrinter.Save( c:\relatorio.qrp ); Dúvida enviada por José Léo, Saudades - SC Pergunta: Preciso verificar se um diretório existe. Se existir, devo mostrar uma mensagem ao usuário perguntando se exclui ou não o diretório. O diretório será passado por parâmetro. Preciso também de renomear um diretório. Como faço estas duas coisas, pois tentei de várias maneiras sem sucesso. Resposta: Para verificar se o diretório existe, você pode utilizar a função DirectoryExists, o exemplo abaixo verifica se o diretório existe. Caso contrário o diretório é criado. uses FileCtrl; procedure TForm1.Button1Click (Sender: TObject); if not DirectoryExists( c:\temp ) then if not CreateDir( C:\temp ) then raise Exception.Create ( Cannot create c:\temp ); Para deletar o diretório, você pode utilizar a função RemoveDir, por exemplo: RemoveDir( c:\temp ); Para renomear um diretório você pode utilizar a rotina abaixo: procedure TForm1.Button1Click(Sender: TObject); f : file; AssignFile(f, C:\2 ); Canvas.TextOut(5, 10, Renomeando C:\2 para C:\3 ); Rename(f, C:\3 ); Dúvida enviada por Bruno, Três Pontas - MG Pergunta: Eu gostaria de saber se existe uma função que preencha com espaço até o final da string. Por exemplo: José da Silva. Resposta: Você pode utilizar o exemplo abaixo. Var S: String; Begin S := Format( %-30s, [Table.FieldByName ( Campo ).AsString]) ; End; * 30 é o tamanho total do campo, dados + espaços. Dúvida enviada por Luis, Santo Antonio da Platina PR 4

Perguntas & Respostas Pergunta: Existe alguma forma, de pegar o valor do componente QRExpression do QuickReport. Pois tenho este componente para somatório, e estou necessitando utilizar o valor gerado por ele. Resposta: Para pegar o valor de um QRExpression você pode utilizar a instrução QRExpr1.Value.dblResult. Veja o exemplo abaixo pegando o valor e atribuindo a um QRLabel. procedure TForm1.QRLabel4Print (sender: TObject; Value: String); Value := FloatTostr(QRExpr1.Value.dblResult); Dúvida enviada por Alessandro, Araras - SP Pergunta: Vocês possuem algum exemplo de um web browser para que eu possa inserir na minha aplicação, usando os componentes da paleta indy? Usando o componente da paleta Internet eu já possuo. Mas este requer que exista o Internet Explorer instalado. Resposta: Existe um componente Freeware que você pode utilizar. Veja em http://www.pbear.com/ htmlviewers.html#thtmllite. Dúvidas enviada por Nirlan, São Matheus - ES Pergunta: Gostaria de ver um exemplo para a criação de aplicações em pacotes. Há alguma matéria publicada? Resposta: Nós temos uma matéria a este respeito que pode ser acessada no link http://www.theclub.com.br/revista/ pacotes.doc. Dúvida enviada por Rafael, Belo Horizonte - MG Pergunta: Gostaria de saber como faço para criar uma rotina dentro em minha aplicação onde o próprio usuário rode os script de atualização do sistema. Gostaria de saber também se existe algum componente que faça este tipo de execução, eu coloco os script sql num arquivo e o componente executa o mesmo. Resposta: Para rodar scripts no banco de dados você pode utilizar um componente chamado SQLScript que pertence ao DBExpressPlus. O DBExpressPlus é uma suíte de componentes gratuitos que facilitam a execução de tarefas comuns no dia-a-dia do programador Delphi. Você poderá fazer o download do DBExpressPlus no seguinte endereço: http://sourceforge.net/projects/dbexpressplus A instalação é bastante simples, basta descompactar o arquivo baixado preferencialmente criando uma pasta em $(Delphi)\Source\dbExpressPlus, onde $(Delphi) indica a pasta de instalação de seu Delphi. Após isso, abra o pacote dbexprplus_r?0.dpk (?=versão do Delphi, 6 ou 7) e clique no botão Compile. Continuando, abra o pacote dbexprplus_d?0.dpk, clique em Compile e depois em Install. Para concluir, acesso o menu Tools Environment Options Library Library Path e adicione o path onde os arquivos foram descompactados, ou seja, $(Delphi)\Source\dbExpressPlus e com isso finalizamos a instalação do dbexpressplus. Se tudo ocorreu sem problemas, você poderá visualizar os novos componentes na paleta de componentes dbexpress. Para conhecer as funcionalidades de todos os componentes, você poderá abrir o projeto de exemplo que acompanha o dbexpressplus, podendo ser encontrado na pasta Demo ($(Delphi)\Source\dbExpressPlus\Demo). Dúvida enviada por Sebastião Nóbrega, Salvador - BA Pergunta: Como faço para trocar o valor (resultado) de uma Query, no DBGrid? Eu trago um campo boolean (true ou false) e quero mostrar (sim ou não) Gostaria de fazer tudo isto em tempo de execução. É possível? Resposta: O SQL Server não tem campo do tipo boolean, então suponho que esteja utilizando um campo do tipo char ou algo semelhante. Neste caso você pode utilizar o comando Case disponível no SQL Server, por exemplo: SELECT Codigo, Nome, CASE Campo WHEN true THEN sim WHEN false THEN não END AS NovoCampo FROM Tabela Dúvida enviada por Amauri, São Paulo - SP 5

Perguntas & Respostas Pergunta: Pode ser usado o comando for in para rer um componente ClientDataSet e atribuir, por exemplo, os nomes dos campos para um componente ListBox? Resposta: Isto pode ser feito da seguinte forma: procedure TForm2.Button1Click (Sender: TObject); Item: TField; for Item in ClientDataSet1.Fields do ListBox1.Items.Add(Item.FieldName); Dúvida enviada por Paulo, Assis - SP Pergunta: Gostaria de saber se vocês têm alguma rotina para instalação de minha aplicação comercial. Resposta: Para instalação de programas nós aconselhamos a utilização do InnoSetup. Nos links a seguir você encontrará informações mais detalhadas sobre este utilitário, http:// www.theclub.com.br/revista/cria0803%5fb.aspx, http:// www.theclub.com.br/revista/inst0604.aspx e http:// www.theclub.com.br/revista/inst0605.aspx. Dúvida enviada por Israel, Três Pontas - MG Pergunta: Tenho um software que abre outros softwares através dele. Como faço para saber se um desses softwares já está sendo executado? Resposta: Você pode trabalhar com o título da janela. O exemplo a seguir mostra como fechar uma aplicação a partir de outra. procedure TForm1.Button1Click (Sender: TObject); Win : THandle; Win := FindWindow(nil, Form1'); if Win <> 0 then PostMessage(Win,WM_QUIT,0,0) else ShowMessage( Programa não encontrado ); // No exemplo acima foi utilizado o POSTMESSAGE para enviar uma mensagem WM_CLOSE para a janela principal. Dúvida enviada por Gustavo, Vitória ES Pergunta: Tenho como fazer uma numeração de página do tipo 1 de 10, onde 10 é a quantidade de páginas do relatório. Resposta: Você pode fazer este tipo de trabalho, mas ele terá que ser manual. O primeiro passo é pegar o total de páginas e jogar para uma iável. Para pegar o total de páginas você pode executar o código abaixo antes de chamar o relatório. QuickRep1.Prepare; TotalPaginas := QuickRep1.PageNumber; TotalPaginas mostrada anteriormente é uma iável do tipo inteiro. Para mostrar isto no QuickReport você pode utilizar um componente QRSysData alterando a propriedade Data para PageNumber e colocar a rotina a seguinte no evento OnPrint. procedure TForm1.QRSysData1Print (sender: TObject; Value: String); Value := Value + / + IntToStr(TotalPaginas) Dúvida enviada por Haroldo, Rio de Janeiro - RJ Pergunta: É possível gerar um documento do WORD a partir de um relatório do QuickReport? Resposta: Isto é possível de ser feito, mas apenas utilizando componentes de terceiros. Para maiores informações veja em www.waler.com. Dúvida enviada por Haroldo, Rio de Janeiro - RJ Pergunta: Gostaria de saber como faço para saber o número de registros afetados por um comando update dentro de um programa. Por exemplo: 6

Perguntas & Respostas Q.Active:=False; Q.Sql.Text:= update bancodados set campoa = B where campoa = C from bancodados Q.ExecSQL; edit.text:= q.(registros afetados); Resposta: Isto pode ser feito, pois o componente Query tem uma propriedade chamada RowsAffected que retorna a quantidade de linhas afetadas no comando Update. Dúvida enviada por Celina, Santos - SP Pergunta: Estou querendo mudar minhas aplicações de Delphi 4 para Delphi 2005 e gostaria de saber se essa migração seria muito complexa, se teria que reescrever todos os programas e aprender o Delphi 2005 ou o ambiente é parecido no que diz respeito a programação win32 e não Web. Resposta: No que diz respeito a programação Win32, você não precisa se preocupar. Os comandos são os mesmos. O ambiente do Delphi 2005 realmente mudou bastante, mas pode ter certeza que foi para melhor. O que você deve tomar muito cuidado é em relação aos componentes de terceiros. Se você utiliza componentes de terceiros verifique se já existem versões destes componentes para o Delphi 2005. Dúvida enviada por Junior, São José do Rio Preto SP Pergunta: Estou mudando para o Delphi 7 e também estou utilizando o Rave Reports. Como posso configurar o Rave Reports para que ele abra o preview do relatório final maximizado,ou seja, em tela cheia. Resposta: Você deve utilizar o componente RVSystem. Neste componente vá até a propriedade SystemPreview e altere a subpropriedade FormState para wsmaximized. Depois disso, vá até o componente RvProject e ligue o componente componente RvSystem na propriedade Engine. Dúvida enviada por Edivaldo, RioBranco - AC Pergunta: Gostaria de saber se é possível alinhar pela direita valores, usando Printer.Canvas.Textout. Se for possível, como posso fazer isto? Resposta: Para fazer o controle de posicionamento de valores durante a impressão, faça o seguinte: uses... type... private public //Definição da função function Tam_Coluna(coluna:integer;valor: Double; mascara:string):integer; Form1: TForm1; implementation Uses Printers; procedure...... {Ao imprimir o valor a ser formatado chame a função de Tam_Coluna. Esta função vai retornar o numero da coluna onde deverá ser impresso o valor já formatado. Informe na iavel Coluna o numero da coluna a ser impressa. Na iável Total informe valor a ser impresso. No terceiro parametro da função Tam_Coluna a mascara desejada} Printer.Canvas.TextOut( Tam_Coluna( Coluna, Total, ###,##0.00 ), Linha, FormatFloat( ###,##0.00, Total ) );... function Tam_Coluna( coluna:integer; valor:double; mascara:string):integer; Masc : string; Tam1,Tam2 : integer; Masc := FormatFloat(mascara,valor); Tam1 := Printer.Canvas.TextWidth(Masc); Tam2 := Printer.Canvas.TextWidth(mascara); Tam_Coluna := coluna + (Tam2-Tam1); Dúvida enviada por André Junior, São Paulo SP 7

Perguntas & Respostas Pergunta: Eu tenho uma conexão com o Firebird usando a Paleta Interbase. Ou seja, uso os componentes IBDatabase, IBTransaction, IBDataset. Tenho 15 IBDatasets e em todos eu adicionei os Fields. Acontece que quando dou um Open no IBDatabase ele demora cerca de 30 segundos pra abrir, quando não trava. Fiz vários testes (faz 2 meses que estou fazendo testes) e descobri que essa demora acontece só no Windows XP. Agora no Win2000 e Win98 executa em 1 segundo, já adicionei nas Exceções do Firewall o FBServer e num adiantou nada. O que pode ter acontecido? Será incompatibilidade com o Windows XP? Resposta: Realmente existe um problema de lentidão. No site da Borland existe uma documentação a este respeito. Você pode ver no link http://bdn.borland.com/article/ 0,1410,28142,00.html Dúvida enviada por Evandro, São Paulo - SP Pergunta: Fiz um projeto. Para cadastrar grava normal, mas ao fechar o programa as informações que gravei não são gravadas. Resposta: Eu suponho que você não esteja trabalhando com o componente ClienteDataSet e não esteja confirmando a gravação do registro. Sendo assim vá até o evento AfterPost do componente ClientDataSet e inclua o seguinte comando: ClientDataSet1.ApplyUpdates(-1); Dúvida enviada por Rui, Paulo Afonso - BA Pergunta: Tenho um componente TPopupmenu numa classe ancestral, nesta classe gostaria de implementar um determinado código, mas para tanto preciso descobrir em cima de que objeto o menu foi acionado. Como faço isso? Obrigado! Resposta: Você pode utilizar o seguinte comando. (PopupMenu1.PopupComponent as TWinControl).Name; Dúvida enviada por Vicente, Bauru - SP Pergunta: Como eu posso instalar TeeChart com as novas versões do QuickReport? Resposta: Para instalar o Teechart para o QuickReport, vá até o menu do Delphi em Components Install Packages. Clique no botão Add... e localize no subdiretório \Bin do Delphi 7 o arquivo dcltqr70.bpl, clique em Abrir e depois em Ok. Pronto, está instalado. Dúvida enviada por Dennis, São Paulo - SP Pergunta: Em uma rede composta de 1 servidor e 2 estações, uma das estações leva um tempo considerável para se conectar ao banco de dados no servidor Firebird. A máquina em questão chegou a ser formatada, mas o problema persiste. Qual poderia ser o motivo desta anomalia? Resposta: A primeira conexão infelizmente é um pouco lenta, mas existe uma saída neste caso que pode melhorar a sua velocidade. A primeira é na linha de conexão utilizar sempre o IP da máquina e uma outra é localizar um arquivo chamado HOSTS. Este arquivo fica no diretório c:\windows\system32\drivers\etc. Inclua neste arquivo o IP e o nome do servidor como está sendo mostrado neste mesmo arquivo. Dúvida enviada por Paulo, Porto Alegre - RS Pergunta: Estou tentando compilar a minha aplicação e estou recebendo o erro: [Fatal Error] Unit StdActns was compiled with a different version of StrUtils. TStringSearchOptions Qual será o motivo deste erro? Resposta: Por algum motivo o arquivo StrUtils.dcu deve ter sido substituído por uma versão mais antiga. Uma saída é você criar um projeto novo, adicionar o arquivo StrUtils.pas que está no diretório: c:\arquivos de programas\ Borland\Delphi7\ Source\Rtl\Common, e compilar o projeto. Com isto será criado um novo arquivo StrUtils.dcu. Pegue este novo.dcu e copie para o diretório c:\arquivos de programas\borland\delphi7\lib. Isto resolverá o seu problema. Dúvida enviada por Áurea, Capii - SP 8

Visual Studio Winforms Expandindo controles Por Alexandre Tarifa Nem sempre os controles disponíveis pelo Visual Studio nos trazem todas as funcionalidades que necessitamos. Algumas vezes ampliar os recursos dos controles ou até mesmo criar um controle em cima de uma já existente pode se tornar um grande negócio. Neste artigo estarei mostrando como expandir um controle TextBox criando algumas funcionalidades e propriedades novas. Criando a aplicação Crie um novo projeto no Visual Studio (File > New > Project), selecione o project type Visual Basic Project, o template Windows Application, nome Controles e clique em OK. Uma janela de design é aberta, porém nada é exibido. Não temos acesso ao design do TextBox, portanto somente o código é alterado. Para ver o código precione F7. Nossa primeira implementação no controle será adicionar uma propriedade para definir se o TextBox receberá somente valores numéricos. Após a criação da aplicação, vamos adicionar o novo controle. No Solution Explorer, clique com o botão direito do mouse sobre o projeto Controles, Add, Add New Item. Selecione o template Custom Control e o nome NovoTextBox. O primeiro passo é alterar no topo do código a herança que é feita no início do código, devemos alterar Inherits System.Windows.Forms.Control para Inherits System.Windows.Forms.TextBox. Esta alteração é feita porque vamos ampliar as funcionalidades de um controle específico. No caso, um TextBox. Para criar uma nova propriedade do controle é simples, temos que declarar uma propriedade chamada Numérico do tipo boleano, 9

Visual Studio conforme abaixo: Private _Numerico As Boolean Public Property Numerico() As Boolean Get Return _Numerico End Get Set(ByVal Value As Boolean) _Numerico = Value End Set End Property Foi adicionado na ToolBox o novo controle, arraste o novo controle para o formulário. Selecione as propriedades do controle (F4), vá na propriedade Numérico e selecione True. Adicione outro NovoTextBox e não altera nenhuma propriedade. Execute a aplicação (F5). Teste com letras o primeiro TextBox e note que nenhum caractere é digitado, digite números, e somente números são adicionados. O próximo passo é sobrescrever a sub OnKeyPress, conforme abaixo: Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs) If _Numerico = True Then If e.keychar >= 0 And e.keychar <= 9 Then e.handled = False Else e.handled = True End If End If End Sub O evento OnKeyPress (quando é digitado algo no TextBox) quando tiver a propriedade Numérico como True, somente caracteres numéricos são aceitos. Para testar a aplicação, devemos compilar a aplicação (Ctrl+Shift+B). Abra o Form1, abra a janela ToolBox (Ctrl + Alt + X), clique com o botão direito do mouse, Add/Remove Items, Browse, selecione o arquivo Controles.exe na pasta Bin do seu projeto, selecione o NovoTextBox e clique em OK. Vamos alterar nosso controle, delete toda a implementação do Evento OnKeyPress e a propriedade numérico. Vamos criar um Enumerador com todas as possibilidades de formatação: Public Enum TipoFormatacao Nenhum ForCep ForData fortelefone forhora End Enum Também crie uma nova propriedade que receberá o valor do Enumerador: Private Formatacao As TipoFormatacao Public Property Formatacao() As TipoFormatacao Get Return _Formatacao End Get Set(ByVal Value As TipoFormatacao) _Formatacao = Value End Set End Property Vamos novamente redefinir OnKeyPress: 10

Visual Studio Protected Overrides Sub OnKeyPress (ByVal e As System.Windows.Forms. KeyPressEventArgs) Agora nosso controle possui uma propriedade chamada TipoFormatacao onde através de uma combo selecionaremos a opção: Select Case _Formatacao Case OpcaoFormata.ForCep If Len(Me.Text) = 5 Then Me.Text = Me.Text & - Me.SelectionStart = Len(Me.Text) + 1 Me.MaxLength = 9 End If Case OpcaoFormata.ForData If Len(Me.Text) = 2 Or Len(Me.Text) = 5 Then Me.Text = Me.Text & / Me.SelectionStart = Len(Me.Text) + 1 Me.MaxLength = 10 End If End Sub Case OpcaoFormata.forHora If Len(Me.Text) = 2 Then Me.Text = Me.Text & : Me.SelectionStart = Len(Me.Text) + 1 Me.MaxLength = 5 End If Case OpcaoFormata.forTelefone If Len(Me.Text) = 0 Then Me.Text = Me.Text & ( Me.SelectionStart = Len(Me.Text) + 1 ElseIf Len(Me.Text) = 3 Then Me.Text = Me.Text & ) Me.SelectionStart = Len(Me.Text) + 1 ElseIf Len(Me.Text) = 8 Then Me.Text = Me.Text & - Me.SelectionStart = Len(Me.Text) + 1 End If End Select Me.MaxLength = 13 Selecione as opções diretamente no TextBox e execute o projeto. Digite os valores e veja que a formatação selecionada é efetuada. Além dessas implementações podemos criar várias, vai da necessidade que temos. Lembrando também que qualquer controle pode ter as suas propriedades expandidas. Se você tem interesse em aprender.net ou discutir.net entre no grupo de usuários Codificando.net - São Paulo. Abraços. Alexandre Tarifa Líder Codificando.net SP Sobre o autor Alexandre Tarifa - alexandretarifa@gmail.com Ministra palestras e treinamentos, MVP (Most Valuable Professional), MCAD (Microsoft Certified Application Developer) e MCT (Microsoft Certified Trainer). Bacharel pela UMESP e pós-graduando pela Universidade Federal de São Carlos em Ciência da Computação. Analista de Sistemas e Líder do grupo de usuários Codificando.net São Paulo (sp.codificando.net). Escreve artigos para a revista MSDN Magazine e para os sites Linha de Código, MSDN Brasil e Enterpriseguys. Visite o blog do autor: http://weblogs.pontonetpt.com/alexandretarifa/. 11

Visual Studio Validando controles com Error Provider por Alexandre Tarifa A não validação dos dados inseridos por um usuário em qualquer aplicação pode trazer transtornos incalculáveis. Quanto antes estas informações forem validadas o sistema ficará mais rápido, seguro e com menos possibilidade de erros. Muitos erros que ocorrem nas aplicações ocorrem por inconsistência de dados e validando a logo na entrada de dados faz com que o erro seja previsto e a ação que utilizaria a informação seja cancelada antes mesmo da utilização do dado. O próximo passo será o design do formulário, utilize o formulário que já vem criado com a aplicação. Altere as seguintes propriedades do Formulário: Tabela 1. Propriedades do formulário Em aplicações que utilizam banco de dados, se não validarmos algumas informações como, por exemplo, uma letra tentando ser adicionada em um campo do tipo numérico nossa aplicação perderá performance, pois efetuará uma conexão com o banco de dados, executará o comando e somente quando o banco de dados retornar um erro que a informação será validada. Na plataforma.net para desenvolvimento de aplicações WinForms foi criado um controle para facilitar toda essa validação, chamado: Error Provider. O Error Provider traz todos os recursos necessários para a validação de uma forma segura e simplificada. Com a utilização deste controle qualquer evento disparado não será executado enquanto todos os campos não estiverem devidamente corretos. Para entender melhor a utilização do controle, criar uma aplicação é a forma mais eficiente. Abra o Visual Studio 2003 (figura 1), selecione em Project Type a linguagem Visual Basic Projects, Templates selecione Windows Application, name digite Error Provider, selecione um caminho em Location e clique em OK. Figura 1. Criando um novo projeto. 12

Visual Studio Adicione no formulário, adicione todos os controles conforme a figura 2, e altere as propriedades dos controles conforme a tabela 2. Com o formulário montado vamos criar toda a validação do formulário utilizando o controle Error Provider. Para adicionar o controle, selecione na ToolBox (figura 3) e de um duplo clique sobre o controle. Figura 3. Toolbox Quando selecionamos o controle ele é adicionado na área de controles sem interface logo abaixo do formulário, esta área é reservada a controles que não serão exibidos diretamente no formulário. Figura 2. Design do formulário Com o controle adicionado, o Error Provider adiciona algumas novas propriedades nos controles para efetuar a validação. A primeira propriedade que vamos alterar será no próprio Error Provider, selecione o controle, vá às propriedades (F4) e altere a propriedade name para errvalidacao. O primeiro controle a ser tratado será o txtnome, será validado se existiu ou não a entrada de dados. Selecione no menu View, Code ou precione F7. Na janela de código selecione nas combos superiores txtnome e Validating. Automaticamente é criado o código do evento, digite o seguinte código: Private Sub txtnome_validating (ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles txtnome.validating If txtnome.text = Then errvalidacao.seterror(sender, Digite um nome ) e.cancel = True Else errvalidacao.seterror(sender, ) End If End Sub 13

Visual Studio Para testar a aplicação, no botão btnok, adicione o seguinte código: Private Sub btnok_click(byval sender As System.Object, ByVal e As System.EventArgs) Handles btnok.click MessageBox.Show( Nome: & txtnome.text & vbcrlf & _ Endereço: & txtendereco.text & vbcrlf & _ Bairro: & txtbairro.text & vbcrlf & _ Cidade: & txtcidade.text & vbcrlf & _ Estado: & cmbestado.text & vbcrlf & _ Email: & txtemail.text & vbcrlf & _ Linguagem: & lstlinguagem.text & vbcrlf) End Sub Execute a aplicação (F5), o formulário será exibido. Não preencha nenhum campo do formulário e clique sobre o botão btnok (figura 4). If txtendereco.text = Then errvalidacao.seterror(sender, Digite um endereço ) e.cancel = True Else errvalidacao.seterror(sender, ) End If End Sub Private Sub txtbairro_validating (ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles txtbairro.validating If txtbairro.text = Then errvalidacao.seterror(sender, Digite um bairro ) e.cancel = True Else errvalidacao.seterror(sender, ) End If End Sub Private Sub txtcidade_validating (ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles txtcidade.validating Figura 4: Execução do exemplo A vantagem da utilização do Error Provider, é que ele não deixa nenhuma funcionalidade ser efetuada enquando um valor não for digitado no TextBox. Todos os controles possuem uma propriedade chamada CausesValidation. Esta propriedade define se o controle quando tiver alguma ação deverá ou não participar da validação, caso esteja como True, o ErrorProvider entra em ação, caso contrário, o ErrorProvider é ignorado. Adicione o código abaixo para complementar com a validação dos outros controles: Private Sub txtendereco_validating(byval sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles txtendereco.validating If txtcidade.text = Then errvalidacao.seterror(sender, Digite uma Cidade ) e.cancel = True Else errvalidacao.seterror(sender, ) End If End Sub Private Sub cmbestado_validating (ByVal sender As Object,ByVal e As System.ComponentModel.CancelEventArgs) Handles cmbestado.validating If cmbestado.text = Then errvalidacao.seterror(sender, Selecione um Estado ) e.cancel = True Else errvalidacao.seterror(sender, ) End If 14

Visual Studio End Sub Private Sub txtemail_validating(byval sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles txtemail.validating If txtemail.text = Then errvalidacao.seterror(sender, Digite um Email ) e.cancel = True Else errvalidacao.seterror(sender, ) End If End Sub Private Sub lstlinguagem_validating(byval sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles lstlinguagem.validating If lstlinguagem.text = Then errvalidacao.seterror(sender, Selecione uma Linguagem ) e.cancel = True Else errvalidacao.seterror(sender, ) End If End Sub Execute a aplicação e teste todos os controles individualmente. Conclusão Se desejar validar os campos de forma segura e de rápido desenvolvimento, utilize o ErrorProvider. Sobre o autor Alexandre Tarifa - alexandretarifa@gmail.com Ministra palestras e treinamentos, MVP (Most Valuable Professional), MCAD (Microsoft Certified Application Developer) e MCT (Microsoft Certified Trainer). Bacharel pela UMESP e pós-graduando pela Universidade Federal de São Carlos em Ciência da Computação. Analista de Sistemas e Líder do grupo de usuários Codificando.net São Paulo (sp.codificando.net). Escreve artigos para a revista MSDN Magazine e para os sites Linha de Código, MSDN Brasil e Enterpriseguys. Visite o blog do autor: http://weblogs.pontonetpt.com/alexandretarifa/. 15

Delphi Dicas rápidas para Delphi 7 Como mostrar Menu Item Hints Quando o mouse está sobre um componente (um TButton, por exemplo) se a propriedade ShowHint é True e se houver algum texto na propriedade Hint, o hint/tooltip será mostrado para o componente. Hints para itens de menu? Por projeto, mesmo se você colocar algo na propriedade Hint de um Menu Item o popup hint não será exibido. No entanto, os Itens do menu Iniciar do Windows mostram hints, e o menu dos Favoritos do Internet Explorer também. É comum usar o evento OnHint nas iáveis globais da aplicação, nas aplicações Delphi, para mostrar os hints do menu como uma barra de status. O Windows não expõe as mensagens necessárias que suportem o evento tradicional OnMouseEnter. No entanto, a implementação do WM_MENUSELECT no TCustomForm (ancestral do TForm) tem o item hint de menu no Application.Hint que pode ser usado no evento Application.OnHint. Se você quer adicionar itens de menu com popup hints nos menus de sua aplicação Delphi você precisa somente apontar a mensagem WM_MenuSelect corretamente. A classe TMenuItemHint hints popup para itens de menu! Como não podemos depender do método Application.ActivateHint para mostrar a janela para os itens de menu (o apontamento de menus é feito totalmente pelo Windows), para obter a janela de hint exibida você precisa criar sua própria versão da janela hint derivando uma nova classe a partir de THintWindow. Segue como criar a classe TMenuItemHint uma janela hint que realmente é exibida nos itens de menu. Primeiro você precisa apontar a mensagem WM_MENUSELECT do Windows: type TForm1 = class(tform)... private procedure WMMenuSelect( Msg: TWMMenuSelect) ; message WM_MENUSELECT; end... implementation... procedure TForm1.WMMenuSelect ( Msg: TWMMenuSelect) ; menuitem : TMenuItem; hsubmenu : HMENU; inherited; // from TCustomForm //(so that Application.Hint is assigned) menuitem := nil; if (Msg.MenuFlag <> $FFFF) or (Msg.IDItem <> 0) then if Msg.MenuFlag and MF_POPUP = MF_POPUP then hsubmenu := GetSubMenu (Msg.Menu, Msg.IDItem) ; menuitem := Self.Menu.FindItem (hsubmenu, fkhandle) ; end else menuitem := Self.Menu.FindItem (Msg.IDItem, fkcommand) ; mihint.doactivatehint(menuitem) ; (*WMMenuSelect*) 16

Delphi A mensagem WM_MENUSELECT é enviada à janela proprietária do menu (Form 1) quando o usuário seleciona (não quando clica) um item de menu. Usando o método FindItem da classe TMenu, você consegue pegar o item de menu que está selecionado no momento. Os parâmetros da função FindItem relatam as propriedades que a mensagem recebeu. Uma vez que você saiba qual o item de menu sobre qual está o mouse, chamaremos o método DoActivateHint da classe TMenuItemHint. Observe que a iável mihint é definida como mihint : TMenuItemHint e é criada no evento OnCreate do Form. Agora vamos fazer a implementação da classe TMenuItemHint. Aqui está a parte da interface: TMenuItemHint = class(thintwindow) private activemenuitem : TMenuItem; showtimer : TTimer; hidetimer : TTimer; procedure HideTime(Sender : TObject) ; procedure ShowTime(Sender : TObject) ; public constructor Create (AOwner : TComponent) ; override; procedure DoActivateHint (menuitem : TMenuItem) ; destructor Destroy; override; Você pode ver toda a implementação no projeto exemplo. Basicamente, a função DoActivateHint chama o método ActivateHint do THintWindow usando a propriedade Hint do TMenuItem (se estiver atribuída). O showtimer é usado para se ter certeza que o HintPause (do Application) transcorre antes do hint ser mostrado. O hidetimer usa o Application.HintHidePause para esconder a janela do hint após um intervalo específico. Quando usar os hints nos itens do menu? Enquanto alguns podem dizer que não é uma boa coisa mostrar hints nos itens de menu, há situações que mostrar hints no menu é muito melhor do que mostrar uma barra de status. Segue o código fonte do Form, com a implementação da classe TMenuItemHint. unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Menus, AppEvnts, StdCtrls, ExtCtrls, ComCtrls; type TMenuItemHint = class(thintwindow) private activemenuitem : TMenuItem; showtimer : TTimer; hidetimer : TTimer; procedure HideTime(Sender : TObject) ; procedure ShowTime(Sender : TObject) ; public constructor Create (AOwner : TComponent) ; override; procedure DoActivateHint (menuitem : TMenuItem) ; destructor Destroy; override; TForm1 = class(tform)... procedure FormCreate(Sender: TObject) ; procedure ApplicationEvents1Hint (Sender: TObject) ; private mihint : TMenuItemHint; procedure WMMenuSelect ( Msg: TWMMenuSelect) ; message WM_MENUSELECT; Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate (Sender: TObject) ; mihint := TMenuItemHint.Create(self) ; (*FormCreate*) 17

Delphi procedure TForm1.ApplicationEvents1Hint (Sender: TObject) ; StatusBar1.SimpleText := App.OnHint : + Application.Hint; (*Application.OnHint*) procedure TForm1.WMMenuSelect ( Msg: TWMMenuSelect) ; menuitem : TMenuItem; hsubmenu : HMENU; inherited; // TCustomForm // (se certifica que o Application.Hint // é atribuído) menuitem := nil; if (Msg.MenuFlag <> $FFFF) or (Msg.IDItem <> 0) then if Msg.MenuFlag and MF_POPUP = MF_POPUP then hsubmenu := GetSubMenu (Msg.Menu, Msg.IDItem) ; menuitem := Self.Menu.FindItem (hsubmenu, fkhandle) ; end else menuitem := Self.Menu.FindItem (Msg.IDItem, fkcommand) ; mihint.doactivatehint(menuitem) ; (*WMMenuSelect*) { TMenuItemHint } constructor TMenuItemHint.Create (AOwner: TComponent) ; inherited; showtimer := TTimer.Create(self) ; showtimer.interval := Application. HintPause; hidetimer := TTimer.Create(self) ; hidetimer.interval := Application. HintHidePause; (*Create*) destructor TMenuItemHint.Destroy; hidetimer.ontimer := nil; showtimer.ontimer := nil; self.releasehandle; inherited; (*Destroy*) procedure TMenuItemHint.DoActivateHint (menuitem: TMenuItem) ; //força a remoção da velha janela //do hint hidetime(self) ; if (menuitem = nil) or (menuitem.hint = ) then activemenuitem := nil; Exit; activemenuitem := menuitem; showtimer.ontimer := ShowTime; hidetimer.ontimer := HideTime; (*DoActivateHint*) procedure TMenuItemHint.ShowTime (Sender: TObject) ; r : TRect; wdth : integer; hght : integer; if activemenuitem <> nil then //position and resize wdth := Canvas.TextWidth (activemenuitem.hint) ; hght := Canvas.TextHeight (activemenuitem.hint) ; r.left := Mouse.CursorPos.X + 16; 18

Delphi r.top := Mouse.CursorPos.Y + 16; r.right := r.left + wdth + 6; r.bottom := r.top + hght + 4; ActivateHint(r,activeMenuItem.Hint) ; showtimer.ontimer := nil; (*ShowTime*) procedure TMenuItemHint.HideTime(Sender: TObject) ; //esconde (destroy) a janela hint self.releasehandle; hidetimer.ontimer := nil; (*HideTime*) end Overwrite no TMemo e TEdit Os controles do Windows TMemo e TEdit não têm a capacidade overwrite. No entanto, é possível simular este comportamento, ajustanto a propriedade SelLength do controle edit ou memo durante o processamento do evento KeyPress. Isso faz com que o caractere que está na posição corrente seja sobrescrito. O exemplo a seguir mostra como emular a capacidade de overwrite de um componente TMemo. O estado do modo de sobrescrever pode ser mudado pressionando a tecla Insert. type TForm1 = class(tform) Memo1: TMemo; procedure Memo1KeyDown (Sender: TObject; Key: Word; Shift: TShiftState) ; procedure Memo1KeyPress (Sender: TObject; Key: Char) ; private { Private declarations } InsertOn : bool; public { Public declarations } Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Memo1KeyDown (Sender: TObject; Key: Word; Shift: TShiftState) ; if (Key = VK_INSERT) and (Shift = []) then InsertOn := not InsertOn; procedure TForm1.Memo1KeyPress (Sender: TObject; Key: Char) ; if ((Memo1.SelLength = 0) and (not InsertOn)) then Memo1.SelLength := 1; Algumas vezes precisamos limpar todos os componentes Edit que estão no Form. Esta tarefa é feita facilmente com o seguinte procedimento: procedure ClearEdits; j : Integer; for j := 0 to ComponentCount-1 do if (Components[j] is TEdit) then (Components[j] as TEdit).Text := ; Como chamar o Ver fonte (view source) em um WebBrowser Aqui está como chamar o Ver fonte do IE (para examinar o HTML) com o componente TWebBrowser. Simplesmente arraste uma instância do componente TWebBrowser em um formulário e um botão (Button) e faça como segue: uses ActiveX; procedure WBViewSourceDialog (AWebBrowser: TWebbrowser) ; 19

Delphi const CGID_WebBrowser: TGUID = {ED016940-BD5B-11cf-BA4E-00C04FD70816} ; HTMLID_VIEWSOURCE = 2; CmdTarget : IOleCommandTarget; vain, vaout: OleVariant; PtrGUID: PGUID; New(PtrGUID) ; PtrGUID^ := CGID_WebBrowser; if AWebBrowser.Document <> nil then try AWebBrowser.Document. QueryInterface(IOleCommandTarget, CmdTarget) ; if CmdTarget <> nil then try CmdTarget.Exec(PtrGUID, HTMLID_VIEWSOURCE, 0, vain, vaout) ; finally CmdTarget._Release; except Dispose(PtrGUID) ; procedure TForm1.FormCreate (Sender: TObject); WebBrowser1.Navigate ( http://www.delphi.about.com ) ; procedure TForm1.Button1Click (Sender: TObject) ; WBViewSourceDialog(WebBrowser1) ; MessageBox com timeout Aqui está como chamar um Message Box com timeout, ele irá fechar a si mesmo após um período de tempo. O truque é chamar uma API não documentada localizada no user32.dll, a API é a MessageBoxTimeOut. A função retorna um valor inteiro para MB_TIMEDOUT (indicando que o período de tempo para o timeout foi alcançado e o Message Box foi automaticamente fechado), ou um valor representando o botão que o usuário clicou. Observe que o valor retornado é sempre 1, quando o Message Box tem somente um botão de OK (MB_OKFlag). //declaração de interface const MB_TIMEDOUT = 32000; function MessageBoxTimeOut (hwnd: HWND; lptext: PChar; lpcaption: PChar; utype: UINT; wlanguageid: WORD; dwmilliseconds: DWORD): Integer; stdcall; external user32 name MessageBoxTimeoutA ; //implementação (Apontamento do evento //OnClick do Button1 no Form1) procedure TForm1.Button1Click (Sender: TObject) ; iret: Integer; iflags: Integer; iflags := MB_OK or MB_SETFOREGROUND or MB_SYSTEMMODAL or MB_ICONINFORMATION; MessageBoxTimeout (Application.Handle, Test a timeout of 2 seconds., MessageBoxTimeout Teste, iflags, 0, 2000) ; iflags := MB_YESNO or MB_SETFOREGROUND or MB_SYSTEMMODAL or MB_ICONINFORMATION; iret := MessageBoxTimeout (Application.Handle, Teste de timeout de 5 segundos., MessageBoxTimeout Teste, iflags, 0, 5000) ; case iret of IDYES: ShowMessage( Yes ) ; IDNO: ShowMessage( No ) ; MB_TIMEDOUT: ShowMessage( TimedOut ) ; 20