sexta-feira, 20 de abril de 2012

Alternando Bitmaps no Fundo de um Form

Um leitor perguntou recentemente sobre imagens de fundo em Forms.... Apesar de já se ter escrito diversos artigos sobre este tópico, sua questão tinhas algumas novidades. Primeiramente, ele desejava que o fundo se alternasse periodicamente entre diferente

Essencialmente, a solução para isto seria a aplicação de outros artigos similares. Em primeiro lugar, para resolver a questão de se ter diversas imagens, os bitmaps devem ser carregados em um array quando o Form for criado. A mudança periódica da imagem s

Finalmente, para tratar do assunto "não leia as imagens do disco", recorremos aos resources. Um arquivo de resource é apenas um caminho para empacotar muito bem qualquer tipo de dados que será anexado ao executável durante o processo de Linkedição. Para o

BITMAP1 BITMAP IMAGE1.BMP

BITMAP2 BITMAP IMAGE2.BMP

BITMAP3 BITMAP IMAGE3.BMP

BITMAP4 BITMAP IMAGE4.BMP

BITMAP5 BITMAP IMAGE5.BMP

A primeira parte de cada linha é o identificador que você utilizará no código para capturar uma imagem em particular. A segunda parte é o tipo de resource (neste caso, bitmap). E a última parte é o nome do arquivo que deve ser utilizado para a imagem. Ist

{$R MYBMPS.RES}
Quando o executável está sendo linkeditado (um passo antes da compilação), o resource será automaticamente anexado ao executável. Para carregar as imagens do resource no array de bitmaps no programa, fiz simplesmente:

for a := 1 to NumBmps do
begin
Bmps[a] := TBitmap.Create;
Bmps[a].LoadFromResourceName(hInstance,'BITMAP'+IntToStr(a));
end;
É basicamente isto... A seguir a listagem da Unit principal:

unit Unit1a;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls;
const
NumBmps = 5;
type
TForm1 = class(TForm)
Timer1: TTimer;
Edit1: TEdit;
CheckBox1: TCheckBox;
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
Bmps : Array[1..NumBmps] of TBitmap;
SelectedBmp : Integer;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
{$R MYBMPS.RES}
procedure TForm1.FormCreate(Sender: TObject);
var
a : Integer;
begin
for a := 1 to NumBmps do
begin
Bmps[a] := TBitmap.Create;
Bmps[a].LoadFromResourceName(hInstance,'BITMAP'+IntToStr(a));
end;
SelectedBmp := 1;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
a : Integer;
begin
for a := 1 to NumBmps do Bmps[a].Free;
end;
procedure TForm1.FormPaint(Sender: TObject);
var
x,y,w,h : Integer;
begin
w := Bmps[SelectedBmp].Width;
h := Bmps[SelectedBmp].Height;
for x := 0 to (Width div w) do
for y := 0 to (Height div h) do
Canvas.Draw(x*w,y*h,Bmps[SelectedBmp]);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Inc(SelectedBmp);
if SelectedBmp > NumBmps then SelectedBmp := 1;
Paint;
end;
end.

domingo, 15 de abril de 2012

Como usar a cláusula UNION em um Query

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.

quinta-feira, 12 de abril de 2012

Visualizar imagem no dbgrid

Para visualizar uma imagem em um DBGrid, você vai ter que criar um descendente dele que aceite essas figuras. O código está abaixo:

unit DBPicGrd;

interface

uses
DBGrids, DB, DBTables, Grids, WinTypes, Classes, Graphics;

type
TDBPicGrid = class (TDBGrid)
protected
procedure DrawDataCell(const Rect: TRect; Field: TField; State:
TGridDrawState); override;
public
constructor Create (AOwner : TComponent); override;
published
property DefaultDrawing default False;
end;

procedure Register;

implementation

constructor TDBPicGrid.Create (AOwner : TComponent);
begin
inherited Create (AOwner);
DefaultDrawing := False;
end;

