segunda-feira, 24 de janeiro de 2011

Texto Para Iniciantes

Introdução à Programação

Caso você já tenha uma base de programação pode pular esta parte, ou pode lê-la caso se sinta inseguro quanto ao seu conhecimento.
Bem, em primeiro lugar, o que este guia exige é uma noção de comandos básicos que todo (ou quase todo) tipo de linguagem exige.
Note que os exemplos serão baseados na programação Delphi, e não qualquer linguagem.

Variáveis

Variável é um nome conhecido por qualquer programador (ou pelo menos deveria ser), este nome significa um endereço na memória onde um certo valor fica guardado. Vejamos um exemplo: se você declara a variável i:

var i:integer; 

 ("var" é nome usado para declarar uma variável em Delphi, "integer" é o tipo de informação que ela deverá armazenar) daí você pode estabelecer um valor para i:

i := 12;  

este valor vai ficar "guardado na memória" para você poder usa-lo mais tarde, por exemplo, para fazer uma conta:

i := 4 * i;

Agora i vale 4 vezes 12 (48).

Loops

Se você já fez algum programa em uma linguagem qualquer deve se lembrar dos famosos FOR e WHILE (loop), caso contrário, vamos a uma introdução a estes comandos:
Em uma linguagem de programação, loop é um comando que faz com que um certo código seja executado enquanto uma certa condição for atendida, um exemplo o ajudará a entender melhor:

var i:integer; //(declara a variável i)
for i := 1 to 30 do
ShowMessage ('O VALOR DE "I" É: ' + IntToStr(I));

 
Este comando fará com que "PARA" (FOR) I = 1, ou seja, o valor inicial de i é 1, "ATÉ" (TO) 30 (inclusive) exiba uma mensagem (SHOWMESSAGE, é o comando de exibir mensagens) escrevendo o valor de i. Portanto serão exibidas 30 mensagens. O valor de i e incrementado automaticamente ao fim do loop. Veja:
for i := 1 to 30 do (i=1) => ShowMessage(...) => (retorna a origem) for i := 1 to 30 do (i=2) => ShowMessage (...) =>
(...)
for i := 1 to 30 do (i=30) => ShowMessage (...) => Fim do loop.

O comando While é semelhante, veja um exemplo de seu uso:

var k:integer; //(declara a variável k).
k := 0 //(define o valor de k como "0".
while k < 10 do
ShowMessage ('k é menor que 10');

 "QUANDO" (WHILE) k é menor que 10 exibe a mensagem "k é menor que 10" (a mensagem em Delphi realmente deve estar entre apóstrofos (aspas simples) e não aspas duplas (como em muitas linguagens)). No entanto este loop não deve ser usado desta forma, pois, ao contrário de "for", while NÃO incrementa automaticamente o número, portanto o loop nunca acabará, pois k é 0 e sempre será 0 (foi definido esse valor em "k := 0"). Portanto seria melhor fazer:

