domingo, 22 de maio de 2011

Recompilando as bibliotecas RTL no Delphi 7 - Adequação ao XP SP3


Com a última atualização do windows em vigor (Service Pack 3) percebi que meu Delphi 7 estava produzindo executáveis que estavam sendo bloqueados pelos Antivirus mais populares (como o AVG e o Avast), acusando-os de contaminados

Após muitas pesquisas, baseado na suposição de que a razão do fenômeno seria o SP3, experimentei a recompilação das bibliotecas RTL, o que resultou em solução do problema.

Para tanto, segue abaixo o procedimento:

    Ir para o diretório Delphi7 e fazer um backup do diretório 'lib';
    Ir para o diretório Delphi7\Source\Rtl. Neste local deve haver o arquivo 'makefile';
    Neste local, deve-se criar um subdiretório '\lib';
    Entrar no command-line e digitar 'MAKE';
    Serão produzidos arquivos 'dcu' no diretório 'lib' criado no passo 3;
    Sobrescrever estes arquivos no diretório lib original do Delphi7;

Pronto. RTL re-compilada.

segunda-feira, 16 de maio de 2011

Retornar o mês por extenso, usando array

Nesta dica, vamos criar uma função para retornar o mês por extenso, somente informando o número do mês.

Programando:

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
function MesExtenso( Mes:Word ) : string;
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

function TForm1.MesExtenso( Mês:Word ) : string; const meses : array[0..11] of PChar = ('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro','Outubro', 'Novembro', 'Dezembro');
begin
result := meses[mes-1];
End;

procedure TForm1.Button1Click(Sender: TObject);
begin
label1.Caption := MesExtenso(3);
end;

end.

terça-feira, 10 de maio de 2011

Usando MessageBox

Para que as mensagens apareçam em portugues (na lingua no sistema) não é necessário a tradução das units.

Invés de usar a função messagedlg eh melhor usar a função MessageBox

Sintax:

MessageBox (Handle, Messagem, Caption, Botoes)
onde

Handle : Endereço do form na memória ; Sempre usu Application.Handle
Messagem : A messagem a ser mostrada
Caption : O titulo da messagem
Botoes : Os Botoes que irao ser mostrados. Na lingua do sistema

MB_ABORTRETRYIGNORE A messagem mostra os tres botoes: Abort, Retry, and Ignore.
MB_OK A messagem mostra um botoao: OK. This is the default.
MB_OKCANCEL A messagem mostra os dois botoes: OK and Cancel.
MB_RETRYCANCEL A messagem mostra os dois botoes: Retry and Cancel.
MB_YESNO A messagem mostra os dois botoes: Yes and No.
MB_YESNOCANCEL A messagem mostra os tres botoes: Yes, No, and Cancel.
Sons
MB_ICONEXCLAMATION, MB_ICONWARNING: Mostra o icone de exclamação e som conrrespondente. Analo aos demais
MB_ICONINFORMATION, MB_ICONASTERISK
MB_ICONQUESTION
MB_ICONSTOP,
MB_ICONERROR,
MB_ICONHAND
Botoes padrao
MB_DEFBUTTON1: Padrao nao precisa ser colocado.
MB_DEFBUTTON2: Coloca o segundo botao como padrao
MB_DEFBUTTON3: Coloca o terceiro botao como padrao
MB_DEFBUTTON4: Coloca o quarto botao como padrao
Respostas
IDABORT
IDCANCEL
IDIGNORE
IDNO
IDOK
IDRETRY
IDYES

Exemplo:

