dicas para delphi

164
Como? 161- Change the StringGrid's CELL color ? 160 - A listbox in a cell of a stringgrid 159 - Pintar um Bitmap diretamente no Canvas do Form 158 - Verificar se a impressora está ligada 157 - Obter a letra do drive onde está o Windows 156 - Mostrar o nome do EXE no caption do form 155 - Fazer pesquisa incremental apenas com DBGrid 154 - Obter tipo de uma propriedade 153 - Consulta SQL que usa a data do sistema 152 - Abrir uma conecção Dial-Up 151 - Pintar uma imagem JPG no form 150 - Executar comando do MS-DOS 149 - Formatar CEP 148 - Permitir cancelar processo demorado 147 - Descobrir se uma data é fim do mês 146 - Programar teclas de atalho do Windows 145 - Obter o tipo de dado de um valor no Registro do Windows 144 - Obter a célula de um StringGrid que está sob o cursor do mouse 143 - Limpar todas as células de um StringGrid 142 - Programar meu aplicativo para abrir arquivos a partir do Windows Explorer 141 - Consultar por mês de um campo data 140 - Criando tabelas via SQL 139 - Obter nomes dos campos de uma tabela 138 - Nomeando um relatório no spool de impressão do Windows 137 - Obter tamanho de um arquivo 136 - Ocultar aplicação da lista de tarefas - CTRL+ALT+DEL 135 - Obter path de um Alias do BDE 134 - Ativar a proteção de tela do Windows 133 - Desligar/Ligar monitor 132 - Abrir e fechar o drive de CD-ROM 131 - Impedir que o form seja arrastado para fora das margens da tela 130 - Mostrar mensagem mesmo que esteja no Prompt do DOS 129 - Copiar todos os registros de uma tabela para o Clipboard 128 - Copiar um registro de uma tabela para o Clipboard 127 - Criar sub-diretório no diretório do EXE 126 - Ocultar o aplicativo do CTRL+ALT+DEL 125 - Personalizar a caixa de mensagem de exceções (erro) do Delphi 124 - Implementar procedure Delay do Pascal no Delphi 123 - Enviar comandos de rolagem vertical para um TMemo 122 - Criar uma DLL de Bitmaps e usá-la 121 - Construir a barra de título do form com um Panel 120 - Criar form sem título que possa ser arrastado

Transcript of dicas para delphi

Page 1: dicas para delphi

Como?161- Change the StringGrid's CELL color ?160 - A listbox in a cell of a stringgrid159 - Pintar um Bitmap diretamente no Canvas do Form158 - Verificar se a impressora está ligada157 - Obter a letra do drive onde está o Windows156 - Mostrar o nome do EXE no caption do form155 - Fazer pesquisa incremental apenas com DBGrid154 - Obter tipo de uma propriedade153 - Consulta SQL que usa a data do sistema152 - Abrir uma conecção Dial-Up151 - Pintar uma imagem JPG no form150 - Executar comando do MS-DOS149 - Formatar CEP148 - Permitir cancelar processo demorado147 - Descobrir se uma data é fim do mês146 - Programar teclas de atalho do Windows145 - Obter o tipo de dado de um valor no Registro do Windows144 - Obter a célula de um StringGrid que está sob o cursor do mouse143 - Limpar todas as células de um StringGrid142 - Programar meu aplicativo para abrir arquivos a partir do Windows Explorer141 - Consultar por mês de um campo data140 - Criando tabelas via SQL139 - Obter nomes dos campos de uma tabela138 - Nomeando um relatório no spool de impressão do Windows137 - Obter tamanho de um arquivo136 - Ocultar aplicação da lista de tarefas - CTRL+ALT+DEL135 - Obter path de um Alias do BDE134 - Ativar a proteção de tela do Windows133 - Desligar/Ligar monitor132 - Abrir e fechar o drive de CD-ROM131 - Impedir que o form seja arrastado para fora das margens da tela130 - Mostrar mensagem mesmo que esteja no Prompt do DOS129 - Copiar todos os registros de uma tabela para o Clipboard128 - Copiar um registro de uma tabela para o Clipboard127 - Criar sub-diretório no diretório do EXE126 - Ocultar o aplicativo do CTRL+ALT+DEL125 - Personalizar a caixa de mensagem de exceções (erro) do Delphi124 - Implementar procedure Delay do Pascal no Delphi123 - Enviar comandos de rolagem vertical para um TMemo122 - Criar uma DLL de Bitmaps e usá-la121 - Construir a barra de título do form com um Panel120 - Criar form sem título que possa ser arrastado119 - Obter status da memória do sistema118 - Definir data/hora de um arquivo117 - Mostrar o diálogo About (Sobre) do Windows116 - Ocultar/exibir o cursor do mouse115 - Converter de Hexadecimal para Inteiro114 - Mudar a cor de um DBEdit dentro de um DBCtrlGrid de acordo com uma condição113 - Colocar uma ProgressBar da StatusBar112 - Executar um programa e aguardar sua finalização antes de continuar111 - Simular o pressionamento de uma combinação de teclas (ex: Ctrl+F2)

Page 2: dicas para delphi

110 - Simular o pressionamento de uma tecla109 - Ligar/desligar a tecla Caps Lock108 - Verificar se uma determinada tecla está pressionada107 - Verificar o estado de NumLock e CapsLock106 - Configurar linhas de diferentes alturas em StringGrid105 - Adicionar o evento OnClick do DBGrid104 - Criar caixas de diálogo em tempo de execução103 - Converter a primeira letra de um Edit para maiúsculo102 - Verificar se uma string contém uma hora válida101 - Verificar se uma string contém um valor numérico válido100 - Mostrar uma mensagem durante um processamento99 - Mostrar um cursor de ampulheta durante um processamento98 - Ler e escrever dados binários no Registro do Windows97 - Mudar a resolução do vídeo via programação96 - Ler e escrever dados no Registro do Windows95 - Adicionar barra de rolagem horizontal no ListBox94 - Simular um CharCase no DBGrid93 - Verificar se uma string é uma data válida92 - Fazer pesquisa incremental com DBGrid e Edit91 - Adicionar zeros à esquerda de um número90 - Limpar um campo tipo data via programação89 - Implementar um campo auto-incremental via programação88 - Obter o endereço IP do Dial-Up87 - Exibir a caixa de diálogo padrão de solicitação de senha do banco de dados86 - Obter a versão da biblioteca ComCtl32.DLL (usada na unit ComCtrls do Delphi)85 - Implementar rotinas assembly em Pascal84 - Exibir o diálogo About do Windows83 - Obter a linha e coluna atual em um TMemo82 - Exibir um arquivo de ajuda do Windows81 - Obter o valor de uma variável de ambiente80 - Determinar se uma janela (form) está maximizada79 - Determinar se o cursor do mouse está em determinado controle78 - Determinar se o aplicativo está minimizado77 - Fechar um aplicativo com uma mensagem de erro fatal76 - Usar o evento OnGetText de um TField75 - Maximizar um form de forma que cubra toda a tela, inclusive a barra de tarefas74 - Verificar, via programação, se Local Share do BDE está TRUE73 - Criar um EXE que seja executado apenas através de outro EXE criado por mim72 - Resolver "Internal error near: IBCheck" do Interbase 5.1.1 Server no NT71 - Inverter os botões do mouse70 - Obter/definir o tempo máximo do duplo-click do mouse69 - Obter os atributos de um arquivo/diretório68 - Obter o espaço total e livre de um disco67 - Obter o tipo de um drive (removível, fixo, CD-ROM, unidade de rede, etc)66 - Obter informações de um volume/disco (label, serial, sistema de arquivos, etc)65 - Alterar o nome de volume (Label) de um disco64 - Saber quais as unidades de disco (drives) estão presentes63 - "truncar" valores reais para apenas n casas decimais62 - Excluir todos os registros de uma tabela (como DELETE ALL do Clipper)61 - Saber se o sistema está usando 4 dígitos para o ano60 - Imprimir caracteres acentuados diretamente para a impressora59 - Imprimir texto justificado com formatação na impressora Epson LX-30058 - Formatar um disquete através de um programa Delphi57 - Alterar (e restaurar) o tamanho da página na impressora56 - Reproduzir um arquivo de som WAV sem o TMediaPlayer

Page 3: dicas para delphi

55 - Obter o nome do usuário e da empresa informado durante a instalação do Windows54 - Mostrar uma barra de progresso enquanto copia arquivos53 - Copiar arquivos usando o Shell do Windows52 - Descobrir o código ASCII de uma tecla51 - Evitar que seu programa apareça na barra de tarefas50 - Usar eventos de som do Windows49 - Mudar a coluna ativa em um DBGrid via programação48 - Fechar o Windows a partir do seu programa47 - Carregar um cursor animado (.ani)46 - Enviar um arquivo para a lixeira45 - Obter o número do registro atual44 - Trabalhar com Filter de forma mais prática43 - Reproduzir um arquivo WAV42 - Executar um programa DOS e fechá-lo em seguida41 - Fechar um programa a partir de um programa Delphi40 - Colocar Hint's de várias linhas39 - Reproduzir um vídeo AVI em um Form38 - Separar (filtrar) caracteres de uma string37 - Colocar zeros à esquerda de números36 - Copiar arquivos usando curingas (*.*)35 - Copiar arquivos34 - Trabalhar com cores no formato string33 - Verificar se determinado programa está em execução (Word, Delphi, etc)32 - Excluir arquivos usando curingas (*.*)31 - Gerar uma tabela no Word através do Delphi30 - Obter a quantidade de registros total e visível de uma tabela29 - Evitar que um programa seja executado mais de uma vez28 - Executar um "COMMIT" no Delphi27 - Posicionar Form's em relação ao Desktop do Windows26 - Saber a resolução de tela atual25 - Verificar se uma unidade de disco (disk-drive) está preparada24 - Salvar/restaurar o tamanho e posição de Form's23 - Definir a quantidade de registros a ser impressa em uma página do QuickReport22 - Onde encontrar tutoriais sobre construção de componentes em Delphi21 - Para que servem OnGetEditMask, OnGetEditText e OnSetEditText do TStringGrid20 - Mostrar um Form de LogOn antes do Form principal19 - Limitar a região de movimentação do mouse18 - Descobrir o nome de classe de uma janela do Windows17 - Ocultar/exibir a barra de tarefas do Windows16 - Evitar a proteção de tela durante seu programa15 - Fazer a barra de título ficar intermitente (piscante)14 - Posicionar o cursor do mouse em um controle13 - Criar cores personalizadas (sistema RGB)12 - Adicionar uma nova fonte no Windows11 - Saber se a impressora atual possui determinada fonte10 - Saber se determinada Font está instalada no Windows9 - Acertar a data e hora do sistema através do programa8 - ENTER em vez de TAB no formulário, no DBGrid e no StringGrid7 - Simular a vírgula através do ponto do teclado numérico6 - Paralizar um programa durante n segundos5 - Criar uma tabela (DB, DBF) através do seu programa4 - Verificar se um diretório existe3 - Verificar se um arquivo existe2 - Criar um Alias temporário através do seu programa1 - Criar um Alias através do seu programa

Page 4: dicas para delphi

159 - Pintar um Bitmap diretamente no Canvas do Form

- Declare a variavel Bmp na seção private:

private Bmp: TBitmap;

- Coloque um botão no Form e no evento OnClick digite:

Bmp:= TBitMap.Create; try Bmp.LoadFromFile('c:\teste\arquivo.bmp'); Canvas.Draw(0,0, Bmp); finally Bmp.Free; end;

Pronto! Irá aparecer a imagem no Canvas. É útil para fazer animações.

Dica enviada por: Alisson Viana JardimRevisada por: Daniel Pereira Guimarães

158 - Verificar se a impressora está ligada

Problema:

Faço impressão direta para a porta da impressora e gostariatestar se a impressora está pronta antes de enviar o relatório. Isto é possível em Delphi?

Solução:

Usando instruções Assembly podemos fazer isto. A funçãoabaixo retorna true se a porta informada está pronta.

Os possíveis parâmetros para esta função são:1 - para LPT12 - para LPT23 - para LPT34 - para LPT4

function tbTestLPT(Port: byte): boolean;var Pto : Word; Rdo : byte;begin Pto := Port -1; asm MOV DX,Pto MOV AX,$0200 {AH := $02 : Leer el estado de la impresora}

Page 5: dicas para delphi

INT $17 MOV Rdo,AH {Guarda el estado en AL} end; Result := Rdo = 144;end;

ObservaçõesProvavelmente esta função não funcionará em Windows NT devido ao acesso em baixo nível.

157 - Obter a letra do drive onde está o WindowsInclua na seção uses: Windows

Problema:

Como saber em qual unidade de disco (drive) o Windows estáinstalado?

Solução:

Esta função retorna a letra do drive onde está instalado oWindows:

function GetWindowsDrive: Char;var S: string;begin SetLength(S, MAX_PATH); if GetWindowsDirectory(PChar(S), MAX_PATH) > 0 then Result := string(S)[1] else Result := #0;end;

{ Exemplo de uso: }

procedure TForm1.Button1Click(Sender: TObject);begin Caption := GetWindowsDrive;end;

156 - Mostrar o nome do EXE no caption do form

{ Esta função extrai apenas o nome do arquivo passado, sem path e extensão }

function Titulo(Nome: String): String;var N, D: String;begin N := ExtractFileName(Nome); { Retira o path }

Page 6: dicas para delphi

D := ChangeFileExt(N,''); { Retira a extensão } { Coloca a primeira letra em maiúscula e o resto em minúscula } Titulo := UpperCase(Copy(D,1,1)) + LowerCase(Copy(D,2,Length(D)-1));end;

{ No OnCreate do form, coloque: }

procedure TForm1.FormCreate(Sender: TObject);begin Caption := Titulo(ParamStr(0));end;

- Dica enviada por: Luiz Eduardo.

155 - Fazer pesquisa incremental apenas com DBGrid

Problema:

Gostaria de fazer um formulário de pesquisa que, ao digitaralgo sobre o DBGrid, o registro correspondendo fosse localizado.

Solução:

- Coloque no form: TTable, TDataSource, TDBGrid e TLabel.

- Ajuste as propriedades do Table1: DatabaseName = TableName = Active = true

- Ajuste as propriedades do DataSource1: DataSet = Table1

- Ajuste as propriedades do DBGrid1: DataSource = DataSource1 Options -> dgEditing = false ReadOnly = true * Pode também ajustar a propriedades Columns para escolher as colunas que serão exibidas.

- Na seção private da unit declare: private FTexto: string;

- No evento OnCreate do form coloque: FTexto := ''; Label1.Caption := '';

Page 7: dicas para delphi

- No evento OnKeyPress do DBGrid1:

procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);begin if Key in [#8, #32..#255] then begin

if Key = #8 then { BackSpace } FTexto := Copy(FTexto, 1, Length(FTexto)-1) else FTexto := FTexto + Key;

{ Posiciona na coluna Nome } Table1.FieldByName('Nome').FocusControl;

{ Escolhe o índice e procura } Table1.IndexFieldNames := 'Nome'; Table1.FindNearest([FTexto]);

{ Mostra o texto procurado } Label1.Caption := FTexto; end;end;

ObservaçõesNo nosso exemplo estamos pesquisando através do campo "Nome". Para esta pesquisa precisamos de um índice com este campo.

154 - Obter tipo de uma propriedadeInclua na seção uses: TypInfo

{ Esta função retorna uma string com o nome do tipo de dado de uma propriedade. Exemplos de retornos: PropType(Button1, 'Caption'); // Retorna 'TCaption' PropType(Edit1, 'Width'); // Retorna 'Integer'; PropType(Edit1, 'Color'); // Retorna 'TColor';}

function PropType(const Obj: TObject; const PropName: string): string;var Info: PPropInfo;begin Info := GetPropInfo(Obj.ClassInfo, PropName); if Assigned(Info) then Result := Info^.PropType^.Name else Result := '';end;

{ Exemplo de uso: - Coloque um TButton e um TEdit; - No OnClick do Button1 coloque o código abaixo; - Execute, digite 'Caption' no Edit1 e clique em Button1.

Page 8: dicas para delphi

}

procedure TForm1.Button2Click(Sender: TObject);begin ShowMessage(PropType(Button1, Edit1.Text));end;

ObservaçõesVerdadeiramente não sei exatamente onde poderíamos aplicar esta dica, mas divulguei-a porque achei interessante. Acredito que o Object Inspector use algo parecido.

153 - Consulta SQL que usa a data do sistema

Problema:

Preciso fazer uma consulta com SQL que me retorne todosos registros em que o valor de um campo do tipo data sejaigual ou anterior à dada do sistema. Como fazer?

Solução:

Query.Close;Query.SQL.Text := 'select * from Tabela where CampoData <= :Hoje';Query.ParamByName('Hoje').AsDate := Date;Query.Open;

ObservaçõesEste exemplo foi testado com tabelas Paradox, mas deve funcionar na maioria dos bancos de dados com pouca ou nenhuma alteração.

152 - Abrir uma conecção Dial-UpInclua na seção uses: Windows

{ A função abaixo abre a caixa de diálogo de conecção com a rede Dial-Up. O parâmetro "name" é o nome da conecção previamente configurada.}

procedure DialUpConnect(const Name: string);begin WinExec(PChar('rundll32.exe rnaui.dll,RnaDial ' + Name), SW_SHOW);end;

{ Exemplo de uso: }

procedure TForm1.Button1Click(Sender: TObject);begin DialUpConnect('NomeDaConecção');end;

Page 9: dicas para delphi

151 - Pintar uma imagem JPG no formInclua na seção uses: Graphics, JPeg

Problema:

Gostaria de pintar imagens de arquivos JPG (JPeg) nos forms de minha aplicação. Isto é possível? Como?

Solução:

Para trabalhar com arquivos JPG você precisa usar um objetoTPicture, assim como colocar no uses a unit JPeg. Siga ospassos abaixo para pintar uma imagem JPG no form:

- No evento OnPaint do form coloque o código abaixo:

procedure TForm1.FormPaint(Sender: TObject);var Imagem: TPicture;begin Imagem := TPicture.Create; try Imagem.LoadFromFile('c:\teste\foto.jpg'); Canvas.StretchDraw(ClientRect, Imagem.Graphic); finally Imagem.Free; end;end;

- E no evento OnResize do form, coloque:

procedure TForm1.FormResize(Sender: TObject);begin Repaint;end;

ObservaçõesNão se esqueça de trocar o nome do arquivo JPG conforme sua necessidade. Este exemplo foi elaborado usando Delphi4.

150 - Executar comando do MS-DOS

Usando WinExec você pode executar qualquer comando do DOS. Para isto chame o COMMAND.COM passando como parâmetro a linha de comando a ser executada. O parâmetro /C é opcional e faz com que a janela do DOS seja fechada assim que o comando terminar. No exemplo abaixo estou executando a seguinte linha de comando: DIR C:\*.*

WinExec('COMMAND.COM /C DIR C:\*.*', SW_SHOW);

Page 10: dicas para delphi

ObservaçõesPara que a janela do DOS não seja exibida, use SW_HIDE no lugar de SW_SHOW.

149 - Formatar CEP

{ Esta função forma CEP como: 99.999-999 }function tbFormataCEP(const CEP: string): string;var I: integer;begin Result := ''; for I := 1 to Length(CEP) do if CEP[I] in ['0'..'9'] then Result := Result + CEP[I]; if Length(Result) <> 8 then raise Exception.Create('CEP inválido.') else Result := Copy(Result, 1, 2) + '.' + Copy(Result, 3, 3) + '-' + Copy(Result, 6, 3);end;

=== Para testar ===

- Coloque um Edit e um Button no form;- No evento OnClick do Button coloque a instrução abaixo:

Edit1.Text := tbFormataCEP(Edit1.Text);

ObservaçõesPara formatar outros códigos como CPF, CGC, etc., pode-se usar a mesma idéia.

148 - Permitir cancelar processo demorado

Problema:

Em determinadas partes no programa existem processos que podemdemorar vários minutos para serem concluídos. Muitas vezes ousuário desiste e deseja cancelar o processamento. Como permitir este cancelamento?

Solução:

Em aplicativos para Windows é comum, em processamentos demorados, o programa mostrar uma janela de diálogo avisandoque o processo pode levar um tempo extra. Nesta mesma janela normalmente coloca-se também um botão "Cancelar" que dá aousuário a opção aguardar ou desistir do processo. Para fazer isto em um aplicativo Delphi, siga os passos abaixo:

Page 11: dicas para delphi

- Vamos considerar em nosso exemplo que o processamento ocorre na unit do Form1.

- Declare, na seção public do Form1, uma variável boolean.

public; Cancelar: boolean;

- Crie um novo form (vou chamá-lo de Form2);- Coloque um botão neste novo form. Programe o OnClick deste botão conforme abaixo:

Form1.Cancelar := true;

- Na parte onde ocorre o loop do processamento demorado coloque algo como:

try { Antes de começar o processamento } Form2.Caption := 'Processamento demorado...'; Form2.Show;

{ No início do loop "Cancelar" precisa ser false } Cancelar := false;

{ Aqui inicia o loop do processamento demorado } while {...} do begin

{ ... Processa algo aqui... }

{ Permite que o programa processe mensagens do Windows } Application.ProcessMessages;

{ Se a variável "Cancelar" foi alterada para true... } if Cancelar then begin ShowMessage('Operação cancelada pelo usuário.'); Break; { Sai do loop } end;

end;

finally Form2.Close; end;

ObservaçõesNão se esqueça de que o Form1 precisa usar Form2 e vice-versa.

147 - Descobrir se uma data é fim do mêsInclua na seção uses: SysUtils

{ Esta função retorna true se a data passada como parâmetro

Page 12: dicas para delphi

é fim de mês. Retorna false caso contrário. }

function tbFimDoMes(const Data: TDateTime): boolean;var Ano, Mes, Dia: Word;begin DecodeDate(Data +1, Ano, Mes, Dia); Result := Dia = 1;end;

146 - Programar teclas de atalho do WindowsInclua na seção uses: Windows, Dialogs

Problema:

Gostaria de programar algumas teclas de atalho para chamar,por exemplo, uma calculadora, quando meu aplicativo estiveraberto. Como fazer?

Solução:

- No evento OnCreate do form coloque o código abaixo:

procedure TForm1.FormCreate(Sender: TObject);begin if not RegisterHotkey(Handle, 1, MOD_CONTROL or MOD_ALT, VK_F11) then ShowMessage('Erro ao programar Ctrl+Alt+F11');

if not RegisterHotkey(Handle, 2, MOD_CONTROL or MOD_ALT, VK_F12) then ShowMessage('Erro ao programar Ctrl+Alt+F12');end;

- No evento OnDestroy do form coloque o código abaixo:

procedure TForm1.FormDestroy(Sender: TObject);begin UnRegisterHotkey(Handle, 1); UnRegisterHotkey(Handle, 2);end;

- Declere a procedure abaixo na seção private:

private procedure WMHotkey(var Msg: TWMHotkey); message WM_HOTKEY;

- Abaixo da palavra implementation escreva a procedure:

procedure TForm1.WMHotkey(var Msg: TWMHotkey);begin case Msg.HotKey of 1: WinExec('calc.exe', SW_SHOW); 2: ShowMessage('Ctrl+Alt+F12 foram pressionadas'); end;

Page 13: dicas para delphi

end;

- Execute este programa e experimente pressionar Ctrl+Alt+F11 ou Ctrl+Alt+F12.

ObservaçõesSe a combinação de teclas já estiver em uso (num atalho, por exemplo), não será possível usá-la em nossa aplicação. Existem outras formas de implementar teclas de atalho em programas escritos em Delphi, mas a forma apresentada é bastante funcional.

145 - Obter o tipo de dado de um valor no Registro do WindowsInclua na seção uses: Registry, Dialogs

{ - Coloque um botão no form; - Altere o evento OnClick do botão conforme abaixo:}

procedure TForm1.Button1Click(Sender: TObject);const cRegPath = 'System\CurrentControlSet\control\FileSystem'; cRegValue = 'ACDriveSpinDown';var Reg: TRegistry; S: string;begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_LOCAL_MACHINE; if Reg.OpenKey(cRegPath, false) then begin case Reg.GetDataType(cRegValue) of rdUnknown: S := 'Tipo Desconhecido'; rdString: S := 'String'; rdExpandString: S := 'ExpandString'; rdInteger: S := 'Inteiro'; rdBinary: S := 'Binário'; end;

ShowMessage(S);

end else ShowMessage('Erro ao abrir chave do Registro'); finally Reg.Free; end;end;

ObservaçõesA unit Dialogs foi acrescentada no uses somente para podermos usar a procedure ShowMessage.

Page 14: dicas para delphi

144 - Obter a célula de um StringGrid que está sob o cursor do mouseInclua na seção uses: Windows

{ Esta procedure pega a linha e coluna da célula onde estiver o mouse. Valores negativos para Linha ou Coluna indicam que o mouse está fora da área cliente do StringGrid }

procedure MouseCell(Grid: TStringGrid; var Coluna, Linha: integer);var Pt: TPoint;begin GetCursorPos(Pt); Pt := Grid.ScreenToClient(Pt); if PtInRect(Grid.ClientRect, Pt) then Grid.MouseToCell(Pt.X, Pt.Y, Coluna, Linha) else begin Coluna := -1; Linha := -1; end;end;

{ Exemplo de uso: - Coloque um botão no form; - Altere o evento OnClick deste botão como abaixo:}

procedure TForm1.Button1Click(Sender: TObject);var Coluna, Linha: integer;begin MouseCell(StringGrid1, Coluna, Linha); if (Coluna >= 0) and (Linha >= 0) then Caption := 'Coluna: ' + IntToStr(Coluna) + ' - ' + 'Linha: ' + IntToStr(Linha); else Caption := 'O mouse não está no StringGrid';end;

{ Para testar: - Execute o programa; - Posicione o cursor do mouse sobre alguma célula do StringGrid; - Pressione TAB até chegar ao botão e pressione ENTER; - O resultado será mostrado no Caption do form;}

ObservaçõesNote que a procedure MouseCell usa um valor negativo (-1) para coluna e linha se o mouse não estiver sobre o StringGrid.

Page 15: dicas para delphi

143 - Limpar todas as células de um StringGrid

Existem três métodos que podemos aplicar para limpar um StringGrid.

{ Limpando uma célula de cada vez: }

procedure TForm1.Button1Click(Sender: TObject);var I, J: integer;begin with StringGrid1 do for I := 0 to ColCount -1 do for J := 0 to RowCount -1 do Cells[I,J] := '';end;

{ Limpando uma linha de cada vez: }

procedure TForm1.Button2Click(Sender: TObject);var I: integer;begin with StringGrid1 do for I := 0 to RowCount -1 do Rows[I].Clear;end;

{ Limpando uma coluna de cada vez: }

procedure TForm1.Button3Click(Sender: TObject);var I: integer;begin with StringGrid1 do for I := 0 to ColCount -1 do Cols[I].Clear;end;

ObservaçõesEm todos os exemplos estamos limpando o StringGrid completamente, inclusive linhas e colunas fixas. Para preservar linhas ou colunas fixas troque os valores iniciais de I ou J conforme a necessidade.

142 - Programar meu aplicativo para abrir arquivos a partir do Windows ExplorerInclua na seção uses: Registry

Problema:

Page 16: dicas para delphi

Criei um editor de textos no Delphi. Agora gostaria que o Windows Explorer usasse este editor para abrir arquivos coma extensão .dpg e .dan. Como fazer?

Solução:

Para fazer isto será necessária a criação de algumas chaves noRegistro do Windows. O exemplo abaixo cria todas as chavesnecessárias.

- Coloque um TButton e no evento OnClick dele coloque o código abaixo:

procedure TForm1.Button1Click(Sender: TObject);var Reg: TRegistry;begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_CLASSES_ROOT; Reg.LazyWrite := false;

{ Define o nome interno (ArquivoDaniel) e uma legenda que aparecerá no Windows Explorer (Arquivo do Daniel) } Reg.OpenKey('ArquivoDaniel', true); Reg.WriteString('', 'Arquivo do Daniel'); Reg.CloseKey;

{ Define o comando a ser executado quando abrir um arquivo pelo Windows Explorer (NomeDoExe %1). O símbolo %1 indica que o arquivo a ser aberto será passado como primeiro parâmetro para o aplicativo - ParamStr(1). } Reg.OpenKey('ArquivoDaniel\shell\open\command', true); Reg.WriteString('', ParamStr(0) + ' %1'); { NomeDoExe %1 } Reg.CloseKey;

{ Define o ícone a ser usado no Windows Explorer: 0 - primeiro ícone do EXE 1 - segundo ícone do EXE, etc } Reg.OpenKey('ArquivoDaniel\DefaultIcon', true); Reg.WriteString('', ParamStr(0) + ',0'); { 0 = primeiro ícone } Reg.CloseKey;

{ Define as extensões de arquivos que serão abertos pelo meu aplicativo }

{ *.dpg } Reg.OpenKey('.dpg', true); Reg.WriteString('', 'ArquivoDaniel'); Reg.CloseKey;

{ *.dan } Reg.OpenKey('.dan', true); Reg.WriteString('', 'ArquivoDaniel'); Reg.CloseKey;

Page 17: dicas para delphi

finally Reg.Free; end;end;

- Coloque um TMemo;- No evento OnShow do Form coloque o código abaixo:

procedure TForm1.FormShow(Sender: TObject);begin { Se o primeiro parâmetro for um nome de arquivo existente... } if FileExists(ParamStr(1)) then { Carrega o conteúdo do arquivo no memo } Memo1.Lines.LoadFromFile(ParamStr(1));end;

*** Para testar ***- Execute este programa;- Clique no botão para criar as chaves no Registro do Windows;- Feche o programa;- Crie alguns arquivos com as extensões .dpg e .dan;- Vá ao Windows Explorer e procure pelos arquivos criados;- Experimente dar um duplo-clique sobre qualquer dos arquivos com uma das extensões acima.

ObservaçõesExistem outros recursos que poderão ser configurados. Porém, para começar, este já é um bom exemplo.

141 - Consultar por mês de um campo data

Problema:

Tenho um cadastro de clientes com Codigo, Nome, DataNasc, etc.Preciso fazer uma consulta onde apareceão apenas os clientesque fazem aniversário em determinado mês. Como fazer?

Solução:

Use uma Query como abaixo:- Coloque no form os seguintes componentes: * TQuery * TDataSource * TDBGrid * TEdit * TButton

- Altere as propriedades dos componentes como abaixo: * Query1.DatabaseName = (alias do BDE) * DataSource1.DataSet = Query1 * DBGrid1.DataSource = DataSource1 - Coloque o código abaixo no evento OnClick de Button1:

Page 18: dicas para delphi

Query1.Close; Query1.SQL.Clear; Query1.SQL.Add('select * from dCli'); Query1.SQL.Add('where extract(month from DataNasc) = :Mes'); Query1.ParamByName('Mes').AsInteger := StrToInt(Edit1.Text); Query1.Open;

- Execute. Digite um número de 1 a 12 no Edit e clique no botão.

ObservaçõesOs números de 1 a 12 representam, respectivamente, os meses de Janeiro a Dezembro. Este exemplo foi testado com Delphi4, BDE5 e tabela Paradox7.

140 - Criando tabelas via SQLInclua na seção uses: dbTables

- Coloque um TButton no form;- Escreve no OnClick do Button como abaixo:

procedure TForm1.Button1Click(Sender: TObject);var Q: TQuery;begin Q := TQuery.Create(Application); try Q.DatabaseName := 'SF'; with Q.SQL do begin Add('Create Table Funcionarios'); Add('( Codigo AutoInc,'); Add(' Nome Char(30),'); Add(' Salario Money,'); Add(' Depto SmallInt,'); Add(' Primary Key (Codigo) )'); end; Q.ExecSQL; finally Q.Free; end;end;

ObservaçõesEste exemplo foi testado com banco de dados Paradox, porém deverá funcionar em vários outros bancos de dados com pouca ou nenhuma alteração.

139 - Obter nomes dos campos de uma tabelaInclua na seção uses: dbTables, Classes, Forms

A função abaixo obtém os nomes de todos os campos de umatabela do banco de dados.

Page 19: dicas para delphi

procedure tbGetFieldNames(const DBName, TblName: string; List: TStringList);var I: integer;begin List.Clear; with TTable.Create(Application) do try DatabaseName := DBName; TableName := TblName; with FieldDefs do begin Update; for I := 0 to Count -1 do List.Add(Items[I].Name); end; finally Free; end;end;

=== Exemplo de uso ===

- Coloque um TMemo e um TButton no Form;- Coloque o código abaixo no evento OnClick do Button:

procedure TForm1.Button1Click(Sender: TObject);var List: TStringList;begin List := TStringList.Create; try tbGetFieldNames(Edit1.Text, Edit2.Text, List); Memo1.Lines.Assign(List); finally List.Free; end;end;

138 - Nomeando um relatório no spool de impressão do WindowsInclua na seção uses: Printers

Problema:

Quando mandamos imprimir no Windows, normalmente o nome do documento aparece na fila de impressão (spool). Como fazercom que aplicativos feitos em Delphi se comporte destaforma? Ou seja, como nomear meus relatórios feitos em Delphi?

Solução:

Page 20: dicas para delphi

Antes de enviar seu relatório, faça assim:

Printer.Title := 'Nome do relatório';

ObservaçõesEsta solução aplica-se perfeitamente aos relatórios feitos usando o objeto Printer. Nos casos de geradores de relatórios, estes provavelmente possuem uma propriedade equivalente.

137 - Obter tamanho de um arquivoInclua na seção uses: SysUtils

{ A função abaixo retorna o tamanho do arquivo, ou -1 se o arquivo não for encontrado }

function tbFileSize(const FileName: string): integer;var SR: TSearchRec; I: integer;begin I := FindFirst(FileName, faArchive, SR); try if I = 0 then Result := SR.Size else Result := -1; finally FindClose(SR); end;end;

136 - Ocultar aplicação da lista de tarefas - CTRL+ALT+DEL

- Declare a função abaixo antes da palavra implementation:

function RegisterServiceProcess(dwProcessID, dwType: Integer): Integer; stdcall; external 'KERNEL32.DLL';

- Coloque dois botões no Form;- No evento OnClick do Button1 coloque:

RegisterServiceProcess(GetCurrentProcessID, 1);

- No evento OnClick do Button2 coloque:

RegisterServiceProcess(GetCurrentProcessID, 0);

=== Para testar ===

Clique no Button1 e pressione CTRL+ALT+DEL. O seu programa

Page 21: dicas para delphi

não aparecerá na lista.

Clique no Button2 e pressione CTRL+ALT+DEL. Agora seu programaaparecerá na lista.

Dica enviada por: Luiz Carlos Manzolli

135 - Obter path de um Alias do BDEInclua na seção uses: BDE

{ A função abaixo retorna o path (caminho) de um Alias do BDE }

function GetAliasPath(AliasName: String):String;var dbDes: DBDesc;begin Result:=''; DBiInit(Nil);// invoca o BDE , se não inicializado If DbiGetDatabaseDesc(PChar(AliasName), @dbDes)= DBIERR_NONE then with dbDes do Result:=StrPas(szPhyName); DBiExit;// Libera o BDEend;

Dica enviada por: Angelo Ricardo Miquelin Neto.

ObservaçõesSe a unit em que essa rotina for colocada utilizar as units DB e DBTABLES, as chamadas a DbiInit() e DbiExit() poderão ser omitidas.

134 - Ativar a proteção de tela do WindowsInclua na seção uses: Windows

{ Ativa a proteção de tela do Windows, se estiver configurada. }

SendMessage(Application.Handle, WM_SYSCOMMAND, SC_SCREENSAVE, 0);

133 - Desligar/Ligar monitorInclua na seção uses: Windows

No Win95 podemos desligar o monitor afim de economizar energia elétrica. Normalmente este recurso é controlado pelopróprio Windows. Porém sua aplicação Delphi também pode fazeristo. O exemplo abaixo desliga o monitor, aguarde 5 segundose re-liga monitor.

Page 22: dicas para delphi

SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, 0);Sleep(5000); { Aguarde 5 segundos }SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, -1);