var k:integer; //(declara a variável k).
begin
k := 0 //(define o valor de k como "0". 
while k < 10 do
begin
ShowMessage ('k é menor que 10);
k := k + 1;
end;

 
Agora o valor de k será incrementado de 1 toda a vez que o loop "retornar", portanto depois de 10 mensagens o loop acabará (k vai de 0 até 9). Não se importe com o "begin" e "end" eles serão discutidos mais adiante.

Introdução a linguagem e migrando para Delphi

Variáveis

 Talvez programadores oriundos de outras linguagens tenham certa dificuldade para se acostumar com os padrões delphi. A declaração de variáveis e seu uso, provavelmente parecerá chato para programadores Visual Basic. Vamos a algumas regras práticas:

  1. Não é possível declarar variáveis em qualquer lugar, apenas no início do procedimento.

  2. Os tipos de dados Delphi não são compatíveis (como no VB), por exemplo, você não pode multiplicar a string "X" pela string "Y", mas sim transformá-las em números inteiros e depois multiplica-los, veja: Z := StrToInt(X) * StrToInt(Y);.

Nem mesmo números inteiros são compatíveis com reais.

Sinal de igual

 Não use o sinal de igual para atribuir valores (como em grande parte das linguagens) mas sim ":=" como na linha abaixo:

 i := 0;

 O sinal de igual é usado apenas para comparação como em comandos "If", veja:

 If i = 0 then
ShowMessage('O valor de i é 0');
else
ShowMessage('O valor de i não é 0';

 Note que não se usa o EndIf como no caso do Visual Basic, por exemplo... Mas pode-se usar o begin e end para determinar o início e o fim como em:

if i = 0 then
begin
ShowMessage('O valor de i é 0');
ShowMessage('Foi usado Begin e End porque foram utilizadas duas linhas');
end
else
ShowMessage('O valor de i não é 0';

 Quando se usa uma única linha não há necessidade de usar Begin e End.

IMPORTANTE

Você deve ter notado que em Delphi não se usam aspas duplas ("), mas aspas simples ('), ou apóstrofo, como preferir. Também é usado ponto e vírgula (;) no final de cada comando (mas não nos que terminam com comandos como If. Mas lembre-se que NÃO se deve usar ponto e vírgula antes de else.

 Outro motivo pelo qual no final de cada declaração usa-se o ponto e vírgula é para mostrar que acabou. Por esta razão pode-se continuar o comando na linha de baixo (menos partir strings ao meio), veja:

 Estaria CORRETO:

MessageDlg ('Esta é uma mensagem!',
mtinformation, [mbok], 0);

 Mas estaria INCORRETO:

MessageDlg ('Esta é uma
mensagem!', mtinformation, [mbok], 0);

 Se for necessário use:

MessageDlg ('Esta é uma' +
+ ' mensagem!', mtinformation, [mbok], 0);

Isso é correto.

Comentários

 Os comentários podem estar entre chaves:

{Este é um comentário que pode estar
em mais de uma linha}

 entre sinais de parênteses e asterisco, como o mostrado abaixo:

(* este é um comentário
que pode estar em mais de uma linha
até que seja colocado o sinal de asterisco e fecha parênteses *)

 Ou pode estar depois de duas barras, para comentários rápidos de apenas uma linha, veja:

// Este comentário não pode passar de uma linha...

Operadores

 Eles são:

* - Multiplicação aritmética.
/ - Divisão de números que obtém um número real (exemplo: 5/2 = 2.5).
div - Divisão de números que obtém um número inteiro (exemplo: 5/2 = 2).
+ - Adição.
- - Subtração.
= - Igual.
<> - Diferente.
> - Maior.
>= - Maior ou igual.
< - Menor.
<= - Menor ou igual.

 Exemplo:

Form1.Canvas.TextOut (1, 1, IntToStr((2 * 5) div 3));

 Form1: Nome do formulário;
Canvas: Propriedade (não apenas do formulário) relacionada com desenho. Neste caso ela é usada para escrever no formulário (com o TextOut), algo como o print do Visual Basic. Sua cor de fundo padrão é branca, mas é possível mudá-la acessando a propriedade brush. O primeiro parâmetro é o left, o segundo é o top e o terceiro é o texto a ser escrito.
IntToStr: Transforma um inteiro em caracteres (como já foi dito anteriormente, o Delphi não possui compatibilidade entre Integers e Strings, a não ser que sejam usadas Variants).

 Iniciantes:

Para quem ainda não está integrado com programação aqui vão alguns conceitos:
Parâmetros: São "valores extras", colocados entre parênteses para fornecer outras informações ao método (function ou procedure). No exemplo mostrado, a função precisa dos parâmetros inteiros (que foram determinado como 1 neste caso) para saber a que distância da margem esquerda e o topo, respectivamente;
Left: Valor inteiro que diz a distância até o canto esquerdo de um objeto;
Top: Valor inteiro que diz a distância até o topo de um objeto;


Dicas...

Usando funções externas (de DLLs)...

Usar funções externas, de uma ou mais DLLs é muito simples, basta declara-las da seguinte forma:

function NomeDaFuncao(Parâmetros: Tipo): TipoRetorno; stdcall; external 'NomeDaDLL';

Você pode ver o nome de uma função da DLL na Visualização Rápida do Windows (se esta estiver sido instalada), para isso encontre o arquivo DLL, clique nele com o botão direito do mouse e escolha visualização rápida.

Manipulando "Application"...

A classe TApplication proporciona muitas manipulações úteis do aplicativo como um todo. Por exemplo, caso você queira que quando um aplicativo for minimizado apareça a hora atual no título da barra de tarefas, e quando ele for restaurado não apareça, use o seguinte código no evento OnLoad do formulário, por exemplo:

Application.OnMinimize := ShowDate;
Application.OnRestore := NShowDate;
 
procedure ShowDate;
begin
TForm1.Timer1Timer(Sender);
Timer1.Enabled := True;
end;
 
procedure NShowDate;
begin
Timer1.Enabled := False;
Application.Title := 'Título do Aplicativo';
end;

Este exemplo considera que o aplicativo possua um relógio que atualiza de tempos em tempos (a cada 250 milésimos de segundo por exemplo). Este é desabilitado quando o formulário é restaurado.

Undo na caixa de texto (Memo)...

Use o seguinte código para Desfazer a última ação em uma caixa de Texto (Memo):

Memo1.Perform(EM_UNDO, 0, 0);

o valor retornado de Memo1.Perform(EM_CANUNDO, 0, 0) será diferente de zero se o comando de Desfazer estiver disponível.

Pegando a posição do cursor...

Use o seguinte código para ver a posição do cursor na tela, ele é muito útil quando o evento usado não possui como parâmetros "X" e "Y":

procedure GetPosition (var X; var Y);
var CPos: TPoint;
begin
GetCursorPos(CPos);
X := CPos.X;
Y := CPos.Y;
end;

Guia Inicial Rápido Para Otimização de Índices


Veja neste artigo a tradução de um post feito por Paul Beach em seu blog, que foi mencionado pelo site firebirdnews.org, mas cujos conceitos se aplicam a praticamente todos os SGBDs.
Abaixo, é apresentado um rápido guia inicial com cinco (na verdade seis) pontos para a otimização de índices, cortesia de Pavel Cisar.
1. Sempre defina TODAS as regras (constraints) de integridade: chaves primárias, estrangeiras e índices únicos. Isto será automaticamente utilizado na otimização de junções (joins).
2. Defina índices separados para CADA COLUNA que será utilizada em regras adicionais de suas consultas (ex: filtros em cláusulas WHERE), que não fazem parte do primeiro ponto (pk's, fk's e uniques).
3. Atualize as estatísticas de seus índices regularmente, visto que dados são inseridos / modificados / excluídos em sua base de dados. Uma boa regra geral é atualizar as estatísticas dentro de suas rotinas de manutenção (quando fizer backup, sweep, etc.), e/ou sempre que você inserir / alterar um quarto de todos os registros, uma vez que a tabela possua mais de 10.000 registros.
4. Uma vez tendo dados representativos do mundo real em seu banco de dados, você pode avaliar a usabilidade dos índices para eliminar aqueles que não ajudam suas instruções SQL (um índice insignificante apenas tornará lento seus inserts e updates!) e adicionar novos índices compostos ou de expressões, que aumentem a performance de instruções específicas.
5. Índices inúteis são normalmente aqueles com baixa seletividade (poucos valores distintos). Execute algumas consultas com filtros condicionais em colunas com baixa cardinalidade e verifique quando o otimizador usa o índice ou não. Se o índice de baixa seletividade é sempre ou frequentemente usado em outras condições de filtro, você pode melhorar a sua seletividade e consequentemente a sua usabilidade, criando um índice composto com as colunas que são usadas nestes outros filtros, ao invés de usar índices independentes em cada coluna.
6. Se você sempre / frequentemente usa um grupo de colunas para filtros, um índice composto nestas colunas pode melhorar a performance do comando, mas faça isso apenas se não estiver satisfeito com a performance que os índices em colunas individuais provêem.

quarta-feira, 19 de janeiro de 2011

Criando formulários

Qual a melhor maneira de criar forms em tempo de execucao:

 

a) Application.CreateForm(TfmClientes, fmClientes);

                Cria o Form; o proprietário é a aplicação.

 

b) fmClientes := TForm.Create(self);

                Cria o Form; o proprietário é ele mesmo.

 

c) fmClientes := TForm.Create(Application);

                Cria o Form; o proprietário é a aplicação.

 

d) fmClientes := TForm.Create(nil);

                Cria o Form; teoricamente sem proprietário; na prática é a aplicação.

 

e) fmClientes := TfmClientes.Create(self);

                Cria o Form; o proprietário é ele mesmo.

 

