você está determinando que todas as vezes que
o procedimento Esperar for chamado, deverá ser passado um valor do tipo
Byte. No entanto, esse tipo de declaração exige que em todas as chamadas ao
procedimento Esperar seja especificado um parâmetro. Se você fizer uma
chamada do tipo:
procedure TForm1.Button1Click(Sender: TObject);
begin
Esperar()
end;
será gerado um erro do tipo: Not enough
actual parameters. Mas você pode declarar e implementar o procedimento da
seguinte forma:
procedure Esperar(Segundos: Byte = 1);
begin
Sleep(Segundos * 1000);
end;
A declaração acima faz com que o procedimento
Esperar assuma o valor 1 caso nenhum parâmetro seja passado. Assim você
poderá fazer uma chamada ao procedimento em qualquer das situações abaixo:
procedure TForm1.Button1Click(Sender: TObject);
begin
Esperar(); // nenhum parâmetro, será assumido o valor 1
Esperar(1);
Esperar // nenhum parâmetro, será assumido o valor 1
end;
O uso do componente TQuery gera
muitas vantagens e economiza muitas linhas de programação. Mas muitas vezes
nos deparamos com situações que parecem não ser resolvidas com sentenças
SQL. Vejamos um exemplo:
Você possui 2 tabelas (VendasExternas
e VendasInternas) e deseja fazer um resumo de todas as vendas de um vendedor
chamado Marcos. Se você usar a sentença
SELECT Nome, Valor FROM
VendasExternas, VendasInternas
WHERE Nome = 'Marcos'
você vai obter como resultado uma
query com 4 campos (Nome, Valor, Nome_1 e Valor_1) e um resultado bem confuso
para ser manipulado.
Para resolver o problema, você
poderá usar a sentença
SELECT Nome, Valor FROM
VendasExternas
WHERE Nome = 'Marcos'
UNION ALL
SELECT Nome, Valor FROM VendasInternas
WHERE Nome = 'Marcos'
A sentença acima pede para que
sejam identificados as vendas de Marcos na tabela VendasExternas, as vendas de
Marcos na tabela VendasInternas e que o resultado da primeira seja unido com o
resultado da segunda produzindo uma query com apenas 2 colunas.
É comum fazermos uso do evento
OnExit quando queremos validar o conteúdo de um Edit. E essa pode ser uma boa
prática quando necessitamos verificar o que foi digitado apenas quando o
usuário terminar de fazer a entrada de dados, como, por exemplo, um Edit que
vai receber o CPF ou CNPJ.
Ao colocarmos um código qualquer
no evento OnExit ele sempre será executado quando o usuário sair do Edit, o
que acontece quando ele pressiona a tecla TAB, clica com o mouse em um outro
Edit ou pressiona um botão OK, por exemplo.
Mas existe uma maneira fácil de
resolver o problema. Basta você cancelar o foco e forçar uma reentrada no
componente Edit2. Como fazer isso? Veja o código:
procedure TForm1.Edit1Exit(Sender: TObject);
begin
MessageDlg('Mensagem...', mtInformation, [mbOk], 0);
// cancela o foco e força novamente a entrada
ActiveControl := nil;
PostMessage(Edit2.Handle, WM_SETFOCUS, 0, 0);
Edit2.SetFocus;
end;
Mas se você executa uma query onde deseja
somar as vendas internas e externas (aqui representadas pelos campos VendInt e
VendExt) você deve executar a seguinte query:
Observe que houve a soma apenas dos registros
onde não existem o valor NULL.
Veja agora como evitar o problema. Abra a
tabela Vendas.db e onde não existe valores definidos para os campos VendInt e
VendExt, entre com 0 (zero). A tabela deverá ficar assim:
Normalmente a linguagem SQL possui
flexibilidade o bastante para você obter os mais variados resultados de
seleção de registros.
Acontece que eventualmente você pode chegar a
uma situação onde precisaria construir uma query com base no resultado de
outra query. AÃ complica, certo?
Mas nestes caso você vai usar algumas API's do BDE e
o problema se tornará uma tarefa bem simples. Veja como:
Vamos imaginar uma query simples, apenas para
efeito de entendimento desta questão: Você possui uma tabela chamada vendas.db
com os campos DataVenda e Valor.
A nossa primeira query vai extrair o mes do
campo DataVenda juntamente com o campo Valor. A sentença seria
então a seguinte:
SELECT
EXTRACT(MONTH FROM datavenda) AS mes, valor
FROM vendas
Muitas vezes precisamos alterar o NetDir do BDE
para que nossas aplicações funcionem corretamente. E com poucas linhas de
código você poderá deixar para que sua própria aplicação faça isso.
Abaixo está uma rotina para alterar o NetDir de
acordo com o drive informado como parâmetro:
Se você precisa armazenar imagens em seu banco
de dados talvez seja interessante usar formatos que ocupam menos espaço. E o
que fazer com aquelas imagens todas em formato bmp? Bom, use a rotina abaixo e
faça a conversão:
procedure TForm1.Button1Click(Sender: TObject);
begin
// após a conversão será criado o arquivo Egito.jpg no mesmo diretório
BmpToJpg('C:\Windows\Egito.bmp');
end;
Depois de construir sua aplicação você pode
precisar associar determinado tipo de arquivo a ela. Exemplo: você cria um
editor de arquivos texto e necessita associar os arquivos com a extensão .txt
ao seu editor.
Para executar esta tarefa você poderá usar o
procedimento abaixo (que na verdade foi divido em dois procedimentos). Veja o
código:
uses Registry; // não esqueça de incluir esta unit
Durante o desenvolvimento de sua aplicação
você pode precisar de uma rotina para criar facilmente nomes de arquivos para
serem usados temporariamente. A função abaixo tem justamente esse propósito.
Veja o código:
// GetTemporaryFile
function GetTemporaryFile(Dir, Prefixo, Ext: string): string;
var
Name: array[0..255] of Char;
beginif (Dir = '') or not DirectoryExists(Dir) thenbegin
GetTempPath(256, Name);
Dir := Name;
end;
GetTempFileName(PChar(Dir), PChar(Prefixo), 0, @Name);
if Ext <> '' then
Result := ChangeFileExt(Name, Ext)
else
Result := Name;
end;
Os parâmetros que você poderá usar são:
Parâmetro
Descrição
Dir
Diretório
onde o arquivo deve ser criado. Se for informado uma string nula será
adotado o diretório temporário do Windows, geralmente 'C:\Windows\Temp'.
Prefixo
Você pode
informar os caracteres iniciais do nome do arquivo temporário.
Dir
Diretório
onde o arquivo deve ser criado. Se for informado uma string nula será
adotado o diretório temporário do Windows, geralmente 'C:\Windows\Temp'.
E para usar esta rotina você deve fazer uma
chamada ao procedimento GetTemporaryFile, da seguinte forma:
Normalmente optamos por destacar a linha de um DBGrid quando um campo
assume valores crÃticos. É o que acontece quando temos um DBGrid e um
campo que assume valor negativo.
Neste caso, precisaremos apenas manipular o evento OnDrawColumnCell. Mas
como fazer? É simples, veja:
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if not (gdSelected in State) and
(Table1.FieldByName('Valor').AsFloat < 0) then
DBGrid1.Canvas.Brush.Color := clRed;
DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if not (gdSelected in State) and
(Table1.FieldByName('Valor').AsFloat < 0) and (DataCol = 2) then
DBGrid1.Canvas.Brush.Color := clRed;
DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
Então você pode incluir a seguinte rotina em sua aplicação:
procedure TForm1.Button1Click(Sender: TObject);
var
R: TRect;
DC: HDc;
DeskCanvas: TCanvas;
Bmp: TBitmap;
begin
// cria o bitmap que vai receber a imagem
Bmp := TBitmap.Create;
Bmp.Height := Screen.Height;
Bmp.Width := Screen.Width;
// copia o conteúdo da área de trabalho para o bitmap
R := Rect(0, 0, Screen.Width, Screen.Height);
DC := GetWindowDC(GetDeskTopWindow);
DeskCanvas := TCanvas.Create;
DeskCanvas.Handle := DC;
Bmp.Canvas.CopyRect(R, DeskCanvas, R);
ReleaseDC(GetDeskTopWindow, DC);
// salva o conteúdo do bitmap para um arquivo
Bmp.SaveToFile('C:\Sistema\Log\Erro.bmp');
end;
Mas para que esta opção possa ser utilizada você precisará ter
certeza que o Outlook está instalado na máquina do usuário. Para
evitar que problemas de incompatibilidade você poderá usar recursos do
próprio Delphi (versão 5 e 6):
Primeiramente você deve adicionar um componente TNMSMTP da paleta
FastNet e depois fazer a implementação da rotina que enviará o
e-mail:
procedure TForm1.Button1Click(Sender: TObject);
begin
// enviar e-mail do elivaldo para um cliente
EnviarEMail('falecom@elivaldo.com.br', 'user@hotname.com.br',
'Nova dica', 'Foi adicionada uma nova dica na página...', '', True);
end;
Muitas vezes você precisa apagar o próprio arquivo da aplicação. Mas como
a aplicação está rodando, normalmente esta operação não seria possÃvel.
Mas você poderá usar o recusro de criar um arquivo BAT e, dentro dele,
incluir os comandos para deleção do aplicativo.
Veja um exemplo:
procedure TForm1.Button1Click(Sender: TObject);
var
F: TextFile;
Bat: string;
begin
Bat := ChangeFileExt(Application.ExeName,'.bat');
AssignFile(F, Bat);
Rewrite(F);
WriteLn(F, Format('DEL "%s"', [Application.ExeName]));
WriteLn(F, Format('DEL "%s"', [Bat]));
CloseFile(F);
WinExec(PChar(Bat), SW_HIDE);
Application.Terminate;
end;