sábado, 15 de maio de 2010

Dicas Delphi - DLLs! Porque e Como utilizar

DLLs são bibliotecas de vinculação dinâmicas (Dynamic Link Libraries) que possibilitam o compartilhamento de funções ou procedimentos entre diferentes softwares.

Uma vantagem que se tem ao utilizar DLLs é que, mesmo sendo utilizado por vários softwares, ela será carregada um única vez na memória do computador e quando a alteração ou substituição de versão da DLL, não será necessária uma compilação dos softwares que à utilizam.

Então, por que utilizar?

1º Pense nos vários softwares que você já desenvolveu e que precisaram utilizar as mesmas funções.

2º Quando alterava uma função era necessário acertar em todos softwares.

3º Onde estão sua funções? No formulário principal?

4º Multi linguagem. Posso utilizar DLLs criadas em qualquer linguagem, assim como qualquer linguagem pode utilizar uma DLL desenvolvida em Delphi (seguindo todos os padrões Windows).

Então, antes de encher o formulário principal de sua aplicação com funções para todo o aplicativo pense seriamente em criar uma DLL para armazená-las.
Mas, para criar ou utilizar uma DLL precisamos concordar com as convenções de chamadas, com os tipos de parâmetros e outros detalhes que veremos a seguir.
Toda função ou procedimento de uma DLL deve seguir estas diretrizes:

• Estar listada na cláusula exports da DLL. Através disso a rotina pode ser acessada externamente.
• As funções exportadas devem conter a instrução stdcall ao final de sua declaração. Isso possibilita a passagem de parâmetros padrão do Win32.
• Os tipos de parâmetros devem ser os tipos padrões do Windows (a maioria compatível com o C).
• As DLLs criadas no Delphi devem capturar todas as possíveis exceções em sua execução. Isso quer dizer que temos que tratar exceções em todo bloco.

Para colocarmos a mão na massa, criaremos uma DLL que terá uma função para calcular o ICMS de um produto. Abra o Delphi e acesse o menu File | New | Other e escolha DLL Wizard. Antes do begin codifique a função:

Function icms(valor, aliquota: Double): Double;
begin
try
Result:=(valor*aliquota)/100;
except
Result:=0;
end;
end;

E abaixo da função é necessário exportar a mesma:

exports
icms;

Agora compile pressionando. Pronto a DLL já deve ter estar criada no mesmo diretório que você salvou o projeto. Então passamos para a utilização dessa DLL. Crie uma nova aplicação através do menu File | New |. Adicione e configure os componentes conforme tabela:

Componente Name Caption Text
Label1 lblValor Valor -
Label2 lblAliquota Aliquota -
Label3 lblIcms ICMS -
Edit1 edtValor Apagado
Edit2 edtAliquota Apagado
Edit3 edtIcms - Apagado
Button1 btnCalcular Calcular

Tabela acima. Configuração dos componentes necessários
Obs: Apagado significa deixar a propriedade Text em branco (sem nada).

Agora clique duas vezes no botão calcular e coloque o seguinte código:

var
resultado: Double;
begin
//A variável resultado recebe o retorno da função contida na DLL
Resultado := icms(StrToFloat(edtValor.Text),
StrToFloat(edtAliquota.Text));
edtIcms.Text := Format('%8.2m', [resultado]);
end;

Para funcionar ainda é necessário fazer a declaração que indique que a função icms está contida na DLL funções.dll. Então, abaixo da cláusula implementation declare:

function icms(valor, aliquota:Double): Double; stdcall; external 'funcoes.dll';

Também é necessário copiar a DLL (funcoes.dll) para o mesmo diretório do software. Pronto, agora compile e teste.

Take care

Dicas Delphi - Criptografando Imagens com o Delphi

Procedure cripto(const BMP: TBitmap; Key: Integer);
var
BytesPorScan: Integer;
w, h: integer;
p: pByteArray;
begin
try
BytesPorScan := Abs(Integer(BMP.ScanLine[1]) -
Integer(BMP.ScanLine[0]));
except
raise Exception.Create('Erro !');
end;

RandSeed := Key;
for h := 0 to BMP.Height - 1 do
begin
P := BMP.ScanLine[h];
for w := 0 to BytesPorScan - 1 do
P^[w] := P^[w] xor Random(256);
end;
end;