f) fmClientes := TfmClientes.Create(Application);

                Cria o Form; o proprietário é a aplicação.

 

g) fmClientes := TfmClientes.Create(nil);

                Cria o Form; teoricamente sem proprietário; na prática é a aplicação.

 

Poderiam me informar a diferenca entre elas?

 

                Quando você cria um Form dinamicamente:

1. se criar através de CreateForm, que é um método de TApplication, você passa como parâmetro a instância da classe e o nome do seu objeto (TfmClientes, fmClientes);

 

2. se criar através de Create - método de TForm, entre outros - você passa como parâmetro o proprietário do componente criado (no caso o Form).

                2.1 se o proprietário for a aplicação, o Form só será destruído quando você finalizar o aplicativo

                     ou se você declarar Free ou Destroy no seu programa; (casos a, c, d, f, g);

                2.2 se o proprietário for ele mesmo (self), o form terá que ser destruído por você;

                2.3 se você criar, por exemplo, Form2 e passar como proprietário Form1; no momento em que

                     Form1 for destruído, Form2 também o será.

 

                Quanto à melhor maneira, depende de como você quer controlar a aplicação, mas leve em conta que enquanto um objeto não é destruído, ele está na memória.

terça-feira, 18 de janeiro de 2011

Como executar um avi no form