Case MessageBox (Application.Handle, Pchar ('Deseja excluir o arquivo' + #13 + Label1.caption), 'Exclusao de arquivo', MB_YESNOCANCEL+MB_EXCLAMATION+MB_DEFBUTTON2) of
idYes: Procedimento
idNo: Procedimento
idCancel: Procedimento
end;

O que fazer quando o StrToIntDef gera uma exceção

Quando utilizamos a função StrToInt e a string original não é um inteiro, o programa gera uma exceção. Para evitar isto, podemos utilizar a função StrToIntDef, que insere um valor predeterminado (default) caso a string não possa ser convertida em inteiro.

Veja o exemplo:

procedure TForm1.Button1Click(Sender: TObject);
var
    NumberString: string;
    Number: Integer;
begin
    NumberString := Edit1.Text;
    Number := StrToIntDef(NumberString, 1000);
    Edit2.Text := IntToStr(Number);
end;

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 uma má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;_'; // Telefone
end;
O evento OnGetEditText ocorre também quando entramos no modo de edição. Neste momento podemos manipularmos o texto da célula atual (linha/coluna) e então podemos simular algo tal como uma tabela onde opções podem ser digitadas através de 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 de edição. Neste momento podemos manipular a entrada e trocar por um texto equivalente. Normalmente usamos este evento em conjunto 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ções

Para 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).

domingo, 8 de maio de 2011

Tutorial para iniciante sobre JOIN's


Para aqueles que tinham dúvidas quanto ao funcionamento dos JOIN's das tabelas no SQL, desenvolvi um pequeno tutorial de apoio...
Tabelas e seus registros:

TABELA_A
Codigo
Nome
1
um
2
dois
3
três
4
quatro
5
cinco

TABELA B
Lanca
Codigo
Valor
1
1
1.000
2
1
2.000
3
1
5.000
4
2
4.000
5
2
9.000
6
3
7.000
7
5
4.000
8
8
7.000

Para a relação entre as tabelas temos:
3 registros para a empresa 1 (que existe na tabela de empresas);
2 registros para a empresa 2 (que existe na tabela de empresas);
1 registros para a empresa 3 (que existe na tabela de empresas);
0 registros para a empresa 4 (que existe na tabela de empresas);
1 registros para a empresa 5 (que existe na tabela de empresas);
1 registros para a empresa 8 (que NÃO existe na tabela de empresas);

Agora vamos ver como ficariam as pesquisas* (SELECT's) com os JOIN's ( INNER, [ LEFT | RIGHT | FULL ] OUTER ):


* Para tais pesquisas vamos usar a seguinte linguagem:

SELECT [CAMPOS]
FROM "TABELA_DA_ESQUERDA"
[INNER] JOIN | {LEFT | RIGHT | FULL } [OUTER]} JOIN "TABELA_DA_DIREITA"

1) INNER JOIN:

SELECT A.NOME "A.NOME",
B.VALOR "B.VALOR"
FROM TABELA_A A
INNER JOIN TABELA_B B ON B.CODIGO = A.CODIGO
 


A.NOME
B.VALOR
1
UM
1.000
2
UM
2.000
3
UM
5.000
4
DOIS
4.000
5
DOIS
9.000
6
TRÊS
7.000
7
CINCO
4.000


Nas pesquisas com INNER JOIN o resultado trará somente as linhas que sejam comum nas 2 tabelas, ligadas pelos campos das tabelas em questão na pesquisa.


2) LEFT OUTER JOIN:

SELECT A.NOME "A.NOME",
B.VALOR "B.VALOR"
FROM TABELA_A A
LEFT OUTER JOIN TABELA_B B ON B.CODIGO = A.CODIGO
 


A.NOME
B.VALOR
1
UM
1.000
2
UM
2.000
3
UM
5.000
4
DOIS
4.000
5
DOIS
9.000
6
TRÊS
7.000
7
QUATRO
NULL
8
CINCO
4.000

Nas pesquisas com LEFT OUTER JOIN o resultado trará todas os registros que estejam na tabela da esquerda do JOIN (neste caso é a TABELA_A) ao menos 1 vez, mesmo que não tenham registros na tabela da direita do JOIN (neste caso é a TABELA_B) ligadas à tabela da esquerda, como é o caso da linha 7.

3) RIGHT OUTER JOIN:
SELECT A.NOME "A.NOME",
B.VALOR "B.VALOR"
FROM TABELA_A A
RIGHT OUTER JOIN TABELA_B B ON B.CODIGO = A.CODIGO


A.NOME
B.VALOR
1
UM
1.000
2
UM
2.000
3
UM
5.000
4
DOIS
4.000
5
DOIS
9.000
6
TRÊS
7.000
7
CINCO
4.000
8
NULL
7.000

Nas pesquisas com RIGHT OUTER JOIN o resultado trará todas os registros que estejam na tabela da direita do JOIN (neste caso é a TABELA_B) ao menos 1 vez, mesmo que não tenham registros na tabela da esquerda do JOIN (neste caso é a TABELA_A) ligadas à tabela da direita, como é o caso da linha 8.

4) FULL OUTER JOIN:
SELECT A.NOME "A.NOME",
B.VALOR "B.VALOR"
FROM TABELA_A A
FULL OUTER JOIN TABELA_B B ON B.CODIGO = A.CODIGO


A.NOME
B.VALOR
1
UM
1.000
2
UM
2.000
3
UM
5.000
4
DOIS
4.000
5
DOIS
9.000
6
TRÊS
7.000
7
QUATRO
NULL
8
CINCO
4.000
9
NULL
7.000