ObservaçõesEste recurso pode não funcionar dependendo da configuração do sistema.

132 - Abrir e fechar o drive de CD-ROMInclua na seção uses: MMSystem

{ Para abrir }mciSendString('Set cdaudio door open wait', nil, 0, handle);

{ Para fechar }mciSendString('Set cdaudio door closed wait', nil, 0, handle);

131 - Impedir que o form seja arrastado para fora das margens da tela

- Na seção Private declare a procedure abaixo:

private procedure WMMove(var Msg: TWMMove); message WM_MOVE;

- Abaixo da palavra implementation escreva a procedure abaixo:

procedure TForm1.WMMove(var Msg: TWMMove); begin if Left < 0 then Left := 0; if Top < 0 then Top := 0; if Screen.Width - (Left + Width) < 0 then Left := Screen.Width - Width; if Screen.Height - (Top + Height) < 0 then Top := Screen.Height - Height;end;

Para testar:

- Execute o programa e tente arrastar o form para fora das margens da tela e veja o que acontece.

Page 23: dicas para delphi

130 - Mostrar mensagem mesmo que esteja no Prompt do DOSInclua na seção uses: Windows

Problema:

Fiz um programa que mostra mensagens de lembrete quando é chegada determinada data/hora. Porém quando o usuário vai para o Prompt do MS-DOS em modo tela cheia, a mensagem não aparece. O que devo fazer?

Solução:

Antes de mostrar a mensagem, coloque sua aplicação na frente das demais.

SetForegroundWindow(Application.Handle);ShowMessage('Teste');

129 - Copiar todos os registros de uma tabela para o ClipboardInclua na seção uses: Clipbrd

Problema:

Gostaria de colocar em minha aplicação o recurso de copiar todos os registros de uma tabela para a área de transferência,permitindo ao usuário colar estes dados em outro aplicativo (ex: MS-Word). Isto é possível?

Solução:

Sim. Siga os passos abaixo:

- Crie seu form normalmente, colocando DataSource, Table e demais componentes;- Coloque um botão e no evento OnClick deste botão coloque o código abaixo:

procedure TForm1.Button1Click(Sender: TObject);const SeparadorCampoValor = ': '; SeparadorCampo = #13#10; { Quebra de linha } SeparadorRegistro = '===========' + #13#10;var S: string; I: integer;begin S := ''; Table1.First; while not Table1.EOF do begin

Page 24: dicas para delphi

for I := 0 to Table1.FieldCount -1 do S := S + Table1.Fields[I].FieldName + SeparadorCampoValor + Table1.Fields[I].AsString + SeparadorCampo; S := S + SeparadorRegistro; Table1.Next; end; Clipboard.AsText := S;end;

Para testar:- Execute este aplicativo;- Clique no botão;- Vá em outro aplicativo (ex: MS-Word) e mande colar (Ctrl+V).

ObservaçõesCUIDADO! Não use este recurso com tabelas grandes, pois poderá usar memória demasiadamente. No teste que fiz, o tamanho da string S atingiu 20K e funcionou normalmente. Mas isto pode variar de uma máquina para outra.

128 - Copiar um registro de uma tabela para o ClipboardInclua na seção uses: Clipbrd

Problema:

Gostaria de colocar em minha aplicação o recurso de copiar um registro de uma tabela para a área de transferência,permitindo ao usuário colar estes dados em outro aplicativo (ex: MS-Word). Isto é possível?

Solução:

Sim. Siga os passos abaixo:

- Crie seu form normalmente, colocando DataSource, Table e demais componentes;- Coloque um botão e no evento OnClick deste botão coloque o código abaixo:

procedure TForm1.Button1Click(Sender: TObject);const SeparadorCampoValor = ': '; SeparadorCampo = #13#10; { Quebra de linha }var S: string; I: integer;begin S := ''; for I := 0 to Table1.FieldCount -1 do S := S + Table1.Fields[I].FieldName + SeparadorCampoValor + Table1.Fields[I].AsString + SeparadorCampo;

Clipboard.AsText := S;end;

Page 25: dicas para delphi

Para testar:- Execute este aplicativo;- Clique no botão;- Vá em outro aplicativo (ex: MS-Word) e mande colar (Ctrl+V).

127 - Criar sub-diretório no diretório do EXEInclua na seção uses: FileCtrl, SysUtils

Problema:

Gostaria de criar um sub-diretório dentro do diretório onde se encontra o EXE de minha aplicação. Como fazer?

Solução:

Primeiramente vamos conhecer algumas funções do Delphique precisaremos usá-las:

ParamStr(Indice) - Retorna valores passados na linha de comando quando executamos o programa. Se o valor de Indice for 0 (zero) será retornado o caminho+nome do EXE.