Agora vamos ao evento OnClick do Button chamar a nossa procedure cripto, basta digitar o seguinte código:

Procedure TForm1.Button1Click(Sender: TObject);
begin
cripto(Image1.Picture.Bitmap, 1);
Image1.Refresh;
end;



Ao chamar a rotina passamos como parâmetro o caminho da imagem que no exemplo foi utilizado o componente image e 1 como um valor inteiro para retornamos a imagem normal, logo após a execução da nossa procedure atualizamos o image para que ele possa exibir nossa imagem criptografada.
Veja algumas fotos do nosso aplicativo em ação. A foto do exemplo com a imagem normal.


Take care

Dicas Delphi - Função DirectoryExists

Neste artigo explicarei como utilizar a função DirectoryExists que tem como objetivo verificar se um determinado diretório existe. Esta função está declarada na unit Sysutils.

No Delphi, crie um novo formulário e coloque um objeto button e um objeto Edit. No evento OnClick do objeto button escreva o seguinte código:


if DirectoryExists(edit1.text) then
Showmessage('Diretorio Existente' )
else
Showmessage('Diretorio Inexistente' )


Explicando o código

Ao clicarmos no botão a função DirectoryExists verificará se o diretório escrito no Editbox existe, caso exista a mensagem "Diretório Existente" será exibida, caso contrário a mensagem "Diretório Inexistente" será exibida.


Take care

Dicas Delphi - Validando o CPF

Function cpf(num: string): boolean;
var
n1,n2,n3,n4,n5,n6,n7,n8,n9: integer;
d1,d2: integer;
digitado, calculado: string;
begin
n1 := StrToInt(num[1]);
n2 := StrToInt(num[2]);
n3 := StrToInt(num[3]);
n4 := StrToInt(num[4]);
n5 := StrToInt(num[5]);
n6 := StrToInt(num[6]);
n7 := StrToInt(num[7]);
n8 := StrToInt(num[8]);
n9 := StrToInt(num[9]);
d1 := n9*2+n8*3+n7*4+n6*5+n5*6+n4*7+n3*8+n2*9+n1*10;
d1 := 11-(d1 mod 11);
if d1> = 10 then
d1 := 0;
d2 := d1*2+n9*3+n8*4+n7*5+n6*6+n5*7+n4*8+n3*9+n2*10+n1*11;
d2 := 11-(d2 mod 11);
if d2> = 10 then
d2 := 0;
calculado:=inttostr(d1)+inttostr(d2);
digitado:=num[10]+num[11];
if calculado=digitado then
cpf := true
else
cpf:=false;
end;


Take care

Dicas Delphi - Deletar um diretório inteiro de uma vez

Problemas para deletar um diretório com subdiretórios? Utilize a função abaixo:

uses
Shellapi, filectrl, //declare estas das units!!!

function DeleteFolder(FolderName: string; LeaveFolder: Boolean): Boolean;
var
r: TshFileOpStruct;
begin
Result := False;
if not DirectoryExists(FolderName) then
Exit;
if LeaveFolder then
FolderName := FolderName + ' *.* '
else
if FolderName[Length(FolderName)] = ' \ ' then
Delete(FolderName,Length(FolderName), 1);
FillChar(r, SizeOf(r), 0);
r.wFunc := FO_DELETE;
r.pFrom := PChar(FolderName);
r.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION;
Result := ((ShFileOperation(r) = 0) and (not r.fAnyOperationsAborted));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
DeleteFolder('c:\temp',false);
end;


Take care

Dicas Delphi - Criar um arquivo texto

Veja abaixo os passos básicos para criação de arquivos texto:

var
F: TextFile;
begin
AssignFile(f,'c:\arquivo_qualquer.txt');
Rewrite(f); //abre o arquivo para escrita
Writeln(f,'Testando'); escreve no arquivo e desce uma linha
Write(f,'Clube Delphi'); //escreve no arquivo sem descer a linha
Closefile(f); //fecha o handle de arquivo
end;