Nas pesquisas com FULL OUTER JOIN o resultado trará todas os registros, ao menos 1 vez, que estejam nas 2 tabelas, tanto a da esquerda do JOIN (neste caso é a TABELA_A) quanto a da direita do JOIN (neste caso é a TABELA_B), como é o caso das linhas 7 e 9. O FULL poderíamos dizer que é uma junção entre o LEFT OUTER JOIN e o RIGHT OUTER JOIN.

domingo, 1 de maio de 2011

Armazanando sons, vídeos em bancos de dados

Um dos recursos mais interessantes nos bancos de dados atuais é a possibilidade de armazenar recursos multimídia juntamente com outras informações. Dessa forma, é possível criar registros com informações mais ricas sobre um determinado assunto. Por exemplo, pode-se armazenar informações sobre um funcionário juntamente com a sua própria foto. No Paradox, por exemplo, existe um tipo de campo destinado especialmente para esse fim.
No entanto, as possibilidades vão muito além do que o simples armazenamento de imagens. É possível armazenar sons, filmes ou qualquer tipo de arquivo, usando o "obscuro" campo BLOB (Binary Large Object), que permite que qualquer arquivo seja "embutido" no banco de dados. Na verdade, o conteúdo do arquivo não é armazenado no registro em si, mas num arquivo separado que é manipulado internamente pelo banco de dados.
Trabalhar com esse tipo de campo no Delphi é muito simples, mas não tão óbvio à primeira vista. A manipulação de campos BLOB, diferentemente dos campos comuns, não deve ser feita diretamente, mas sim por meio do objeto TBlobField, descendente do TField, que disponibiliza recursos especiais para esse fim. Para isso, você deve sempre se referir ao campo BLOB no código como sendo um TBlobField, utilizando typecasting.
Vamos supor que você tenha um arquivo de som MyWave.wav que será armazenado no campo "SOM" da tabela "MyTable". Para carregar o conteúdo do arquivo no campo SOM, basta fazer assim:
TBlobField(MyTable.FieldByName('SOM')).LoadFromFile('MeuWave.wav');
Neste exemplo, você usou o recurso de typecasting para manipular o campo como sendo um objeto TBlobField, carregando o arquivo através do método LoadFromFile que existe nesse objeto. Fácil, não é?
Se você quiser salvar o conteúdo do campo "SOM" no arquivo "MyWaveCopy.wav", basta fazer assim:
TBlobField(MyTable.FieldByName('SOM')).SaveToFile('MyWaveCopy.60wav');
Para remover o conteúdo do campo "SOM" (limpá-lo), você também deve usar um método apropriado:
TBlobField(MyTable.FieldByName('SOM')).Clear;
Para saber se o campo SOM possui algum conteúdo, use a propriedade IsNull:
with MyTable do
  if not TBlobField(FieldByName('SOM')).IsNull then
  TBlobField(FieldByName('SOM')).SaveToFile('MyWaveCopy.wav');
A maneira mais simples de utilizar o conteúdo de um campo BLOB já armazenado é primeiro gravá-lo novamente em um arquivo em disco, usando o método SaveToFile, e depois manipulá-lo normalmente. No caso de um conteúdo em formato wave, por exemplo, você deve primeiro gravá-lo num arquivo .wav, e então reproduzí-lo através do TMediaPlayer ou pela função SndPlaySound.
Usando os mesmos métodos, você também pode armazenar e manipular filmes AVI, apresentações, documentos, enfim, o que a sua imaginação mandar. Mas tenha em mente que o armazenamento de arquivos de som ou outros tipos vai aumentar consideravelmente o tamanho do seu banco de dados, por isso esse recurso deve ser utilizado com cuidado. Uma boa medida para reduzir esse problema é compactar o arquivo antes de armazená-lo. Para utilizá-lo depois, basta gerar o arquivo novamente em disco e descompactá-lo. Para saber quanto um campo BLOB está ocupando num registro do seu arquivo, em bytes, use a propriedade BlobSize:
TBlobField(MyTable.FieldByName('SOM')).BlobSize;
Obs: Para armazenar imagens ou texto em formato RichText (RTF), use os tipos GRAPHIC e FORMATED MEMO do Paradox, que são destinados a esses tipos de dados. O Delphi também possui objetos para a manipulação desses campos: TGraphicField e TMemoField, ambos descendentes do TBlobField.

Curso de Delphi: 7.Consultas SQL