procedure TDBPicGrid.DrawDataCell (const Rect: TRect; Field: TField;
State: TGridDrawState);
var
bmp : TBitmap;
begin
with Canvas do
begin
FillRect(Rect);
if Field is TGraphicField then
try
bmp := TBitmap.Create;
bmp.Assign (Field);
Draw (Rect.Left, Rect.Top, bmp);
finally
bmp.Free;
end
else
TextOut (Rect.Left, Rect.Top, Field.Text);
end;
end;

procedure Register;
begin
RegisterComponents ('Custom', [TDBPicGrid]);
end;
end.

domingo, 8 de abril de 2012

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 clientes que 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:

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ções

Os números de 1 a 12 representam, respectivamente

sábado, 31 de março de 2012

Como pegar a posição do mouse na tela

Para obter os valores das coordenadas do mouse de qualquer parte da tela, basta que se utiliza a função da API do Windows GetCursorPos. Esta função é interessante pois oferece ao programador os valores (x,y) de qualquer ponto da tela e não somente da aplicação.

Para implementação, esta função pode ser utilizada da seguinte maneira:

procedure TForm1.Timer1Timer(Sender: TObject);
var
pt: TPoint;
begin
GetCursorPos(pt); // Pega a posição atual do mouse;
//Mostra os valores das coordenadas do mouse
label1.caption := IntToStr(pt.x) + ',' + IntToStr(pt.y);
end;

Esta é mais uma das milhares de funções da API do Windows.

Enviar um email pelo delphi

smtp.postmessage.toAddress := 'StringList (por ex uma listbox';
smtp.postmessage.FromAdreess := 'ex: meu_email@123.pt';
smtp.userid := 'ex: user@123.pt'
smtp.host := 'ex: smtp@123.pt'
smtp.postmessage.subject := 'Assunto'
smtp.postmessage.body := 'Texto da mensagem (stringlist)'

smtp.connect;
smtp.sendmail;
smtp.disconnect;

Contribuição:
O Anonymous.nick enviou um complemento explicando melhor o procedimento para enviar um e-mail usando o Delphi.

Fazer um aplicativo completo para manipulação de e-mails é um tanto trabalhoso e não é o assunto desta dica. Muitas vezes, porém, queremos apenas dar ao nosso software a capacidade de enviar simples e-mails. Isto é fácil, especialmente porque o Delphi5 nos oferece o componente TNMSMTP (paleta FastNet) que faz praticamente todo o trabalho para nós. Precisamos apenas alterar algumas propriedades e chamar alguns métodos para que a mensagem seja enviada. Vamos para a prática:

1. Coloque um componente TNMSMTP no form.

2. Coloque um botão e no evento OnClick deste botão escreva:

procedure TForm1.Button1Click(Sender: TObject);
begin

{ Seu servidor SMTP }
NMSMTP1.Host := 'smtp.servidor.com.br';

{ Porta SMTP, **NÃO MUDE ISTO** }
NMSMTP1.Port := 25;

{ Nome de login do usuário }
NMSMTP1.UserID := 'MeuLogin';

{ Conecta ao servidor }
NMSMTP1.Connect;

{ Se ocorrer algum erro durante a conexão com o servidor, avise! }
if not NMSMTP1.Connected then
raise Exception.Create('Erro de conexão');

with NMSMTP1.PostMessage do begin
{ Seu e-mail }
FromAddress := 'meuemail@meuserver.com.br';

{ Seu nome }
FromName := 'Meu Nome';

{ E-mail do destinatário }
ToAddress.Clear;
ToAddress.Add('destinatario@servidor.com.br');

{ Assunto da mensagem }
Subject := 'Assunto da mensagem';

{ Corpo da mensagem }
Body.Clear;
Body.Add('Primeira linha da mensagem');
Body.Add('Segunda linha da mensagem');
Body.Add(''); { Linha em branco }
Body.Add('Última linha da mensagem');