///Rotina para ler de um arquivo texto:
var
f: TextFile;
linha: string;
begin
AssignFile(f,'c:\arquivo_qualquer.txt');
Reset(f); //abre o arquivo para leitura;
while not eof(f) do
begin
Readln(f,linha); //le do arquivo e desce uma linha. O conteúdo lido é transferido para a variável linha
Memo1.lines.add(linha);
end;
Closefile(f);
end;


Take care

Dicas de Delphi - Formatando CPF

Esta dica mostra como formatar uma cadeia de string referente ao CPF. Passe a string a ser formatada para a função.

function FormataCPF(CPF: string): string;
begin
Result := Copy(CPF,1,3)+'.'+Copy(CPF,4,3)+'.'+Copy(CPF,7,3)+'-'+Copy(CPF,10,2);
end;


Take care

Dicas Delphi - Formatando CNPJ

Esta dica mostra como formatar uma cadeia de string referente ao CNPJ. Informe para a função a string a ser formatada.

function FormataCNPJ(CNPJ: string): string;
begin
Result :=Copy(CNPJ,1,2)+'.'+Copy(CNPJ,3,3)+'.'+Copy(CNPJ,6,3)+'/'+
Copy(CNPJ,9,4)+'-'+Copy(CNPJ,13,2);
end;


Take care

Dicas Delphi - Alterando a cor de fundo do Edit

Crie uma aplicação, depois adicione ao Form dois Edits e um Button. Apague o nome do Edit em sua propriedade Text. Crie a procedure MudancaDeFoco na área de implementação e declare a mesma na área privada do Form.


Procedure TForm1.MudancaDeFoco(Sender: TObject);
var
I: integer;
Ed: TEdit;
begin
for I := 0 to ComponentCount - 1 do
if Components[I] is TEdit then
begin
Ed := Components[I] as TEdit;
if Ed.Focused then
Ed.Color := clYellow
else
Ed.Color := clOlive;
end;
end;

Agora faça a chamada à procedure no evento OnEnter e OnExit de cada Edit, como mostrado abaixo.

procedure TForm1.Edit1Enter(Sender: TObject);
begin
MudancaDeFoco (Sender);
end;

procedure TForm1.Edit1Exit(Sender: TObject);
begin
MudancaDeFoco (Sender);
end;


Take care

Dicas Delphi - Somando as linhas selecionadas de um DBGrid

Adicione em um formulário os seguintes componentes: um DBGrid, um DataSource, um ClientDataSet, um Button e um Edit. Faça a ligação entre o DBGrid, DataSource e ClientDataSet. Adicione o arquivo employee.xml através da propriedade FileName do ClientDataSet. Adicione no DBGrid as colunas referente aos campos EMPNO, LASTNAME, FIRSTNAME e SALARY. Altere as propriedades Options.dgMultiSelect, Options.dgRowSelect e Options.dgAlwaysShowSelection para True do DBGrid.

No OnClick do botão digite o seguinte código:

var
i: Integer;
Soma: Currency;
begin
Soma := 0;
for i := 1 to DBGrid1.SelectedRows.Count do
begin
ClientDataSet1.GotoBookMark(Pointer(DBGrid1.SelectedRows.Items[i-1]));
Soma := Soma + ClientDataSet1.FieldByName('Salary').AsFloat;
end;
Edit1.Text := FormatFloat('R$ ###,##0.00', Soma);
end;


Rode a aplicação, marque alguns campos e clique sobre o botão para somas as linhas selecionadas (Figura). Você pode criar uma função genérica, recebendo como parâmetro o DBGrid e o campo que será usado na soma.


Take care

Dicas Delphi - Movendo o foco para o próximo Edit

A propriedade MaxLenght de um componente descendente de TCustomEdit (Edit, DBEdit, etc.) especifica o número máximo de caracteres que o usuário pode inserir no controle. Esta dica mostra como mover imediatamente para o próximo controle (seguindo a ordem do tab) quando o número máximo de caracteres for alcançado.


Procedure TForm1.Edit1Change(Sender: TObject) ;
begin
if Sender is TEdit then
with Sender as TEdit do
if MaxLength = GetTextLen then
Self.SelectNext(TCustomEdit(Sender), True, True);
end;


Take care

Dicas Delphi - Manipulando arquivos INI

Se você precisa salvar ou obter dados de um arquivo INI, utilize as seguintes rotinas:

{ Declare em uses IniFiles }