ExtractFilePath(NomeArq) - Retorna o caminho (path) do nome de arquivo informado. Exemplo: S := 'C:\NomeDir\Programa.exe'; ExtractFilePath(S); { retorna: 'C:\NomeDir\' }

DirectoryExists(CaminhoDir) - Retorna true se o diretório informado existe. False em caso contrário.

CreateDir(CaminhoDir) - Tenta criar o diretório informado.Se conseguir, retorna true. Caso contrário retorna false.

Agora que sabemos como trabalham estas funções, vamosescrever uma função que precisamos para criar um sub-diretório conforme proposto.

function CriaSubDir(const NomeSubDir: string): boolean;var Caminho: string;begin Caminho := ExtractFilePath(ParamStr(0)) + NomeSubDir; if DirectoryExists(Caminho) then Result := true else Result := CreateDir(Caminho);end;

Exemplo de uso:

- Chame a função no evento OnCreate do form:

Page 26: dicas para delphi

procedure TForm1.FormCreate(Sender: TObject);begin if not CriaSubDir('MeuSubDir') then ShowMessage('Não foi possível criar o sub-diretório MeuSubDir.');end;

126 - Ocultar o aplicativo do CTRL+ALT+DEL

Inclua no implementation de seu programa a seguinte linha:

function RegisterServiceProcess(dwProcessID, dwType: Integer): Integer; stdcall; external 'KERNEL32.DLL';

e depois no OnCreate ponha a seguinte linha:

RegisterServiceProcess(GetCurrentProcessID, 1);

Isso vai fazer o programa nao aparecer no CTRL+ALT+DEL,mas seu form principal vai continuar aparecendo. Para ocultartambém o form, basta por no OnCreate antes da linha acimaa seguinte linha:

Application.ShowMainForm:=False;

Resposta enviada por: dexter07

ObservaçõesSegundo o autor desta resposta, esta solução foi testada em Win95, mas também deve funcionar em Win98. Não sabe se funciona em NT.

125 - Personalizar a caixa de mensagem de exceções (erro) do Delphi

Problema:

Quando ocorre uma exceção no Delphi, ele automaticamenteexibe uma mensagem de erro. Gostaria de poder personalizarestas mensagens, acrescentando, por exemplo, o e-mail do suporte técnico. Isto é possível?

Solução:

Sim. Siga os passos abaixo:

- Declare um método (procedure) na seção private do form principal conforme abaixo:

private procedure ManipulaExcecoes(Sender: TObject; E: Exception);

Page 27: dicas para delphi

- Vá até a seção implementation e implemente este método, conforme o exemplo:

procedure TForm1.ManipulaExcecoes(Sender: TObject; E: Exception);begin MessageDlg(E.Message + #13#13 + 'Suporte técnico:'#13 + '[email protected]', mtError, [mbOK], 0);end;

- No evento OnCreate do Form principal escreva o código abaixo:

procedure TForm1.FormCreate(Sender: TObject);begin Application.OnException := ManipulaExcecoes;end;

=== Para testar ===

- Coloque um Button no form;- No evento OnClick deste botão coloque o código abaixo:

procedure TForm1.Button1Click(Sender: TObject);begin StrToInt('ABCD'); { Isto provoca uma exception }end;

ObservaçõesCuidado! Não coloque código que possa gerar exceção na rotina que manipula as exceções, pois se ocorrer uma exceção neste rotina, esta será chamada recursivamente até estourar a pilha.

124 - Implementar procedure Delay do Pascal no DelphiInclua na seção uses: Windows, Forms

Problema:

O Pascal para DOS possui uma procedure chamada Delay queserve para pausar o processamento atual em "n" milésimos de segundo. Como implemento isto no Delphi?

Solução:

Simles. Veja:

procedure Delay(MSec: Cardinal);var Start: Cardinal;begin Start := GetTickCount;

Page 28: dicas para delphi

repeat Application.ProcessMessages; until (GetTickCount - Start) >= MSec;end;

=== Exemplos de uso: ===

Delay(1000); { Aguarda 1 segundo }Delay(5000); { Aguarda 5 segundos }Delay(60000); { Aguarda 60 segundos - 1 minuto }

ObservaçõesAlém da procedure Delay criada acima, o programador Delphi pode usar também a API do Windows Sleep. Há porém uma diferença: Delay permite que que o programa continue a processar as mensagens do Windows (mouse, teclado, etc).

123 - Enviar comandos de rolagem vertical para um TMemoInclua na seção uses: Windows

Problema:

Gostaria que o meu programa rolasse automaticamente o conteúdo de um TMemo, simulando o deslizamento da barra derolagem vertical. Isto é possível no Delphi?

Solução:

Sim. Utilizando mensagens do Windows isto é fácil. Vejamosalgums exemplos:

SendMessage(Memo1.Handle, WM_VSCROLL, SBPAGEDOWN, 0);

Onde: Memo1.Handle = manipulador da janela do Memo1. WM_VSCROLL = Mensagem do Windows - rolagem vertical. SB_PAGEDOWN = Comanndo de rolagem - página para baixo.

Outros exemplos:

{ Página para cima }SendMessage(Memo1.Handle, WM_VSCROLL, SBPAGEUP, 0);

{ Linha para baixo }SendMessage(Memo1.Handle, WM_VSCROLL, SBLINEDOWN, 0);

{ Linha para cima }SendMessage(Memo1.Handle, WM_VSCROLL, SBLINEUP, 0);

ObservaçõesAlém desta técnica existem API's do Windows que fazem um trabalho equivalente.

Page 29: dicas para delphi

122 - Criar uma DLL de Bitmaps e usá-la

Problema:

Gostaria de colocar algums bitmaps em uma DLL e usá-los emtempo de execução. É possível fazer isto em Delphi?

Solução:

Sim. Siga os passos abaixo para criar a DLL de bitmaps:

- Crie um arquivo de recursos (.RES) contendo os Bitmaps. Use o Image Editor do Delphi para criar este arquivo. Salve-o com o nome BMPS.RES na pasta onde será salvo o projeto do Delphi;- Crie um novo projeto no Delphi;- Remova todos os forms do projeto;- Salve este projeto com o nome DLLBmp.dpr;- Abra o arquivo de projeto (DLLBmp.dpr) e altere para ficar somente com as linhas abaixo:

{$R BMPS.RES} library DLLBmp; end.

- Compile o projeto (Ctrl+F9). Será criado o arquivo DLLBmp.DLL.- Feche o projeto atual e crie um novo projeto;- Salve-o na mesma pasta que salvou o anterior, mas com outro nome qualquer;- Coloque no form um Edit e um Button;- No evento OnClick do Button coloque o código abaixo:

procedure TForm1.Button1Click(Sender: TObject);var Bmp: TBitmap; HandleDLL: THandle;begin { Carrega a DLL } HandleDLL := LoadLibrary('DLLBmp.DLL'); if HandleDLL = 0 then ShowMessage('Não foi possível carregar DLLBmp.DLL') else try Bmp := TBitmap.Create; try Bmp.Handle := LoadBitmap(HandleDLL, PChar(Edit1.Text)); if Bmp.Handle = 0 then ShowMessage('Não foi possível carregar o Bitmap.') else { Pinta o Bitmap no form } Canvas.Draw(0, 0, Bmp); finally

Page 30: dicas para delphi

Bmp.Free; end; finally { Libera a DLL } FreeLibrary(HandleDLL); end;end;

=== Para testar ===

- Execute este projeto;- Digite no Edit1 o nome que foi dado ao Bitmap no arquivo de recursos (.RES);- Clique no botão. O bitmap deverá ser pintado no form.

ObservaçõesO arquivo DLL poderá ser colocado na pasta onde estiver o EXE, no diretório do Windows ou ainda no sub-diretório System do Windows. Além de bitmaps podemos colocar qualquer outro tipo de recurso em DLL's.

121 - Construir a barra de título do form com um Panel

Pegue o arquivo tbtitle.zip na seção Download do IntereSite: www.ulbrajp.com.br/~tecnobyte

120 - Criar form sem título que possa ser arrastado

Problema:

Fazer um relógio num form é fácil. Porém gostaria que esseform não possuísse a barra de título, mas que o usuárioainda pudesse arrastá-lo com o mouse. Isto é possível no Delphi?

Solução:

Sim, é possível e é fácil. Siga os passos abaixo:

- Crie um novo projeto;- Mude as seguintes propriedades do Form1: BorderStyle = bsNone, FormStyle = fsStayOnTop,- Coloque um Label;- Coloque um Timer;- Altere o evento OnTimer do Timer1 conforme abaixo:

procedure TForm1.Timer1Timer(Sender: TObject);begin Label1.Caption := TimeToStr(Time);end;

- Altere o evento OnCreate do Form1 conforme abaixo:

Page 31: dicas para delphi

procedure TForm1.FormCreate(Sender: TObject);begin Width := 80; Height := 40; Label1.Left := 10; Label1.Top := 10;end;

- Vá na seção private do Form1 e declare a procedure abaixo:

private procedure WMNCHitTest(var Msg: TMessage); message WM_NCHitTest;public { Public declarations }end;

- Vá na seção implementation e escreva a procedure abaixo:

implementation

{$R *.DFM}

procedure TForm1.WMNCHitTest(var Msg: TMessage);begin if GetAsyncKeyState(VK_LBUTTON) < 0 then Msg.Result := HTCAPTION else Msg.Result := HTCLIENT;end;

- Execute e experimente arrastar form com o mouse.

ObservaçõesPara fechar este aplicativo pressione Alt+F4. Uma alternativa mais elegante é colocar um menu local (PopupMenu) com um comando para fechar.

119 - Obter status da memória do sistemaInclua na seção uses: Windows, SysUtils

- Coloque um TMemo no form- Coloque um TButton no form e altere seu OnClick conforme abaixo:

procedure TForm1.Button1Click(Sender: TObject);const cBytesPorMb = 1024 * 1024;var M: TMemoryStatus;begin M.dwLength := SizeOf(M); GlobalMemoryStatus(M);

Page 32: dicas para delphi

Memo1.Clear; with Memo1.Lines do begin Add(Format('Memória em uso: %d%%', [M.dwMemoryLoad])); Add(Format('Total de memória física: %f MB', [M.dwTotalPhys / cBytesPorMb])); Add(Format('Memória física disponível: %f MB', [M.dwAvailPhys / cBytesPorMb])); Add(Format('Tamanho máximo do arquivo de paginação: %f MB', [M.dwTotalPageFile / cBytesPorMb])); Add(Format('Disponível no arquivo de paginação: %f MB', [M.dwAvailPageFile / cBytesPorMb])); Add(Format('Total de memória virtual: %f MB', [M.dwTotalVirtual / cBytesPorMb])); Add(Format('Memória virtual disponível: %f MB', [M.dwAvailVirtual / cBytesPorMb])); end;end;

118 - Definir data/hora de um arquivoInclua na seção uses: SysUtils

{ Esta função altera a data e hora de um arquivo. Se obter sucesso retorna true, caso contrário retorna false. }

function DefineDataHoraArq(NomeArq: string; DataHora: TDateTime): boolean;var F: integer;begin Result := false; F := FileOpen(NomeArq, fmOpenWrite or fmShareDenyNone); try if F > 0 then Result := FileSetDate(F, DateTimeToFileDate(DataHora)) = 0; finally FileClose(F); end;end;

{ Exemplo de uso 1: Usa a data atual do sistema (Now) }

if DefineDataHoraArq('c:\teste\logo.bmp', Now) then ShowMessage('Data/Hora do arquivo definida com sucesso.')else ShowMessage('Não foi possível definir data/hora do arquivo.');

{ Exemplo de uso 2: Usa uma data fixa }var DataHora: TDateTime;begin { Define a data para 5-Fev-1999 e a hora para 10:30 } DataHora := EncodeDate(1999, 2, 5) + EncodeTime(10, 30, 0, 0);

Page 33: dicas para delphi

if DefineDataHoraArq('c:\teste\logo.bmp', DataHora) then ShowMessage('Data/Hora do arquivo definida com sucesso.') else ShowMessage('Não foi possível definir data/hora do arquivo.');end;

117 - Mostrar o diálogo About (Sobre) do WindowsInclua na seção uses: ShellApi

procedure TForm1.Button1Click(Sender: TObject);begin ShellAbout(Handle, 'Sistema Financeiro', 'Marcelo Senger', Application.Icon.Handle);end;

ObservaçõesDica enviada por: Marcelo Senger

116 - Ocultar/exibir o cursor do mouseInclua na seção uses: Windows

- Escreva a função abaixo:

function MouseShowCursor(const Show: boolean): boolean;var I: integer;begin I := ShowCursor(LongBool(true)); if Show then begin Result := I >= 0; while I < 0 do begin Result := ShowCursor(LongBool(true)) >= 0; Inc(I); end; end else begin Result := I < 0; while I >= 0 do begin Result := ShowCursor(LongBool(false)) < 0; Dec(I); end; end;end;

- Exemplos de uso:

MouseShowCursor(false); { Oculta o cursor }

MouseShowCursor(true); { Exibe o cursor }

Page 34: dicas para delphi

115 - Converter de Hexadecimal para InteiroInclua na seção uses: SysUtils

Problema:

A função IntToHex do Delphi converte inteiro para hexadecimal. O que preciso, no entanto, é fazer o contrário,ou seja, converter de hexadecimal para inteiro. Existeisto pronto no Delphi ou terei que escrever uma funçãopara isto?

Solução:

A função StrToInt pode receber uma string no formato de umnúmero decimal ou hexadecimal. Então podemos usá-la assim:

var I: integer;begin I := StrToInt('$' + Edit1.Text); {...}end;

ObservaçõesNo Delphi, um número na notação decimal deve iniciar com o símbolo $.

114 - Mudar a cor de um DBEdit dentro de um DBCtrlGrid de acordo com uma condição

Problema:

Uso um DBCtrlGrid e gostaria que, quando o valor de um determinado campo for negativo, o DBEdit ligado a este campo seja exibido em vermelho e, caso contrário, em azul. Isto é possível?

Solução:

- Monte o form normalmente colocando DataSource, Table, DBCtrlGrid e os DBEdit's, DBText's, etc.

- Escreva no manipulador do evento OnPaintPanel do DBCtrlGrid conforme abaixo:

procedure TForm1.DBCtrlGrid1PaintPanel(DBCtrlGrid: TDBCtrlGrid; Index: Integer);begin if Table.FieldByName('NomeDoCampo').AsFloat < 0 then DBEdit1.Font.Color := clRed else DBEdit1.Font.Color := clBlue;end;

Page 35: dicas para delphi

ObservaçõesNeste exemplo mudamos a cor da fonte do componente DBEdit, Porém, pode-se também mudar a cor do próprio componente (DBEdit1.Color).

113 - Colocar uma ProgressBar da StatusBar

- Coloque uma StatusBar no form.

- Adicione dois paineis na StatusBar (propriedade Panels).

- Ajuste as propriedades do primeiro painel conforme abaixo: Style = psOwnerDraw Width = 150

- Coloque uma ProgressBar no form e mude sua propriedade Visible para false.

- No evento OnDrawPanel da StatusBar digite o código abaixo:

procedure TForm1.StatusBar1DrawPanel(StatusBar: TStatusBar; Panel: TStatusPanel; const Rect: TRect);begin { Se for o primeiro painel... } if Panel.Index = 0 then begin { Ajusta a tamanho da ProgressBar de acordo com o tamanho do painel } ProgressBar1.Width := Rect.Right - Rect.Left +1; ProgressBar1.Height := Rect.Bottom - Rect.Top +1; { Pinta a ProgressBar no DC (device-context) da StatusBar } ProgressBar1.PaintTo(StatusBar.Canvas.Handle, Rect.Left, Rect.Top); end;end;

- Coloque um Button no form- Digite no evento OnClick do Button o código abaixo:

procedure TForm1.Button1Click(Sender: TObject);var I: integer;begin for I := ProgressBar1.Min to ProgressBar1.Max do begin { Atualiza a posição da ProgressBar } ProgressBar1.Position := I; { Repinta a StatusBar para forçar a atualização visual } StatusBar1.Repaint; { Aguarda 50 milisegundos } Sleep(50); end;

{ Aguarde 500 milisegundos } Sleep(500);

Page 36: dicas para delphi

{ Reseta (zera) a ProgressBar } ProgressBar1.Position := ProgressBar1.Min; { Repinta a StatusBar para forçar a atualização visual } StatusBar1.Repaint;end;

- Execute e clique no botão para ver o resultado.

ObservaçõesCom um pouco de criatividade podemos fazer outras coisas interessantes usando o evento OnDrawPanel da StatusBar.

112 - Executar um programa e aguardar sua finalização antes de continuarInclua na seção uses: Windows

{ Esta função faz isto. }

function ExecAndWait(const FileName, Params: string; const WindowState: Word): boolean;var SUInfo: TStartupInfo; ProcInfo: TProcessInformation; CmdLine: string;begin { Coloca o nome do arquivo entre aspas. Isto é necessário devido aos espaços contidos em nomes longos } CmdLine := '"' + Filename + '"' + Params; FillChar(SUInfo, SizeOf(SUInfo), #0); with SUInfo do begin cb := SizeOf(SUInfo); dwFlags := STARTF_USESHOWWINDOW; wShowWindow := WindowState; end; Result := CreateProcess(nil, PChar(CmdLine), nil, nil, false, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, PChar(ExtractFilePath(Filename)), SUInfo, ProcInfo);

{ Aguarda até ser finalizado } if Result then begin WaitForSingleObject(ProcInfo.hProcess, INFINITE); { Libera os Handles } CloseHandle(ProcInfo.hProcess); CloseHandle(ProcInfo.hThread); end;end;

- Exemplo de uso:

ExecAndWait('c:\windows\notepad.exe', '', SW_SHOW);

Page 37: dicas para delphi

ObservaçõesNão se esqueça de informar o caminho (path) do arquivo completo. Esta função foi desenvolvida para Delphi 32 bits (2, 3, 4,...).

111 - Simular o pressionamento de uma combinação de teclas (ex: Ctrl+F2)Inclua na seção uses: Windows

{ Mantém pressionada CTRL }keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY or 0, 0);

{ Pressiona F2 }keybd_event(VK_F2, 0, 0, 0);

{ Libera (solta) CTRL }keybd_event(VK_CONTROL, $45, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);

ObservaçõesNeste exemplo pressionamos Ctrl+F2. Não se esqueça das teclas que precisam manter pressionadas: Ctrl, Alt, Shift.

110 - Simular o pressionamento de uma teclaInclua na seção uses: Windows

A API keybd_event do Windows serve para fazer isto. No exemploabaixo estamos simulando o pressionamento da tecla F2:

keybd_event(VK_F2, 0, 0, 0);

Para testar faça o exemplo a seguir:

- Mude a propriedade KeyPreview do form para true.- Escreva no evento OnKeyDown do form como abaixo:

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);begin if Key = VK_F2 then ShowMessage('F2 pressionada');end;

- Coloque um botão e escreva no OnClick (do botão) como abaixo:

procedure TForm1.Button1Click(Sender: TObject);begin keybd_event(VK_F2, 0, 0, 0);end;

Page 38: dicas para delphi

ObservaçõesConsulte as constantes para os códigos das teclas (ex: VK_RETURN, VK_DOWN, etc).

109 - Ligar/desligar a tecla Caps LockInclua na seção uses: Windows

{ Esta função liga/desliga Caps Lock, conforme o parãmetro State }

procedure tbSetCapsLock(State: boolean);begin if (State and ((GetKeyState(VK_CAPITAL) and 1) = 0)) or ((not State) and ((GetKeyState(VK_CAPITAL) and 1) = 1)) then begin keybd_event(VK_CAPITAL, $45, KEYEVENTF_EXTENDEDKEY or 0, 0); keybd_event(VK_CAPITAL, $45, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0); end;end;

{ Exemplos de uso: }

tbSetCapsLock(true); { Liga Caps Lock }

tbSetCapsLock(false); { Desliga Caps Lock }

ObservaçõesAparentemente, podemos usar esta mesma técnica para ligar/desligar Num Lock. Neste caso trocaríamos VK_CAPITAL por VK_NUMLOCK. Por incrível que pareça não funcionou (pelo menos no teste que fiz). E tem mais: isto está na documentação do (R)Windows.

108 - Verificar se uma determinada tecla está pressionadaInclua na seção uses: Windows

{ Esta função retorna true se a tecla informada estiver pressionada. False em caso contrário. }

function tbKeyIsDown(const Key: integer): boolean;begin Result := GetKeyState(Key) and 128 > 0;end;

{ Exemplos de uso: }

if tbKeyIsDown(VK_CONTROL) then { Tecla Ctrl pressionada }

if tbKeyIsDown(VK_MENU) then { Tecla Alt pressionada }

if tbKeyIsDown(VK_SHIFT) then

Page 39: dicas para delphi

{ Tecla Shift pressionada }

if tbKeyIsDown(VK_F2) then { Tecla F2 pressionada }

ObservaçõesQualquer tecla pode ser verificada. Para isto basta saber o código virtual (Virtual Key Code) da tecla.

107 - Verificar o estado de NumLock e CapsLockInclua na seção uses: Windows

{ Esta função retorna true se a tecla informada estiver ligada. False em caso contrário }

function tbKeyIsOn(const Key: integer): boolean;begin Result := GetKeyState(Key) and 1 > 0;end;

{ Exemplo de uso: }

if tbKeyIsOn(VK_NUMLOCK) then { ... NumLock está ligada }else { ... NumLock está desligada }

ObservaçõesQualquer tecla que possua os estados On/Off pode ser verificada. Basta, para isto, saber seu código. O código de CapsLock é VK_CAPITAL.

106 - Configurar linhas de diferentes alturas em StringGrid

- Coloque o StringGrid no form.- No evento OnCreate do form coloque o código abaixo:

procedure TForm1.FormCreate(Sender: TObject);begin StringGrid1.RowHeights[0] := 15; StringGrid1.RowHeights[1] := 20; StringGrid1.RowHeights[2] := 50; StringGrid1.RowHeights[3] := 35;end;

ObservaçõesCuidado para não especificar uma linha inexistente.

Page 40: dicas para delphi

105 - Adicionar o evento OnClick do DBGrid

Problema:

Meu programa precisa processar algo quando o usuário clicarno DBGrid em um determinado form. O problema é que o DBGrid nãopossui o evento OnClick. É possível adicionar este evento no DBGrid?

Solução:

É possível sim. Afinal é muito simples. Siga os passos abaixopara resolver seu problema:

- Monte seu form normalmente, colocando o DBGrid e demais componentes;- Vá na seção "private" da unit e declare a procedure abaixo:

private procedure DBGridClick(Sender: TObject);

- Logo após a palavra "implementation", escreva a procedure:

implementation

{$R *.DFM}

procedure TForm1.DBGridClick(Sender: TObject);begin ShowMessage('Clicou no DBGrid.');end;

- Coloque as instruções abaixo no evento OnCreate do Form:

procedure TForm1.FormCreate(Sender: TObject);begin DBGrid1.ControlStyle := DBGrid1.ControlStyle + [csClickEvents]; TForm(DBGrid1).OnClick := DBGridClick;end;

- E pronto. Execute e teste.

ObservaçõesO segredo principal desta dica está OnCreate do Form. A primeira instrução ativa o evento OnClick. A segunda instrução acessa o manipulador do evento OnClick. Para isto precisamos tratar o DBGrid como se fosse Form, pois o evento OnClick está declarado como protegido (protected) na classe TDBGrid.

104 - Criar caixas de diálogo em tempo de execuçãoInclua na seção uses: Forms, StdCtrls, Buttons

Page 41: dicas para delphi

A função abaixo demonstra a criação de uma caixa de diálogoque pode ser usada para permitir ao usuário digitar o seunome:

{ Esta função retorna true se for pressionado OK e false em caso contrário. Se for OK, o texto digitado pelo usuário será copiado para a variável Nome }

function ObterNome(var Nome: string): boolean;var Form: TForm; { Variável para o Form } Edt: TEdit; { Variável para o Edit }begin Result := false; { Por padrão retorna false } { Cria o form } Form := TForm.Create(Application); try { Altera algumas propriedades do Form } Form.BorderStyle := bsDialog; Form.Caption := 'Atenção'; Form.Position := poScreenCenter; Form.Width := 200; Form.Height := 150; { Coloca um Label } with TLabel.Create(Form) do begin Parent := Form; Caption := 'Digite seu nome:'; Left := 10; Top := 10; end; { Coloca o Edit } Edt := TEdit.Create(Form); with Edt do begin Parent := Form; Left := 10; Top := 25; { Ajusta o comprimento do Edit de acordo com a largura do form } Width := Form.ClientWidth - 20; end; { Coloca o botão OK } with TBitBtn.Create(Form) do begin Parent := Form; { Posiciona de acordo com a largura do form } Left := Form.ClientWidth - (Width * 2) - 20; Top := 80; Kind := bkOK; { Botão Ok } end; { Coloca o botão Cancel } with TBitBtn.Create(Form) do begin Parent := Form; Left := Form.ClientWidth - Width - 10; Top := 80; Kind := bkCancel; { Botão Cancel } end;

Page 42: dicas para delphi

{ Exibe o form e aguarda a ação do usuário. Se for OK... } if Form.ShowModal = mrOK then begin Nome := Edt.Text; Result := true; end; finally Form.Free; end;end;

Para chamar esta função siga o exemplo abaixo:

procedure TForm1.Button1Click(Sender: TObject);var S: string;begin if ObterNome(S) then Edit1.Text := S;end;

ObservaçõesOs componentes Label, Edit (var Edt) e BitBtn's (botões) não são destruídos explicitamente (Componente.Free). Isto não é necessário, pois ao criá-los informei como proprietário o Form (ex: TLabel.Create(Form)). Neste caso, estes componentes são destruídos automaticamente ao destruir o Form (Form.Free).

103 - Converter a primeira letra de um Edit para maiúsculo

with Edit2 doif Text <> '' then Text := AnsiUpperCase(Text[1]) + Copy(Text, 2, Length(Text));

Isto pode ser colocado, por exemplo, no OnExit do Edit.

Você pode também converter durante a digitação. Para isto coloque o código abaixo no evento OnKeyPress do Edit:

if Edit1.SelStart = 0 then Key := AnsiUpperCase(Key)[1]else Key := AnsiLowerCase(Key)[1];

102 - Verificar se uma string contém uma hora válida

- Use a função abaixo:

function StrIsTime(const S: string): boolean;begin try StrToTime(S); Result := true;

Page 43: dicas para delphi

except Result := false; end;end;

101 - Verificar se uma string contém um valor numérico válido

- Use uma das funções abaixo, conforme o tipo de dado que se quer testar:

function StrIsInteger(const S: string): boolean;begin try StrToInt(S); Result := true; except Result := false; end;end;

function StrIsFloat(const S: string): boolean;begin try StrToFloat(S); Result := true; except Result := false; end;end;

100 - Mostrar uma mensagem durante um processamento

Problema:

Um processamento em meu sistema é bastante demorado e por istocolocar apenas o cursor de ampulheta continua deixando o usuário confuso, pensando que o sistema travou. É possívelexibir uma mensagem enquanto um processamento demorado ocorre?

Sim. E é fácil. Vejamos:

- Crie um form com a mensagem. Um pequeno form com um Label já é suficiente. Aqui vou chamá-lo de FormMsg.- Vá em Project|Options e passe o FormMsg de "Auto-create forms" para "Available forms".- Abaixo vou simular um processamento demorado, usando a API Sleep:

procedure TForm1.Button1Click(Sender: TObject);

Page 44: dicas para delphi

var Form: TFormMsg; I: integer;begin Form := TFormMsg.Create(Self); try Form.Label1.Caption := 'Processamento demorado...'; Form.Show; for I := 1 to 5 do begin Form.UpDate; Sleep(1000); { Aguarda um segundo } end; finally Form.Free; end;end;

ObservaçõesA função Sleep é uma API do Windows e serve para paralisar a aplicação por um determinado dempo. Este tempo é em milisegundos.

99 - Mostrar um cursor de ampulheta durante um processamento

- Salve o cursor atual- Defina o novo cursor (crHourGlass é ampulheta)- Faça o processamento- Restaure o cursor.

Vejamos:

var PrevCur: TCursor;begin PrevCur := Screen.Cursor; try Screen.Cursor := crHourGlass; { Coloque aqui as instruções do processamento } finally Screen.Cursor := PrevCur; end;end;

ObservaçõesExistem diversos outros cursores pré-definidos no Delphi. Dê uma olhada na propriedade Cursor de um componente visual para ver uma lista de todos eles. Você poderá também criar o seu próprio cursor.

98 - Ler e escrever dados binários no Registro do WindowsInclua na seção uses: Registry

Page 45: dicas para delphi

Coloque no Form:- três edits;- dois botões.

Logo abaixo da palavra implementation declare:

type

{ Declara um tipo registro } TFicha = record Codigo: integer; Nome: string[40]; DataCadastro: TDateTime; end;

- Escreva o evento OnClick do Button1 conforme abaixo:

procedure TForm1.Button1Click(Sender: TObject);var Reg: TRegistry; Ficha: TFicha;begin { Coloca alguns dados na variável Ficha } Ficha.Codigo := StrToInt(Edit1.Text); Ficha.Nome := Edit2.Text; Ficha.DataCadastro := StrToDate(Edit3.Text);

Reg := TRegistry.Create; try { Define a chave-raiz do registro } Reg.RootKey := HKEY_CURRENT_USER;

{ Abre uma chave (path). Se não existir cria e abre. } Reg.OpenKey('Cadastro\Pessoas\', true);

{ Grava os dados (o registro) } Reg.WriteBinaryData('Dados', Ficha, SizeOf(Ficha)); finally Reg.Free; end;end;

- Escreva o evento OnClick do Button2 conforme abaixo:

procedure TForm1.Button2Click(Sender: TObject);var Reg: TRegistry; Ficha: TFicha;begin Reg := TRegistry.Create; try { Define a chave-raiz do registro } Reg.RootKey := HKEY_CURRENT_USER;

Page 46: dicas para delphi

{ Se existir a chave (path)... } if Reg.KeyExists('Cadastro\Pessoas') then begin { Abre a chave (path) } Reg.OpenKey('Cadastro\Pessoas', false);

{ Se existir o valor... } if Reg.ValueExists('Dados') then begin { Lê os dados } Reg.ReadBinaryData('Dados', Ficha, SizeOf(Ficha)); Edit1.Text := IntToStr(Ficha.Codigo); Edit2.Text := Ficha.Nome; Edit3.Text := DateToStr(Ficha.DataCadastro); end else ShowMessage('Valor não existe no registro.') end else ShowMessage('Chave (path) não existe no registro.'); finally Reg.Free; end;end;

ObservaçõesQualquer tipo de dado pode ser gravado e lido de forma binária no registro do Windows. Para isto você precisa saber o tamanho do dado. Para dados de tamanho fixo, use SizeOf(). Lembrete: não grave dados muito extensos no Registro do Windows (ex: imagens), pois isto prejudicará o desempenho do sistema.

97 - Mudar a resolução do vídeo via programação

- Coloque um ListBox no form- Modifique o OnCreate do form assim:

procedure TForm1.FormCreate(Sender: TObject);var i : Integer; DevMode : TDevMode;begin i := 0; while EnumDisplaySettings(nil,i,Devmode) do begin with Devmode do ListBox1.Items.Add(Format('%dx%d %d Colors', [dmPelsWidth,dmPelsHeight, 1 shl dmBitsperPel])); Inc(i); end;end;

- Coloque um botão no form- Altere o evento OnClick do botão conforme abaixo:

procedure TForm1.Button1Click(Sender: TObject);var

Page 47: dicas para delphi

DevMode : TDevMode;begin EnumDisplaySettings(nil,Listbox1.ItemIndex,Devmode); ChangeDisplaySettings(DevMode,0);end;

ObservaçõesNos testes que fiz, nem tudo funcionou adequadamente. Mas vale a pena experimentar.

96 - Ler e escrever dados no Registro do WindowsInclua na seção uses: Registry

- Coloque no form dois edits e dois botões.- No evento OnClick do Button1 escreva o código abaixo:

procedure TForm1.Button1Click(Sender: TObject);var Reg: TRegistry;begin Reg := TRegistry.Create; try { Define a chave-raiz do registro } Reg.RootKey := HKEY_CURRENT_USER; { Abre a chave (path). Se não existir, cria e abre. } Reg.OpenKey('MeuPrograma\Configuração', true); { Escreve um inteiro } Reg.WriteInteger('Numero', StrToInt(Edit1.Text)); { Escreve uma string } Reg.WriteString('Nome', Edit2.Text); finally Reg.Free; end;end;

- No evento OnClick do Button2, escreva:

procedure TForm1.Button2Click(Sender: TObject);var Reg: TRegistry;begin Reg := TRegistry.Create; try Reg.RootKey := HKEY_CURRENT_USER; if Reg.KeyExists('MeuPrograma\Configuração') then begin Reg.OpenKey('MeuPrograma\Configuração', false);

if Reg.ValueExists('Numero') then Edit1.Text := IntToStr(Reg.ReadInteger('Numero')) else ShowMessage('Não existe valor com o nome "Numero"');

if Reg.ValueExists('Nome') then

Page 48: dicas para delphi

Edit2.Text := Reg.ReadString('Nome') else ShowMessage('Não existe valor com o nome "Nome"');

end else ShowMessage('Não existe a chave no registro'); finally Reg.Free; end;end;

ObservaçõesUser o aplicativo RegEdit.exe do windows para ver o registro. Cuidado para não alterar as configurações do Windows!

95 - Adicionar barra de rolagem horizontal no ListBox

{ - Coloque um ListBox no form; - Altere o OnCreate do Form conforme abaixo:}

procedure TForm1.FormCreate(Sender: TObject);var I, Temp, MaxTextWidth: integer;begin { Adiciona algumas linhas no ListBox } Listbox1.Items.Add('Linha 1'); Listbox1.Items.Add('Linha 2, longa para que seja necessária a barra de rolagem horizontal'); Listbox1.Items.Add('Linha 3');

if Listbox1.Items.Count > 1 then begin

{ Obtém o comprimento, em pixels, da linha mais longa } MaxTextWidth := 0; for I := 0 to Listbox1.Items.Count - 1 do begin Temp := ListBox1.Canvas.TextWidth(ListBox1.Items[I]); if Temp > MaxTextWidth then MaxTextWidth := Temp; end;

{ Acrescenta a largura de um "W" } MaxTextWidth := MaxTextWidth + Listbox1.Canvas.TextWidth('W');

{ Envia uma mensagem ao ListBox } SendMessage(ListBox1.Handle, LB_SETHORIZONTALEXTENT, MaxTextWidth, 0); end;end;

{ Para ocultar use a instrução abaixo: }

SendMessage(ListBox1.Handle, LB_SETHORIZONTALEXTENT, 0, 0);

Page 49: dicas para delphi

94 - Simular um CharCase no DBGrid

Para converter a digitação para maiúsculo, coloque isto noevento OnKeyPress do DBGrid:

Key := AnsiUpperCase(Key)[1];

Para converter para minúsculo, troque por:

Key := AnsiLowerCase(Key)[1];

93 - Verificar se uma string é uma data válida

Escreva a função abaixo:

function tbStrIsDate(const S: string): boolean;begin try StrToDate(S); Result := true; except Result := false; end;end;

Para testar:- Coloque um Edit no form;- Coloque um Button;- No evento OnClick do botão coloque o código abaixo:

if tbStrIsDate(Edit1.Text) then ShowMessage(Edit1.Text + ' é data válida.')else ShowMessage(Edit1.Text + ' NÃO é data válida.');

92 - Fazer pesquisa incremental com DBGrid e Edit

Problema:

Gostaria de montar um formulário de pesquisa com um DBGrid eum Edit de modo que, enquanto o usuário digita um nome doEdit, o registro vai sendo localizado no DBGrid. Como fazer?

- Crie um índice na tabela com campo a ser usado na pesquisa.

Coloque no Form:

- Um DataSource

Page 50: dicas para delphi

- Um Table- Um DBGrid- Um Edit

Altere as seguintes propriedades:

- DataSource1.DataSet = Table1- Table1.DatabaseName = 'NomeDoAlias'- Table1.TableName = 'NomeDaTabela'- Table1.IndexFieldNames = 'NomeDoCampo'- Table1.Active = true- DBGrid1.DataSource = DataSource1

Escreva a instrução abaixo no evento OnChange do Edit:

Table1.FindNearest([Edit1.Text]);

ObservaçõesEste exemplo considera que o campo seja tipo string. Para outros tipos de campos pode ocorrer erro dependendo dos valores digitados no Edit1.

91 - Adicionar zeros à esquerda de um número

Existem várias formas. Vejamos uma:

function tbStrZero(const I: integer; const Casas: byte): string;var Ch: Char;begin Result := IntToStr(I); if Length(Result) > Casas then begin Ch := '*'; Result := ''; end else Ch := '0';

while Length(Result) < Casas do Result := Ch + Result;end;

{ Exemplo de como usá-la: }

var S: string; Numero: integer; {...}begin {...} S := tbStrZero(Numero, 6); {...}end;

Page 51: dicas para delphi

ObservaçõesSe o comprimento desejado (Casas) não for suficiente para conter o número, serão colocados asteriscos.

90 - Limpar um campo tipo data via programação

Table1.FieldByName('Data').Clear;

{ ou }

Table1.FieldByName('Data').AsString := '';

ObservaçõesPodemos usar este recurso para limpar também campos numéricos, string, etc.

89 - Implementar um campo auto-incremental via programaçãoInclua na seção uses: dbTables

procedure tbAutoInc(Table: TTable; const FieldName: string);var Q: TQuery;begin if not Table.FieldByName(FieldName).IsNull then Exit;

Q := TQuery.Create(nil); try Q.DatabaseName := Table.DatabaseName; Q.SQL.Add('select max(' + FieldName + ') from ' + Table.TableName); Q.Open; try Table.FieldByName(FieldName).AsInteger := Q.Fields[0].AsInteger +1; finally Q.Close; end; finally Q.Free; end;end;

{ Chame esta procedure no evento BeforePost de um Table: }procedure TForm1.Table1BeforePost(DataSet: TDataSet);begin tbAutoInc(Table1, 'Codigo');end;

Page 52: dicas para delphi

ObservaçõesA função acima incrementa o campo somente se estiver vazio. Assim podemos dar ao usuário a opção de digitar neste campo ou deixá-lo vazio para que seja auto-incrementado. Existem várias outras formas de implementar este recurso.

88 - Obter o endereço IP do Dial-UpInclua na seção uses: WinSock

{ Esta função retorna o endereço IP do Dial-Up. }

function GetLocalIP : string;type TaPInAddr = array [0..10] of PInAddr; PaPInAddr = ^TaPInAddr;var phe : PHostEnt; pptr : PaPInAddr; Buffer : array [0..63] of char; I : Integer; GInitData : TWSADATA;begin WSAStartup($101, GInitData); Result := ''; GetHostName(Buffer, SizeOf(Buffer)); phe :=GetHostByName(buffer); if phe = nil then Exit; pptr := PaPInAddr(Phe^.h_addr_list); I := 0; while pptr^[I] <> nil do begin result:=StrPas(inet_ntoa(pptr^[I]^)); result := StrPas(inet_ntoa(pptr^[I]^)); Inc(I); end; WSACleanup;end;

ObservaçõesSe o endereço IP for designado pelo servidor, a cada conecção teremos um endereço IP diferente e, obviamente, se não estivermos conectados, não conseguiremos obtê-lo.

87 - Exibir a caixa de diálogo padrão de solicitação de senha do banco de dadosInclua na seção uses: DbPwDlg

{ Coloque um botão no form e escreve seu evento OnClick como abaixo }

procedure TForm1.Button1Click(Sender: TObject);var pw: TPasswordDialog;

Page 53: dicas para delphi

begin pw := TPasswordDialog.Create(Self); try pw.Caption := 'Banco de Dados'; pw.GroupBox1.Caption := 'Senha'; pw.AddButton.Caption := '&Adicionar'; pw.RemoveButton.Caption := '&Remover'; pw.RemoveAllButton.Caption := 'Remover &Tudo'; pw.OKButton.Caption := '&OK'; pw.CancelButton.Caption := '&Cancelar'; pw.ShowModal; finally pw.Free; end;end;

ObservaçõesAs senhas adicionadas nesta caixa de diálogo são adicionadas na sessão (TSession) atual. Isto é útil quando colocamos senha em tabelas Paradox, ou mesmo quando trabalhamos com banco de dados Client Servidor, e queremos que o usuário digite a senha de acesso. Se não fizermos desta forma, nem adicionarmos via programação as senhas necessárias, esta caixa de diálogo será mostrada quando o programa tentar abrir uma tabela com senha. A grande vantagem aqui é que podemos traduzir os Caption's dos componentes.

86 - Obter a versão da biblioteca ComCtl32.DLL (usada na unit ComCtrls do Delphi)Inclua na seção uses: ComCtrls

{ A versão desta biblioteca determina a aparência de alguns controles do Delphi, tais como ToolBar e CoolBar. O exemplo abaixo obtém a versão desta biblioteca.

Para este exemplo, coloque um TEdit e um TButton no Form. O evento OnClick do botão escreva o código abaixo: }

procedure TForm1.Button1Click(Sender: TObject);var Ver: Cardinal; MaiorVer, MenorVer: Word;begin Ver := GetComCtlVersion; MaiorVer := HiWord(Ver); MenorVer := LoWord(Ver); Edit1.Text := IntToStr(MaiorVer) + '.' + IntToStr(MenorVer);end;

ObservaçõesNormalmente, a versão 4.72 está presente quando o Internet Explorer 4 está instalado.

Page 54: dicas para delphi

85 - Implementar rotinas assembly em Pascal

{ O Delphi permite a implementação de rotinas assembly mescladas ao código Pascal. Não entrarei em detalhes minuciosos, mas darei alguns exemplos básicos de como implementar rotinas simples que retornam números inteiros.}

{ Soma dois inteiros de 8 bits }function Soma8(X, Y: byte): byte;asm mov al, &X add al, &Yend;

{ Soma dois inteiros de 16 bits }function Soma16(X, Y: Word): Word;asm mov ax, &X add ax, &Yend;

{ Soma dois inteiros de 32 bits }function Soma32(X, Y: DWord): DWord;asm mov eax, &X add eax, &Yend;

{ A chamada a estas funções são feitas da mesma forma que chamamos uma função Pascal. Exemplo: }var A: byte;begin A := Soma8(30, 25); { A = 55 }end;

84 - Exibir o diálogo About do WindowsInclua na seção uses: Windows

{ About padrão do Windows }ShellAbout(Handle, 'Windows', '', 0);

{ Personalizada }ShellAbout(Handle, 'NomePrograma', 'Direitos autorais reservados a'#13'Fulano de Tal', Application.Icon.Handle);

83 - Obter a linha e coluna atual em um TMemo

Page 55: dicas para delphi

{ === SOLUÇÃO 1 === }

{ Esta procedure obtém a linha e coluna atual de um TMemo }procedure tbGetMemoLinCol(Memo: TMemo; var Lin, Col: Cardinal);begin with Memo do begin Lin := Perform(EM_LINEFROMCHAR, SelStart, 0); Col := SelStart - Perform(EM_LINEINDEX, Lin, 0); end;end;

{ Use-a como abaixo: }

var Lin, Col: Cardinal;begin tbGetMemoLinCol(Memo1, Lin, Col); { ... }end;

{ === SOLUÇÃO 2 === }

var Lin, Col: integer;begin Lin := Memo1.CaretPos.y; Col := Memo1.CaretPos.x; {...}end;

- A segunda solução foi apresentada por: Vanderley Pereira Rocha

82 - Exibir um arquivo de ajuda do WindowsInclua na seção uses: Windows

{ Você precisa saber: - Caminho e nome do arquivo; - A estrutura do arquivo de Help.

No exemplo abaixo abre o arquivo de ajuda da Calculadora do Windows e vai para o tópico n. 100}

procedure TForm1.Button1Click(Sender: TObject);begin WinHelp(0, 'c:\Win95\Help\Calc.hlp', HELP_CONTEXT, 100);end;

ObservaçõesPara utilizar um arquivo de ajuda em seu programa desenvolvido em Delphi, basta usar os recursos do próprio Delphi. O exemplo acima é somente para mostrar o uso de uma API para este fim.

Page 56: dicas para delphi

81 - Obter o valor de uma variável de ambienteInclua na seção uses: Windows

{ Esta função recebe o nome da variável de ambiente que queremos acessar e retorna uma string com seu valor, ou uma string vazia se a variável não existir. } function tbGetEnvVar(const VarName: string): string;var I: integer;begin Result := '';

{ Obtém o comprimento da variável } I := GetEnvironmentVariable('PATH', nil, 0);

if I > 0 then begin SetLength(Result, I); GetEnvironmentVariable('PATH', PChar(Result), I); end;end;

{ Para usá-la, faça como neste exemplo: }Edit1.Text := tbGetEnvVar('PATH');

80 - Determinar se uma janela (form) está maximizadaInclua na seção uses: Windows

if IsZoomed(Form1.Handle) then { Form1 está maximizado }else { Form2 NÃO está maximizado }

ObservaçõesVeja a pergunta n. 78.

79 - Determinar se o cursor do mouse está em determinado controleInclua na seção uses: Windows

{ Os exemplos abaixo verificam se o cursor do mouse está em Button1: }

{ Solução 1: }var Pt: TPoint; Rct: TRect;

Page 57: dicas para delphi

begin GetCursorPos(Pt); GetWindowRect(Button1.Handle, Rct); if PtInRect(Rct, Pt) then { Está no botão } else { NÃO está no botão }end;

{ Solução 2: }var Pt: TPoint;begin GetCursorPos(Pt); if WindowFromPoint(Pt) = Button1.Handle then { Está no botão } else { Não está no botão }end;

ObservaçõesA API GetWindowRect obtém o retângulo (TRect) ocupado por uma janela. Podemos usar GetClientRect para obter o somente da parte cliente da janela. Podemos também usar a propriedade BoundsRect que existe na maioria dos componentes visuais, ou mesmo informar qualquer outro retângulo da tela. Se usarmos a propriedade BoundsRect, precisaremos converter as coordenadas clientes para coordenadas de tela (com a função ClientToScreen). Um lembrete: a solução 2 só poderá ser aplicada a controles ajanelados.

78 - Determinar se o aplicativo está minimizadoInclua na seção uses: Windows

if IsIconic(Application.Handle) then { Minimizado }else { Não minimizado }

ObservaçõesPode-se verificar qualquer janela (form). Só um lembrete: quando clicamos no botão de minimizar do form principal, na verdade ele é oculto e o Application é que é minizado.

77 - Fechar um aplicativo com uma mensagem de erro fatalInclua na seção uses: Windows

procedure TForm1.Button1Click(Sender: TObject);begin FatalAppExit(0, 'Erro fatal na aplicação.');end;

Page 58: dicas para delphi

ObservaçõesA função FatalAppExit é uma API do Windows. Esta mostra uma caixa de diálogo (normalmente branca) com a mensagem passada no segundo parâmetro. Quando a caixa de diálogo é fechada a aplicação é finalizada. O evento OnCloseQuery dos forms não são chamados quando usamos esta função.

76 - Usar o evento OnGetText de um TField

{ Problema: Tenho um sistema de contas a receber, onde um campo chamado "Tipo" contém um número inteiro que indica o tipo do documento conforme abaixo:

1 - Promissória 2 - Duplicata 3 - Boleto

Gostaria que, ao exibir os dados (num DBGrid por exemplo), fosse exibido o nome e não o número, ou seja, "Promissória" em vez de "1".

Solução:

Isto pode ser feito de várias formas, mas aqui vou mostrar como resolver usando o evento OnGetText do TField. Vejamos:

- Adicione todos os campos no Field Editor; - Clique no campo "Tipo"; - Vá ao Object Inspector e dê um duplo-click no evento OnGetText; - Neste evento, digite o código abaixo:}

procedure TForm1.Table1TipoGetText(Sender: TField; var Text: String; DisplayText: Boolean);begin if DisplayText then begin case Table1Tipo.AsInteger of 1: Text := 'Promissória'; 2: Text := 'Duplicata'; 3: Text := 'Boleto'; else Text := 'Desconhecido'; end; end else Text := Table1Tipo.AsString;end;

Page 59: dicas para delphi

ObservaçõesAo exibir será exibido os nomes. Mas ao digitar continue com os 1, 2, 3, etc. Para usar este recurso em relatórios, acesse a propriedade DisplayText em vez de AsString para obter o valor do campo.

75 - Maximizar um form de forma que cubra toda a tela, inclusive a barra de tarefas

{ É um "maximizar" com jeitinho brasileiro... mas funciona. No evento OnShow do form coloque o código abaixo: }

Top := 0;Left := 0;Width := Screen.Width;Height := Screen.Height;

ObservaçõesNos testes que fiz, mesmo com a barra de tarefas marcada como "Sempre Visível", funcionou perfeitamente. Fiz os testes usando o Win95. Talvez em novas versões, possa apresentar problemas.

74 - Verificar, via programação, se Local Share do BDE está TRUEInclua na seção uses: Registry, SysUtils, Windows

{ Esta função retorna true se Local Share estiver "TRUE". Caso contrário, retorna false. }

function tbBDELocalShare: boolean;const BdeKey = 'SOFTWARE\Borland\Database Engine\Settings\SYSTEM\INIT'; Ident = 'LOCAL SHARE';var Reg: TRegistry;begin Result := false; Reg := TRegistry.Create; try Reg.RootKey := HKEY_LOCAL_MACHINE; if Reg.OpenKey(BdeKey, False) then if Reg.ValueExists(Ident) then Result := UpperCase(Reg.ReadString(Ident)) = 'TRUE'; finally Reg.Free; end;end;

{ Use-a como abaixo: }if tbBDELocalShare then

Page 60: dicas para delphi

{ Local Share está TRUE }else { Local Share está FALSE }

ObservaçõesA função acima faz a verificação no registro do Windows. Por isto está sujeita a falha caso o BDE coloque as configurações em outro local (é o caso do BDE salvar as configurações no formato do Windows 3.x). O ideal seria usar uma API do BDE, mas até o momento não conheço uma que retorne esta informação. Caso alguém saiba, queira por gentileza nos informar.

73 - Criar um EXE que seja executado apenas através de outro EXE criado por mimInclua na seção uses: Windows

{ Problema:

Gostaria que um determinado programa (Prog1.EXE) fosse executado apenas através de outro programa (Prog2.EXE).

Solução:

Antes da linha "Application.Initialize;" de Prog1.dpr (programa a ser chamado), coloque o código abaixo:}

if ParamStr(1) <> 'MinhaSenha' then begin { Para usar ShowMessage, coloque Dialogs no uses } ShowMessage('Execute este programa através de Prog2.EXE'); Halt; { Finaliza }end;

{ No Form1 de Prog2 (programa chamador) coloque um botão e escreva o OnClick deste botão como abaixo:}

procedure TForm1.Button1Click(Sender: TObject);var Erro: Word;begin Erro := WinExec('Pro2.exe MinhaSenha', SW_SHOW); if Erro <= 31 then { Se ocorreu erro... } ShowMessage('Erro ao executar o programa.');end;

ObservaçõesAqui o parâmetro passado foi 'MinhaSenha'. Você deverá trocar 'MinhaSenha' por algo que apenas você saiba (uma senha). Caso uma pessoa conheça esta senha, será possível chamar este programa passando-a como parâmetro. Neste caso sua "trava" estará violada.

Page 61: dicas para delphi

72 - Resolver "Internal error near: IBCheck" do Interbase 5.1.1 Server no NT

Recebi esta mensagem do desenvolvedor Alexsando S. Pimenta.Como deve ser do interesse de outros desenvolvedores, coloquei-a aqui:==== Mensagem original ====Olá Daniel, Anote está solução, muitos tem o mesmo problema mas não conseguem a solução tão facilmente como eu. Look: Problema:Estou com um problemão. Trabalho com o NT 4 workstation Service Pack 3, Delphi 3 e Interbase 4.2.xxx. E instalei oInterbase 5.1.1 Server nesta máquina. Até aí tudo bem. Quandofui rodar a aplicação deram alguns problemas de conversão dotipo de Dado. Analisando o problema percebi que haviaesquecido de instalar o Client do Interbase. Foi aí que começaram os problemas. Tentei instalar o client, porém oinstalador após preparar os arquivos de instalação mostravaa seguinte mensagem e parava : Titulo da janela = "Severe",mensagem = "Internal error near: IBCheck"; comecei a ler osmanuais, em certo ponto aconselhava desinstalar qualquerversão posterior do Interbase da minha máquina. Foi então quedesinstalei o Interbase 4.2.xxx (através do "Control Panel","Add/Remove Programs"). Nova tentativa de instalar o client,o erro persistia. Resolvi desinstalar (através do "ControlPanel", "Add/Remove Programs") todo o Interbase da minhamáquina e começar tudo de novo. Porém quando tentei instalarnovamente o Interbase Server, surpresa, o erro apareceu novamente. Mas agora não havia interbase instalado. Fuidesinstalando Delphi, BDE, ... e nada. Entrei no Regedit,pois o desinstalador, normalmente, faz o trabalho incompletoe é necessário excluir um monte de lixo do Registry. Deparei com a seguintes chaves:

hkey_local_machine\system\controlset001\enum\root\legacy_interbase_guardhkey_local_machine\system\controlset001\enum\root\legacy_interbase

Tentei excluí-las, porém são chaves protegidas, e o regeditnão permitiu que eu excluísse-as. Poderiam me dar uma solução para eu poder instalar o Interbaseem minha máquina?

Preciso disto com urgência. Obrigado,Alexsandro PimentaXenon Software Comércio e Serviços [email protected]

Page 62: dicas para delphi

Solução:Sr. Alexsandro, Esse erro: 'Internal error near: IBCheck' acontece apenasem algumas máquinas NT 4. Na hora da instalação, é criada uma chave com valor errado. Entre no registry do Windows e altere a opção, PATH de bináriopara string, da chave: HKEY_CURRENT_USER\Environment

Renata OlivaInprise Support Center

71 - Inverter os botões do mouseInclua na seção uses: Windows

{ Para inverter: }SwapMouseButton(true);

{ Para voltar ao normal: }SwapMouseButton(false);

70 - Obter/definir o tempo máximo do duplo-click do mouseInclua na seção uses: Windows

{ - Coloque um botão no form e escreva seu OnClick como abaixo: }

procedure TForm1.Button6Click(Sender: TObject);var Tempo: Cardinal;begin { Obtém } Tempo := GetDoubleClickTime; ShowMessage(IntToStr(Tempo) + ' milisegundos');

{ Define } SetDoubleClickTime(300);end;

ObservaçõesUm duplo-click nada mais é que dois cliques consecutivos (óbvio). Porém estes dois cliques podem ser interpretados de duas formas: dois cliques isolados ou um duplo-click. Para o Windows resolver esta situação, ele usa o que chamo de "tempo máximo do duplo-click". Se

Page 63: dicas para delphi

o intervalo entre o primeiro e o segundo click for menor ou igual a esse tempo, então houve duplo-click. E você pode alterar este tempo. O padrão do Windows é 500 milisegundos. Um tempo muito curto (ex: 100), faz com que o duplo-click tenha que ser muito rápido (quase impossível), enquanto muito longo (ex: 2000) faz com que o Windows interprete dois clicks isolados como duplo-click.

69 - Obter os atributos de um arquivo/diretórioInclua na seção uses: Windows

{ No form: - Coloque um memo; - Coloque um edit; - Coloque um botão e escreva seu OnClick como abaixo: }

procedure TForm1.Button1Click(Sender: TObject);var Attr: DWord;begin Memo1.Clear; Attr := GetFileAttributes(PChar(Edit1.Text)); if Attr > 0 then with Memo1.Lines do begin if (Attr and FILE_ATTRIBUTE_ARCHIVE) > 0 then Add('Archive'); if (Attr and FILE_ATTRIBUTE_COMPRESSED) > 0 then Add('Compressed'); if (Attr and FILE_ATTRIBUTE_DIRECTORY) > 0 then Add('Directory'); if (Attr and FILE_ATTRIBUTE_HIDDEN) > 0 then Add('Hidden'); if (Attr and FILE_ATTRIBUTE_NORMAL) > 0 then Add('Normal'); if (Attr and FILE_ATTRIBUTE_OFFLINE) > 0 then Add('OffLine'); if (Attr and FILE_ATTRIBUTE_READONLY) > 0 then Add('ReadOnly'); if (Attr and FILE_ATTRIBUTE_SYSTEM) > 0 then Add('System'); if (Attr and FILE_ATTRIBUTE_TEMPORARY) > 0 then Add('Temporary'); end;end;

68 - Obter o espaço total e livre de um discoInclua na seção uses: Windows

{ - Coloque um memo (TMemo) no form; - Coloque um botão e altere seu OnClick como abaixo: }

procedure TForm1.Button1Click(Sender: TObject);var

Page 64: dicas para delphi

SetoresPorAgrup, BytesPorSetor, AgrupLivres, TotalAgrup: DWord;begin Memo1.Clear; if GetDiskFreeSpace('C:\', SetoresPorAgrup, BytesPorSetor, AgrupLivres, TotalAgrup) then with Memo1.Lines do begin Add('Setores por agrupamento: ' + IntToStr(SetoresPorAgrup)); Add('Bytes por setor: ' + IntToStr(BytesPorSetor)); Add('Agrupamentos livres: ' + IntToStr(AgrupLivres)); Add('Total de agrupamentos: ' + IntToStr(TotalAgrup)); Add('----- Resumo -----'); Add('Total de bytes: ' + IntToStr(TotalAgrup * SetoresPorAgrup * BytesPorSetor)); Add('Bytes livres: ' + IntToStr(AgrupLivres * SetoresPorAgrup * BytesPorSetor)); end;end;

{ O exemplo acima retorna as medidas em Bytes, Setores e Agrupamentos. Se preferir algo mais simples, use funções do Delphi. Veja: }

Memo1.Lines.Add('Total de bytes: ' + IntToStr(DiskSize(3)));Memo1.Lines.Add('Bytes livres: ' + IntToStr(DiskFree(3)));

{ Onde o parâmetro (3) é o número da unidade, sendo 1=A, 2=B, 3=C, ... }

ObservaçõesPara usar as funções DiskSize e DiskFree coloque SysUtils em uses.

67 - Obter o tipo de um drive (removível, fixo, CD-ROM, unidade de rede, etc)Inclua na seção uses: Windows, Dialogs

{ - Coloque um edit (Edit1) e um botão no form; - Altere o OnClick do botão conforme abaixo: }

procedure TForm1.Button1Click(Sender: TObject);var S: string; Tipo: byte;begin Tipo := GetDriveType(PChar(Edit1.Text[1] + ':\')); case Tipo of 0: S := 'Tipo indeterminado'; 1: S := 'Drive não existe'; DRIVE_REMOVABLE: S := 'Disco removível'; DRIVE_FIXED: S := 'Disco Fixo'; DRIVE_REMOTE: S := 'Unidade de rede'; DRIVE_CDROM: S := 'CD-ROM';

Page 65: dicas para delphi

DRIVE_RAMDISK: S := 'RAM Disk'; else S := 'Erro'; end; ShowMessage(S);end;

{ Para pegar o tipo da unidade atual troque...} Tipo := GetDriveType(PChar(Edit1.Text[1] + ':\'));{ por } Tipo := GetDriveType(nil);

ObservaçõesPara testar digite a letra do drive no Edit1 e clique no botão. A unit Dialogs foi colocada no uses apenas por causa da procedure ShowMessage. Para exibir todas as unidades existentes e seus respectivos tipos, use a função tbGetDrives (da pergunta 64) em conjunto com este exemplo.

66 - Obter informações de um volume/disco (label, serial, sistema de arquivos, etc)Inclua na seção uses: Windows, System

{ - Coloque um memo (TMemo) no form; - Coloque um botão e escreve seu evento OnClick como abaixo: }

procedure TForm1.Button1Click(Sender: TObject);var SLabel, SSysName: PChar; Serial, FileNameLen, X: DWord;begin Memo1.Clear; GetMem(SLabel, 255); GetMem(SSysName, 255); try GetVolumeInformation('C:\', SLabel, 255, @Serial, FileNameLen, X, SSysName, 255); with Memo1.Lines do begin Add('Nome do volume (Label): ' + string(SLabel)); Add('Número Serial: ' + IntToHex(Serial, 8)); Add('Tamanho máximo p/ nome arquivo: ' + IntToStr(FileNameLen)); Add('Sistema de Arquivos: ' + string(SSysName)); end; finally FreeMem(SLAbel, 255); FreeMem(SSysName, 255); end;end;

Page 66: dicas para delphi

65 - Alterar o nome de volume (Label) de um discoInclua na seção uses: Windows

{ Da unidade C: }SetVolumeLabel('c:\', 'NovoLabel');

{ Da unidade atual: }SetVolumeLabel(nil, 'NovoLabel');

ObservaçõesVeja a pergunta nº 66.

64 - Saber quais as unidades de disco (drives) estão presentesInclua na seção uses: Windows

{ A função abaixo retorna uma string contendo as letras de unidades de discos presentes. }

function tbGetDrives: string;var Drives: DWord; I: byte;begin Result := ''; Drives := GetLogicalDrives; if Drives <> 0 then for I := 65 to 90 do if ((Drives shl (31 - (I - 65))) shr 31) = 1 then Result := Result + Char(I);end;

{ Para saber se uma determinada unidade está presente, basta fazer algo como: }if Pos('A', tbGetDrives) > 0 then ShowMessage('Unidade A: presente.')else ShowMessage('Unidade A: ausente.');

ObservaçõesA string retornada pela função tbGetDrives está sempre em letras maiúsculas.

63 - "truncar" valores reais para apenas n casas decimais

{ Às vezes você precisa considerar apenas duas casas de valores reais, mas o Delphi não oferece algo pronto para isto. Se usarmos funções como Round que vem com o Delphi, o valor será arredondado (e não truncado). Com Round() o valor abaixo será 135.55 (e não 135.54) com duas casas decimais.

Page 67: dicas para delphi

}

ValorReal := 135.54658;

{ Somente a parte inteira - nenhuma casa decimal }X := Trunc(ValorReal); // X será 135

{ Duas casas }X := Trunc(ValorReal * 100) / 100; // X será 135.54

{ Três casas }X := Trunc(ValorReal * 1000) / 1000; // X será 135.5465

ObservaçõesIsto pode não funcionar se ValorReal for muito alto. Isto por causa da multiplicação que poderá estourar a capacidade do tipo em uso. Lembre-se: os tipos reais aceitam valores muuuiiiito altos.

62 - Excluir todos os registros de uma tabela (como DELETE ALL do Clipper)

procedure tbDBDeleteAll(const DataSet: TDataSet);begin with DataSet do while RecordCount > 0 do Delete;end;

{ Chame-a como nos exemplos abaixo: }tbDBDeleteAll(Table1);outbDBDeleteAll(Query1);

ObservaçõesSe houver um filtro ou range ativo, somente os registros filtrados serão excluídos. Portanto é diferente de Table1.EmptyTable. Esta função poderá ser chamada no evento BeforeDelete do Table (ou Query) principal em um formulário mestre-detalhe para excluir os itens (da parte detalhe).

61 - Saber se o sistema está usando 4 dígitos para o ano

{ Para não correr o risco de surpresas desagradáveis, é melhor que seu programa em Delphi verifique se o Windows está ajustado para trabalhar com 4 dígitos para o ano. Assim seu programa pode alertar o usuário quando o ano estiver sendo representado com apenas 2 dígitos. A função abaixo retorna true se estiver ajustado para 4 dígitos.}

Page 68: dicas para delphi

function Is4DigitYear: Boolean;begin result:=(Pos('yyyy',ShortDateFormat)>0);end;

60 - Imprimir caracteres acentuados diretamente para a impressora

{ Usando comandos da impressora podemos fazer isto de uma forma bastante simples. Quando enviamos o caractere ASCII número 8 (oito) para a impressora, a cabeça de impressão retrocede uma posição, pois este caractere é o BackSpace. Então podemos imprimir a letra sem acento e, sem seguida, voltar e imprimir o acento desejado. Vejamos um exemplo:

- Coloque um botão no form; - Altere o evento OnClick deste botão conforme abaixo:}

procedure TForm1.Button2Click(Sender: TObject);var F: TextFile;begin AssignFile(F, 'LPT1'); Rewrite(F); try { Regra: caractere sem acento + chr(8) + acento } WriteLn(F, 'Este e' + #8 + '''' + ' um teste.'); WriteLn(F, 'Acentuac' + #8 + ',a' + #8 + '~o.'); WriteLn(F, 'Vovo' + #8 + '^'); WriteLn(F, 'U' + #8 + '''' + 'ltimo.'); WriteLn(F, #12); // Eject finally CloseFile(F); end;end;

ObservaçõesUsando este recurso, a acentuação não fica excelente, mas melhora bastante.

59 - Imprimir texto justificado com formatação na impressora Epson LX-300

{ A impressora Epson LX-300 dispõe de um comando que justifica o texto. Este recurso é interessante, pois com ele podemos continuar a enviar os comandos de formatação de caracteres como condensado, negrito, italico, expandido, etc.

Para o exemplo abaixo: - Coloque um botão no form;

Page 69: dicas para delphi

- Altere o evento OnClick deste botão como abaixo: }

procedure TForm1.Button1Click(Sender: TObject);const cJustif = #27#97#51; cEject = #12;

{ Tamanho da fonte } c10cpi = #18; c12cpi = #27#77; c17cpi = #15; cIExpandido = #14; cFExpandido = #20; { Formatação da fonte } cINegrito = #27#71; cFNegrito = #27#72; cIItalico = #27#52; cFItalico = #27#53;var Texto: string; F: TextFile;begin Texto := c10cpi + 'Este e um teste para impressora Epson LX 300. ' + 'O objetivo e imprimir texto justificado sem deixar ' + 'de usar formatacao, tais como: ' + cINegrito + 'Negrito, ' + cFNegrito + cIItalico + 'Italico, ' + cFItalico + c17cpi + 'Condensado (17cpi), ' + c10cpi + c12cpi + '12 cpi, ' + c10cpi + cIExpandido + 'Expandido.' + cFExpandido + ' Este e apenas um exemplo, mas voce podera adapta-lo ' + 'a sua realidade conforme a necessidade.';

AssignFile(F, 'LPT1'); Rewrite(F); try WriteLn(F, cJustif, Texto); WriteLn(F, cEject); finally CloseFile(F); end;end;

ObservaçõesEste recurso de justificação da Epson LX-300 pode ser usado em qualquer linguagem de programação.

58 - Formatar um disquete através de um programa Delphi

{ Coloque o código abaixo imediatamente abaixo da palavra implementation: }

Page 70: dicas para delphi

const SHFMT_ID_DEFAULT = $FFFF;

{ Opções de formatação } SHFMT_OPT_QUICKFORMAT = $0000; { Formatação rápida } SHFMT_OPT_FULL = $0001; { Formatação completa } SHFMT_OPT_SYSONLY = $0002; { Copia sistema }

{ Códigos de errros } SHFMT_ERROR = $FFFFFFFF; { Ocorreu erro } SHFMT_CANCEL = $FFFFFFFE; { Foi cancelado } SHFMT_NOFORMAT = $FFFFFFFD; { Não formatou }

function SHFormatDrive(Handle: HWND; Drive, ID, Options: Word): LongInt; stdcall; external 'shell32.dll' name 'SHFormatDrive'

{ Coloque um botão no form e altere o evento OnClick dele conforme abaixo: }

procedure TForm1.Button3Click(Sender: TObject);var Erro: DWord; Msg: string;begin Erro := SHFormatDrive(Handle, 0, SHFMT_ID_DEFAULT, SHFMT_OPT_QUICKFORMAT); case Erro of SHFMT_ERROR: Msg := 'Ocorreu um erro.'; SHFMT_CANCEL: Msg := 'A formatação foi cancelada.'; SHFMT_NOFORMAT: Msg := 'Não foi possível formatar.'; else Msg := 'Disco formatado com sucesso.'; end; ShowMessage(Msg);end;

ObservaçõesPara formatação completa troque SHFMT_OPT_QUICKFORMAT por SHFMT_OPT_FULL. O segundo parâmetro (zero no exemplo) indica a unidade, sendo que A é 0 (zero), B é 1, etc.

57 - Alterar (e restaurar) o tamanho da página na impressoraInclua na seção uses: tbPrn

{ - Peque em nosso Download o arquivo tbPrn.zip. Ele contém a unit tbPrn.pas, onde está a função tbPrnSetPaperSize usada no exemplo abaixo;

- Adicione a unit tbPrn.pas em seu projeto;

- Siga o exemplo abaixo para criar seus relatórios usando o TPrinter.}

Page 71: dicas para delphi

procedure TForm1.Button1Click(Sender: TObject);var Papel: TtbPrnPaper;begin Papel.Size := 256; // 256 é o tam. personalizado Papel.Width := 2100; // 21 cm Papel.Height := 1000; // 10 cm Papel := tbPrnSetPaperSize(Papel); try Printer.BeginDoc; try { coloque aqui os comandos para impressão } finally Printer.EndDoc; end; finally tbPrnSetPaperSize(Papel); // Restaura o tamanho end;end;

{ Papel.Size refere-se ao tamanho do papel. Veja alguns: 0 - Default 1 - Letter 5 - Legal 8 - A3 9 - A4 11 - A5 256 - Custom (personalizado) }

ObservaçõesSó será necessário informar Papel.Height e Papel.Width quando Papel.Size for 256.

56 - Reproduzir um arquivo de som WAV sem o TMediaPlayerInclua na seção uses: MMSystem

{ Síncrona: aguarda terminar a reprodução para continuar: }SndPlaySound('C:\Win95\Media\Office97\Lembrete.wav', SND_SYNC);

{ Assíncrona: a execução continua normalmente enquanto ocorre a reprodução: }SndPlaySound('C:\Win95\Media\Office97\Lembrete.wav', SND_ASYNC);

{ Contínua: a reprodução é repetida num efeito de loop. Este tipo de reprodução precisa ser assíncrona: }SndPlaySound('C:\Win95\Media\Office97\Lembrete.wav', SND_ASYNC or SND_LOOP);

{ Interrompe uma reprodução contínua: }SndPlaySound(nil, 0);

Page 72: dicas para delphi

ObservaçõesA reprodução contínua pode ser usada, por exemplo, para altertar o usuário em uma situação extremamente crítica. Se o equipamento não possuir placa de som, o arquivo não será reproduzido.

55 - Obter o nome do usuário e da empresa informado durante a instalação do WindowsInclua na seção uses: Registry

{ Coloque um botão no form e altere seu evento OnCkick como abaixo: }

procedure TForm1.Button1Click(Sender: TObject);var Reg: TRegIniFile; S: string;begin Reg := TRegIniFile.Create('SOFTWARE\MICROSOFT\MS SETUP (ACME)\'); try S := Reg.ReadString('USER INFO','DefName',''); S := S + #13; S := S + Reg.ReadString('USER INFO','DefCompany',''); ShowMessage(S); finally Reg.free; end; end;

54 - Mostrar uma barra de progresso enquanto copia arquivos

Veja a pergunta nº 53.

53 - Copiar arquivos usando o Shell do WindowsInclua na seção uses: ShellApi

{ - Coloque um botão no form e altere o evento OnClick deste botão conforme abaixo: } procedure TForm1.Button1Click(Sender: TObject);var Dados: TSHFileOpStruct;begin FillChar(Dados,SizeOf(Dados), 0); with Dados do begin wFunc := FO_COPY;

Page 73: dicas para delphi

pFrom := PChar('c:\teste\*.txt'); pTo := PChar('a:\'); fFlags:= FOF_ALLOWUNDO; end; SHFileOperation(Dados);end;

ObservaçõesEsta forma de copiar arquivos oferecem várias vantagens. O Shell avisa para pôr um próximo disco quando o atual estiver cheio. Mostra a barra de progresso. Pode copiar arquivos usando máscara de uma forma extremamente simples.

52 - Descobrir o código ASCII de uma tecla

{ - Coloque um Label no form (Label1); - Mude a propriedade KeyPreview do form para true; - Altere o evento OnKeyDown do form como abaixo: }

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);begin Label1.Caption := Format('O código da tecla pressionada é: %d', [Key]);end;

ObservaçõesPara testar execute e observe o Label enquanto pressiona as teclas desejadas.

51 - Evitar que seu programa apareça na barra de tarefasInclua na seção uses: Windows

{ Você já observou a caixa "Propriedades", aquela que mostra as propriedades de um arquivo no Windows Explorer, não aparece na lista do Alt+Tab e tampouco na barra de tarefas?

Isto ocorre porque ela funciona como uma ToolWindow, enquanto os demais aplicativos funcionam como AppWindow. Porém podemos mudar o comportamento de nossos programas feito em Delphi para que se comportem como uma ToolWindow também.

Para experimentar, crie um novo projeto e altere o Project1.dpr como abaixo (não esqueça do uses): }

program Project1;

uses Forms, Windows, Unit1 in 'Unit1.pas' {Form1};

{$R *.RES}

Page 74: dicas para delphi

var ExtendedStyle : Integer;begin Application.Initialize;

ExtendedStyle := GetWindowLong(Application.Handle, gwl_ExStyle); SetWindowLong(Application.Handle, gwl_ExStyle, ExtendedStyle or ws_Ex_ToolWindow and not ws_Ex_AppWindow);

Application.CreateForm(TForm1, Form1); Application.Run;end.

ObservaçõesAo executar observe a barra de tarefas e teste o Alt+Tab (seu programa não estará lá!).

50 - Usar eventos de som do Windows

{ Evento Som Padrão }MessageBeep(0); { ou Beep; }

{ Evento Parada Crítica }MessageBeep(16);

{ Evento Pergunta }MessageBeep(32);

{ Evento Exclamação }MessageBeep(48);

{ Evento Asterisco }MessageBeep(64);

49 - Mudar a coluna ativa em um DBGrid via programação

{ Usando número da coluna (zero é a primeira coluna): }DBGrid1.SelectedIndex := 0;

{ Usando o nome do campo }DBGrid1.SelectedField := Table1.FieldByName(Edit2.Text);

ObservaçõesAconselho usar o nome do campo quando o que importa é o campo e não a posição. Use o número da coluna somente quando o que importa é a posição, e não o campo.

48 - Fechar o Windows a partir do seu programa

Page 75: dicas para delphi

{ Reinicia o Windows }ExitWindowsEx(EWX_REBOOT, 0);

{ Desliga o Windows }ExitWindowsEx(EWX_SHUTDOWN, 0);

{ Força todos os programa a desligarem-se }ExitWindowsEx(EWX_FORCE, 0);

47 - Carregar um cursor animado (.ani)

{ Altere o evento OnCreate do Form conforme abaixo: }

procedure TForm1.FormCreate(Sender: TObject);begin Screen.Cursors[1] := LoadCursorFromFile('c:\win95\cursors\globe.ani'); Button1.Cursor := 1;end;

ObservaçõesPara este exemplo é necessário ter o arquivo de cursor conforme apontado e também ter, no form, um Button1. Para usar este cursor em outros componentes basta atribuir à propriedade Cursor do componente em questão o valor 1 (um). Exemplo: Edit1.Cursor := 1; Form1.Cursor := 1;, etc.

46 - Enviar um arquivo para a lixeiraInclua na seção uses: ShellApi

{ Coloque a procedure abaixo na seção implementation }

procedure ArqParaLixeira(const NomeArq: string; var MsgErro: string);var Op: TSHFileOpStruct;begin MsgErro := ''; if not FileExists(NomeArq) then begin MsgErro := 'Arquivo não encontrado.'; Exit; end; FillChar(Op, SizeOf(Op), 0); with Op do begin wFunc := FO_DELETE; pFrom := PChar(NomeArq); fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_SILENT; end; if ShFileOperation(Op) <> 0 then MsgErro := 'Não foi possível enviar o arquivo para a lixeira.';end;

{ - Coloque um botão no Form;

Page 76: dicas para delphi

- Altere o evento OnClick do botão conforme abaixo: }

procedure TForm1.Button1Click(Sender: TObject);var S: string;begin ArqParaLixeira('c:\Diretorio\Teste.doc', S); if S = '' then ShowMessage('O arquivo foi enviado para a lixeira.') else ShowMessage(S);end;

45 - Obter o número do registro atual

Table1.RecNo()

44 - Trabalhar com Filter de forma mais prática

Se você está habituado a usar este código no filter...

Table1.Filter := 'Nome = '''+ Edit1.Text + '''';ouTable1.Filter := 'Data = ''' + DateToStr(Date) + '''';

Tente usar este:

Table1.Filter := 'Nome = ' + QuotedStr(Edit1.Text);ouTable1.Filter := 'Data = ' + QuotedStr(DateToStr(Date));

ObservaçõesA função QuitedStr() coloca apóstrofos envolvendo a string. Se houver um apóstrofo como parte da string, ela o subtitui por dois apóstrofos, para que seja corretamente interpretado.

43 - Reproduzir um arquivo WAVInclua na seção uses: MMSystem

PlaySound('C:\ArqSom.wav', 1, SND_ASYNC);

ObservaçõesTroque o nome do arquivo (C:\ArqSom.wav) pelo arquivo desejado.

42 - Executar um programa DOS e fechá-lo em seguida

{ Coloque isto no evento OnClick de um botão: }

Page 77: dicas para delphi

WinExec('command.com /c programa.exe',sw_ShowNormal);

{ Se quizer passar parâmetros pasta adicioná-los após o nome do programa. Exemplo: }

WinExec('command.com /c programa.exe param1 param2',sw_ShowNormal);

ObservaçõesSe quizer que a janela do programa não apareça, troque sw_ShowNormal por sw_Hide.

41 - Fechar um programa a partir de um programa Delphi

{ - Coloque um botão no form e altere seu evento OnClick conforme abaixo: }

procedure TForm1.Button1Click(Sender: TObject);var Janela: HWND;begin Janela := FindWindow('OpusApp'), nil); if Janela = 0 then ShowMessage('Programa não encontrado') else PostMessage(Janela, WM_QUIT, 0, 0);end;

ObservaçõesEste exemplo fecha o MS Word 97 se estiver aberto. A mensagem WM_QUIT fecha o programa da forma "ignorante". Isto significa que se houver dados não salvos, o programa a ser fechado não oportunidade para salvá-los. Uma alternativa mais suave é trocar a mensagem WM_QUIT por WM_CLOSE. Veja as perguntas 18 e 36.

40 - Colocar Hint's de várias linhas

{ - Coloque um TButton no Form; - Altere o evento OnCreate do Form como abaixo: }

procedure TForm1.FormCreate(Sender: TObject);begin Button1.Hint := 'Linha 1 da dica' + #13 + 'Linha 2 da dica' + #13 + 'Linha 3 da dica'; Button1.ShowHint := true;end;

39 - Reproduzir um vídeo AVI em um Form

Page 78: dicas para delphi

{ - Crie um novo projeto. Este já deverá ter o Form1; - Adicione um novo Form (Form2); - Coloque, no Form1, um TMediaPlayer (paleta System) e um botão; - Altere o evento OnClick do botão como abaixo: } procedure TForm1.Button1Click(Sender: TObject);begin with MediaPlayer1 do begin FileName := 'c:\speedis.avi'; Open;

{ Ajusta tamanho do Form } with MediaPlayer1.DisplayRect do begin Form2.ClientHeight := Bottom - Top; Form2.ClientWidth := Right - Left; end;

Display := Form2; Form2.Show; Play; end;end;

ObservaçõesEm vez de ajustar o Form ao vídeo, podemos ajustar o vídeo ao Form. Para isto troque o trecho with..end; por MediaPlayer1.DisplayRect := Form2.ClientRect;

38 - Separar (filtrar) caracteres de uma string

{ Abaixo da palavra implementation digite: }

type TChars = set of Char;

function FilterChars(const S: string; const ValidChars: TChars): string;var I: integer;begin Result := ''; for I := 1 to Length(S) do if S[I] in ValidChars then Result := Result + S[I];end;

{ Para usar a função: - Coloque um botão no Form; - Altere o evento OnClick deste botão conforme abaixo: }

procedure TForm1.Button4Click(Sender: TObject);begin { Pega só letras } ShowMessage(FilterChars('D63an*%i+/e68l13',

Page 79: dicas para delphi

['A'..'Z', 'a'..'z'])); { Pega só números } ShowMessage(FilterChars('D63an*%i+/e68l13', ['0'..'9']));end;

ObservaçõesSe quizer usar este função em outras unit's, coloque a declaração do tipo TChars na seção interface. Coloque aí também uma declaração da função FilterChars. E não se esqueça da cláusula uses.

37 - Colocar zeros à esquerda de números

{ Isto coloca zeros à esquerda do número até completar 6 casas }S := FormatFloat('000000', 5);

Observações"S" precisa ser uma variável string.

36 - Copiar arquivos usando curingas (*.*)

{ - Coloque um Button no Form; - Altere o evento OnClick deste Button conforme abaixo: }

procedure TForm1.Button2Click(Sender: TObject);var SR: TSearchRec; I: integer; Origem, Destino: string;begin I := FindFirst('c:\Origem\*.*', faAnyFile, SR); while I = 0 do begin if (SR.Attr and faDirectory) <> faDirectory then begin Origem := 'c:\Origem\' + SR.Name; Destino := 'c:\Destino\' + SR.Name; if not CopyFile(PChar(Origem), PChar(Destino), true) then ShowMessage('Erro ao copiar ' + Origem + ' para ' + Destino); end; I := FindNext(SR); end;end;

ObservaçõesNo exemplo acima, se o arquivo já existir no destino, a função falha (não copia). Para que a função possa sobreescrever o arquivo destino (caso exista), altere o último parâmetro de CopyFile para false. CUIDADO! Se um arquivo for sobreescrito, estará perdido para sempre! Veja as perguntas nº 35 e 53.

Page 80: dicas para delphi

35 - Copiar arquivos

{ - Coloque um Button no Form; - Altere o evento OnClick deste Button conforme abaixo: }

procedure TForm1.Button2Click(Sender: TObject);var Origem, Destino: string;begin Origem := 'c:\Origem\NomeArq.txt'; Destino := 'c:\Destino\NomeArq.txt'; if not CopyFile(PChar(Origem), PChar(Destino), true) then ShowMessage('Erro ao copiar ' + Origem + ' para ' + Destino);end;

ObservaçõesNo exemplo acima, se o arquivo já existir no destino, a função falha (não copia). Para que a função possa sobreescrever o arquivo destino (caso exista), altere o último parâmetro de CopyFile para false. CUIDADO! Se um arquivo for sobreescrito, estará perdido para sempre! Veja as perguntas nº 36 e 53.

34 - Trabalhar com cores no formato string

procedure TForm1.Button3Click(Sender: TObject);begin

{ Exibe as cores atuais dos Edit's } ShowMessage(ColorToString(Edit1.Color)); ShowMessage(ColorToString(Edit2.Color));

{ Altera as cores dos Edit's } Edit1.Color := StringToColor('clBlue'); Edit2.Color := StringToColor('$0080FF80');

end;

33 - Verificar se determinado programa está em execução (Word, Delphi, etc)

{ Coloque um Button no Form e altere o evento OnClick deste como abaixo: }

procedure TForm1.Button1Click(Sender: TObject);begin { Verifica o Delphi } if FindWindow('TAppBuilder', nil) > 0 then ShowMessage('O Delphi está aberto') else ShowMessage('O Delphi NÃO está aberto');

Page 81: dicas para delphi

{ Verifica o Word } if FindWindow('OpusApp', nil) > 0 then ShowMessage('O Word está aberto') else ShowMessage('O Word NÃO está aberto');

{ Verifica o Excell } if FindWindow('XLMAIN', nil) > 0 then ShowMessage('O Excell está aberto') else ShowMessage('O Excell NÃO está aberto');end;

ObservaçõesHá uma margem de erro nesta verificação: pode haver outros programas que possuam uma janela com os mesmos nomes. Você mesmo pode criar aplicativos em Delphi e, propositadamente, criar uma janela com um destes nomes. Veja a pergunta nº 18.

32 - Excluir arquivos usando curingas (*.*)

{ - Coloque um Button no Form; - Altere o evento OnClick do Button conforme abaixo: }

procedure TForm1.Button2Click(Sender: TObject);var SR: TSearchRec; I: integer;begin I := FindFirst('c:\Teste\*.*', faAnyFile, SR); while I = 0 do begin if (SR.Attr and faDirectory) <> faDirectory then if not DeleteFile('c:\Teste\' + SR.Name) then ShowMessage('Não consegui excluir c:\Teste\' + SR.Name); I := FindNext(SR); end;end;

ObservaçõesNo exemplo acima todos os arquivos do diretório c:\Teste serão excluídos. CUIDADO! Arquivos excluídos desta forma não vão para a lixeira. Veja a pergunta nº 46.

31 - Gerar uma tabela no Word através do DelphiInclua na seção uses: ComObj

{ - Coloque um botão no Form; - Altere o evento OnClick do botão conforme abaixo: }

procedure TForm1.Button1Click(Sender: TObject);var Word: Variant;

Page 82: dicas para delphi

begin { Abre o Word } Word := CreateOleObject('Word.Application'); try { Novo documento } Word.Documents.Add; try { Adiciona tabela de 2 linhas e 3 colunas } Word.ActiveDocument.Tables.Add( Range := Word.Selection.Range, NumRows := 2, NumColumns := 3); { Escreve na primeira célula } Word.Selection.TypeText(Text := 'Linha 1, Coluna 1'); { Próxima célula } Word.Selection.MoveRight(12); { Escreve } Word.Selection.TypeText(Text := 'Linha 1, Coluna 2'); Word.Selection.MoveRight(12); Word.Selection.TypeText(Text := 'Linha 1, Coluna 3'); Word.Selection.MoveRight(12); Word.Selection.TypeText(Text := 'Linha 2, Coluna 1'); Word.Selection.MoveRight(12); Word.Selection.TypeText(Text := 'Linha 2, Coluna 2'); Word.Selection.MoveRight(12); Word.Selection.TypeText(Text := 'Linha 2, Coluna 3'); { Auto-Formata } Word.Selection.Tables.Item(1).Select; { Seleciona a 1º tabela } Word.Selection.Cells.AutoFit; { auto-formata } { Imprime 1 cópia } Word.ActiveDocument.PrintOut(Copies := 1); ShowMessage('Aguarde o término da impressão...'); { Para salvar... } Word.ActiveDocument.SaveAs(FileName := 'c:\Tabela.doc'); finally { Fecha documento } Word.ActiveDocument.Close(SaveChanges := 0); end; finally { Fecha o Word } Word.Quit; end;end;

ObservaçõesForam usados neste exemplo o Delphi4 e MS-Word97.

30 - Obter a quantidade de registros total e visível de uma tabelaInclua na seção uses: DbiProcs

Os componentes TTable e TQuery possuem a propriedade

Page 83: dicas para delphi

RecordCount que indicam a quantidade de registros da tabela.No entanto esta propriedade é dependente de filtros, ou seja, se tivermos uma tabela com dez registros com campo "Codigo" de 1 a 10 e aplicarmos o filtro mostrado a seguir,a propriedade RecordCount retornará 5 e não 10.

Table1.Filter := 'Codigo <= 5';Table1.Filtered := true;

Se quizermos obter a quantidade total de registros,independentemente de filtros, devemos usar uma API do BDEconforme abaixo:

var Total: integer;begin Check(DbiGetRecordCount(Table1.Handle, Total)); ShowMessage('Total de registros: ' + IntToStr(Total));end;

ObservaçõesPara testar o exemplo acima, o Table1 precisa estar aberto.

29 - Evitar que um programa seja executado mais de uma vez

{ Muitos programas Windows permitem apenas uma cópia em execução de cada vez. Isto é interessante principalmente quando é um grande aplicativo, pois duas cópias ao mesmo tempo usuaria muito mais memória. Em aplicativos desenvolvidos em Delphi podemos ter esta característica. Vejamos:

- Crie um novo projeto; - Mude o "Name" do Form1 para DPGFormPrinc; - Altere o código-fonte do arquivo Project1.dpr conforme abaixo: }

program Project1;

uses Forms, Windows, Unit1 in 'Unit1.pas' {DPGFormPrinc};

{$R *.RES}

var Handle: THandle;begin Handle := FindWindow('TDPGFormPrinc', nil); if Handle <> 0 then begin { Já está aberto } Application.MessageBox('Este programa já está aberto. A cópia ' +

Page 84: dicas para delphi

'anterior será ativada.', 'Programa já aberto', MB_OK); if not IsWindowVisible(Handle) then ShowWindow(Handle, SW_RESTORE); SetForegroundWindow(Handle); Exit; end; Application.Initialize; Application.CreateForm(TDPGFormPrinc, DPGFormPrinc); Application.Run;end.

ObservaçõesPara testar este programa você deverá compilar o projeto e fechar o Delphi. Depois, procure o Project1.exe (projeto compilado) usando o Windows Explorer e tente executá-lo mais de uma vez e veja o que acontece. Mas porque alterar o name do form principal para "DPGFormPrinc"? Este poderia ser qualquer outro nome, mas preferi usar as iniciais do meu nome (DPG). Procurei deixar um nome bem pessoal para não correr o risco de colocar um nome que possa ser encontrado em outro aplicativo do Windows. Por exemplo: se deixar Form1, será bem fácil encontrar outro aplicativo feito em Delphi que possua uma janela com este nome, o que causaria problema.

28 - Executar um "COMMIT" no DelphiInclua na seção uses: DbiProcs

{ Se estiver usando TTable, coloque nos eventos AfterPost e AfterDelete a seguinte linha: }

dbiSaveChanges(Table1.Handle);

{ Para TQuery, a instrução é semelhante: }

dbiSaveChanges(Query1.Handle);

27 - Posicionar Form's em relação ao Desktop do Windows

{ Quando usamos a propridade Position de um Form para centralizá-lo estamos sujeitos a um inconveniente: dependendo da posição/tamanho da barra de tarefas do Windows, o nosso Form poderá ficar parcialmente coberto por ela. Uma forma eficaz de resolver este problema é posicionar o form considerando apenas a área livre do Desktop. Vejamos este exemplo:

- Crie um novo projeto; - Na seção implementation digite a procedure abaixo:}

procedure FormPos(Form: TForm; const Horz, Vert: byte);{ Horz: 1=esquerda, 2=centro, 3=direita Vert: 1=topo, 2=centro, 3=em baixo }var

Page 85: dicas para delphi

R: TRect;begin if not SystemParametersInfo(SPI_GETWORKAREA, 0, @R, 0) then R := Rect(0, 0, Screen.Width, Screen.Height); with Form do case Horz of 1: Form.Left := 0; 2: Form.Left := (R.Right - R.Left - Width) div 2; 3: Form.Left := R.Right - Width; end; with Form do case Vert of 1: Form.Top := 0; 2: Form.Top := (R.Bottom - R.Top - Height) div 2; 3: Form.Top := R.Bottom - Height; end; end;

{ - Coloque dois TEdit's: Edit1 e Edit2; - Coloque um TButton e altere o evento OnClick deste conforme abaixo:}

procedure TForm1.Button1Click(Sender: TObject);begin FormPos(Form1, StrToInt(Edit1.Text), StrToInt(Edit2.Text));end;

ObservaçõesPara testar, execute este exemplo e experimente digitar números de 1 a 3 em ambos os Edit's e clique no Button para ver o resultado. O Edit1 indica a posição horizontal (esquerda, centro e direita) e o Edit2 indica a posição vertical (topo, centro e em baixo).

26 - Saber a resolução de tela atual

{ Coloque um TButton no Form e altere o evento OnClick deste botão como abaixo: }

procedure TForm1.Button1Click(Sender: TObject);begin ShowMessage('Largura: ' + IntToStr(Screen.Width) + #13 + 'Altura: ' + IntToStr(Screen.Height));end;

ObservaçõesO objeto Screen contém várias informações importantes: largura e altura da tela, fontes instaladas no Windows, etc.

Page 86: dicas para delphi

25 - Verificar se uma unidade de disco (disk-drive) está preparadaInclua na seção uses: System, SysUtils

{ - Crie um novo projeto; - Na seção implementation da Unit1 digite a função abaixo: }

function DriveOk(Drive: Char): boolean;var I: byte;begin Drive := UpCase(Drive); if not (Drive in ['A'..'Z']) then raise Exception.Create('Unidade incorreta'); I := Ord(Drive) - 64; Result := DiskSize(I) >= 0;end;

{ - Coloque no Form1 um TEdit (Edit1) - Coloque no Form1 um TButton - Altere o evento OnClick do Button1 conforme abaixo: }

procedure TForm1.Button1Click(Sender: TObject);begin if DriveOk(Edit1.Text[1]) then ShowMessage('Drive OK') else ShowMessage('Drive não preparado');end;

ObservaçõesPara testar você deverá executar o exemplo e digitar no Edit a letra do drive a ser testado (não precisa os dois-pontos). Após digitar, clique no Button1.

24 - Salvar/restaurar o tamanho e posição de Form's

{ Crie uma nova Unit conforme abaixo: }unit uFormFunc;

interfaceuses Forms, IniFiles, SysUtils, Messages, Windows;

procedure tbLoadFormStatus(Form: TForm; const Section: string);procedure tbSaveFormStatus(Form: TForm; const Section: string);

implementation

procedure tbSaveFormStatus(Form: TForm; const Section: string);var Ini: TIniFile; Maximized: boolean;begin

Page 87: dicas para delphi

Ini := TIniFile.Create(ChangeFileExt( ExtractFileName(ParamStr(0)),'.INI')); try Maximized := Form.WindowState = wsMaximized; Ini.WriteBool(Section, 'Maximized', Maximized); if not Maximized then begin Ini.WriteInteger(Section, 'Left', Form.Left); Ini.WriteInteger(Section, 'Top', Form.Top); Ini.WriteInteger(Section, 'Width', Form.Width); Ini.WriteInteger(Section, 'Height', Form.Height); end; finally Ini.Free; end;end;

procedure tbLoadFormStatus(Form: TForm; const Section: string);var Ini: TIniFile; Maximized: boolean;begin Maximized := false; { Evita msg do compilador } Ini := TIniFile.Create(ChangeFileExt( ExtractFileName(ParamStr(0)),'.INI')); try Maximized := Ini.ReadBool(Section, 'Maximized', Maximized); Form.Left := Ini.ReadInteger(Section, 'Left', Form.Left); Form.Top := Ini.ReadInteger(Section, 'Top', Form.Top); Form.Width := Ini.ReadInteger(Section, 'Width', Form.Width); Form.Height := Ini.ReadInteger(Section, 'Height', Form.Height); if Maximized then Form.Perform(WM_SIZE, SIZE_MAXIMIZED, 0); { A propriedade WindowState apresenta Bug. Por isto usei a mensagem WM_SIZE } finally Ini.Free; end;end;

end.

{ Em cada formulário que deseja salvar/restaurar: - Inclua na seção uses: uFormFunc - No evento OnShow digite: tbLoadFormStatus(Self, Self.Name); - No evento OnClose digite: tbSaveFormStatus(Self, Self.Name);}

ObservaçõesO arquivo INI terá o nome do executável e extensão INI e será salvo no diretório do Windows. A palavra Self indica o Form relacionado com a unit em questão. Poderia ser, por exemplo, Form1, Form2, etc. Onde aparece Self.Name poderá ser colocado um nome a sua escolha. Este nome será usado como SectionName no arquivo INI e deve ser idêntico no

Page 88: dicas para delphi

evento OnShow e OnClose de um mesmo Form, porém para cada Form deverá ser usado um nome diferente.

23 - Definir a quantidade de registros a ser impressa em uma página do QuickReport

Ou seja, gostaria que, ao visualizar ou imprimir um relatóriodo Quick Report, saia em cada página apenas um registro,mesmo que o espaço permita mais de um.

Existem pelo menos duas formas de resolver este problema:

1. A forma mais simples consiste em alterar a altura (Height) da banda Detail do nosso relatório de modo que a altura total da página seja inferior a duas vezes a altura da banda. Desta forma, cada registro será impresso em uma nova página, teoricamente por falta de espaço na página atual.

2. Uma outra forma mais sofisticada é usar o evento AfterPrint da banda Detail. Nele testamos se ainda não chegou no fim da tabela e, caso positivo, pedimos uma nova página:

if not Table1.EOF then QuickRep1.NewPage;

Deve existir outras alternativas, mas as duas anterioresfuncionaram bem nos testes realizados.

22 - Onde encontrar tutoriais sobre construção de componentes em Delphi

Pegue apostila no download.

21 - Para que servem OnGetEditMask, OnGetEditText e OnSetEditText do TStringGrid

O evento OnGetEditMask ocorre quando entramos no modo de edição.Neste momento podemos verificar em qual linha/coluna se encontra o cursor e então, se quiser, poderá especificar umamáscara de edição. Exemplo:

procedure TForm1.StringGrid1GetEditMask(Sender: TObject; ACol, ARow: Integer; var Value: String);begin if (ARow = 1) and (ACol = 1) then Value := '(999) 999-9999;1;_'; // Telefoneend;

Page 89: dicas para delphi

O evento OnGetEditText ocorre também quando entramos no modode edição. Neste momento podemos manipularmos o texto dacélula atual (linha/coluna) e então podemos simular algo talcomo uma tabela onde opções podem ser digitadas atravésde números. Exemplo:

procedure TForm1.StringGrid1GetEditText(Sender: TObject; ACol, ARow: Integer; var Value: String);begin if (ARow = 1) and (ACol = 2) then begin if StringGrid1.Cells[ACol, ARow] = 'Ótimo' then Value := '1' else if StringGrid1.Cells[ACol, ARow] = 'Regular' then Value := '2' else if StringGrid1.Cells[ACol, ARow] = 'Ruim' then Value := '3'; end;end;

O evento evento OnSetEditText ocorre quando saímos do modo deedição. Neste momento podemos manipular a entrada e trocarpor um texto equivalente. Normalmente usamos este evento emconjunto com o evento OnGetEditText. Exemplo:

procedure TForm1.StringGrid1SetEditText(Sender: TObject; ACol, ARow: Integer; const Value: String);begin if (ARow = 1) and (ACol = 2) then begin if Value = '1' then StringGrid1.Cells[ACol, ARow] := 'Ótimo' else if Value = '2' then StringGrid1.Cells[ACol, ARow] := 'Regular' else if Value = '3' then StringGrid1.Cells[ACol, ARow] := 'Ruim' end;end;

ObservaçõesPara testar o exemplo anterior crie um novo projeto e coloque no Form1 um TStringGrid. Mude os três eventos mencionados conforme os exemplos. Execute e experimente digitar nas céluas 1 e 2 da primeira linha (na parte não fixada, é claro!).

20 - Mostrar um Form de LogOn antes do Form principal

{ * Crie um novo Projeto. Este certamente terá o Form1. * Adicione um novo Form (Form2). * Coloque no Form2 dois botões TBitBtn. * Mude a propriedade Kind do BitBtn1 para bkOK. * Mude a propriedade Kind do BitBtn2 para bkCancel. * Vá no menu "Project/Options" na aba "Forms" e passe o Form2 de "Auto-create Forms" para "Available Forms".

Page 90: dicas para delphi

* Abra o arquivo Project.dpr (menu Project/View Source). * Altere o conteúdo deste arquivo conforme abaixo:}

program Project1;

uses Forms, Controls, Unit1 in 'Unit1.pas' {Form1}, Unit2 in 'Unit2.pas' {Form2};

{$R *.RES}

var F: TForm2;

begin F := TForm2.Create(Application); try if F.ShowModal = mrOK then begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end; finally F.Free; end;end.

ObservaçõesO Form2 do exemplo é o Form de LogOn. Este deverá ser preparado para que se possa escolher o usuário, digitar a senha, etc.

19 - Limitar a região de movimentação do mouseInclua na seção uses: Windows

{ Coloque um botão no form e altera o evento OnClick dele conforme abaixo: }

procedure TForm1.Button1Click(Sender: TObject);var R: TRect;begin { Pega o retângulo da área cliente do form } R := GetClientRect; { Converte as coordenadas do form em coordenadas da tela } R.TopLeft := ClientToScreen(R.TopLeft); R.BottomRight := ClientToScreen(R.BottomRight); { Limita a região de movimentação do mouse } ClipCursor(@R); ShowMessage('Tente mover o mouse para fora da área cliente do Form'); { Libera a movimentação } ClipCursor(nil);

Page 91: dicas para delphi

end;

ObservaçõesCuidado! Isto pode irritar o usuário do seu programa.

18 - Descobrir o nome de classe de uma janela do Windows

Muitas vezes precisamos saber qual o nome de classede uma determinada janela. Quando são janelas desenvolvidaspor nós, você olha no código-fonte. Mas e se não for, comoé o caso do Delphi?

Por exemplo:

Para verificar se o Delphi está sendo executado, procuramosno Windows pela janela cujo nome de classe seja TAppBuilder.Mas como verificar então se o Internet Explorer está sendo executado? Precisaremos saber o nome de classe da janela deste programa. Então o que fazer?

Use o TBWinName. Pegue-o no download de www.ulbrajp.com.br/usuario/tecnobyte

17 - Ocultar/exibir a barra de tarefas do WindowsInclua na seção uses: Windows

{ Coloque no Form dois Botões: BotaoOcultar e BotaoExibir. No evento OnClick do BotaoOcultar escreva: }

procedure TForm1.BotaoOcultarClick(Sender: TObject);var Janela: HWND;begin Janela := FindWindow('Shell_TrayWnd', nil); if Janela > 0 then ShowWindow(Janela, SW_HIDE);end;

{ No evento OnClick do BotaoExibir escreva: }

procedure TForm1.BotaoExibirClick(Sender: TObject);var Janela: HWND;begin Janela := FindWindow('Shell_TrayWnd', nil); if Janela > 0 then ShowWindow(Janela, SW_SHOW);end;

Page 92: dicas para delphi

{ Execute e teste, clicando em ambos os botões }

ObservaçõesA tarefa mais difícil é descobrir o nome de classe da janela da barra de tarefa do Windows, mas isto é fácil se você usar o TBWinName. Pegue-o no link download de www.ulbrajp.com.br/usuario/tecnobyte O resto é usar as APIs do Windows para manipulação de Janelas. Veja a pergunta nº 18.

16 - Evitar a proteção de tela durante seu programaInclua na seção uses: Windows

{ Na seção "private" do Form principal acrescente: }procedure AppMsg(var Msg: TMsg; var Handled: Boolean);

{ Na seção "implementation" acrescente (troque TForm1 para o nome do seu form principal): }procedure TForm1.AppMsg(var Msg: TMsg; var Handled: Boolean);begin if (Msg.Message = wm_SysCommand) and (Msg.wParam = sc_ScreenSave) then Handled := true;end;

{ No evento "OnCreate" do form principal, coloque: }Application.OnMessage := AppMsg;

15 - Fazer a barra de título ficar intermitente (piscante)Inclua na seção uses: Windows

{ Coloque um TTimer no Form desejado. Define a propriedade Interval do Timer para 1000 (1 segundo). Modifique o evento OnTimer do Timer conforme abaixo: }

procedure TForm1.Timer1Timer(Sender: TObject);begin FlashWindow(Handle, true); FlashWindow(Application.Handle, true);end;

14 - Posicionar o cursor do mouse em um controleInclua na seção uses: Windows

{ Digite a procedure abaixo imediatamente após a palavra implementation no código do seu formulário. }

procedure MouseParaControle(Controle: TControl);var IrPara: TPoint;

Page 93: dicas para delphi

begin IrPara.X := Controle.Left + (Controle.Width div 2); IrPara.Y := Controle.Top + (Controle.Height div 2); if Controle.Parent <> nil then IrPara := Controle.Parent.ClientToScreen(IrPara); SetCursorPos(IrPara.X, IrPara.Y);end;

{ Para testar, coloque no Form um botão e troque o name dele para btnOK e modifique o evento OnShow do Form conforme abaixo: }

procedure TForm1.FormShow(Sender: TObject);begin MouseParaControle(btnOk);end;

ObservaçõesA função "MouseParaControle" recebe um parâmetro do tipo TControl. Isto significa que você poderá passar para ela qualquer controle do Delphi, tais como: TEdit, TButton, TSpeedButton, TPanel, etc. Pode ser até mesmo o próprio Form.

13 - Criar cores personalizadas (sistema RGB)

{ Coloque um TButton no form e escreva o evento OnClick deste como abaixo: }procedure TForm1.Button1Click(Sender: TObject);var Vermelho, Verde, Azul: byte; MinhaCor: TColor;begin Vermelho := 0; Verde := 200; Azul := 150; MinhaCor := TColor(RGB(Vermelho, Verde, Azul)); Form1.Color := MinhaCor;end;

ObservaçõesA quantidade de cada cor primária é um número de 0 a 255. Observe que a cor retornada pela função RGB() está no formato do Windows (ColorRef); é por isto que fiz a conversão TColor(RGB(...)).

12 - Adicionar uma nova fonte no Windows

{ Coloque o código abaixo no OnClick de um botão }AddFontResource(PChar('c:\MyFonts\Monospac.ttf'));

Page 94: dicas para delphi

ObservaçõesTroque o nome do arquivo do exemplo anterior pelo nome desejado. Arquivos de fonte possuem uma das seguintes extensões: FON, FNT, TTF, FOT. Veja também a pergunta nº 10.

11 - Saber se a impressora atual possui determinada fonteInclua na seção uses: Printers

{ Coloque este código no OnClick de um botão }with Printer.Fonts do if IndexOf('Draft 10cpi') >= 0 then ShowMessage('A impressora possui a fonte.') else ShowMessage('A impressora NÃO possui a fonte.');

ObservaçõesIsto pode ser útil quando queremos usar fonte da impressora quando for uma matricial ou fonte do Windows quando for uma Jato de Tinta ou Laser. Veja também a pergunta nº 10.

10 - Saber se determinada Font está instalada no Windows

{ Coloque este código no OnClick de um botão }with Screen.Fonts do if IndexOf('Courier New') >= 0 then ShowMessage('A fonte está instalada.') else ShowMessage('A fonte não está instalada.');

ObservaçõesVeja também a pergunta nº 11.

9 - Acertar a data e hora do sistema através do programa

{ Coloque dois TEdit no form. Coloque um TButton no form e altere o evento OnClick deste botão como abaixo:}procedure TForm1.Button1Click(Sender: TObject);var DataHora: TSystemTime; Data, Hora: TDateTime; Ano, Mes, Dia, H, M, S, Mil: word;begin Data := StrToDate(Edit1.Text); Hora := StrToTime(Edit2.Text); DecodeDate(Data, Ano, Mes, Dia); DecodeTime(Hora, H, M, S, Mil); with DataHora do begin

Page 95: dicas para delphi

wYear := Ano; wMonth := Mes; wDay := Dia; wHour := H; wMinute := M; wSecond := S; wMilliseconds := Mil; end; SetLocalTime(DataHora);end;

ObservaçõesNo Edit1 digite a nova data e no Edit2 digite a nova hora.

8 - ENTER em vez de TAB no formulário, no DBGrid e no StringGrid

{ Mude a propriedade "KeyPreview" do Form para true. }

{ No evento "OnKeyPress" do Form acrescente o código abaixo: }

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);begin if Key = #13 then begin Key := #0; Perform(WM_NEXTDLGCTL, 1, 0); end;end;

{ Em StringGrid, escreva o evento OnKeyPress como abaixo: }

procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);begin if Key = #13 then StringGrid1.Perform(WM_KEYDOWN, VK_TAB, 0);end;

{ Em DBGrid, escreva o evento OnKeyPress como abaixo: }

procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);begin if Key = #13 then DBGrid1.Perform(WM_KEYDOWN, VK_TAB, 0);end;

ObservaçõesÉ bom lembrar que a tecla ENTER no Windows tem seu papel já bem definido quando se trata de caixa de diálogo: executar a ação padrão, normalmente o botão OK. Se não tomar cuidado poderá confundir o usuário, em vez de ajudá-lo.

Page 96: dicas para delphi

7 - Simular a vírgula através do ponto do teclado numérico

{ Na seção "private" do Form principal acrescente: }procedure AppMsg(var Msg: TMsg; var Handled: Boolean);

{ Na seção "implementation" acrescente (troque TForm1 para o nome do seu form principal): }procedure TForm1.AppMsg(var Msg: TMsg; var Handled: Boolean);begin if Msg.Message = WM_KEYDOWN then if Msg.wParam = 110 then Msg.wParam := 188;end;

{ No evento "OnCreate" do form principal, coloque: }Application.OnMessage := AppMsg;

{ Uma segunda alternativa (José Geraldo - ES): Coloque o código abaixo no evento OnKeyPress do componente onde se quer a conversão (Edit, DBEdit, etc). Neste caso a conversão funcionará apenas neste componente (óbvio). }

if Key = '.' then Key = DecimalSeparator;

ObservaçõesNa primeira alternativa, sempre que for pressionado o ponto do teclado numérico (da direita do teclado), este será convertido para vírgula, independentemente do controle que estiver em foco. Já na segunda, o ponto pode ser de qualquer lugar do teclado.

6 - Paralizar um programa durante n segundosInclua na seção uses: Windows

{ Pausa por 1 segundo }Sleep(1000);

{ Pausa por 10 segundos }Sleep(10000);

ObservaçõesEsta pausa não é interrompida pelo pressionamento de alguma tecla, como acontecia com InKey() do Clipper.

5 - Criar uma tabela (DB, DBF) através do seu programaInclua na seção uses: dbTables, DB

procedure CriaTabelaClientes;var Tabela: TTable;begin Tabela := TTable.Create(Application);

Page 97: dicas para delphi

try Tabela.DatabaseName := 'C:\'; { ou Tabela.DatabaseName := 'NomeAlias'; }

Tabela.TableName := 'Clientes.DB'; Tabela.TableType := ttParadox; { ou ttDBase }

{ Somente Delphi4 } if Tabela.Exists then { Se a tabela já existe... } Exit; {***}

{ Cria a tabela } Tabela.FieldDefs.Add('Codigo', ftInteger, 0, true); Tabela.FieldDefs.Add('Nome', ftString, 30, true); Tabela.FieldDefs.Add('DataNasc', ftDate, 0, false); Tabela.FieldDefs.Add('RendaMes', ftCurrency, 0, false); Tabela.FieldDefs.Add('Ativo', ftBoolean, 0, true); { etc, etc, etc } Tabela.CreateTable;

{ Cria os Índices } Tabela.AddIndex('ICodigo', 'Codigo', [ixPrimary, ixUnique]); Tabela.AddIndex('INome', 'Nome', [ixCaseInsensitive]); { etc, etc, etc } finally Tabela.Free; end;end;

ObservaçõesPara verificar se o arquivo já existe na versão 3 ou anterior do Delphi, você deverá usar a função "FileExists" do Delphi.

4 - Verificar se um diretório existeInclua na seção uses: FileCtrl, Dialogs

if DirectoryExists('C:\MEUSDOCS') then ShowMessage('O diretório existe')else ShowMessage('O diretório não existe');

3 - Verificar se um arquivo existeInclua na seção uses: SysUtils, Dialogs

if FileExists('c:\carta.doc') then ShowMessage('O arquivo existe')else ShowMessage('O arquivo não existe');

Page 98: dicas para delphi

2 - Criar um Alias temporário através do seu programaInclua na seção uses: DB

{ Enxergar somente configurações da sessão atual }Session.ConfigMode := cmSession;{ Adicionar o Alias }Session.AddStandardAlias('MeuAlias', 'C:\DirProg', 'PARADOX');

ObservaçõesVeja a pergunta nº 1.

1 - Criar um Alias através do seu programaInclua na seção uses: DB

{ se o alias não existir... }if not Session.IsAlias('MeuAlias') then begin { Adiciona o alias } Session.AddStandardAlias('MeuAlias', 'C:\DirProg', 'PARADOX'); { Salva o arquivo de configuração do BDE } Session.SaveConfigFile;end;

ObservaçõesPara criar um alias do dBase troque a string 'PARADOX' por 'DBASE'. No caso acima usei como path o caminho "C:\DirProg", mas se você quiser poderá trocar este caminho por ExtractFilePath(ParamStr(0)) para que o alias seja direcionado para o local onde está seu .EXE. Neste último caso será necessário incluir na seção uses: SysUtils, System.

A listbox in a cell of a stringgrid

Here's another great trick by programmer illusionists.  What appears as embedded comboboxes within a stringgrid is actually just a combobox floating above the stringgrid, and it just so happens to be the exact same size as the stringgrid cell underneath it.

Here's the basics:

  procedure TfrmMain.FormCreate(Sender: TObject);  begin    StringGrid1.DefaultRowHeight := ComboBox1.Height;  end;

  procedure TfrmMain.StringGrid1DrawCell(Sender: TObject; Col, Row:     Integer; Rect: TRect; State: TGridDrawState);  var    R: TRect;  begin    if (Col >= StringGrid1.FixedCols) and      (Row >= StringGrid1.FixedRows) and      (gdFocused in State) then

Page 99: dicas para delphi

      with ComboBox1 do      begin        BringToFront;        CopyRect(R, Rect);        R.TopLeft :=     frmMain.ScreenToClient(                         StringGrid1.ClientToScreen(R.TopLeft));        R.BottomRight := frmMain.ScreenToClient(                         StringGrid1.ClientToScreen(R.BottomRight));        SetBounds(R.Left, R.Top, R.Right-R.Left, R.Bottom-R.Top);     end;  end;

  procedure TfrmMain.StringGrid1TopLeftChanged(Sender: TObject);  var    R: TRect;  begin    with StringGrid1 do        CopyRect(R, CellRect(Col, Row));

   with ComboBox1 do    begin      Visible := False;      R.TopLeft :=     frmMain.ScreenToClient(                       StringGrid1.ClientToScreen(R.TopLeft));      R.BottomRight := frmMain.ScreenToClient(                       StringGrid1.ClientToScreen(R.BottomRight));      SetBounds(R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top);    end;

   with StringGrid1 do      if (TopRow <= Row) and (TopRow + VisibleRowCount > Row) then         ComboBox1.Show;  end;

  procedure TfrmMain.ComboBox1Change(Sender: TObject);  begin    with StringGrid1 do      Cells[Col, Row] := ComboBox1.Text;  end;

In essence, the main routine here is the stringgrid's OnDrawCell event handler.  Of course, I also set the stringgrid's DefaultRowHeight property to be the same height as the combobox.  In addition, the stringgrid's OnTopLeftChanged event handler is used to hide the combobox when the user scrolls out of view.  Also, when the user selects an item from the combobox, simply place the text in the current Col/Row.

You can also do a couple other little tricks such as setting the stringgrid's Objects[] property to point to the combobox, as well as possibly setting the combobox's Parent property to point to the stringgrid. However, I've had problems with the Parent approach -- namely, that of dropping down the listbox associated with the combobox.

"Change the StringGrid's CELL color ?" by EDDIE SHIPMAN

Here's how:

Page 100: dicas para delphi

procedure TForm1.StringGrid1DrawCell(Sender: TObject; Col, Row: Integer; Rect: TRect; State: TGridDrawState);var TempPString:Array [0..255] of char;begin If (gdFixed in State){or (gdSelected in State)} then exit;

StringGrid1.Canvas.Brush.Style:=bsSolid; {You could add some color here, if desired:} Case Col of 1: StringGrid1.Canvas.Brush.Color:=clRed; 2: StringGrid1.Canvas.Brush.Color:=clWhite; 3: StringGrid1.Canvas.Brush.Color:=clBlue; end; {Erase data} StringGrid1.Canvas.FillRect(Rect); {Get text in a PChar string} StrPCopy(TempPString,StringGrid1.Cells[Col,Row]); {DrawText--see other options in Windows API help; Change the DT_LEFT to DT_RIGHT for right justified txt!} DrawText(StringGrid1.Canvas.Handle,TempPString,-1,Rect,DT_LEFT);end;

Sort a TStringGrid by Columns?

type   TMoveSG = class(TCustomGrid); // reveals protected MoveRow procedure

{...}

procedure SortGridByCols(Grid: TStringGrid; ColOrder: array of Integer); var   i, j:   Integer;   Sorted: Boolean;

function Sort(Row1, Row2: Integer): Integer; var   C: Integer; begin   C      := 0;   Result := AnsiCompareStr(Grid.Cols[ColOrder[C]][Row1], Grid.Cols[ColOrder[C]][Row2]);   if Result = 0 then   begin     Inc(C);     while (C <= High(ColOrder)) and (Result = 0) do     begin       Result := AnsiCompareStr(Grid.Cols[ColOrder[C]][Row1],         Grid.Cols[ColOrder[C]][Row2]);       Inc(C);     end;   end; end;

begin   if SizeOf(ColOrder) div SizeOf(i) <> Grid.ColCount then Exit;

Page 101: dicas para delphi

  for i := 0 to High(ColOrder) do     if (ColOrder[i] < 0) or (ColOrder[i] >= Grid.ColCount) then Exit;

  j := 0;   Sorted := False;   repeat     Inc(j);     with Grid do       for i := 0 to RowCount - 2 do         if Sort(i, i + 1) > 0 then         begin           TMoveSG(Grid).MoveRow(i + 1, i);           Sorted := False;         end;   until Sorted or (j = 1000);   Grid.Repaint; end;

procedure TForm1.Button1Click(Sender: TObject); begin   { Sort rows based on the contents of two or more columns.     Sorts first by column 1. If there are duplicate values     in column 1, the next sort column is column 2 and so on...}   SortGridByCols(StringGrid1, [1, 2, 0, 3, 4]); end;

 

...export a TStringGrid to a MS Word table?

uses   ComObj;

procedure TForm1.Button1Click(Sender: TObject); var   WordApp, NewDoc, WordTable: OLEVariant;   iRows, iCols, iGridRows, jGridCols: Integer; begin   try     // Create a Word Instance     // Word Instanz erzeugen     WordApp := CreateOleObject('Word.Application');   except     // Error...     // Fehler....     Exit;   end;

  // Show Word   // Word anzeigen   WordApp.Visible := True;

  // Add a new Doc   // Neues Dok einfügen   NewDoc := WordApp.Documents.Add;

  // Get number of columns, rows   // Spalten, Reihen ermitteln   iCols := StringGrid1.ColCount;   iRows := StringGrid1.RowCount;

Page 102: dicas para delphi

  // Add a Table   // Tabelle einfügen   WordTable := NewDoc.Tables.Add(WordApp.Selection.Range, iCols, iRows);

  // Fill up the word table with the Stringgrid contents   // Tabelle ausfüllen mit Stringgrid Daten   for iGridRows := 1 to iRows do     for jGridCols := 1 to iCols do       WordTable.Cell(iGridRows, jGridCols).Range.Text :=         StringGrid1.Cells[jGridCols - 1, iGridRows - 1];

  // Here you might want to Save the Doc, quit Word...   // Hier evtl Word Doc speichern, beenden...

  // ...      // Cleanup...   WordApp := Unassigned;   NewDoc := Unassigned;   WordTable := Unassigned; end;

...convert a TStringGrid to HTML?

{ The SGridToHtml() function converts a Stringgrid to a HTML Code.   Parameters: SG: TStringGrid to convert               Dest: TMemo to show the HTML Code               BorderSize: Size of border (0 = show no border) {   Mit der Funktion SGridToHtml() können StringGrids in HTML Code umgewandelt werden.   SG bezieht sich auf das TStringGrid, welches codiert werden soll.   in Dest (vom Typ TMemo) wird der HTML Code erzeugt.   BorderSize bestimmt, wie dick der Tabellenrahmen sein soll. 0 = kein Rahmen }

procedure SGridToHtml(SG: TStringgrid; Dest: TMemo; BorderSize: Integer); var    i, p: integer;   SStyle1, SStyle2, Text: string; begin   Dest.Clear;   Dest.Lines.Add('<html>');   Dest.Lines.Add('<body>');   Dest.Lines.Add('  <table border="' + IntToStr(BorderSize) + '" width="' +     IntToStr(SG.Width) + '" height="' + IntToStr(SG.Width) + '">');

  for i := 0 to SG.RowCount - 1 do   begin     Dest.Lines.Add('  <tr>');     for p := 0 to SG.ColCount - 1 do     begin       SStyle1 := '';       SStyle2 := '';       if fsbold in SG.Font.Style then       begin         SStyle1 := SStyle1 + '<b>';

Page 103: dicas para delphi

        SStyle2 := SStyle2 + '</b>';       end;       if fsitalic in SG.Font.Style then       begin         SStyle1 := SStyle1 + '<i>';         SStyle2 := SStyle2 + '</i>';       end;       if fsunderline in SG.Font.Style then       begin         SStyle1 := SStyle1 + '<u>';         SStyle2 := SStyle2 + '</u>';       end;       Text := sg.Cells[p, i];       if Text = '' then Text := ' ';       Dest.Lines.Add('    <td width="' + IntToStr(sg.ColWidths[p]) +         '" height="' + IntToStr(sg.RowHeights[p]) +         '"><font color="#' + IntToHex(sg.Font.Color, 6) +         '" face="' + SG.Font.Name + '">' + SStyle1 +         Text + SStyle2 + '</font></td>');     end;     Dest.Lines.Add('  </tr>');   end;   Dest.Lines.Add('  </table>');   Dest.Lines.Add('</body>');;   Dest.Lines.Add('</html>'); end;

// Example, Beispiel procedure TFormCSVInport.Button6Click(Sender: TObject); begin   SGridToHtml(StringGrid1, Memo1, 1);   Memo1.Lines.SaveToFile('c:\test.html'); end;

...export a StringGrid to an Excel-File?

{1. With OLE Automation }

uses   ComObj;

function RefToCell(ARow, ACol: Integer): string; begin   Result := Chr(Ord('A') + ACol - 1) + IntToStr(ARow); end;

function SaveAsExcelFile(AGrid: TStringGrid; ASheetName, AFileName: string): Boolean; const   xlWBATWorksheet = -4167; var   Row, Col: Integer;   GridPrevFile: string;   XLApp, Sheet, Data: OLEVariant;   i, j: Integer; begin

Page 104: dicas para delphi

  // Prepare Data   Data := VarArrayCreate([1, AGrid.RowCount, 1, AGrid.ColCount], varVariant);   for i := 0 to AGrid.ColCount - 1 do     for j := 0 to AGrid.RowCount - 1 do       Data[j + 1, i + 1] := AGrid.Cells[i, j];   // Create Excel-OLE Object   Result := False;   XLApp := CreateOleObject('Excel.Application');   try     // Hide Excel     XLApp.Visible := False;     // Add new Workbook     XLApp.Workbooks.Add(xlWBatWorkSheet);     Sheet := XLApp.Workbooks[1].WorkSheets[1];     Sheet.Name := ASheetName;     // Fill up the sheet     Sheet.Range[RefToCell(1, 1), RefToCell(AGrid.RowCount,       AGrid.ColCount)].Value := Data;     // Save Excel Worksheet     try       XLApp.Workbooks[1].SaveAs(AFileName);       Result := True;     except       // Error ?     end;   finally     // Quit Excel     if not VarIsEmpty(XLApp) then     begin       XLApp.DisplayAlerts := False;       XLApp.Quit;       XLAPP := Unassigned;       Sheet := Unassigned;     end;   end; end;

// Example:

procedure TForm1.Button1Click(Sender: TObject); begin   if SaveAsExcelFile(stringGrid1, 'My Stringgrid Data', 'c:\MyExcelFile.xls') then     ShowMessage('StringGrid saved!'); end;

{**************************************************************} {2. Without OLE }

procedure XlsWriteCellLabel(XlsStream: TStream; const ACol, ARow: Word;   const AValue: string); var   L: Word; const   {$J+}   CXlsLabel: array[0..5] of Word = ($204, 0, 0, 0, 0, 0);

Page 105: dicas para delphi

  {$J-} begin   L := Length(AValue);   CXlsLabel[1] := 8 + L;   CXlsLabel[2] := ARow;   CXlsLabel[3] := ACol;   CXlsLabel[5] := L;   XlsStream.WriteBuffer(CXlsLabel, SizeOf(CXlsLabel));   XlsStream.WriteBuffer(Pointer(AValue)^, L); end;

function SaveAsExcelFile(AGrid: TStringGrid; AFileName: string): Boolean; const   {$J+} CXlsBof: array[0..5] of Word = ($809, 8, 00, $10, 0, 0); {$J-}   CXlsEof: array[0..1] of Word = ($0A, 00); var   FStream: TFileStream;   I, J: Integer; begin   Result := False;   FStream := TFileStream.Create(PChar(AFileName), fmCreate or fmOpenWrite);   try     CXlsBof[4] := 0;     FStream.WriteBuffer(CXlsBof, SizeOf(CXlsBof));     for i := 0 to AGrid.ColCount - 1 do       for j := 0 to AGrid.RowCount - 1 do         XlsWriteCellLabel(FStream, I, J, AGrid.cells[i, j]);     FStream.WriteBuffer(CXlsEof, SizeOf(CXlsEof));     Result := True;   finally     FStream.Free;   end; end;

// Example:

procedure TForm1.Button2Click(Sender: TObject); begin   if SaveAsExcelFile(StringGrid1, 'c:\MyExcelFile.xls') then     ShowMessage('StringGrid saved!'); end;

{**************************************************************} {3. Code by Reinhard Schatzl }

uses   ComObj;

// Hilfsfunktion für StringGridToExcelSheet // Helper function for StringGridToExcelSheet function RefToCell(RowID, ColID: Integer): string; var   ACount, APos: Integer; begin   ACount := ColID div 26;   APos := ColID mod 26;

Page 106: dicas para delphi

  if APos = 0 then   begin     ACount := ACount - 1;     APos := 26;   end;

  if ACount = 0 then     Result := Chr(Ord('A') + ColID - 1) + IntToStr(RowID);

  if ACount = 1 then     Result := 'A' + Chr(Ord('A') + APos - 1) + IntToStr(RowID);

  if ACount > 1 then     Result := Chr(Ord('A') + ACount - 1) + Chr(Ord('A') + APos - 1) + IntToStr(RowID); end;

// StringGrid Inhalt in Excel exportieren // Export StringGrid contents to Excel function StringGridToExcelSheet(Grid: TStringGrid; SheetName, FileName: string;   ShowExcel: Boolean): Boolean; const   xlWBATWorksheet = -4167; var   SheetCount, SheetColCount, SheetRowCount, BookCount: Integer;   XLApp, Sheet, Data: OLEVariant;   I, J, N, M: Integer;   SaveFileName: string; begin   //notwendige Sheetanzahl feststellen   SheetCount := (Grid.ColCount div 256) + 1;   if Grid.ColCount mod 256 = 0 then     SheetCount := SheetCount - 1;   //notwendige Bookanzahl feststellen   BookCount := (Grid.RowCount div 65536) + 1;   if Grid.RowCount mod 65536 = 0 then     BookCount := BookCount - 1;

  //Create Excel-OLE Object   Result := False;   XLApp  := CreateOleObject('Excel.Application');   try     //Excelsheet anzeigen     if ShowExcel = False then       XLApp.Visible := False     else       XLApp.Visible := True;     //Workbook hinzufügen     for M := 1 to BookCount do     begin       XLApp.Workbooks.Add(xlWBATWorksheet);       //Sheets anlegen       for N := 1 to SheetCount - 1 do       begin         XLApp.Worksheets.Add;       end;

Page 107: dicas para delphi

    end;     //Sheet ColAnzahl feststellen     if Grid.ColCount <= 256 then       SheetColCount := Grid.ColCount     else       SheetColCount := 256;     //Sheet RowAnzahl feststellen     if Grid.RowCount <= 65536 then       SheetRowCount := Grid.RowCount     else       SheetRowCount := 65536;

    //Sheets befüllen     for M := 1 to BookCount do     begin       for N := 1 to SheetCount do       begin         //Daten aus Grid holen         Data := VarArrayCreate([1, Grid.RowCount, 1, SheetColCount], varVariant);         for I := 0 to SheetColCount - 1 do           for J := 0 to SheetRowCount - 1 do             if ((I + 256 * (N - 1)) <= Grid.ColCount) and               ((J + 65536 * (M - 1)) <= Grid.RowCount) then               Data[J + 1, I + 1] := Grid.Cells[I + 256 * (N - 1), J + 65536 * (M - 1)];         //-------------------------         XLApp.Worksheets[N].Select;         XLApp.Workbooks[M].Worksheets[N].Name := SheetName + IntToStr(N);         //Zellen als String Formatieren         XLApp.Workbooks[M].Worksheets[N].Range[RefToCell(1, 1),           RefToCell(SheetRowCount, SheetColCount)].Select;         XLApp.Selection.NumberFormat := '@';         XLApp.Workbooks[M].Worksheets[N].Range['A1'].Select;         //Daten dem Excelsheet übergeben         Sheet := XLApp.Workbooks[M].WorkSheets[N];         Sheet.Range[RefToCell(1, 1), RefToCell(SheetRowCount, SheetColCount)].Value :=           Data;       end;     end;     //Save Excel Worksheet     try       for M := 1 to BookCount do       begin         SaveFileName := Copy(FileName, 1,Pos('.', FileName) - 1) + IntToStr(M) +           Copy(FileName, Pos('.', FileName),           Length(FileName) - Pos('.', FileName) + 1);         XLApp.Workbooks[M].SaveAs(SaveFileName);       end;       Result := True;     except       // Error ?     end;   finally     //Excel Beenden

Page 108: dicas para delphi

    if (not VarIsEmpty(XLApp)) and (ShowExcel = False) then     begin       XLApp.DisplayAlerts := False;       XLApp.Quit;       XLAPP := Unassigned;       Sheet := Unassigned;     end;   end; end;

//Example procedure TForm1.Button1Click(Sender: TObject); begin   //StringGrid inhalt in Excel exportieren   //Grid : stringGrid, SheetName : stringgrid Print, Pfad : c:\Test\ExcelFile.xls, Excelsheet anzeigen   StringGridToExcelSheet(StringGrid, 'Stringgrid Print', 'c:\Test\ExcelFile.xls', True); end;

 

Page 109: dicas para delphi

GERAL Stringscopy - Copia uma substring, dentro de uma stringVarvtexto, Copia: String;beginvtexto := Edit1.Text ; // descobriu o valor de textoCopia := copy(vtexto,2,2); // copia de vtexto, apartir da segunda letra dois caracteresLabel1.Caption := Copia; // o label exibira as duas letrasend; // delete - Deleta uma substring dentro de uma string. ex: Delete (Mystring, 2,1) // delete da variável mysring, na segunda posição, 1 caractere insert - Insereuma substring em uma string .ex: Insert ("z", mystring, 1 ) //insere a letra z no começo da string Inttostr - Converte um valor inteiro para string. ex: MyString := Inttostr(Shape1.top) //A variaável mystring recebe o valor top do componente Shape1length - Retorna o número de caracteres de uma string ex: canvas.textout ( 10, 10, ' Número de caracteres =' + InttoStr (length MmyString ))); //exibe o número de caracteres contido em uma string.Lowercase - Converte para menúsculos os caracteres alfabétiocs de uma string;Lowercase( 'SORTE' ); // tranformar para 'sorte'Pos - Esta função retorna um valor integer correspondente a posição de uma string dentro de uma outra string.Var VPalavra : string; VNumero : Integer; BeginVPalavra := ' Pernambuco ' ;VNumero := Pos ( ' a ' , VPalavra ) ; // Numero retorna o valor 5end;

STR-Esta procedure converte um valor inteiro ou real para uma string.// a variável Vs recebe o valor da variável VnVar Vn : real;Vs : string Begin Vn := 100 ; Str (Vn, Vs) ; end;

StrtoInt - Esta função converte um valor string para um valor inteiro.// A variável Vlocal recebe o valor ( inteiro ) top do componente Shape1VarvLocal : String;Begin Vlocal : InttoStr ( Shape1. Top) ;EndUppercase - Esta rotina substitui todas as letras minúsculas de uma string por letras maiúsculas.Uppercase ('casa');// Retorna 'CASA'VAL - Esta rotina extrai o valor numérico ( tipo real ou integer ) de uma String;Sua sintaxe é :Val ( S ; var v ; var Code : integer );Observe o exemplo abaixo :VarN, C : integer ;BeginVal ( Edit1. Text, N, C ) ;

Page 110: dicas para delphi

Button1. Top := N ; End ;// Se a variável C tiver valor diferente de 0 significa que ouve erra na conversção. ( ex : O texto do Edit não é um número intéiro válido )Declarando uma strings:var terra: string //declaração simplesmarte: string [5] //delimitado 5 caracteres para a stringvenus: shortstring //string de menos de 256 caracteres

Format//Para coloca zeros a esquerda dos números encontrados.%5 mostra o valor da variável inteira "VNum"// .5d por que são 5 caracteresEdit1.text:= Format('%5.5d',[VNum]);

//Colocar zeros a esquerda de um valor Real digitado no EditEdit1.Text := FormatFloat(‘000000’,StrToFloat(Edit1.Text));//Colocar zeros a esquerda de um valor inteiro digitado no EditEdit1.Text := FormatFloat(‘000000’,StrToInt(Edit1.Text));Formatando com estilo de moeda//Formatando um valor RealEdit1.Text := FormatFloat(‘#,##0.00’,vSalario);//Formatando uma StringEdit1.Text := FormatFloat(‘#,##0.00’,StrToFloat(Edit1.Text));Obs- (#) Cerquilha, para números obcionais. (,) Ponto para separar milhar. (.) Virgula para separar casas decimais.//A linha abaixo exibe em um label, seu top. Misturando String do InteiroLabel1.Caption := Format('O top deste label é %d',[Label1.top]);//Lendo uma variável inteiraLabel.Caption := Format ('O número guardado é : %d, [i]);// Para exibir o valor Hexadecimal de uma variável integer(i)Label1.Caption := Format('$%x',[i]);//Formatando uma Data:dbedit1.text:=formatDateTime('dd/mm/yyyy hh:mm',now);

Delete - Ex:Delete(MyString) // deleta da variável MyString, na segunda posição, um caractereInsert - Ex:Insert ('z',MyString,1) // Insere a letra z no começo da StringInttoStr - Ex:MyString := InttoStr(Shape1.top)//A variável MyString recebe o valor top do componente Shape1

MensagensMenssagem simplesShowMessage( ' texto da menssagem ' ); Caixa de messagemMessageDlg( ' aviso ' , mtInformation, [mbOk], 0 );

if MessageDlg('Quer sair do programa',mtInformation,[mbYes,mbNo],0) = mrYes thenForm1.close;

if Application.MessageBox('Confirmar Exclusão','Atenção',mb_YesNo + mb_iconQuestion) = idYes then{comandos...}

If Application.MessageBox('Confirma Exclusão?','ATENÇÃO',MB_ICONEXCLAMATION + MB_YESNO) = IDYES Then

Page 111: dicas para delphi

DataModule1.Tb_Alunos.Delete;

INPUTBOX e INPUTQUERYINPUTBOX//A linha abaixo exibe uma caixa de diálogo onde digitamos um valor que será exibido em um labelLabel1.Caption := InputBox('digite','integer','');<B.INPUTQUERY< b>//Sensível à maiúsculas e minúsculas. Veja abaixo dois exemplos.Exemplo1procedure TForm1.Button3Click(Sender: TObject);varNS: string;clickOK: Boolean; // clickok foi inventadobeginNS := 'Nome fixo';Label1.Caption := NS;clickOK := InputQuery('Input Box', 'digite', NS);if clickOK thenLabel1.Caption := 'The new string is ''' + NS + '''';end;

Exemplo2varr : string; begininputQuery( ' ver ' , ' senha ' , r );if r = ' s ' thenshape1.Visible := trueelseshowmessage( ' senha errada ' );end;Tratando ErrosDeletando um registrotryDMAgenda.tbAgenda.Delete;exceptOn E:EDBEngineError doShowMessage('Registro em uso por outro USUÁRIO. Exclusão Cancelada';end;

Datas InválidasTryStrtoDate(Edit1.text);excepton EconvertError doShowMessage('Data Inválida');end;

Centralizar um componeteNo evento OnResize digiteNo evento abaixo, toda vez que o form sor redimencionado, o Button ficara no centroButton1.Top := Form1.ClientHeight div 2 - Button1.Height div 2;Button1.Left := Form1.ClientWidth div 2 - Button1.Width div 2;

SenhasColocar senha numa tabela Paradox //...e retirar em tempo de execução: Session.AddPassword('Senha-Da-Tabela');

Page 112: dicas para delphi

... Session.RemovePassword;outra opção...Session.AddPassword('Senha'); Table1.Active := True;// vincule o Table1 ao Session>

Encryptar uma stringfunction Encrypt( Senha:String ): String;ConstChave : String = 'Jesus';Varx,y : Integer;NovaSenha : String;beginfor x := 1 to Length( Chave ) do beginNovaSenha := '';for y := 1 to Length( Senha ) doNovaSenha := NovaSenha + chr( (Ord(Chave[x]) xor Ord(Senha[y])));Senha := NovaSenha;end;result := Senha;end;

Rotina para um janela de Login...varcontador : Integer ;beginif not DataModule1.Table1.findkey([edit1.text]) then // a coluna senha, na tabela, tem que ser a primeirabeginShowMessage( ' senha errada ' ) ;inc ( contador ) ;if contador = 3 thenShowMessage ( ' vc teve 3 chances ' ) ;exit ;end ; formSenha.Close ;formPrincipal.Enabled := true ;end ;

findfieldContador : Integer;//colocar em na área var ou usesvar // no evento onClick do botão OKs : TstringField; //unit dbbegins:= DataModlule1.Table1.findfield('senha')as TstringField; // procura na coluna senhaif s.value <> Edit1.text thenbeginShowMessage('senha invalida');inc(contador);if Contador = 3 thenbeginShowMessage('vc teve 3 chances');formPrincipal.Close;end;

Page 113: dicas para delphi

exit;formSenha.Close;formPrincipal.Enabled := true;end;

Trabalhando com o teclado#0=Null #8=Backspace #13=Enter#27=Escape #32=Espaço #127=Delete//fazer o Enter, substituir o Tab...if key = #13 then Edit1.SetFocus; // o Edit recebe o foco

//fazer o Enter, substituir o Tab...(II)SelectNext(ActiveControl,true,true);// joga o foco no proximo componente///Cancelando uma teclaif (Key = ‘A’) or (Key = 'a') thenKey := #0;

Levar o foco para o componente anterior// No evento OnKeyDown digite:if Key = (Vk_Up) thenPerform(Wm_NextDlgCtl,1,0);

Caracteres especiais// declare uma constante com os caracteres especiais... ConstchrEspecial : Set of Char =['@','#','$','%'];//no evento OnKeyPress, digite:If key in ChrEspecial thenShowMessage('esta letra é especial');

// Para digitar só maiúsculas...Key := Upcase(Key); //colocar no evento OnKeyPress de um Edit

Emular o pressionamento de um botãoIf (key = VK_F1) then btnAjuda.Onclick(Self);//no evento OnKeyPress

Para desabilitar o CTRL+ALT+DEL e ALT+TABVarnumero: integer;beginSystemParametersInfo(97,Word(true),@numero,0);end;{ Para habilitar é só chamar a mesma função com Word(false) }

Trabalhando com a Guia DialogsSaveDialogif SaveDialog1.Execute thenbeginMemo1.Lines.SaveToFile (SaveDialog1.FileName); // pode ser um RichEditend;OpenDialogif OpenDialog1.Execute thenbeginMemo1.Lines.LoadFromFile(OpenDialog1.FileName) ; // poderia ser um RichEditend ;OpenPictureDialog

Page 114: dicas para delphi

if OpenPictureDialog1.Execute then image1.Picture.LoadFromFile (OpenPictureDialog1.fileName) ; // carrega uma imagem no componenteFontDialogif FontDialog1.Execute thenbeginMemo1.Font := Font;// poderia ser um RichEditend;ou...with FontDialog1 dobr> beginFont := Label1.Font;if Execute thenLabel1.Font := Font;end;colordialogif colordialog1.Execute thenbeginwith ColorDialog1 dobeginColor := Label1.Color;ou...if Execute thenLabel1.Color := Color;end;RichEdit.Color := Color;end;PrintDialogPrintDialog1.Execute;

Trabalhando com Data e HoraDateToStr(Date) ==> 21/09/01TimeToStr(Time) ==> 11:50:00FormatDateTime('d',Date); ==>21FormatDateTime('d/m/y',Date);==> 21/9/01FormatDateTime('dd/mm/yy',Date); ==>21/09/01FormatDateTime('ddd/dd/mm/yy',Date); ==> Sex/05/09/01FormatDateTime('dddd/dd/mmmm/yyyy',Date); ==> Sexta-feira/Setembro/1999FormatDateTime('ddddd',Date); ==> 05/09/99FormatDateTime('dddddd',Date); ==> Sexta=Feria, 21 de Setembro de 2001

Label1.caption := timetostr(time);Label1.caption := datetostr(date);// Somar uma datavarTs1, ts2 : TTimeStamp;Data1, Data2 : TDateTime;Dias : Integer;beginDate1 := StrtoDate(edit1.text);Date2 := StrtoDate(edit2.text); Ts1 := DateTimetoTimeStamp(Data1);Ts2 := DateTimetoTimeStamp(Data2);Dias := Ts2.Date - Ts1.Date;Edit3.Text := InttoStr(Dias);if Dias > 10 thenShowMessage('Passaram-se 10 dias');end;

Page 115: dicas para delphi

O Dia da Semanafunction DayOfWeek(Data:TDataTime):Integer;Ex.:Label1.Caption:= 'Data e Hora Atual' + DateTimeToStr(Now);- Retorna o dia da semana em um inteiro de 1 a 7.

Métodos e Propriedades do FormShow // exibe um formHide // esconde um form mas não o descarregaPrint // imprime um formSetFocus // establece o foco para um form ou componenteBringtoFront // envia o frente

Form1.formstyle := fsOntop; // para um formulário aparcer sobre outros sempre

Texto em um formcanvas.textout(0,0,'Este texto aparece no form. Top e Left zerados');

Form ElípticoNo evento OnCreate do form, digite:var hR : THandle;begin{cria uma form de formato elíptico}hR := CreateEllipticRgn (0,0,Width,Height);SetWindowRgn (Handle,hR,True);end;Obs. Também é bom alterar a propriedade BorderStyle para bsNone. O tamanho da elípse é definido pelo tamanho do form.

Para criar um form em tempo de execuçãoNovoForm:= TfmFilho.Create (self);NovoForm.Parent := self;

Form em tempo de execução IIApplication.CreateForm(TForm2, Form2); //Cria o formForm2.ShowModal ;Form2.free; // Libera o form da memória

Form em tempo de execução IIIApplication.CreateForm(TFormTal, FormTal);FormTal.ShowModal;FormTal.Free;

Criando um QuickReport em tempo de execuçãoqrMovCaixa := TqrMovCaixa.Create(self);DMNL.qrMovCaixa.Open;qrMovCaixa.Preview;qrMovCaixa.Free;

evitar que se tente abrir o mesmo Form, duas vezesif form1 = nil then // se o form1 ainda não foi criado...... comandos para criar um form...//colocar no evento OnClose:form1 := nil;

Para executar um outro aplicativo apartir do Delphi

Page 116: dicas para delphi

If Winexec('c:\windows\calc.exe',sw_shownormal)= 2 then showmessage('Arquivo não encontrado');

Diretório do aplicativo// No evento OnCreate, digite:varPathName: string;beginPathName := ExtractFilePath (ParamStr (0));Label1.Caption := 'Estamos em: '+ PathName;end;

O Componente TComboBoxPara abrir um TComboBox sem clica-lo, digite: ComboBox1.DroppedDown := True;

StringList - Lista de stringsColocar na cláusula uses a unit 'Classes'Declarar a instância da classe{ Private declarations }MinhaLista: TStringList;Executar o método construtor para instanciar a classeMinhaLista := TStringList.Create();Depois de instanciada, os métodos e propriedades da classe ficam disponíveisMinhaLista.Add(Edit1.Text);Ver o conteúdo...Label1.Caption := MinhaLista.GetText ;ou...vari : integer;beginfor i := 0 to MinhaLista.Count-1 doListBox1.Items.Add (MinhaLista.Strings[i]);end;Último passo: Destruir a instância com o método destrutorMinhaLista.Destroy;Trabalhando com Case... ofCriando seleçõesvar Seletor : char;beginSeletor := 'C';Case Seletor of'A' : ShowMessage('Escolhido A');'B' : ShowMessage('Escolhido B');'C' : BeginShowmessage('Escolhido C');Halt; // encerra o programaend;else// caso não seja uma destas letrasShowMessage('Não escolhido um destes ítems');end;Trabalhando com Case II Case RadioGroup1.ItemIndex of0 : Form2.BorderStyle := bsDialog;1 : Form2.BorderStyle := dbNone;end;

Page 117: dicas para delphi

Usando o RepeatvarN : String;beginRepeat;N := Inputbox('GetNumber', 'Insira um número','');Until N:= '7';end;Atribuir Mesmo Valor para Vários Edits em um Formfor i := 0 to ComponentCount - 1 doif Components[i] is TEdit thenTEdit(Components[i]).Text := Valor;

Testa se há disco no Drive A:function TForm1.TemDiscoNoDrive(const drive : char): boolean;varDriveNumero : byte;EMode : word;beginresult := false;DriveNumero := ord(Drive);if DriveNumero >= ord('a') thendec(DriveNumero,$20);EMode := SetErrorMode(SEM_FAILCRITICALERRORS);tryif DiskSize(DriveNumero-$40) <> -1 thenResult := true else messagebeep(0);finallySetErrorMode(EMode);end;end;

procedure TForm1.Button1Click(Sender: TObject);beginif TemDiscoNoDrive('a') thenShowMessage('Tem disco no drive A:')else ShowMessage('Não tem disco no drive A:');end;

Usando Enter no lugar de TAB// Coloque no form: keypreview = true. No ONKEYDOWN, digite:if (Key= VK_RETURN) or (Key= VK_DOWN) thenbeginKey := 0;Perform(WM_NEXTDLGCTL, 0, 0);endelseif (Key= VK_UP) thenbeginKey := 0;Perform(WM_NEXTDLGCTL, 1, 0);end;Close em um FormOnCloseQuery //No evento OnCloseQuery. A segunda opção ("Não") recebe o foco.CanClose := Application.MessageBox( 'Confirme Operação','Terminar Aplicação ?',

Page 118: dicas para delphi

MB_ICONQUESTION + MB_YESNO + MB_DEFBUTTON2 ) = ID_YES;

Salvar dados antes de fechar://no evento OnClose:if Table1.Modified thenif Application.MessageBox('Gravar alterações?','Dados Alterado',MB_ICONQUESTION + MB_YESNO) = IDYES thenTable1.PostelseTable1.Cancel

Obtendo o número serial do HDFunction SerialNum(FDrive:String) :String;Var Serial:DWord; DirLen,Flags: DWord; DLabel : Array[0..11] of Char; begin TryGetVolumeInformation(PChar(FDrive+':\'),dLabel,12,@Serial,DirLen,Flags,nil,0); Result := IntToHex(Serial,8); ExceptResult :=''; end; end;

BANCO DE DADOSSENHAS// Senha usadas na maioria dos programasNo Campo Var, Digite :Contador : integer;Vs : stringEm Usues, Digite : DB;No botão Ok, digiteif not Table1.FindKey([edit1.Text]) then // o campo chave é NomebeginShowMessage('UsuárioDesconhecido');inc (contador);if contador = 4 thenbeginShowMessage(‘ Sua chance acabou');FmPrincipal.Close;end;Exit; (* para encerrar *)end;vs:=Table1.findField(‘Login’).asString;if vs<>Edit2.text thenbeginShowMessage('Senha Errada');inc(contador);if contador=4 thenfmPrincipal.close;Edit2.setFocus;exit;end;

Page 119: dicas para delphi

fmPrincipal.Enabled:=True;fmSenha.close;

Criando TabelasAtravés da função FieldDefs.ADD. Parâmetros: nome do campo, tipo, Tamanho, Chave_Primária.Procedure Cria_Tabela(Alias,Nome_Tabela:String);BeginWith TTable.Create(Application) do beginActive := False;DatabaseName :=Alias; TableName := Nome_Tabela;;TableType := ttDefault;FieldDefs.Add('CODCLI', ftString, 5, False);FieldDefs.Add('NOMCLI', ftString, 40, False);FieldDefs.Add('DATCAD', ftDate, 0, False);CreateTable;Free;end;end;

Como Usar:procedure TForm1.Button1Click(Sender: TObject);beginCria_Tabela('C:\Temp','Alunos.db');end;

LOCALIZAR//nesta caixa de diálogo, o campo nome tem que ser o primeirovar // uma variárvel tem que ser criada.nome : string;

Nome : = inputbox( ' Localizar ' , ' digite o nome ' , ' ' ) ;if nome <> ' ' thenbeginif not table1.findkey ( [ nome ] ) thenshowmessage ( ' nome não encontrado ' ) ;end;Simplificando: Table1.findkey([edit1.text])

outable1.setkey; table1.fields[0].AsString := Edit1.text;Table1.GotoKey;

Apenas a linha abaixo :Table1.FindKey([Edit1.Text]);Apenas a linha abaixo :Table1.FindNearest([Edit1.Text]);Table1.SetKey; // Primeiro campo é a chaveTable1.FieldName('Cidade') := Edit1.Text;Table1.GotoKey;

Table1.IndexName := 'NomeCliente'; // procurar em um índice secundárioTable1.Open;Table1.SetKey;

Page 120: dicas para delphi

table1NomeCliente.AsString := Edit1.Text;Table1.GotoNearest;.// Procurar em um índice primário ou secundárioTable1.IndexName := 'Nome'Table1.Open;Table1.SetKey;Table1Nome_Cliente.AsString := Edit1.Text;Table1.GotoNearest;

Locate// procura em um índice primário ou secundárioTable1.Locate('Nome',Trim(Edit1.text),[LoPartialKey,loCaseInsensitive]);if not DM.Table1.Locate('Vendedor;Data',VarArrayOf([EditVendedor.text, EditData.text]),[loCaseInsensitive]) thenShowMessage('O vendedor não realizou venda nesa data');

FindKey //Procura um nome em um campo. ( no primeiro campo ).// No evento OnClick do Botão Ok, digitebeginif not DataModule.tsenha.FindKey ( [ editNome.text ] ) thenbeguinShowMessage ( ' senha desconhecida ' );Exit;end ;

ExceçõesAccess violationDecrare a constante:constChaveViolada = 9729;No evento OnPostError da tabela, digite:if (E is EDBEngineError) thenif (E as EDBEngineError).Error[0].Errorcode = ChaveViolada thenbeginTable1.Cancel;ShowMessage('este código já existe');end;abort

Outras exceçõesif(E is EDBEngineError) thenwith EDBEngineError(E) docase Errors[0].ErrorCode ofDBIERR_KEYVIOL: ShowMessage('Cliente já cadastrado.');DBIERR_REQDERR: ShowMessage('Campo obrigatório não preenchido.');endelseShowMessage('Erro no banco de dados:' + #13#13 + E.Message);Action := daAbort;

0 SQL //Seleciona todos os campos da tabela clienteSelect * from cliente

Page 121: dicas para delphi

//Selecione todos os campos da tabela cliente e produtoSelect * from cliente, produto

//Selecione o campo nproduto da tabela produtoSelect Nproduto form produto

//Selecione os campos nproduto e descrição da tabela produtoSelect nprodutos, descrição from produto

//Selecione todos os campos da tabela produto onde nproduto seja igual a 004Select * from produto where nproduto = 004

//Selecione os campos descrição e preço produto onde nprodutoseja igual a 004Select descrição, preço from produto Where nproduto = 004

//Selecione todos os campos da tabela cliente onde nclienteseja maior que 01 e menor que 04Select * from cliente where ncliente > 01 and ncliente < 04

//Exibir seus dados em ordem ascendente (A a Z, 0 a 9). SELECT Sobrenome, Nome FROM Funcionários ORDER BY Sobrenome;SELECT Sobrenome, Nome FROM Funcionários ORDER BY Sobrenome ASC;

//Selecione todos os campos da tabela cliente organizadopor nomeSelect * form cliente order by nome

//Selecione os campos nprodutos e descrição da tabela produto organizado por descriçãoSelect nProdutos, descrição from produto order by descrição

//Selecione todos os campos da tabela produto organizado por nproduto em ordem descendenteSelect * from produto order by nproduto desc

//Classificar em ordem descendente (Z a A, 9 a 0), adicione a palavra reservada DESC ao final de cada campoSELECT Sobrenome, Salário FROM Funcionários ORDER BY Salário DESC, Sobrenome;

//Esse exemplo ordena os registros pelo sobrenome, em ordem descendente (Z-A).SELECT Sobrenome, Nome FROM Funcionários ORDER BY Sobrenome DESC;

//Esse exemplo ordena, primeiro, por categoria ID e depois por nome do produto.SELECT CategoriaID, ProdutoNome, PreçoUnit FROM Produtos ORDER BY CategoriaID, NomeProduto;

//Selecione os campos descrição, preço e o valor de preço + 20 de tabela produto onde nproduto = 004Select descrição, preço, preço + 20 from produto where nproduto = 004

//Selecione todos os campos da tabela Leitores onde o campo nome seja iguas a 'João'Select * from Leitores where Nome = 'João Cabral'

//Selecione todos os campos da tabela cliente onde o campo nome inicie com Vis* desprezando os outros caracteresSelect * from cliente where nome LIKE 'Vis%'

//Selecione todos os campo da tabela leitor onde o campo CPF é nuloSelect * from Leitor where CPF is Null

Select nproduto + '', '' + descrição AS Itens, preço from produto

Page 122: dicas para delphi

Selecione nproduto + '', '' + descrição AS Itens, preço (junte os campos como Itens) da tabela produto

//Qual seria o salário se cada funcionário recebesse um aumento de 10 porcento. Não altera o valor original dos salários.SELECT Sobrenome, Salário AS Atual, Salário * 1.1 AS Proposto FROM Funcionários;

//Coloca o título Nome no topo da coluna "Sobrenome". O título Salário, no topo da coluna "Salário".SELECT Sobrenome AS Nome, Salário FROM Funcionários;

Select nproduto from pedido/ produto where nPedido = 1Select nproduto from pedido / produto where nProduto = 2Select nproduto from pedido / produto where npedido = 1 UNION ALL Select nproduto From pedido/ produto where nProduto = 2

Select * from pedido where nproduto beteeen 2 and 5Selecione todos os campos da tabela pedido onde o campo nproduto esteja entre 2 e 5

Selecione todos os campos da tabela pedido onde o campo npedido esteja entre 2 e 5Select * from pedido where nproduto IN ( 2,5 )

Select DISTINCT * from pedido/produtoSelecione retirando as duplicatas do campo nproduto da tabela pedido/produto

Select TOP 3 from produtoSelecione os primeiros 3 registros da tabela produto

Select Ucase ( descrição) from produtoSelecione ( descrição ) o campo descrição em maiúsculo da tabela produtoSelect COUNT ( * ) as quantidade from produto where preço > 50,00

//Conta o número de registros que têm uma entrada no campo "CódigoPostal" e nomeia o campo retornado como "Tcp".SELECT Count(CódigoPostal) AS Tcp FROM Clientes;

Selecione o campo descrição em maiusculo da tabela produtoSelect SUM ( quantidade) from pedido/produto where nproduto = 1Selecione a soma do campo soma da tabela pedido/produto onde nproduto= 1Select min ( quantidade ) from pedido/ produto Selecione a menor quantidade do campo quantidade da tabela pedido / produto: pedido/produto

Select MAX ( quantidade ) from pedido / produto

//Seleciona Departamento da tabela Funcionários e NomeSupv da tabela Supervisores: SELECT Funcionários.Departamento, Supervisores.NomeSupv FROM Funcionários INNER JOIN Supervisores WHERE Funcionários.Departamento = Supervisores.Departamento; //O exemplo abaixo usa o título Nasc para nomear o objeto Field retornado no objeto Recordset resultante: SELECT DataNasc AS Nasc FROM Funcionários;//O exemplo abaixo usa o título Contagem para nomear o objeto Field retornado no objeto Recordset resultante:SELECT COUNT(FuncionárioID) AS Contagem FROM Funcionários;

SELECT CategoriaID, Sum(UnidadesNoEstoque) FROM Produtos GROUP BY CategoriaID HAVING Sum(UnidadesNoEstoque) > 100 AND LIKE "BOS*";

// O exemplo abaixo habilita o usuário a ver as informações de salário (mesmo que não tenha outra permissão para ver a tabela Folha de Pagamentos) desde que o proprietário da consulta tenha tal permissão:SELECT Sobrenome, Nome, Salário FROM Funcionários ORDER BY Sobrenome WITH OWNERACCESS

Page 123: dicas para delphi

OPTION;

//O número de funcionários e os salários médio e máximo.SELECT Count(*) AS [Total de Funcionários], Avg(Salário) AS [Salário Médio], Max(Salário) AS [Salário Máximo] FROM Funcionários;

//Para cada registro, mostra Sobrenome e Salário no primeiro e último campos. A seqüência de caracteres "tem um salário de" é retornada como o campo do meio de cada registro.SELECT Sobrenome, 'tem um salário de', Salário FROM Funcionários;

//Cria uma lista de nomes de departamentos únicos e o número de funcionários em cada um destes departamentos.SELECT Departamento, Count([Departamento]) AS Tbc FROM Funcionários GROUP BY Departamento;

//Para cada título de função único, calcula o número de funcionários do departamento de Vendas que têm este título.SELECT Título, Count(Título) AS Tbc FROM Funcionários WHERE Departamento = 'Vendas' GROUP BY Título;

//Calcula o número de itens em estoque para cada combinação de número e cor do item. SELECT Item, Sum(Unidades) AS Tbc FROM ItensEmEstoque GROUP BY Item, Cor;

//Seleciona os títulos de cargos do departamento de Produção atribuídos a mais de 50 funcionários.SELECT Título, Count(Título) FROM Funcionários WHERE Departamento = 'Produção' GROUP BY Título HAVING Count(Título) > 50;

//Esse exemplo seleciona os departamentos que tenham mais de 100 funcionários.SELECT Departamento, Count([Departamento]) FROM Funcionários GROUP BY Departamento HAVING Count(Departamento) > 100;

//Seleciona todos os registros de "Novos Clientes" e os adiciona à tabela "Clientes" (quando não são designadas colunas individuais, os nomes das colunas das tabelas SELECT devem corresponder exatamente aos da tabela INSERT INTO).INSERT INTO Clientes SELECT [Novos Clientes].* FROM [Novos Clientes];

//Esse exemplo cria um novo registro na tabela "Funcionários"INSERT INTO Funcionários (Nome,Sobrenome, Título) VALUES ("André", "Pereira", "Estagiário");

Seleciona todos os estagiários de "Estagiários" que foram contratados há mais de 30 dias e adiciona seus registros à tabela "Funcionários".INSERT INTO Funcionários SELECT Estagiários.* FROM Estagiários WHERE DataContrato < Now() - 30;

//Aumenta o Valor do Pedido em 10 % e o valor do Frete em 3 % para embarques do Reino Unido: UPDATE Pedidos SET ValorPedido = ValorPedido * 1.1, Frete = Frete * 1.03 WHERE PaísEmbarque = 'RU';

//Muda os valores no campo "RelatórioPara" para 5 para todos os registros de funcionários que atualmente têm valores de RelatórioPara de 2.UPDATE Funcionários SET RelatórioPara = 5 WHERE RelatórioPara = 2;

//Aumenta o "PreçoUnit" de todos os produtos não suspensos do fornecedor 8 em 10 porcento.UPDATE Produtos SET PreçoUnit = PreçoUnit * 1.1 WHERE FornecedorID = 8 AND Suspenso = No;

//Reduz o PreçoUnit de todos os produtos não suspensos fornecidos pela Tokyo Traders em 5 porcento. As tabelas "Produtos" e "Fornecedores" têm uma relação um para vários.UPDATE Fornecedores INNER JOIN Produtos ON Fornecedores.FornecedorID = Produtos.FornecedorID SET PreçoUnit = PreçoUnit * .95 WHERE NomeEmpresa = 'Tokyo Traders' AND Suspenso = No;

Page 124: dicas para delphi

//Exclui todos os registros de funcionários cujo título seja Estagiário. Quando a cláusula FROM inclui apenas uma tabela, não é necessário indicar o nome da tabela na instrução DELETE.DELETE *FROM Funcionários WHERE Título = 'Estagiário';

//Exclui todos os registros de funcionários cujo título seja Estagiário e que também tenham um registro na tabela "FolhadePagamento". As tabelas "Funcionários" e "FolhadePagamento" têm uma relação um por um.DELETE Funcionários.* FROM Funcionários INNER JOIN FolhaDePagamento ON Funcionários.FuncionárioID = FolhadePagamento.FuncionárioID WHERE Funcionários.Título = 'Estagiário';

//Retorna todos os produtos cujo preço unitário é maior que o preço de qualquer produto vendido com um desconto de 25 % ou mais: SELECT * FROM Produtos WHERE PreçoUnit > ANY (SELECT PreçoUnit FROM PedidoDetalhes WHERE Desconto >= .25);

//Retorna todos os produtos com um desconto de 25 % ou mais: SELECT * FROM Produtos WHERE ProdutoID IN (SELECT ProdutoID FROM PedidoDetalhes WHERE Desconto >= .25);

//Retorna os nomes dos funcionários cujos salários sejam iguais ou superiores à média de salários de todos os funcionários na mesma função. Para a tabela Funcionários é dada o alias "T1":SELECT Sobrenome, Nome, Título, Salário FROM Funcionários AS T1 WHERE Salário >= (SELECT Avg(Salário) FROM Funcionários WHERE T1. T1.Título = Funcionários.Título) Order by Title;

//Lista o nome, título e salário de todos os representantes de vendas cujos salários sejam superiores aos de todos os gerentes e diretores.SELECT Sobrenome, Nome, Título, Salário FROM Funcionários WHERE Título LIKE "*Repr Vendas*" AND Salário > ALL (SELECT Salário FROM Funcionários WHERE (Título LIKE "*Gerente*") OR (Título LIKE "*Diretor*"));

//Lista o nome e preço unitário de todos os produtos cujo preço unitário seja igual ao do Licor de Cacau.SELECT NomeProduto, PreçoUnit FROM, Produtos WHERE PreçoUnit = (SELECT PreçoUnit FROM [Produtos] WHERE NomeProduto = "Licor de Cacau");

//Lista a empresa e o contato de cada empresa de todos os clientes que fizeram pedidos no segundo trimestre de 1995.SELECT NomeContato, NomeEmpresa, ContatoTítulo, Fone FROM Clientes WHERE ClienteID IN (SELECT ClienteID FROM Pedidos WHERE DataPedido BETWEEN #1/04/95# AND #1/07/95#);

//Lista os funcionários cujo salário seja maior que a média dos salários de todos os funcionários.SELECT Sobrenome, Nome, Título, Salário FROM Funcionários T1 WHERE Salário >= (SELECT AVG(Salário) FROM Funcionários WHERE Funcionários.Título = T1.Título) ORDER BY Título;

//Seleciona o nome de todos os funcionários que tenham registrado pelo menos um pedido. Isto também poderia ser feito com INNER JOIN.SELECT Nome, Sobrenome FROM Funcionários AS E WHERE EXISTS (SELECT * FROM Pedidos AS O WHERE O.FuncionárioID = E.FuncionárioID);

//Altera o campo Efetuado do arquivo de serviços para 2 caso o mesmo tenha parecer técnico da entidade encaminhanhamento diferente de nulo.UPDATE servico SET efetuado = 2 WHERE numero_servico = ANY (SELECT servico.numero_servico FROM servico INNER JOIN encaminhamento ON (servico.numero_servico = encaminhamento.

Page 125: dicas para delphi

numero_servico) AND (servico. ano_servico = encaminhamento.ano_servico) WHERE (((servico.efetuado) Is Null) AND ((encaminhamento.parecer_tecnico) Is Not Null))GROUP BY servico.numero_servico ORDER BY servico.numero_servico);

Query - Parametros// digitar no SQL do query{ Select * from geral where Nome like :ordNa properties Params colocar : Name := Ord, Value := %}

Fieldsvar s : string;begins := Table1.Fields [0].FieldName; //retorna o nome do primeiro campo da tabelas := Table1.Fields [1] .asString; // retorna o conteúdo 2º campo da tabelas := Table1.FieldByName( ' nome ' ).AsString; //retorna o valor na coluna 'nome's := Table1['Nome'] ; //retorna o valor do compo selecionado

Label1.Caption := s ; // retorna o valor da string

Indexar uma TabelaTable1.IndexFieldNames := 'Nomecli';Table2.IndexFieldNames := 'Data, Vendedor';

ListBox// esta rotina exibe em um listbox os campos de uma tabelavari: Integer;beginListBox1.Clear;for i := 0 to table1.fieldcount - 1 doListbox1.items.add(table1.fields[i].fieldname);end;

//Faz um ListBox exibir o conteúdo de uma tabelavari: Integer;beginListBox1.Clear;for i := 0 to Table1.FieldCount - 1 doListBox2.Items.Add(Table1.Fields[i].AsString);end;

BOOKMARKS//guardar uma posição no registrovarBM :tBookMark;{...}// Grava um Registroif bm = nil then // se bm está vazio então...bm := table1.GetBookMark; // marque umouif BookMark = nil then BookMark := Table1.GetBookMark;{++}

Page 126: dicas para delphi

// ir para o registro guardadoif BookMark <> nil then // se o BookMark não está vazio...begin table1.GotoBookMark(BookMark) // vá para o marcadoend;ou..if BM <> nil thenbeginBM := table1.GetBookMark(BM);

{++}//limpa da memória o registro guardadoif BookMark <> nil then // se o BookMark não está vazio então faça..beginTable1.FreeBookMark (BookMark); // libere o marcado..BookMark := nil; // deixe-o vazioend;ouif bm <> nil thenbeginTable1.FreeBookMark (bm);bm := nil;end;// conjunto de comandosif BookMark < > nil thenbegintable1.GotoBookMark(BookMark);Table1.FreeBookmark(BookMark);BookMark := nil;end; Gravar em um banco de dadostabel1.edit;// abre o datasettabel1['senha'] := 'Marvel'; // edita 'Marvel' no campo senhatabel1.post; // grava a informação

FilterTable1.Filtered := false;Table1.Filter := 'idade > 30 ' ;(ex: Table1.Filter := 'Nota1>=' + '''' + Edit1.text + ''''';)Table1.Filtered := true;

Filter IITable1.SetRangeStart;Table1.FieldbyName('código') := 100;//Table1Codigo.AsInteger := 100Table1.KeyExclusive := False;Table1.SetRageEnd;Table1.FieldbyName('Codigo') := 200; //Table1Codigo.AsInteger := 200Table1.KeyExclusive := true;Table1.ApplyRange

// Aplicar um filtro usando um CHECKBOXTable1.Filtered := checkbox1.Checked;// No componente TABLE, no evento OnFilterRecordAccept := Table1['Nome']= Edit1.Text// Um botão pode seguir para o próximo ítem procuradoTable1.FindNext

Page 127: dicas para delphi

Soma// RecordCount, conta quantos registros ha na TabelaLabel1.Caption := InttoStr(Table1.Recordcount);

Os estados de um Data Baseif Table1.State = dsEdit thenbegin...Para saber o Estado de um DataBase. Digite no Evento OnStateChange do DataSourse:Var S : String; beginCase Table1.State ofdsInactive : S := 'Inativo';dsBrownse : S := 'Browse';dsEdit : S := 'Edição';dsInsert : S := 'Inserção';dsSetKey : S := 'SetKey';dsCalcFields : S := 'CalkFields';end;Label1.Caption := S;

//Para digitar só números em um editNo evento KeyPress, digite: if not (Key in['0'..'9',Chr(8)]) then Key:= #0;// Obs: Chr(8), para BackSpace e DecimalSeparator, para a vírgula dentro dos colchetes.AliasCriando um alias..Check(DBiAddAlias(Nil, Pchar('AliasName'),Nil, Pchar('AliasPath), true));AliasName = nome do alias;AliasPath = caminho do alias;Inclua em Uses = BDE e BD;

Criando um alias temporário// Utilizando o componente TSession// No evento OnShow, digite:session1.ConfigMode:=cmSession;Session1.AddStandardAlias('NomedoAlias','C:\Arquivos de Programas\Arquivos comuns\Borland Shared\Data','PARADOX');Table1.OPen;// No componete TTable, digite o nome do Alias e o nome da tabela

Atualizando as informações em ambiente de redeAcessando a mesma tabela concorrente com outra estação ou outro objeto Query, Tablea) Crie procedure para uso no evento OnActive:Procedue TTorm1.FormRefresh(Sender: TObject);beginTable1.Refresh;... TableN.Refresh;end;b)No evento OnActive do formulário acrescente a linha:Application.OnActive := FormRefresh;c) No evento OnShow do formulário acreste a linhaFormRefresh(Sender);d) No evento OnAfterPost de cada objeto TTable acrescente as linhas;Table.FlushBuffer;

Page 128: dicas para delphi

FormRefres(Self);

Salvando os Dados Fisicamente em uma TabelaUSES DBIProcs; Nos eventos OnAfterPost e OnAfterDelete, digite:DBISaveChanges(Table1.handle); Salvando Os dados Visicamente II USES BDE:DbiSaveChandges((Dataset as TTable).Handle);O DBNavigator//Para pegar o nome do botão que foi pressionadoDBNavigator1.BtnClick(nbNext);

// pegando o botão clicadoif Button in [nbFirst,nbLast,nbPrior,nbNext] then DBNavigator.DataSource.DataSet.Refresh;

MULTIMIDIAImagem no FormColocar uma figura bmp, no form sem o PicturevarBitMap : TBitMap;BeginBitMap : = TBitMap.Creat ;With BitMap doBiguinLoadFromFile( ' c : \ figura . bmp' ) ;Transparent := true ;Form1. Canvas . Draw (50,50, bitMap);end:end; //Desktop, imagem no form//Procedure TForm E. FormResize(Sender: tobject);Var R : TRect ;DC : HDc ;Canv : TCanvas ;BeginR : = Rect (0,0, Screen.Width, Screen.Height);DC : = GetWindowDC (GetDeskTopWindow);Canv := TCanvas.Create;Canv . Handle := DC;Canvas . CopyRect(R,Canv,R);ReleaseDC (GetDeskTopWindow, DC);end;

CopyFile, para copiar arquivosCopyFile(pchar('c:\conto.txt'),('a:\conto.txt'),false);// no final: true=não regrava o arquivo, se false, ele regrava.

A Tecla Pressionada//No evento OnKeyDown, digite:Label1.Caption := Format('O código da tecla é: %d', [Key]);

O componente TMediaPlayer

Page 129: dicas para delphi

Para ouvir um som With MediaPlayer1 dobeginFileName := 'c:\bettoven.wav'; // pode ser um MidOpen;Play;end;

Para ver um *.avi no form...with MediaPlayer1 dobeginFileName := 'c:\super.avi';Open;Display := Form2;Form2.Show;Play;end;

Arquivos TextoCarregando o texto em um RichEditRichEdit1.Lines.LoadFromFile('c:\aviso.txt');//colocando coresReachEdit1.Font.Color := clGreen;Estilos de Texto//testo em negritoif CheckNegrito.Checked then //Para o botão NegritoMemo1.Font.Style := Memo1.Font.Style + [fsBold] // coloca em estilo negritoelseMemo1.Font.Style := Memo1.Font.Style - [fsBold]; // retira o estilo negrito//Memo1.Font.Style := Memo1.Font.Style + [fsItalic] // Para o botão Itálico//Memo1.Font.Style := Memo1.Font.Style + [fsUnderline] // Para o botão Sublinhado

//testo em negrito IIif BoldButton.Down thenCurrText.Style := CurrText.Style + [fsBold]elseCurrText.Style := CurrText.Style - [fsBold];end;function TMainForm.CurrText: TTextAttributes;beginif Editor.SelLength > 0 then Result := Editor.SelAttributeselse Result := Editor.DefAttributes;end;

Alinhamento do texto{taLeftJustify, taCenter, taRightJustify}Label1.Alignment := taLeftJustify;Trabalhando com Arquivos .INIAcrescente a unit inifiles na guia uses//declare uma variável inifile:ArqIni: TIniFile;//no evento OnCreate, do form, digite:ArqIni := TIniFile.Create('c:\windows\ArqIni.ini');lendo um arquivo ini// lendo um valor string:EditString.Text := ArqIni.ReadString('String', 'texto', '');

Page 130: dicas para delphi

//lendo um valor inteiro:EditString.Top := ArqIni.ReadInteger('Integer', 'altura', 0);//lendo um valor booleanEditString.Visible := ArqIni.ReadBool('Boolean', 'visivel',False);//lendo um arquivo ini em um meno:Memo1.Lines.LoadFromFile('c:\inicial.ini');gravando em um arquivo .ini//gravando um valor stringArqIni.WriteString('String', 'texto', EditString.Text);//gravando um valor inteiroArqIni.WriteInteger('Integer', 'altura', SpinEdit1.value);// gravando um valor booleanArqIni.WriteBool('Boolean', 'visivel', CheckBox1.Checked);

//no evento OnDestroy, do form, libere o nosso arquivoArqIni.Free;

Movimentofazer um panel ter seu texto em movimentovar texto : string;begintexto : = panel1.caption;panel1.caption := copy(texto,2,length (texto)) + texto[1];end;

ColorGridForm1.Color := ColorGrid1.ForegroundColor ; //botão esquerdo do mouseForm1.Color := ColorGrid1.BackgroundColor ;// botão direito do mouse

Movendo Arquivosvarorigem, destino : string;beginorigem := 'c:\delete\faq.txt';destino:= 'c:\games\faq.txt';if not copyfile(pchar(origem),pchar(destino),true) thenshowMessage ( 'problemas com' + origem + 'para' + destino)

MOVENDO UM OBJETO// Coleque em um objeto ( ex: um Button) // Na guia VAR, digiteMouseDownSpot : TPoint;Capturing : bool;// No evento OnMouseDownSetCapture(Button1.Handle);Capturing := true;MouseDownSpot.X := x;MouseDownSpot.Y := Y;// No evento OnMouseMoveif Capturing thenbeginButton1.Left:= Button1.Left-(MouseDownSpot.x -x);Button1.Top:= Button1.Top - (MouseDownSpot.y -y);end;// No evento OnMouseUp

Page 131: dicas para delphi

if Capturing thenbeginReleaseCapture;Capturing := false;Button1.Left := Button1.Left - (MouseDownSpot.x -x);Button1.Top := Button1.Top - (MouseDownSpot.y - y);end;

Arquivos Help// digite a linha abaixo para chamar um arquivo helpWinHelp(Form1.handle, 'c:\Ajuda.hlp', HELP_CONTENTES,0);

Randomize//A linha de comando abaixo faz o label exibir aleatóriamente um número de 1 a 100Label1.Caption := InttoStr(Random(100));

Hint//colocar no evento OnCreate do form principal..Application.HintColor := clYellow; // define a cor de todos os hintsApplication.HintPause := 200; // define o tempo de espera de um hintbtnOk.ShowHint := true; // habilita a exibição de um hintbtnOk.Hint := 'Clique aqui';// define o textoEdit1.hint := 'Primeira linha' + #13 + 'segunda linha';//Hint com quebra de linha

Criar um componente em tempo de execuçãovarPictImg1 : TImage;//declarando um TImagebeginPictImg1 := tImage.Create(self);PictImg1.Height := 200;pictImg1.Width := 200;PictImg1.Picture.LoadFromFile('C:\1.bmp');PictImg1.parent := Self;end;

Cores com RGB//o form abaixo recebe a cor composta por:" red, green e blue"Form1.Color := Rgb(100, 100, 100);

Progess BarCriando um ProgressBar em tempo de execução//Declare a procedure abaixoprocedure TestProgress(Form: TForm; Count: SmallInt);varProgressBar1: TProgressBar;i: SmallInt;beginProgressBar1 := TProgressBar.Create(Form);tryProgressBar1.Parent := Form;ProgressBar1.Align := alBottom;ProgressBar1.Min := 0;ProgressBar1.Max := Count;ProgressBar1.Step := 1;for i := 1 to Count doProgressBar1.Stepit;

Page 132: dicas para delphi

ShowMessage('Now the ProgressBar control will be freed');finallyProgressBar1.Free;end;end;Finalmente, facha a chamada para o ProgessBar...TestProgress(Self, 1000);form2.show;

O Componente TCalendarCalendar1.PrevYear;//para exibir o ano anteriorCalendar1.NextYear;//para exibir o proximo anoCalendar1.PrevMonth;//para exibir o mês anteriorCalendar1.NextMonth;//para exibir o próximo mêsCalendar1.CalendarDate := CalendarDate - 1;// vai para um dia anteriorCalendar1.CalendarDate := CalendarDate + 1;// vai para o proximo dia

Arquivos .iniAcresentar em Uses: IniFiles;Declare:Tini : TInifile;Criando do arquivo. No evento OnCreate:Tini := TInifile.Create('c:\super.ini'); Lendo em um arquivo...Label1.Caption := Tini.ReadString('Label','titulo','');Label1.top := Tini.ReadInteger('Label','top',0);Label1.visible := Tini.ReadBool('Label','ver',true);

Gravando em um arquivo...Tini.WriteString('label','titulo','Olá Mundo');Tini.WriteInteger('label','top',10);Tini.WriteBool('label','ver',true);

Ao findar tudo...IniFile.Destroy;

Dias da semanavarWeekDay : array[1..7] of string;DayNo : integer;QDay : string;beginweekday[1] := 'domingoweekday[2] := 'segunda';weekday[3] := 'ter‡a';weekday[4] := 'quarta';weekday[5] := 'quinta';weekday[6] := 'sexta';weekday[7] := 'sabado'; DayNo := DayofWeek(Date); // pega numero do dia da semana..// a mensagem exibe o valor do array na posi‡Æo n. da semanaShowMessage('O dia ‚: ' + WeekDay[DayNo]);

Verificando os dígitoso do anoFunction AnoQuatroDigitos: Boolean;beginResult := (Pos('yyyy',SHortDateFormat)>0);

Page 133: dicas para delphi

if Result = True thenShowMessage('O ano esta configurado para quatro dígitos.')elseShowMessage('O ano não esta configurado para quatro dígitos.'); end;

Trabalhando com Frames// No menu File>New, insira um TFrame. Declare em { Private declarations }FFrame: TFrame;// Dois botões usando a mesma variável do frame...// botão um..if FFrame <> nil thenFFrame.Free;FFrame := TFrame1.Create(pnlParent);FFrame.Align := alClient;FFrame.Parent := pnlParent;

// botão dois..if FFrame <> nil thenFFrame.Free;FFrame := TFrame2.Create(pnlParent);FFrame.Align := alClient;FFrame.Parent := pnlParent;

Jogar uma imagem direto para um campo na tabelavarBMP : TBitMap;beginBMP := TBitmap.Create;if OpenPicutrueDialog1.Execute thenbeginBMP.LoadFromFile(OpenPictureDialog1.FileName);Table1Graphic.Assign(BMP);end;TPrinter//Uses PrintersBiginDoc = inicia uma impressãoEndDoc = finaliza uma impressãoAbrot = interrompe a impressãoPriting = para saber se esta havendo uma impressãoprinters = lista as impressoras instaladasPrinterIndex = indica a impessora selecionadaFonts = lista as fontes da impressoraOrientation ( em Portrait ou LandScape) = orientação do papelPageHeight = Altura da páginaPageWidth = Largura da páginaPageNumber = Número da página atual

INTERNET

Para executar um página da Web IWinexec ( 'start c:\windows\index.html',sw_ShowMinimized )

Page 134: dicas para delphi

Para executar um página da Web IIShellExecute(Handle, 'open', HTMLFile, nil, nil, SW_SHOWNORMAL); Chamando um site utilizando o seu browse padrão. Coloque em USES:UrlMon;HlinkNavigateString(nil, 'http://www.geocities.com/escolarte'); //Verificando se você está conectado a Internet//Inclua um componente TCP no Form, e digite o código:if (TCP1.LocalIP = '0.0.0.0' or TCP1.LocalIP = '127.0.0.1') then ShowMessage('Não existe conexão') else ShowMessage('Existe Conexão')

Page 135: dicas para delphi

Original : http://www.drbob42.com/delphi4/actions.htm

A new and handy feature of Delphi 4 - also present in C++Builder 4 by the way - is the TActionList component, found in the "Standard" tab of the component palette. With an ActionList, we can group and manage "actions" (event handling code) between different components and even re-use them among different applications! This article shows how to use Actions and ActionLists - without writing a single line of Delphi or C++ code - and contains some nice gotchas too...

Using TActionListStart a new application, and drop a TActionList component on the Form. Right-click with the mouse on the ActionList1 component to get the Action List Editor. The Action List Editor shows the action categories, and for each action category the individual actions that are available for the current application. We can define new actions, or select a number of existing (standard) actions. The latter can be done by right-clicking with the mouse in the Action List Editor, and selecting the New Standard Action menu:

This will give us a new dialog with the (current) list of standard actions. Note that we can select more than one action at the same time by holding down the Ctrl key and clicking on each individual item (see left figure below).

Page 136: dicas para delphi

After we click on OK, we return to the Action List Editor which now shows two categories (Edit and Window) and four actions in total (Copy, Cut and Paste for the Edit categories, and MinimizeAll for Windows) - see right figure above. It's now time to add some controls to the Form and connect them to these actions.

Control ActionGo to the Win32 tab of the component palette, and drop a ToolBar component on the form. Right-click on it and select "New Button" to add a new button. Repeat this until you have four buttons next to each other on the toolbar (tip: you may want to insert a separator between the third and fourth button). Now, click the left button, and set its Action property to EditCopy1. Set the Action property of the second button to EditCut1, and the third button to EditPaste1. Finally, set the Action property of the last button to WindowMinimizeAll1. Before we compile and run this application, let me remind you that we now have four fully functional toolbar buttons without having written a single line of code. That's because we're using standard behavior that's already been provided to us as "standard" re-usable Actions. But it gets even better, because we can share these actions with multiple components. Go back to the Standard tab of the component palette, and drop a TMainMenu component on the Form. Double-click on it (to get into the Menu Designer). Right-click on the Menu Designer select "Insert from Template" and pick the Edit menu template. This gives us a list of 10 menu items, while we only need three (Cut, Copy and Paste), but at least it saves us some typing. You can easily remove the menu items that you don't need, by the way. Go to the Cut1 menu item, and set its Action property to EditCut1. Set the Action property of the Copy1 menu item to EditCopy1, and let Paste1 point to EditPaste1. We're now almost ready to compile and run our application, but we need one more thing. Let's drop three normal buttons on the form (again from the Standard tab), and connect them to EditCut1, EditCopy1 and EditPaste1 like we've done twice before already. Note that the "regular" buttons automatically get captions with "Cut", "Copy" and "Paste", where the speedbuttons on the ToolBar remain empty (their Hint property it set, but not their caption).

Page 137: dicas para delphi

A solution to this potential (confusing) problem can be implemented by assigning an ImageList to the ActionList, so each action can get associated with a specific image. To do this, drop a TImageList (from the Win32 tab) on the Form, and right-click on it to fill it with some images. Set the Images property of the ActionList a component to ImageList1, and double-click again on the ActionList to get the Action List Editor where we can now specify which image should be used by which individual Action item by setting the ImageIndex for each individual action:

Note that the speedbuttons on the toolbar and the images next to the menu texts still don't show the images from the ImageList1 at design-time. In order to let them "share" the same images, we must set the Images property of the ToolBar1 component to ImageList1, and do the same with the Images property of the MainMenu1 component. The ImageIndex properties will now be copied from the index belonging to the Action components, so each action will look the same on a speedbutton or as a menu-item. The really final thing we need to do is drop a TEdit component on the Form (after all, we would need some Edit control to test the Cut, Copy and Paste actions with, right?). After that, your application should resemble the following screenshot (at least a little bit, I hope):

Page 138: dicas para delphi

Action!Now, save your work, compile and run the application. Initially, all buttons and menu-items will be disabled, meaning that we cannot Cut or Copy text, nor can we Paste any text at this time. If your clipboard is filled with some text, and you select the editbox, then the Paste buttons and menu-item get enabled automatically (at the same time). We can then select the Paste menu, for example, and the text from the clipboard will be pasted inside the editbox. As soon as we select some text from the editbox, the Cut and Copy buttons and menu-items will get enabled as well (we can only Cut and Copy selected text, of course). We can now click on the Cut or Copy speedbutton in the toolbar to get the effect we want. Note that each Action items somehow "knows" when it can be executed (in our case: when the current control is an editbox or memo, and - in case of Cut and Copy - whether or not any text is currently selected). The Action items can enable and disable all controls that are associated with them as soon as something changes that influences them (like selecting text, or moving the focus from the editbox to another control, for example).

Problems?This all seems to work fine. However, if you try to Cut, Copy or Paste text inside the editbox using any of the "normal" buttons, then you will find that they do not appear to work. For some reason, the big Cut button doesn't cut the text, nor does the bit Paste button paste it. In fact, they only seem to result in de-selecting the text in the editbox (if any text was selected), and moving the focus away... Strange! Well, that last piece of information, regarding the focus, should have been a subtle hint: the buttons take away the focus before the Action can be executed. In other words: the Action expects an editbox to have the focus, but by the time the Action it executed, it's the button that has the focus (if not for the Button's Click method that fires the action, the action wouldn't even have been fired, since giving the button the focus means disabling the action and all controls associated with the action). Of course, the workaround is never to use any controls that can get the focus (like a TButton which has a Windows handle), so the focus will never be list when we click on any Action-bound control again. This is not something that's documented too well, however, and I must admit that even I fell into this trap (while performing my Delphi 4 Workout in London, by the way), so be aware.