{ Anexar arquivos(Se não quiser anexar arquivos, apague as 3 linhas seguintes) }

Attachments.Clear;

{ Endereço do anexo }
Attachments.Add('c:\diretorio\arquivo.ext');

end;

{ Manda o e-mail }
NMSMTP1.SendMail;
{ Disconecta do servidor }
NMSMTP1.Disconnect;
end;

Pronto! É só fazer as adaptações necessárias e você terá envio de e-mails em sua aplicação.

Observações:
Para enviar o mesmo e-mail para vários destinatário de uma só vez basta adicionar os endereços de e-mails de todos os destinatários em NMSMTP1.PostMessage.ToAddress.

segunda-feira, 12 de março de 2012

Manipulação de arquivos texto no delphi


Bem, vamos falar inicialmente da escrita de arquivos texto. Existem algumas palavras reservadas, das quais irei falar de apenas algumas delas, que serão abordadas neste artigo. Para conhecer todas as palavras reservadas, relacionadas a manipulação de arquivos, entrem no help do Delphi com o seguinte tema: "Input and output procedures and functions"

Palavra Reservada
Função
AssignFile
Associa o arquivo manipulado a uma variável do tipo File
Append
Abre um arquivo existente para inserção de novos dados
Eof
Verifica se a posição atual do cursor indica o fim do arquivo
Write / Rewrite
Escreve valores diversos no arquivo. O rewrite após a escrita posiciona o cursor na próxima linha do arquivo
Read / Readln
Lê diversos valores no arquivo. O readln após a leitura posiciona o cursor na próxima linha do arquivo

Bem, irei agora explicitar dois exemplos contendo a manipulação de arquivos textos. O primeiro deles, ilustrará a inserção de dados em um arquivo. O segundo irá ilustrar a leitura de dados.

function GravaArquivoLogTransacao(TipoTransacao: TTipoTransacao): Integer;
const
NomArquivo: String = "LogTransacao.txt";
var
Path: String;
Arquivo: TextFile;
begin
        Path := ExtractFilePath(Application.ExeName);
        if not DirectoryExists(Path) then begin
                CreateDir(Path);
        end;
        if not FileExists(Path + NomArquivo) then begin
                FileCreate(Path + NomArquivo);
        end;
        Try
        AssignFile(Arquivo, Path + NomArquivo);
        Append(Arquivo);
        Write(Arquivo, FormatFloat("000000", Transacao.TransactionID) + " / " + FormatFloat("000000", Transacao.GlobalID));
        case TipoTransacao of
        ttBeginTran: WriteLn(Arquivo, " - BeginTran: " + DateToStr(Date) + " " + TimeToStr(Time) + " por usuário: " + IntToStr(UserID));
        ttCommit: WriteLn(Arquivo, " - Commit: " + DateToStr(Date) + " " + TimeToStr(Time) + " por usuário: " + IntToStr(UserID));
        ttRollBack: WriteLn(Arquivo, " - RollBack: " + DateToStr(Date) + " " + TimeToStr(Time) + " por usuário: " + IntToStr(UserID));
end;
CloseFile(Arquivo);
Result := 1;
Except
Result := -1;
End;
end;
Na função acima, ilustro a geração de um log de transações de uma aplicação. Observe que as palavras que realizam a "escrita" no arquivo estão destacadas.
procedure LeArquivoLogTransacao(NomeArquivo: String);
var
strFile: TextFile;
strLine: String;
begin
        AssignFile(strFile, NomeArquivo);
        Reset(strFile);
        Readln(strFile, strLine);
        while not Eof(strFile) do begin
                ShowMessage(strLine);
                Readln(strFile, strLine);
        end;
end;
Já na função acima, realizamos a leitura do arquivo e lançamos uma mensagem contato o conteúdo lido a cada linha.

Curso de Delphi: 7.Consultas SQL