Crie dois formulários e adicione o componente TmediaPlayer no seu form, depois coloque um botão e adicione o código abaixo no evento onclick do mesmo.

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
with MediaPlayer1 do
begin
   // coloque o path de um avi
   FileName := ' C:\Arquivos de programas\Borland\Delphi6\Demos\CoolStuf\speedis.avi';
   Open;
   Display := Form2;
   Form2.Show;
   Play;
end;
end;

Número de cores aceitas pelo monitor

O código abaixo apresenta a implementação de uma função que retorna o número de cores suportadas pelo monitor.

Esta função baseia-se na utilização de uma API do Windows, chamada GETDC.:

Function QtdeCores : integer;var h : HDC;
begin
Result := 0; try h := GetDC( 0 );
Result :=1 shl ( GetDeviceCaps( h, PLANES ) * GetDeviceCaps( h, BITSPIXEL ));
finally
ReleaseDC( 0, h );
end;
end;

Para executar esta função coloque um objeto edit e um objeto button, no evento onclick do botão insira o seguinte código:

edit1.text:= inttostr(Qtdecores);

Ao clicar no botão o objeto edit recebe a quantidade de cores que o monitor está suportando.

Como mudar a resolução do vídeo via programação

1º Coloque um listbox no form

Modifique o OnCreate do form assim:
 
procedure TForm1.FormCreate(Sender: TObject);
var
  i : Integer;
  DevMode : TDevMode;
begin
  i := 0;
  while EnumDisplaySettings(nil,i,Devmode) do begin
  with Devmode do
  ListBox1.Items.Add(Format('%dx%d %d Colors',
  [dmPelsWidth,dmPelsHeight, 1 shl dmBitsperPel]));
  Inc(i);
  end;
end;
- Coloque um botão no form
- Altere o evento OnClick do botão conforme abaixo:
 
procedure TForm1.Button1Click(Sender: TObject);
var
  DevMode : TDevMode;
begin
  EnumDisplaySettings(nil,Listbox1.ItemIndex,Devmode);
  ChangeDisplaySettings(DevMode,0);
end;

segunda-feira, 17 de janeiro de 2011

Bloquear Mouse e Teclado

Para testar essa dica coloque um Timer sete o interval para 5000 e um Botão e coloque o código abaixo!
O código travará o mouse e teclado por 5 segundos!

Use com cuidado e responsabilidade... Não me venha travar o mouse sem programar uma ação para destravá-lo!

unit Unit1;

interface

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

type
TForm1 = class(TForm)
  Button1: TButton;
  Timer1: TTimer;
  procedure Button1Click(Sender: TObject);
  procedure Timer1Timer(Sender: TObject);
private
  { Private declarations }
public
  { Public declarations }
end;
procedure BlockInput(ABlockInput : boolean); stdcall; external 'USER32.DLL';
var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
BlockInput(True);
Timer1.Enabled:=True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
BlockInput(false);
Timer1.Enabled:=false;
end;

end.

Sugestão para tratamento de erros no Delphi / Cliente-Servidor

