sábado, 20 de outubro de 2007

6

Como retornar múltiplos resultados numa função?

Você já teve a necessidade de retornar múltiplos valores numa função? normalmente a primeira idéia é criar uma procedure com parâmetros passados por referência como abaixo:

procedure GetCalculo(const Valor1, Valor2:Double; var Soma, Media:Double);
begin
Soma := Valor1 + Valor2;
Media := Soma / 2;
end;

//Testando
procedure TForm1.Button1Click(Sender: TObject);
var
Soma, Media:Double;
begin
GetCalculo(100,50,Soma,Media);
ShowMessage('Soma: '+FloatToStr(Soma)+#13+'Media: '+FloatToStr(Media));
end;

Isso funciona perfeitamente, mas veja que precisei declarar as funções que vou receber. Agora imagina se fosse 10 valores no retorno! além da procedure ficar imensa você ainda teria que declarar as variáveis que seriam passadas como referência. Uma técnica mais elegante de fazer isso é criar um record e usar esse tipo na nossa função. Veja o exemplo acima alterado.

//definindo o tipo
type
TCalculo = record
Soma,
Media:Double;
end;

Form1 = Class(TForm)
...


implemetation

function
TForm1.GetCalculo(const Valor1, Valor2:Double):TCalculo;
begin
//Repare que o result agora pode receber vários resutados
Result.Soma := Valor1 + Valor2;
Result.Media :=
Result.Soma / 2;
end;

//Testando
procedure TForm1.Button1Click(Sender: TObject);
var
Calculo: TCalculo;
begin
Calculo := GetCalculo(100,50);
ShowMessage('Soma: '+FloatToStr(Calculo.Soma)+#13+'Media: '+FloatToStr(Calculo.Media));
end;

Com eu falei, não existe muita diferença nessa técnica com a passagem por parâmetros se considerarmos o número de parâmetros, mas com certeza numa função que retorna vários resultados, a segunda opção tornará o seu código muito mais legível e elegante. Até a próxima.


0

Função para validar CPF no SQL Server

/*
Cristiano Martins Alves
Para testar: SELECT DBO.CPF_VALIDO('16195473247')
*/
CREATE FUNCTION CPF_VALIDO(@CPF VARCHAR(11))
RETURNS CHAR(1)
AS
BEGIN
DECLARE @INDICE INT,
@SOMA INT,
@DIG1 INT,
@DIG2 INT,
@CPF_TEMP VARCHAR(11),
@DIGITOS_IGUAIS CHAR(1),
@RESULTADO CHAR(1)

SET @RESULTADO = 'N'

/*
Verificando se os digitos são iguais
A Principio CPF com todos o números iguais são Inválidos
apesar de validar o Calculo do digito verificado
EX: O CPF 00000000000 é inválido, mas pelo calculo
Validaria
*/

SET @CPF_TEMP = SUBSTRING(@CPF,1,1)

SET @INDICE = 1
SET @DIGITOS_IGUAIS = 'S'

WHILE (@INDICE <= 11)
BEGIN
IF SUBSTRING(@CPF,@INDICE,1) <> @CPF_TEMP
SET @DIGITOS_IGUAIS = 'N'
SET @INDICE = @INDICE + 1
END;

--Caso os digitos não sejão todos iguais Começo o calculo do digitos
IF @DIGITOS_IGUAIS = 'N'
BEGIN
--Cálculo do 1º dígito
SET @SOMA = 0
SET @INDICE = 1
WHILE (@INDICE <= 9)
BEGIN
SET @Soma = @Soma + CONVERT(INT,SUBSTRING(@CPF,@INDICE,1)) * (11 - @INDICE);
SET @INDICE = @INDICE + 1
END

SET @DIG1 = 11 - (@SOMA % 11)

IF @DIG1 > 9
SET @DIG1 = 0;

-- Cálculo do 2º dígito }
SET @SOMA = 0
SET @INDICE = 1
WHILE (@INDICE <= 10)
BEGIN
SET @Soma = @Soma + CONVERT(INT,SUBSTRING(@CPF,@INDICE,1)) * (12 - @INDICE);
SET @INDICE = @INDICE + 1
END

SET @DIG2 = 11 - (@SOMA % 11)

IF @DIG2 > 9
SET @DIG2 = 0;

-- Validando
IF (@DIG1 = SUBSTRING(@CPF,LEN(@CPF)-1,1)) AND (@DIG2 = SUBSTRING(@CPF,LEN(@CPF),1))
SET @RESULTADO = 'S'
ELSE
SET @RESULTADO = 'N'
END
RETURN @RESULTADO
END

sexta-feira, 19 de outubro de 2007

2

Dica: Permitir apenas uma instância da aplicação.

As vezes necessitamos limitar a abertura de apenas uma instância da nossa aplicação. O objetivo aqui é demonstrar como fazer isso:

Abra o fonte do seu arquivo DPR e adicione na uses as seguintes units:

uses
System, Windows,
...


E codifique como o exemplo abaixo

var
Instancia: THandle;
begin
Instancia:= CreateMutex(nil, false, 'InstanciaIniciada');
if WaitForSingleObject(
Instancia, 0) = wait_Timeout then
begin
Application.MessageBox('Atenção o programa já está aberto!.','Atenção',MB_ICONINFORMATION);;
Exit;
end;

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

Nesse exemplo criamos um objeto do tipo THandle chamado
instancia, em seguida instanciamos o objeto com o nome da nossa janela (InstanciaIniciada), a apartir dai verificamos se já existe uma instância rodando com WaitForSingleObject, caso exista exibimos a mensagem para o usuários e fechamos a aplicação.

1

Dica: Utilizar formatos diferentes no FormatFloat

Muitas vezes temos a necessidade de formatos diferentes para números POSITIVOS e NEGATIVOS. O que pouca gente sabe é que o FormatFloat faz isso pra nós! Podemos passar no parâmetro format, uma string com os dois formatos separados por ; (ponto e vírgula)
veja:

ShowMessage(FormatFloat('R$ 0.00,;"("R$ 0.00,")"',-1500)); //Número negativo entre parênteses
ShowMessage(FormatFloat('R$ 0.00,;R$ 0.00,-',-1500)); //Número negativo com sinal a direita
ShowMessage(FormatFloat('R$ 0.00,;R$ 0.00,-',1500)); //Número positivo

1

Dica: Form sem barra de títulos. Utilizando API

Muitas vezes precisamos de um form sem barra de títulos quando a idéia é apenas exibir uma informação ao usuário. Sabemos que se alterarmos a propriedade BorderStyle para none conseguimos esse efeito, no entanto o visual não é muito bom, o form fica com uma aparência FLAT e nem sempre é o que queremos (a menos que seja um Splash).

Crie um novo projeto no delphi, coloque o Label e defina as seguintes propriedades:
Align: alClient
Alingment: taCenter
Layout: tlCenter

Seu form deve se parecer com este




Deixe o form com o tamanho que desejar. E no evento onCreate coloque.


procedure TForm1.FormCreate(Sender: TObject);
begin
{Removendo Barra de tírulos}
SetWindowLong(Handle,GWL_STYLE, GetWindowLong(Handle, GWL_STYLE ) and not WS_CAPTION);
end;


Veja a diferença entre as duas técnicas



Utilizando a API

Utilizando BorderStyle = bsNone



Para mais informações sobre a API acesse: http://msdn2.microsoft.com/en-us/library/ms633591.aspx