Procedure GravaIni(aTexto: string);
var
ArqIni: TIniFile;
begin
ArqIni := TIniFile.Create('c:\Arquivo.ini');
try
ArqIni.WriteString('Dados', 'Texto', aTexto);
finally
ArqIni.Free;
end;
end;

procedure LeIni(var aTexto: string);
var
ArqIni: TIniFile;
begin
ArqIni := TIniFile.Create('c:\Arquivo.ini');
try
aTexto := ArqIni.ReadString('Dados', 'Texto', aTexto);
finally
ArqIni.Free;
end;
end;

Para gravar e ler, utilize o seguinte código:

procedure TForm1.Button1Click(Sender: TObject);
begin
GravaIni('ClubeDelphi');
end;

procedure TForm1.Button2Click(Sender: TObject);
var
aTexto: string;
begin
LeIni(aTexto);
ShowMessage(aTexto);
end;


Entendendo o código

WriteString grava em um arquivo INI, os dados passados como parâmetro, onde Dados é o nome da seção do arquivo INI (valor que fica entre colchetes []), Texto é a variável do arquivo e o parâmetro aTexto é o valor que será salvo no arquivo.
Se o arquivo (Arquivo.ini) não existir, ele será criado automaticamente. Para carregar os dados do arquivo INI, a técnica é praticamente a mesma. Se desejar armazenar/ler outros tipos de dados como Boolean e integer, por exemplo, basta alterar os métodos para WriteBool, WriteInteger, ReadInteger e ReadBool, respectivamente.


Take care

Dicas Delphi - Validando uma Data

Para validar uma data, utilize a seguinte função:

function ValidarData(const aData: string): Boolean;
begin
try
StrToDate(aData);
Result := True;
except
Result := False;
end;
end;

Para testar, use o código:

if not ValidarData (Edit1.Text) then
ShowMessage('Data Inválida');


Take care

Dicas Delphi - Calculando Parcelas

Função que retorna o valor de cada parcela para financiamento ou pagamento de bens em prestações. Para usar acrescente a unit Math em uses.

function VlPrestacao(C, J, N: Real): Real;
begin
Result := C*((J/100)/(1-(Power(1/(1+(J/100)),N) )));
end;

Onde:
C: representa o valor do bem (capital)
J: a taxa de juros mensal no formato '#.##'( ex: 3,00 - tres por cento)
N: é o número de parcelas, em meses.

Retorna o valor de cada parcela.

Exemplo:

editQualquer.text := FormatFloat('R$ ##.##',VlPrestacao(C,J,N));

Take care

Dicas Delphi - Gera Resultado de Consulta no Excel

A Procedure GerarExcel recebe como parâmetro o nome de um componente de consulta, TQuery1 ou um ClientDataSet por exemplo, e gera uma planilha no Excel com os campos e registros da consulta. Observe o código abaixo:

procedure TForm1.GerarExcel(Consulta:TQuery);
var
coluna, linha: integer;
excel: variant;
valor: string;
begin
try
excel:=CreateOleObject('Excel.Application');
excel.Workbooks.add(1);
except
Application.MessageBox ('Versão do Ms-Excel'+
'Incompatível','Erro',MB_OK+MB_ICONEXCLAMATION);
end;
Consulta.First;
try
for linha:=0 to Consulta.RecordCount-1 do
begin
for coluna:=1 to Consulta.FieldCount do
begin
valor:= Consulta.Fields[coluna-1].AsString; excel.cells [linha+2,coluna]:=valor;
end;
Consulta.Next;
end;
for coluna:=1 to Consulta.FieldCount do
begin
valor:= Consulta.Fields[coluna-1].DisplayLabel;
excel.cells[1,coluna]:=valor;
end;
excel.columns.AutoFit;
excel.visible:=true;
except
Application.MessageBox ('Aconteceu um erro desconhecido durante a conversão'+
'da tabela para o Ms-Excel','Erro',MB_OK+MB_ICONEXCLAMATION);
end;
end;

Take care

Windows Phone Developer Tools CTP

Salve, salve

A MS lançou o novo CTP do WinPhone 7 para developers. Quem tiver a versão final do VS 2010 (RTM) precisará deste CTP.

Clique aqui

Take care