Todas as vezes que são abertas as tabelas é colocado o comando StartTransaction antes da abertura das mesmas.
Quando acontece algum erro na abertura das tabelas, o Delphi dispara uma mensagem de erro. Este erro pode ter sido provocado por diversos motivos mas é certo que o erro foi de alteração de uma ou mais tabelas no Banco de Dados. é aconselhável que se coloque uma rotina de tratamento de erro listada abaixo: 
- Onde estão as tabelas, coloque as suas tabelas que serão abertas; 
- Onde será mostrada a mensagem coloque uma mensagem qualquer avisando sobre o erro 
try
   if F_Menu.DBSistema.IsSQLBased then 
      F_Menu.DBSistema.StartTransaction;
   Tabela1.Open;
   Tabela2.Open;
   Tabela3.Open;
   Tabela4.Open;
except
   on EDatabaseError do
     if MessageDlg(, mtError, [mbOK], 0) <> mrOK Then
       raise;
     end;
ShowModal;  
Sugestão  Delphi / Oracle  
      Criar uma função que irá verificar qual o código de erro enviado pela exceção e então emitir uma mensagem em português. Abaixo está uma idéia desta rotina que será inserida no formulário principal da sua aplicação.  
procedure TF_Menu.ErrorMsg(Sender : TObject; E: exception);
begin
if e is EDBengineError then
      TrataErro(E as edbEngineError)
else
    application.showException(E);
end;  
procedure TF_Menu.TrataErro(E: eDBEngineError);
var
nSQLError   : integer;
cSQLMessage : string;
cTable      : string;
x           : integer;
begin
    nSQLError := 0;
    cSQLMessage := '';
    for x:=0 to e.ErrorCount -1 do
       if e.errors[x].NativeError <> 0 then
       begin
          nSQLError   := e.errors[x].NativeError;
          cSQLMessage := e.errors[x].message;
       end;
       if nSQLError <> 0 then
       begin
          cTable := '';
          x      := pos('table"',cSQLMessage);
          if x > 0 then
          begin
             cTable := copy(cSQLMessage,x+7,20);
             x      := pos('"',cTable);
             if x > 0 then cTable := copy(cTable,1,x-1);
          end;
       case nSQLError of
               1  : showmessage('Este registro já está cadastrado.');
          2292 : showmessage('Este resgistro não pode ser excluído porque'+#10+
                     'existem outros que dependem dele e que não foram excluídos');
        12203 : showmessage('Base de Dados está fora do ar. Favor entrar'+#10+
                     'em contato com o responsável pela rede na '+#10+
                     'localidade selecionada ou tente mais tarde.');
       else
          showmessage(IntToStr(nSQLError)+' '+cSQLMessage);
       end;
    end
else
    showmessage('Algo errado aconteceu!');
end;
 
procedure TF_Menu.FormCreate(Sender: TObject);
begin
  Application.OnException := ErrorMsg;
end;

Tradução de Mensagens Delphi

Depois de algum tempo pesquisando uma forma de fazer aparecer as mensagens em português, consegui uma solução muito fácil de implementar no ambiente de programação do Delphi 3.
 
CHEGA DE YES/NO !!!
 
messagedlg('Confirma ? mtConfirmation, [mbYes, mbNo], 0);
 
Aí vai:
 
1 - No diretório DELPHI3\LIB, copie o arquivo consts.dcu para consts.old;
2 - Inicie o Delphi e crie um nova Unit;
3 - Insira nesta, o arquivo consts.int do diretório DELPHI3\DOC E faça as devidas alterações nas mensagens que desejares alterar e nas partes duplicadas da Unit como "implement" e etc, também deixe o
cabeçalho como Unit Consts.
4 - Salve esta nova Unit no diretório DELPHI\LIB e pronto todas as mensagens alteradas por você estarão aplicadas nos seus próximos programas sem uma linha de programa e da forma que você quiser.

Linkar um OBJ ao executável

Primeiro você deve "linkar" o OBJ ao seu executável.  No Delphi , isto é feito com a diretriz de compilação $L.  Fica, na sua unit principal, assim:

{$L MyOBject.OBJ}  

Incluindo as chaves.

Logo depois, você deve declarar a função contida em MyObject.OBJ da forma usual.  Você precisara conhecer os parâmetros usados pela mesma, bem como o tipo e a ordem em que sao passados.   Voce deve incluir tambem a diretriz PASCAL ou CDECL.  Sugiro tentar primeiro com PASCAL.  Ficaria assim (na
secao implementation:

function (Parametro1 : TipoDoParametro1, Parametro2 : TipoDoParametro2):
TipoDoRetorno; pascal;

se nao der certo, tente:

function (Parametro1 : TipoDoParametro1, Parametro2 : TipoDoParametro2):
TipoDoRetorno; cdecl;

caso nao seja uma funcao e sim uma procedure, tente

procedure (Parametro1 : TipoDoParametro1, Parametro2 : TipoDoParametro2);
pascal;
ou
procedure (Parametro1 : TipoDoParametro1, Parametro2 : TipoDoParametro2);
cdecl;

Se voce nao sabe quais os parametros usados pela funcao/procedure, uma solucao seria linkar o seu OBJ num programa qualquer e disassembla-lo.  Ai pelo menos voce sabera a quantidade e o tipo de cada parametro. De qualquer forma, para saber para que serve cada um, tera que ser na tentativa e erro...a nao ser que voce tambem tenha paciencia para analisar o codigo disassemblado.

OBS:  Se o seu OBJ nao estiver num formato reconhecivel pelo LINK do Delphi (um formato similar ao COFF), voce pode tentar outros Linkers, e criar uma dll.  Existem varios linkers gratuitos, que reconhecem varios formatos (exemplos, sao lcclnk, djlnk, walk2lnk e o proprio linker da microsoft...tambem gratuito).

Traduzir captions e botões da MESSAGEDLG

Para traduzir algumas as mensagens do Delphi que aparecem nos botões e nas caixas de avisos da função MessageDlg, você necessita dos arquivos de recursos do Delphi (*.RC).
Possuo o Delphi 2 - Developers, que vem acompanhado de alguns destes arquivos de recursos.  No meu caso, eles estão gravados em C:\DELPHI2\SOURCE\VCL.
Os arquivos *.RC são arquivos "só texto", e contêm diversas mensagens utilizadas nos programas compilados no Delphi.  O exemplo que se segue realiza alterações nos arquivos CONSTS.RC e DBCONSTS.RC.  A alteração de outros arquivos "RC" pode ser feita de modo similar.   Para maiores detalhes, envie-me um e-mail (paulosd@dglnet.com.br), ou, melhor ainda, consulte o livro "Dominando o Delphi" (edição para o Delphi 1), de Marcos Cantù, ed. Makron Books.   O assunto "Usando recursos de tabelas de strings" está no capítulo 21, página 876.  Não sei se a edição para o Delphi 2 cobre este assunto.

a) Faça uma cópia dos arquivos CONSTS.RC e DBCONSTS.RC em um diretório seguro, para o caso de algo sair errado.

b) Pelo mesmo motivo, faça uma cópia dos arquivos CONSTS.RES e DBCONSTS.RES, que estão no diretório LIB do Delphi.   No meu caso, o diretório destes arquivos é C:\DELPHI2\LIB.

c) Use o Bloco de Notas para abrir e alterar os arquivos CONSTS.RC e DBCONSTS.RC. (O Edit também serviria;  entretanto, para acentuação correta no Windows, o Bloco de Notas é melhor).

Você só deve alterar as strings que estão entre aspas. Não altere o nome das constantes, que estão no início de cada linha.
Por exemplo, localize o seguinte bloco, em CONSTS.RC:

SCancelButton, "Cancel"
SYesButton, "&Yes"
SNoButton, "&No"

Altere para:

SCancelButton, "Cancelar"
SYesButton, "&Sim"
SNoButton, "&Não"

Não é necessário alterar todas as mensagens.  Se desejar, altere apenas aquelas que você utiliza em seus sistemas.  Lembre-se de salvar as alterações efetuadas.

d) Acione o prompt do DOS, e execute do seguinte modo o compilador de recursos do Delphi 2 (BRC32.EXE), que está no diretório BIN do Delphi (no meu caso, C:\DELPHI2\BIN):

C:\DELPHI2\BIN\BRC32 -R CONSTS.RC
C:\DELPHI2\BIN\BRC32 -R DBCONSTS.RC

(No Delphi 1, o compilador tem o seguinte nome:   BRC.EXE).

e) Os dois comandos anteriores irão gerar os arquivos CONSTS.RES e DBCONSTS.RES.  Copie os dois "*.RES" para o diretório LIB do DELPHI (no meu caso C:\DELPHI2\LIB)

f) Crie uma aplicação no Delphi que utilize a função MessageDlg, e botões "BitBtn".  Ao rodar o seu programa, as mensagens já devem aparecer traduzidas.