Delphi em Alguns capítulos!

Started by Trojan, 31 de July , 2007, 06:30:27 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Trojan

Capítulo 1
 - Conceito de Programação Orientada a Objeto
Para compreendermos melhor a novo ambiente de desenvolvimento da Borland o Delphi é necessário que você, aprenda e, tenha em mente os conceitos de POO (Programação Orientada a Objetos), não confunda os conceitos com POE (Programação Orientada a Eventos) muito difundido com o Access 2.0 © (um ambiente baseado em Objetos), mas ao longo deste capítulo você vai notar as sensíveis diferenças que existem entre esses dois conceitos.
A POO e a POE são facilmente confundidas, mas lembre-se a POO contém a POE mas a POE não contém a POO, um objeto pode existir mesmo que não exista nenhum evento associado a ele, mas um evento não pode existir se não houver um objeto a ele associado. Outra característica que pode causar confusão são ambientes Orientados a Objetos e ambientes Baseados em Objetos. Em ambiente Orientado a Objetos consegue-se criar e manipular objetos enquanto que o Baseado em Objetos não é possivel a criação de objetos apenas a sua manipulação.
A POO é um conceito desenvolvido para facilitar o uso de códigos de desenvolvimento em interfaces gráficas. Sendo a Borland, uma das primeiras a entrar neste novo conceito, possui suas principais linguagens de programação (tais como Object Pascal e C++), totalmente voltadas para este tipo de programação. A POO atraiu muitos adeptos principalmente pelo pouco uso de código que o projeto (diferente de sistema) carrega no programa fonte, ao contrário das linguagens mais antigas como o Clipper'87 © muito utilizado no final da década de 90 e início da década de 90. O resultado desta "limpeza" no código resulta que a manutenção do projeto torna-se muito mais simples.
Orientação a Objeto
Antes de começarmos a falar realmente de linguagem orientada a objetos e necessário que você possua os conceitos básicos da orientação a objetos, são eles:

 
Objeto - é qualquer estrutura modular que faz parte de um produto. Uma janela por exemplo, é um objeto de uma casa, de um carro ou de um software com interface gráfica para o usuário.
Atributos - São as características do objeto, como cor e tamanho, a janela, por exemplo, tem atributos como o modelo, tamanho, abertura simples ou dupla, entre outros.
Encapsulação - é um mecanismo interno do objeto "escondido" do usuário. Uma pessoa pode abrir uma janela girando a tranca sem precisar saber o que há dentro dela.
Ação - é a operação efetuada pelo objeto. Todas as janelas, por exemplo, controlam a iluminação e temperatura ambiente, dependendo do seu design.
Herança - um objeto novo nem sempre é criado do zero. Ele pode "herdar" atributos e ações de outros já existentes. Um basculante herda atributos das janelas e das persianas.
Polimorfismo - é a capacidade de objetos diferentes reagirem segundo a sua função a uma ordem padrão. O comando  "abre", por exemplo, faz um objeto entrar em ação, seja ele uma janela, uma porta ou uma tampa de garrafa.
Ligação - é quando um objeto conecta a sua ação a outro. Um sensor de claridade, por exemplo, ativa o acendimento automático da iluminação de rua.
Embutimento - Permite a um objeto incorporar funções de outros, como um liqüidificador que mói carne com a mudança do tipo da lâmina.

 - Object Pascal
Object Pascal é uma linguagem Orientada a Objetos não pura mas híbrida por possuir características de programação não só visual mas também escrita, para os programadores que já conhecem técnicas de estruturas de programação, com o C, Basic, Pascal ou xBASE entre outras linguagens a Object Pascal providência uma migração de forma natural oferecendo um produto de maior complexibilidade. Object Pascal força a você executar passos lógicos isto torna mais fácil o desenvolvimento no ambiente Windows© de aplicações livres ou que utilizam banco de dados do tipo Cliente/Servidor, trabalha com o uso de ponteiros para a alocação de memória e todo o poder de um código totalmente compilável. Além disso possibilita a criação e reutilização (vantagem de re-uso tão sonhado com a Orientação a Objetos) de objetos e bibliotecas dinâmicas (Dynamic Link Libraries - DLL). 
Object Pascal contém todo o conceito da orientação a objetos incluindo encapsulamento, herança e polimorfismo. Algumas extensões foram incluídas para facilitar o uso tais como  conceitos de propriedades, particulares e públicas, e tipos de informações em modo run-time, manuseamento de  exceções, e referências de classes. O resultado de toda esta junção faz com que Object Pascal consiga suportar as facilidades de um baixo nível de programação, tais como:
•   Controle e acesso das subclasses do Windows© (API);
•   Passar por cima das mensagens de loop do Windows©;
•   Mensagens semelhantes as do Windows©;
•   Código puro da linguagem Assembler.

 Como deu para perceber a base de toda a programação Delphi é a linguagem Object Pascal, então neste capítulo trataremos exclusivamente deste tipo de programação.
Símbolos Especiais
A Object Pascal aceita os seguintes caracteres ASCII:

?   Letras - do Alfabeto Inglês: A até Z e a até z.
?   Dígitos - Decimal:  0 até 9 e HexaDecimal: 0 até 9 e A até F (ou a até f)
?   Brancos - Espaço (ASCII 32) e todos os caracteres de controle ASCII (ASCII 0 até ASCII 31), incluindo final de linha e Enter (ASCII 13).
?   Especiais - Caracteres: + - * / = < > [ ] . , ( ) : ; ^ @ { } $ #
?   Símbolos - Caracteres: <=  >=  :=  ..   (*  *)  (.  .)  //
?
 O colchetes esquerdo ( [ ) e equivalente ao (. e o colchetes direito ( ] ) e equivalente a .). A chave esquerda ( { ) e equivalente ao (* e a chave direita ( } ) e equivalente a *).
Palavras Reservadas
A Object Pascal se utiliza das seguintes palavras reservadas, não podendo as mesmas serem utilizadas ou redefinidas:

And   Exports   Library   Set
Array   File   Mod   Shl
As   Finnaly   Nil   Shr
Asm   For   Not   String
Begin   Function   Object   Then
Case   Goto   Of   To
Class   If   On   Try
Const   Implementation   Or   Type
Constructor   In   Packed   Unit
Destructor   Inherited   Procedure   Until
Div   Initialization   Program   Uses
Do   Inline   Property   Var
Downto   Interface   Raise   While
Else   Is   Record   With
End   Label   Repeat   Xor
Except         

Uma outra lista a seguir, apresenta as diretivas que são utilizadas em contextos de identificação de objetos:

Absolute   Export   Name   Published
Abstract   External   Near   Read
Assembler   Far   Nodefault   Resident
At   Forward   Override   Stored
Cdecl   Index   Private   Virtual
Default   Interrupt   Protected   Write
Dynamic   Message   Public   
Números

É possível definir variáveis e constantes de tipos de Inteiro ou Real através de qualquer decimal ordinário ( 0 a 9 ), mas a Object Pascal também aceita a notação Hexadecimal utilizados com o prefixo dollar ( $ ) ou a notação científica ( E ).
Constantes
Uma constante é um identificador com valor(es) fixo(s). Um bloco de declarações constante possui a seguinte expressão:
[Declaração Constante]  [Identificador]  (=)  [constante] (;)
A lista abaixo apresenta um conjunto de funções que podem ser utilizadas para a declaração das constantes:

Ab   Length   Ord   SizeOf
Chr   Lo   Pred   Succ
Hi   Low   Ptr   Swap
High   Odd   Round   Trunc
Alguns exemplos para a definição de Constantes:
const Min = 0;
Max = 100;
Centro = (Max - Min) div 2;
Beta = Chr(225);
NumLetras = Ord('Z') - Ord('A') + 1;
MensOla = 'Instrução inválida';
MensErro = ' Erro: ' + MensOla + '. ';
PosErr = 80 - Length(MensErro) div 2;
Ln10 = 2.302585092994045684;
Ln10R = 1 / Ln10;
DigNumericos = ['0'..'9'];
LetrasAlpha = ['A'..'Z', 'a'..'z'];
AlphaNum = LetrasAlpha + DigNumericos;
Expressões
As expressões em Object Pascal (como em qualquer linguagem) é formada por operadores e operandos; os operadores são divididos em quatro categorias básicas:
Únicos   @, Not
Multiplicativos   >, /, div, mod, and, shl, shr, as
Adicionais   +, -, or, xor
Relacionais   =, < >, <, >, < =, > =, in, is
As expressões obdecem as regras básicas de lógica para a precedência da execução das operações.
Identificadores
Identificadores podem ser constantes, tipos, variáveis, procedures, funções, unidades, programas e campos de registros.
Não existe limite de caracteres para o nome de um identificador mas apenas os 63 primeiros caracteres são significantes (não podendo ser idêntico ao nome das palavras reservadas). O nome de um identificador deve ser iniciado por Letras ou o carácter underscore ( _ ). O resto é formado por Letras, Dígitos, carácter underscore (ASCII $5F). Não é permitido a utilização de espaços para a formação do nome.
? Exemplo de identificadores válidos: Form1, SysUtils.StrLen, Label1.Caption
with... do...;
Delimita um determinado bloco de declarações para um identificador específico evitando a declaração deste identificador. A sintaxe do comando é: WITH {nome do identificador} DO {comandos};. Ex:

begin
     { ... comandos iniciais ... }
     with form1 do
     begin
        Caption := 'Teste';      ? Equivalente a Form1.Caption
        BorderStyle := bsSizable;   ? Equivalente a Form1.BorderStyle
     end;
end;
array [ ... ] of ...;
Define um conjunto de variáveis ou constantes de um mesmo tipo. A sintaxe do comando é: array [{quantidade de ocorrencias}] of {Tipo};. Os arrays são controlados por três funções:

Função   Valor de Retorno
Low   Primeiro elemento
High   Aponta para o último elemento
SizeOf   Tamanho do array
Ex:

const
    t: array [1..50] of Char    { Declara 50 elementos para o tipo Char }
var
    s : array[1..100] of Real   { Declara 100 elementos para o tipo real }
   ind: Integer;
begin
    for Ind := Low(s) to High(s) do s[Ind] := 0;     { Zera os elementos do array S }
    if SizeOf(t) = 'C' then exit;              { Se o último elemento do array T for 'C' sai do bloco }
    { ... outros comandos... }
end;

Declarações
Declarações descrevem ações de um algorítmo a serem executadas.
begin... end;
Prende um conjunto de declarações em um bloco de comandos determinado. A sintaxe do comando é: BEGIN {comandos} END;. Ex:

begin
     { ... comandos iniciais ... }
     begin
        { ... bloco 1 ... }
     end;
     begin
        { ... bloco 2 ... }
     end;
     { ... comandos finais ... }
end;

if... then... else...;
Esta expressão escolhe entre o resultado de uma condição booleana o caminho verdadeiro (then) ou falso (else). A sintaxe do comando é: IF {condição} THEN {bloco de comandos} ELSE {bloco de comandos};. Ex:

begin
     { ... comandos iniciais ... }
     if  x > 2 then
        { ... Bloco verdadeiro ... }
     else
        { ... Bloco falso ... };
end;

goto... ;
Transfere a execução de um programa para o ponto determinado pelo Label. A sintaxe do comando é: GOTO {Label};. Ex:

label
   primeiro;
begin
     { ... comandos iniciais ... }
     if x = 2 then
        goto primeiro;
     { ... outros comandos ... }
Primeiro:
     { ... comandos do Primeiro ... }
end;

case... of... else... end;
Consiste de uma lista de declarações que satizfaz a condição de um seletor de expressões, se nenhuma parte da lista satisfizer ao seletor executa os comandos do sub-comando else. Para o seletor serão válidos os tipos definidos, tipo Inteiros ou LongInt. A sintaxe do comando é: CASE {seletor} OF {Expressão 1}: {comando da expressão 1}; {Expressão 2}: {comando da expressão 2}; {Expressão n}: {comando da expressão n} ELSE {comando}; end;. Ex:

begin
     { ... comandos iniciais ... }
     case x of
        1: { ... Bloco para x = 1 ... }
        2, 3: { ... Bloco para x = 2 ou X = 3... }
        4..6: { ... Bloco para  4 <= x <= 6 ... }
     else
        { ... Bloco para  x < 1 ou x > 6 ... };
     end;
end;

repeat... until;
Repete um determinado bloco de declarações até a condição booleana do subcomando until ser satisfeita. A sintaxe do comando é: REPEAT {comandos}; until {condição};. Ex:

begin
     { ... comandos iniciais ... }
     x := 0;
     repeat
        x := x + 1
     until (x = 2);
end;

for... to (downto)... do...;
Incrementa em 1 uma determinada variável inteira, repetindo um bloco de comandos, até que esta atinja o valor final do intervalo, o subcomando downto realiza o incremento reverso. A sintaxe do comando é: FOR {variavel} := {valor inicial} to (downto) {valor final} do {bloco de comandos};. Ex:

begin
     { ... comandos iniciais ... }
     for i := 1 to 10 do      ? Executa o [comandos A] para i = 1,2,3,4,5,6,7,8,9 e 10
        { ... Comandos A ... }
     for s := 10 downto 1 do   ? Executa o [comandos B] para i = 10,9,8,7,6,5,4,3,2 e 1
        { ... Comandos B... }
end;

while... do...;
Repete um bloco de comandos enquanto que determinada condição booleana seja satisfeita. A sintaxe do comando é: WHILE {condição} DO {bloco de comandos};. Ex:

begin
     { ... comandos iniciais ... }
     while i := 1 do      ? Repete o [Bloco de comandos] enquanto i = 1
        { ... Bloco de comandos ... }
end;

break; ou continue...;
O comando break interrompe um bloco de repetição for, while ou repeat saindo do bloco. A sintaxe do comando é: BREAK; enquanto que o comando continue retorna a primeira instrução do bloco de repetição for, while ou repeat. A sintaxe do comando é: CONTINUE;. Ex:

begin
    { ... comandos iniciais ... }
    for i := 1 to 10 do
    begin
        if i = 8 then
            break;          ? Salta para os [comandos C]
        {... comandos A...}
        if i = 5 then
            continue;         ? Retorna para o comando for pulando os [comandos B]
        {...  comandos B ...}
    end;
    {...  comandos C ...}
end;
Blocos de Procedimentos ou Funções
As procedures ou funções são declaradas na seção de tipos de declarações (abaixo do comando type) pertencendo ao objeto ou serem do tipo public (públicas - executadas por outras unidades) ou private (particulares - restritas a unidade local).
Procedure
procedure {cabeçalho}; var {declaração das variáveis}; {bloco de comandos};
O cabeçalho da procedure é composto pelo nome do procedimento e variáveis que serão recebidas (ou modificadas através da declaração var, ex: procedure teste(var x:string);).

procedure soma(a,b: integer);      ? Início enviando as variáveis A e B do tipo inteiro.
var               ? Declaração de variáveis locais.
   c: integer;
begin               ? Corpo do procedimento.
   c := a + b;
end;

Function
function {cabeçalho} : {resultado}; var {declaração das variáveis}; {bloco de comandos};
As funções se diferem dos procedimentos pela obrigatoriedade do retorno de um resultado, podendo este resultado ser retornado pela declação: {nome da função} := valor ou result := valor.

function soma(a,b: integer) : integer;   ? Início enviando as variáveis A e B do tipo inteiro.
begin               ? Corpo do procedimento.
   soma := a + b;            ? ou  result := a + b;
end;
? Junto com o Delphi 2.0 vem o manual de Object Pascal em formato .HLP, caso a linguagem seja novidade para você aconselho que você dê uma boa olhada (o Delphi 1.0 traz o mesmo manual, mas em formato .PDF), mas não se preocupe com o que foi explicado acima já está mais do que suficiente para uma boa inicialização com o Delphi.
Tudo o que vimos a cima é o que normalmente temos em outras linguagens comuns, mas o caracteriza realmente a linguagem Orientada em Objetos é o trabalho e a manipulação com os mesmos.
Características de Objetos
Mas afinal de contas, o que é um objeto ? Como foi dito anteriormente, um objeto é qualquer tipo de elemento, ou componente, que envolva dados e código dentro de um único pacote.
Uma vantagem de programar na POO e quanto a Herança dos objetos, este método faz com que seja possível um objeto 'Filho' poder herdar todas as características e conteúdos de um objeto 'Pai'. Tirando um pouco do Pascal da geladeira (a partir do Pascal versão 7.0 a Borland tornou possível a utilização simplificada de todo o conceito de POO) aqui vai um código completo de declaração de dois objetos, o primeiro chamado de TPai e o segundo de Tfilho:

TPai = object
    Nome: PChar;
    constructor Init (P: PChar);
    destructor Done;
    procedure MudaNome(P: PChar);
    procedure ShowName;
end;

TFilho = object(TPai)
    procedure MudaNome(P: PChar);
end;

O segundo objeto TFilho herda do objeto TPai o ponteiro variável Nome, a constructor Init, o destructor Done e a procedure ShowName, apenas a procedure MudaNome terá o funcionamento como uma característica única para cada objeto. O Delphi possui inúmeros "pais" (classes de objetos) prontos para serem usados por você, tais como:
TForm: Centro das aplicações Delphi, utilizados na criação de janelas, caixas de diálogo entre outros.
TMenu: Responsável pela concepção de menus e menu popup.
TButtonControl: Simplifica o refinamento do controle da janela serve de base para os componentes como: Botões, Check Box e Radio Box.
Programando com objetos Delphi
Quando iniciado o Delphi, é criado automaticamente um novo projeto e um objeto formulário (derivado da classe TForm) para o suporte dos demais objetos. Explorando o Editor de Códigos (Code Editor) você poderá observar a declaração do novo objeto da classe TForm que foi produzido automaticamente com a criação do novo formulário. Examinando o conteúdo deste código criado para o objeto, teremos:

unit Unit1;         ? Abertura de uma nova unidade

interface         ? Parâmetros do obejetos

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,    ? Uso de outras unidades
  Forms, Dialogs;

type
  TForm1 = class(TForm)               ? A declaração do objeto inicia aqui
  private
    { Private declarations }
  public
    { Public declarations }
  end;            ? Aqui é o final da declaração

var
  Form1: TForm1;       ? Atribui a variável Form1 as características do objeto TForm1

implementation         ? Início da parte a ser implementada

{$R *.DFM}         ? Diretiva de compilação que agrega o desenho da tela (em                        .DFM) com o mesmo nome da unidade
end.            ? Final da parte implementada

Um novo tipo de objeto TForm1, é declarado derivado da classe TForm, que também é um outro objeto. Relembre um objeto é um tipo de elemento capaz de guardar dados e código dentro de um único pacote. Até agora, o tipo TForm1 não contém campos ou métodos, isso acontecerá com a adição de alguns componentes neste objeto.
Observando o código, notamos que existe uma variável declarada com o nome Form1 para o novo tipo de objeto TForm1:
var
    Form1: TForm1;

Form1 é a chamada de instância ao tipo TForm1. Esta variável refere-se ao formulário em si, aonde será adicionado componentes e desenhado a interface entre o computador e o usuário que for operar o sistema. É sempre notado declarações de uma ou mais instâncias referidas ao tipo de objeto. Futuramente será mostrado o poder deste tipo de declarações quando falarmos sobre janela MDI (Multiple Document Interface - Interface de documento múltiplos) gerenciando várias "janelas filhas", não permitindo que estas "janelas filhas" saiam do espaço criado pela "janela pai".
Adicionando alguns componentes ao formulário, veremos como o Delphi completará a aplicação escrevendo automaticamente o código, e permitindo que ao final tornar-se-á possível a compilação (lembra-se do Clipper©, com .EXE), execução e distribuição da aplicação.
Em nosso formulário, colocaremos um botão que, em tempo de execução, ao ser dado um clique com o mouse sobre este objeto, o formulário mude sua cor. Aperte a tecla F12 para retornar a visão do formulário e na palheta de objetos (Componnent Pallete) clique no objeto   (button localizado na página Standard) e clique no formulário. Na janela da Object Inspector clique na página Events e clique duas vezes sobre a ação OnClick e insira o seguinte código:

procedure TForm1.Button1Click(Sender: TObject);
begin
   Form1.Color := clGreen;
end;
Reparando no código completo da aplicação, veremos:

unit Unit1;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs;

type
  TForm1 = class(TForm)                   
      Button1: TButton;            ? Um novo dado foi aqui inserido
      procedure Button1Click(Sender: TObject);   ? Declarado um novo método
  private
    { Private declarations }
  public
    { Public declarations }
  end;               

var
  Form1: TForm1;

implementation            

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);      ? O código do novo método
begin
   Form1.Color := clGreen;
end;

end.               
O novo objeto TForm1 agora apresenta um campo Button1 - o botão que você adicionou ao formulário. TButton e o tipo do objeto, e Button1 é o objeto botão propriamente dito. Com o tempo você colocará novos componentes ao formulário.
Rode o projeto, clicando no botão   (Run), dê um clique no botão e veja o que acontece. Pare a aplicação fechando a janela com Alt+F4.
? Só por curiosidade, salve este arquivo, feche-o e abra o arquivo UNIT1.DFM (com a opção File | Open File...) notaremos que o Delphi criou um arquivo com todas as propriedades dos objetos criados e que a declaração do objeto Form1 engloba todos os outros, noções de Encapsulamento.
Renomeando os objetos e os componentes
Você sempre deve utilizar a janela do Object Inspector para renomear os objetos criados. Por exemplo, o nome padrão do formulário e Form1 mude a propriedade Name para fCores. O Delphi se encarregará de mudar qualquer referência que existia ao Form1. Então o código apresentará a seguinte modificações:

unit Unit1;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs;

type
  TfCores = class(TForm)                         ? Aqui foi modificado
      Button1: TButton;            
      procedure Button1Click(Sender: TObject);   
  private
    { Private declarations }
  public
    { Public declarations }
  end;               

var
  fCores: TfCores;               ? Aqui foi modificado

implementation            

{$R *.DFM}

procedure TfCores.Button1Click(Sender: TObject);      ? Aqui foi modificado
begin
   Form1.Color := clGreen;            ? Aqui não !!!
end;

end.               
? O Delphi modificará apenas os códigos gerados automaticamente pôr ele. Os códigos para a ação OnClick foram gerados por você e o Delphi não os modificará. Cabe a você a manutenção neste caso. Isto foi idealizado para preservar o conteúdo original do seu código.

procedure TfCores.Button1Click(Sender: TObject);      
begin
  fCores.Color := clGreen;            
end;

Trojan

Capítulo 2
 - Conhecendo o Delphi
Se você teve algumas dúvidas no capítulo anterior sobre a área de trabalho do Delphi não se preocupe, neste capítulo você poderá saná-las completamente, também será mostrado o método de estrutura de aplicações Client/Server.
? Caso você seja usuário do Delphi 1.0 na barra de menu selecione a opção Help e Interactive Tutors, você receberá uma aula On-Line sobre a nova área de trabalho.
Os elementos da interface Delphi foram divididos do seguinte modo:
Elementos Visíveis
O ambiente de trabalho do Delphi é formado por objetos que estão visíveis tão logo que o aplicativo seja iniciado formando a área de trabalho.
 
Visão Geral dos objetos visíveis do Ambiente Delphi
Form
Os formulários (objeto Form) são os pontos centrais para o desenvolvimento Delphi. Você se utilizará deles para desenhar sua comunicação com o usuário, colocando e organizando outros objetos. Estes objetos são arrastados da Component Palette, mostrada na janela localizada acima.
Você pode imaginar que o formulário é um objeto que contém outros objetos. Sua aplicação ficará localizada em um formulário principal e este interagirá com outros formulários criados. É possível aumentar, mover ou ocupar completamente a tela do monitor, ou até mesmo ultrapassá-la. Um formulário básico inclui os seguintes componentes:
?   Controles de menu;
?   Botões de maximização e minimização;
?   Barra de título; e
?   Bordas redimensionáveis.
O código gerado, na área conhecida como Code Editor, fica exatamente atrás do objeto formulário, clique na barra de notas, em Unit1, se alguma coisa for desconhecida para você, leia maiores explicações no Capítulo I.
? É possível enviar um formulário para a impressora, para isto existem duas maneiras:
1.   Tipo um PrintScreen de Tela, coloque o seguinte comando "[Nome do formulário].Print;" no evento onShow do formulário; ou
2.   Para imprimir um formulário no tamanho de um papel A4, através do uso de comandos da biblioteca Printer, veja o Apêndice D para maiores detalhes.
Code Editor
O editor de códigos providência total acesso ao código gerado pelo projeto, incluindo alguns dos mais poderosos recursos para a edição. Pode ser selecionado tipos de cores para os elementos do programa (como por exemplo comentários, palavras reservadas, códigos assembler, ...) para tanto a partir do menu principal entre em Tools | Options..., localize a página Colors.
? Para outras informações adicionais sobre o modo de usar este editor, procure referências no Help OnLine no tópico Code Editor.
Ao ser aberto um novo projeto, o Delphi gera automaticamente na página do Code Editor uma Unit com o arquivo código (.PAS). Para ver o código de uma Unit em particular, simplesmente Click na tabulação de página. O Code Editor mostrará sempre o nome do arquivo corrente ativo na tabulação de página.
? É possível alternar entre o objeto Form e a Code Editor através do pressionamento da tecla F12, do botão botão   (Toggle Form/Unit) da SpeedBar, ou ainda através das opções do menu View | Toggle Form/Unit. (curiosidade: o acesso rápido através da tecla Alt + Letra sublinhada para esta opção está marcado sobre a letra G)
Component Palette
Componentes (ou objetos) são os elementos que você usará para trabalhar com a aplicação. Foram incluídos objetos em várias páginas, tais como caixas de diálogos e botões, a palheta inclui também alguns espaços em branco para ser permitida a adição de novos objetos. Alguns objetos não serão visíveis enquanto a aplicação estiver executando, eles fazem parte do serviço da DDE (Dynamic Data Exchange).
Os objetos da palheta foram divididos em grupos de funcionalidade em diferentes páginas. Por exemplo, os objetos que representam as janelas tradicionais do Windows© (tais como fontes, palheta de cores, ...) foram colocados na página Dialogs da palheta.
Você poderá criar seus próprios objetos como também instalar outros já prontos, para isso foi colocado os espaços vazios. Por exemplo poderá ser instalado novos controles e objetos do Visual Basic© 4.0 (Objetos OCX - ou para os portadores do Delphi 1.0 o do Visual Basic© 3.0 os objetos VBX). Uma das principais vantagens da POO é que muito em breve deverá ser colocado no mercado pacotes de objetos prontos para serem integrados aos sistemas o que facilitará ainda mais o desenvolvimento e a manutenção dos mesmos.
Object Inspector
Providência a conexão entre a interface visual e o código. É Composto por duas páginas Properties (propriedades) e Events (Eventos) que mostrará as propriedades e eventos do objeto selecionado.
Disponibiliza um fácil caminho para a personalização dos objetos. Você usará a página de Propriedades para personalizar os objetos colocados no formulário (inclusive o próprio formulário), e a página de Eventos para gerenciar a navegação entre certas partes do código do programa.
O seletor de objetos (Object Selector - localizado em um objeto do tipo ComboBox no topo do Object Inspector) mostra o nome e o tipo de todos os componentes do formulário corrente (inclusive o próprio). Você pode usar o seletor de objetos para localizar facilmente qualquer objeto no formulário.
SpeedBar
Contém os botões mais freqüentemente utilizados. Fornecendo deste modo um atalho de navegação ao menu principal do Delphi.
É possível a personalização da SpeedBar colocando nela os caminhos do menu principal que você mais utiliza, bastando para isso:
1.   Redimensione a SpeedBar. Para tanto posicione o cursor do mouse sobre o ponto de encontro da SpeedBar com a Component Palette conforme o desenho abaixo:
 
2.   Quando o cursor do mouse mudar de formato, clique o botão esquerdo do mouse e arraste abrindo a área da SpeedBar.
3.   Clique com o botão direito do mouse na área aberta, apareça um menu PullDown contendo entre outras opções a opção Properties, selecione-a.
4.   As categorias e os comando são divididos de acordo com o menu, clique em cima dos comandos disponíveis e arraste-os para a área aberta de acordo com a sua necessidade, para retirar os botões da SpeedBar faça o processo inverso.
Elementos não Visíveis
Alguns elementos não estão prontamente visíveis quando o Delphi é iniciado mas você poderá ter acesso a eles bastando para isso selecionar a opção na barra de menu.
Project Manager
O Gerenciador de Projetos contém uma lista de formulários ou unidades utilizados pela aplicação, e serve para controlar estes formulários ou unidades, adicionando-os ou removendo-os do projeto, organizando as opções do projeto, entre outros.
? Você também poderá colocar um botão para iniciar o Gerenciador de Projetos através da SpeedBar  ,
 
Menu Designer
O Menu Designer permite a criação de menus para os seus formulários. Você pode criar menus ou menus do tipo pulldown através dos objetos MainMenu ou PopupMenu (localizado na página Standard na Component palette). A criação completa de Menus será colocada de forma mais abrangente no Capítulo IV.
 
Fields Editor
Para o Delphi é possível editar e modificar as propriedades de quaisquer campos dos objetos de tabelas associadas ao banco de dados, a Fields Editor em conjunto com a Object Inspector controlam o modo de mostrar determinados campos de arquivos, é importante lembrar que esta modificação não afetará os campos da tabela, apenas para o formulário ativo em questão. Sua utilização efetiva será mostrada a partir do Capítulo V.
 
Add fields... é responsável pela adição de definições de campos da tabela, é possível inserir um ou mais campos, dependendo de sua utilização para o formulário.
New field... permite a criação de um novo campo, este pode ser a derivação de um ou mais campos da tabela.
Cut envia para área de transferência e elimina todas as definições do campo selecionado.
Copy copia para a área de transferência todas as definições do campo selecionado.
Paste recebe da área de transferência todas as definições do campo selecionado criando-o.
Delete exclui quaisquer definição para os campos.
Select all seleciona todas as definições dos campos.
Retrieve Attributes atualiza os atributos do campo selecionado com os campos do dicionário de dados.
Save attributes salva os atributos do campo selecionado para o dicionário de dados.
Save attributes as... salva os atributos do campo selecionado para o dicionário de dados permitindo a renomeação do campo.
Associate attributes... faz a associação dos atributos do campo selecionado com determinado campo do dicionário de dados.
Unassociate attributes remove a associação dos atributos do campo selecionado com determinado campo do dicionário de dados.
Repositório de Objetos
O Repositório de Objetos do Delphi 2.0 armazena e gerencia os objetos da aplicação: Formulários, Data Modules, geradores experts, e DLL (Dinamic Linked Library - Bibliotecas de acesso dinâmico). Na essência, ele centraliza as localizações dos objetos envolvidos agrupado-os. A proliferação dos objetos no repositório incrementa as seguintes vantagens:
•   Suporte a equipe de desenvolvimento para referência aos objetos da rede.   
•   Uma customização de todo o desenvolvimento em grupos lógicos de objetos, facilitando o re-uso dos mesmos.
O Delphi possui diversas características quanto a sua utilização. Tem os Tutors e Experts que são as ferramentas responsáveis para guiar-nos através de técnicas, tais como, manipulação de componentes e criação de simples aplicações. Além disso o Delphi oferece uma coleção de modelos para formulários, janelas de diálogo e até mesmo aplicações completas na ferramenta New Items. A janela do New Items é sempre chamada automaticamente quando a opção File | New... do menu principal é executada.
 
? É possível para você criar novas janelas, ou projetos, automáticos no Delphi. Para a nossa sorte a Borland não esconde o jogo e mostra como se cria uma template visite o diretório \BORLAND\DELPHI 2.0\OBJREPOS, o equivalente no Delphi 1.0 é encontrado no diretório \DELPHI\GALLERY, todos os exemplos são auto-explicativos.
? Para definir o projeto padrão que o New Items executará no início de cada projeto, clique com o botão direito acima da janela e escolha a opção Properties aparecerá as listas Pages e Objects, defina quaisquer dos objetos como New Form ou Main Form.
? Observe que a segunda folha da janela New Items (terá o nome do seu arquivo com a extensão .DPR) é o seu projeto corrente, ou seja, uma nova janela poderá ser derivada, por característica de herança, de uma outra janela já existente.
Estrutura de Aplicações com o Delphi 2.0
Um dos objetivos de desenhar aplicações do tipo Client / Server para o desenvolvimento é a reutilização dos objetos, das regras de negócio e das telas do projeto. O Delphi Client / Server Suite 2.0 é o único que implementa uma arquitetura incorporando a tecnologia RAD (Rapid Application Development - Desenvolvimento Rápido de Aplicações) com o desenvolvimento totalmente OO (Object Orientation - Orientado a Objetos) para a redução do tempo de desenvolvimento e manutenções improváveis. Adicionando, uma arquitetura aonde é possível a separação da GUI (Grafic Unit Interface - Unidade de Interface Gráfica), das regras de negócio lógicas e do desenho do banco de dados de acordo com o modelo representado abaixo:
 
Benefícios:
1.   A separação do desenho da GUI (através dos objetos Forms) com a área de ligação lógica de dados (através dos objetos Data Modules) permite que se cause um menor impacto sobre ambas as áreas. As mudanças podem ser executadas nas telas de entrada ou nas ligações, independentemente, de acordo com os requerimentos do usuário.
2.   A separação do desenho da GUI com a área de ligação lógica de dados realizada com uma certa habilidade aos eventos envolvidos, poderá não necessariamente deverá ser controlada por um habilidoso DBA (Database Administrator - Administrador de Banco de Dados), com suas fantásticas regras de negócio, podendo inclusive ser mantida por um "analista de informações".
3.   O desenho do banco de dados, a construção das metodologias de negócio e o desenho e a criação das janelas de entrada são efetivados dentro da aplicação. O desenvolvimento, então paralelamente, resultará em uma maior rapidez.
4.   Herdando as janelas de entrada, em níveis de utilização, reduz-se drasticamente o processo de codificação, e em conseqüência, o processo futuro de manutenção. As mudanças lógicas das regras de negócio ou a incorporação de novos padrões, são feitas automaticamente para todos os objetos herdados.
5.   O repositório de objetos, os formulários reusáveis e a utilização dos objetos Data Modules, envolve em eliminação da duplicação de códigos e de trabalhos com desenhos de janelas, e em conseqüência na redução da equipe de desenvolvimento.
Implementação efetiva
Objetos Data Module
A partir do Delphi 2.0 foi incorporado o uso de objetos conhecidos por Data Module, que servem para que suas aplicações providenciem um desenho centralizado da definição de acesso aos dados e das regras de negócio. Os objetos Data Modules, também podem ser separados por negócios lógicos (como exemplo por áreas: compras, vendas, estoque, etc.) formando caminhos de conexões simples.
 
•   Os objetos Data Modules podem ser aplicados a objetos tais como Tables, Stored Procedures, ou Queries permitindo a centralização dos eventos envolvidos em antes e depois da gravação, exclusão, inserção ou edição dos dados. E até mesmo na colocação de novos objetos de controle para maior facilidade.
•   As relações de dados Master / Detail são definidas em menor quantidade. Possibilita então ao desenvolvedor criar aplicações do tipo Client / Server de forma mais fácil, rápida, e segura se utilizando das propriedades dos objetos Datasources ou utilizando o Database Form Expert.
•   Os formulários das aplicações, podem ser ligados diretamente a um ou mais objetos Data Module para a propagação das regras de negócio sem a necessidade de execução de um código extra.
•   Os objetos Data Modules são classes de objetos que pertencem a interação dos dados do database server. Isolando totalmente o acesso ao banco de dados com a aplicação Client, simplificando deste modo toda a manutenção realizada.
•   O Acesso ao Delphi aos bancos de dados se processa da seguinte maneira:
 
Distribuição Lógica da Aplicação:
Os objetos Data Module foram desenvolvidos para criar uma centralização lógica de todas as regras de negócio, separando a área de visão do usuário com a área do desenho do Banco de Dados. Este sólido fundamento de suporte são distribuídos em um n-número de aplicações e arquiteturas servidoras disponíveis, tais como CICS da IBM, TopEnd da ATT, Tuxedo da Novell, Object Broker da Digital, IONA da Orbix e muitas outras.
Dicionário de Dados Escalável
O dicionário de dados é utilizado para armazenar informações sobre o uso dos dados contidos nas suas tabelas. O dicionário deve ser como uma árvore genealógica trabalhando como um inspetor de modificações que permitem um armazenamento facilitado. O dicionário deve conter informações dos atributos dos campos tais como: valores mínimo, máximo e comuns (valores default), máscaras utilizadas, etc. A utilização do dicionário de dados traz as seguintes vantagens:
1.   Consistência:  Campos idênticos são armazenados centralmente no dicionário isto reduz o tempo de definição das duplicidades. Um desenvolvedor poderá criar os campos complementares com domínios e aplicações apropriadas.
2.   Redução do Tráfico da Rede: O Delphi permite que a validação dos dados seja feita nas máquinas client ou no servidor. O Dicionário de dados permite que a manutenção dos atributos dos campos do lado client seja validado de forma eficiente reduzindo a necessidade do tráfego da rede.
 
Herdando os Formulários
O desenvolvimento de aplicações corporativas de uma forma padronizada é um fato de suma importância para as empresas envolvidas. Mas conseguir e manter este padrão é uma tarefa considerada praticamente impossível, já que as aplicações devem se modernizar na velocidade que o mercado de informática exige. Os formulários herdados do Delphi são simples extensões da programação orientada a objetos, conseguindo manter, de forma automática, os padrões e as modificações realizadas nos projetos. E em conjunto com o Repositório de Objetos, padroniza, organiza e centraliza os formulários resultando em modificações de curtíssimo tempo.
 
Ferramentas Auxiliares de SQL
Para o trabalho com bases de dados padrão SQL (Structure Query Language - Linguagem estruturada de Consultas), o Delphi conta com as seguintes ferramentas RAD que auxiliam ao desenvolvimento.
Monitor SQL
Um monitor SQL é um ferramenta para testes, depuração e execução de consultas SQL em aplicações Client / Server. Isto resulta em um aumento da produtividade de desenvolvimento e melhor performance da aplicação.
O monitor SQL, intercepta as chamadas entre as máquinas client e o servidor. Esta informação auxilia ao desenvolvedor em problemas relacionados as declarações SQL e otimiza este tipo de transação. Uma série de caminhos de interceptações podem ser traçados, dependendo da necessidade do desenvolvedor, para que as informações a serem colocadas em um relatório on-line sejam as mais imprescindíveis o possível. É possível inclusive salvar e imprimir o relatório gerado para consultas ou testes posteriores.
 
SQL Explorer
A ferramenta SQL Explorer providencia uma informação centralizada do gerenciamento das demandas da base de dados; tais como, suporte a modificação e criação de tabelas, sinônimos, procedimentos de gravação, triggers (gatilhos disparados pelo banco) e execução das regras de negócio interativas do SQL. Uma ferramenta gráfica que proporciona um esquema de integridade da base da dados e contém as ferramentas essenciais para os administradores de bancos de dados.
O SQL Explorer, unicamente para o Delphi, administra de forma intuitiva e fácil o banco de dados. A simplicidade de uso da interface gráfica é um perfeito caminho para representar o complexo relacionamento que existe no banco de dados do servidor. Apresenta um esquema para informações em bancos como Oracle©, Sybase©, InterBase, Informix©, DB2© e outros. O desenvolvedor poderá trilhar campos, tabelas e procedimentos do banco dentro da construção da aplicação Delphi rapidamente, podendo ser direcionado para múltiplos servidores e múltiplos bancos.
 
O SQL Explorer, também administra o Dicionário de Dados. Sua interface de uso simplicado permite facilmente definir novos domínios para os atributos dos campos e associação entre tabelas.
InterBase NT - Banco de Dados Relacional
O Delphi Client / Server Suite 2.0 inclui uma licença para dois usuários do uso do banco de dados InterBase NT. Desenvolvedores podem criar em máquinas standalone aplicações usando este poderoso banco de dados (concorrente de bancos como Oracle©, Sybase©, Informix©, DB2© e outros). Com o crescimento do volume de dados e do tamanho da aplicação, ambos, o InterBase e o Delphi conseguem interagir de forma harmoniosa.
O InterBase é um banco de dados de alta performance produzido pela Borland, como plataforma para SQL Server. Está disponível em mais de 15 sistemas operacionais incluindo:  DOS e Windows© 3.1, Windows© 95, Windows© NT, NetWare©, SCO©, Sun OS©, Sun Solaris©, HP-UX©, IBM AIX©, SGI IRIX©, etc.
O InterBase é um banco a nível ANSI SQL 92, suportando eventos programados e exceções ocorridas no modelo por acesso de múltiplos usuários. Oferece chaves de controle a nível de registros para arquiteturas Multi-Gerenciais causando um performance muito superior a uma leitura das operações de banco, em contrário das leituras de blocagem de operações escritas realizadas por outros bancos.
A versão local do InterBase, disponível apenas com a cópia Client / Server Suite 2.0, providencia aos desenvolvedores um caminho rápido para o desenvolvimento de protótipos e de sistemas com um banco de padrão ANSI 92 SQL. Esta versão propicia as mesmas funcionalidades da versão multi-usuário para NT e Unix, incluindo controles de transações, procedimentos de gravação (stored procedures), uso de triggers (gatilhos disparados do banco), ou eventos de alerta. Imagine o desenvolvimento de um grande sistema sendo realizado em um Laptop dentro de um trem, avião ou até mesmo na frente do cliente, apenas o acesso ao banco de dados final é que será modificado.
Utilizando o Delphi Client/Server Suite 2.0, desenvolvedores poderão conceber e desenhar protótipos e testar a aplicação final em uma única máquina. O InterBase oferece um excepcional acesso a interface gráfica do Windows©, incluindo a configuração das propriedades, um perfeito gerenciador de bancos nativo 32 bits, total interatividade com ferramentas SQL, e uma completa documentação em formato de Help do Windows©  (arquivos .HLP).

Trojan

Capítulo 3
Projeto Piloto
É óbvio que fica mais simples o aprendizado de uma nova ferramenta quando se faz algum tipo de aplicativo, principalmente um que seja útil, então ao longo deste estudo, iremos desenvolver um aplicativo destinado ao Cadastro de Compact Disc (CD's). Todas as pessoas hoje em dia tem montes de CD's, virou uma espécie de febre, então, porque não fazer um sistema para cadastrá-los e controlá-los, quanto tempo você já perdeu pensando em qual deles está aquela música que você quer ouvir? Ou uma capa que seu filho rasgou, que tal imprimi-la novamente? E no capítulo multimídia aprenderemos um método para tocar o CD.
Para darmos partida ao nosso primeiro aplicativo (Projeto Piloto), definiremos inicialmente as nossas necessidades:
1.   Permitir o cadastro completo e a consulta aos CD's;
2.   Ser possível separar os CD's em categorias, facilitando deste modo a busca e o armazenamento;
3.   Quanto as músicas deve ser permitido o cadastro do autor e o tempo de duração;
4.   Permitir a inclusão da foto da capa do CD; e
5.   Comportar relatórios de conferência e reimpressão da capa.
O acesso Delphi a arquivos pode ser feito através de duas maneiras local ou remoto, sendo a segunda apenas possível pela cópia CLIENT-SERVER é voltadas a bases de dados mais complexas como ORACLE© ou SYBASE©, inicialmente, restringiremos o nosso estudo a base de dados locais conseguida através da versão Desktop. Lembre-se que à versão Desktop contém acesso a criação e a definição de bases dBase e Paradox, além de outras conseguidas através de ODBC.
Com base no que foi sugerido acima, vamos definir as tabelas:
CATEGORIA
Objetivo: Dados das categorias do CD.
Campos: SIGLA DA CATEGORIA - Abreviação da descrição da categoria.
DESCRIÇÃO DA CATEGORIA - Descrição da Categoria.

BÁSICO
Objetivo: Dados iniciais do CD.
Campos: CÓDIGO DO DISCO - Código do CD, encontrado na própia capa.
NOME DO DISCO - Nome do CD.
TIPO DO DISCO - Tipo de Gravação do CD: AAA, AAD, ADD ou DDD.
FOTO DA CAPA - Armazenará a foto da capa do CD.
SIGLA DA CATEGORIA - Ligação para o código da Categoria.

MÚSICAS
Objetivo: Dados das músicas do CD.
Campos: 
CÓDIGO DO DISCO - Ligação com o CD.
NUMERO DA FAIXA - Número da faixa.
NOME DA MÚSICA - Título da música.
NOME DO AUTOR - Nome do autor da música.
TEMPO DA MÚSICA - Tempo de duração da música MMSS.
Criando o Modelo Relacional
Para criar um modelo relacional simples e trabalhar com bases locais você pode optar por dois modos do tipo dBase ou Paradox, particularmente eu prefiro trabalhar com Paradox, mas você rapidamente notará que tanto faz, trabalhe com aquela que você se sinta mais a vontade.
? Escolha a base de acordo com o porte do sistema: Para sistemas pequenos e simples e com poucos dados use o dBase, para sistemas médio, multi-usuário, com uma boa quantidade de dados escolha a base Paradox e para sistemas complexos em várias plataformas e acessos multi-usuário opte por InterBase.
Vamos agora visualizar um modelo que demonstrará como as tabelas deverão se relacionar no sistema, este modelo também facilitará as relações e a integração dos formulários do sistema quando construiremos nossas consultas e relatórios.
 
No modelo de entidade e relacionamento acima lê-se:
•   1 registro da entidade Básico se relaciona com 1 registro da entidade Categoria enquanto que 1 registro da entidade Categoria se relaciona com n registros da entidade Básico,
•   1 registro da entidade Músicas se relaciona com 1 registro da entidade Básico enquanto que 1 registro da entidade Básico se relaciona com n registros da entidade Música.
Com o MER nas mãos já se tem a idéia de como deve ficar as estruturas das tabelas, então, vamos queimar um pouco de neurônios.
Trabalhando com DataBase Engine Configuration
Criando o Alias
O ALIAS é simplesmente um apelido (sinônimo) a ser dado para o banco de dados, este apelido permitirá que no lugar de falarmos para ao Delphi que a nossa base se encontra em C:\SISTEMA\... ou D:\DESENV\SISTEMA\..., simplesmente digamos se encontra em AliasX ou AliasY, isto facilitará o seu trabalho quando você por exemplo quiser modificar o diretório do sistema, basta mudar o endereço do ALIAS e não sair modificando vários formulários.
? Outra vantagem em se criar um Alias está na mudança da base, basta reapontarmos o Alias para outra base que o sistema automaticamente verá estas novas informações. Lembre-se que para isto ser possível é necessário que o nome das tabelas e dos campos sejam necessariamente os mesmos, incluindo o tamanho e o tipo (no apêndice B é encontrado uma tabela para a conversão das diversas bases de dados).
Para trabalhar com ALIAS o caminho mais interessante e com o Database Engine Configuration, no arquivo de programas do Delphi dê um duplo clique sobre o ícone  , a configuração do banco de dados se divide em várias páginas:
?   Drivers - Controla os arquivos de acesso locais e ODBC dos bancos de dados utilizados;
?   Aliases - Controle dos sinônimos dos sistemas;
?   System - Define os recursos do Windows que serão alocados pela aplicação;
?   Date - Especifica os fo rmatos utilizados para campos tipo data;
?   Time - Especifica os formatos utilizados para campos tipo hora; e
?   Number - Especifica os formatos utilizados para campos tipo numérico.
Se atualmente você estiver utilizando a versão de desenvolvimento, os drivers que aparecerão serão: dBase, InterBase e Paradox, na versão Client/Server além desses serão colocados: Oracle, Informix, SyBase entre outros.
Mude para a página Aliases e click no botão New Alias, informe:
New alias name: AliasDisco
Alias type: STANDARD
Botão OK

Path: C:\SISTEMA\CADDISCO
Default Driver: Paradox
Neste momento o seu ALIAS AliasDisco foi criado para a banco de dados Paradox, no formato Padrão localizado no diretório C:\SISTEMA\CADDISCO, no menu principal escolha a opção File e Save, o BDE salvou o seu arquivo de configuração chamado IDAPI.CFG.
? Crie com o Gerenciador de Arquivos o diretório C:\SISTEMA\CADDISCO, aonde será localizado o sistema.
? Para a base dBase a única diferença seria o comando Default Driver: DBASE.
Encerre o Database Engine Configuration.

Trabalhando com DataBase DeskTop
Criando o Banco de Dados via Estrutura
Para criar suas tabelas, dispõe-se de duas maneiras: o modo declarações em SQL ou pela janela de estrutura, inicialmente, utilizaremos a janela de estrutura, pois além de mais simples é mais prático, a menos que você trabalhe com bases de acesso remoto, evite o modo declarações em SQL para manusear a estrutura de tabelas, principalmente tabelas simples como é o caso do Paradox ou o dBase, apesar que existem muitos fanáticos por CREATE TABLE, ALTER TABLE e DROP's. Em seguida mostrarei como criar as mesmas tabelas utilizando o método SQL.
? Lembre-se de apagar as tabelas antes de criá-las novamente. Senão não será possível executar uma única declaração SQL.
Retorne ao Delphi, no menu principal escolha a opção TOOLS|DataBase DeskTop, maximize a tela para permitir uma melhor visualização.
Com o nosso sinônimo (ALIAS) criado iremos agora definir as nossas tabelas. Inicialmente vamos definir como nossa área de trabalho: No menu principal, opção File|Working Directory..., na opção Aliases: selecione AliasDisco, note que a opção Working Directory será automaticamente modificada para :AliasDisco:, finalmente confirme clicando no botão OK. O diretório apontado pelo Alias, agora será o default, ou seja, tudo o que fizermos será apontado para o diretório.

Dos campos, o único que merece uma explicação e FOT_CAPA ele foi escolhido neste formato (Binary) pois guardará uma imagem BitMap (extensão .BMP) da Capa do CD, todos os outros campos são caracteres alfanuméricos, com a exceção do COD_DISCO que é um campo Numérico e chave.
Para esta tabela precisamos ainda criar um índice secundário, para tanto na opção Table properties: chame a opção Secondary Indexes e clique no botão Define..., marque no campo Nom_Disco (na lista Fields) e clique Na seta ( -> ) o campo passou para a lista Indexed Fields, clique no botão OK e digite SI_NomDisco para o nome do indice e clique no botão OK.
Para salvar sua tabela clique no botão Save as... na opção Nome do Arquivo: insira o nome da tabela - Basico.
Crie agora as seguintes tabelas:
1. Categor
Field Name   Type   Size   Key
SIG_CATEG   A   2   *
DES_CATEG   A   40   
2. Musica
Field Name   Type   Size   Key
COD_DISCO   N      *
NUM_FAIXA   N      *
NOM_MUSICA   A   60   
NOM_AUTOR   A   40   
TMP_MUSICA   A   4   

Criando os Relacionamentos via Estrutura
Os relacionamentos entre as tabelas poderia ter sido criado no momento da construção das mesmas, mas acredito que deste modo seja mais simples, a partir do menu principal, opção File, opção Open, e opção Table..., será aberto uma janela com todas as tabelas, clique na tabela BASICO e sua estrutura será mostrada, clique no botão Restructure, ou a partir do menu principal, opção Table, opção Restructure..., na opção Table properties: alterne para a opção Referential Integrity e clique no botão Define..., no lado esquerdo (Lista Fields) dê um duplo clique no campo SIG_CATEG e no lado direito (Lista Tables) dê um duplo clique na tabela CATEGOR.DB, clique no botão de OK para confirmar e será solicitado o nome para o índice.
Para o nome do índice crie um padrão de FK_ + {nome do campo} + {nome tabela pai}, uma padronização dos nomes dos índices facilita a procura futuramente, então para o nosso índice crie FK_SigCateg_Basico.
Também é possível acessar o Database Desktop através do ícone localizado no grupo de trabalho DELPHI.
Encerre o Database Desktop e retorne ao Delphi, ou apague as tabelas e...
Criando o Banco de Dados via SQL
Para os fanáticos por declarações SQL, vamos criar a mesma base de dados via SQL, se você ainda não o fez, observe no tópico anterior como colocar o ALIAS na área de trabalho. Isto será de muita utilidade quando formos salvar o nosso trabalho.
No menu principal, opção File, opção New, e opção SQL File, será mostrada uma janela para ser digitada a declaração SQL, observe na barra de comandos o botão Select Alias, ou a partir do menu principal opção SQL/Select Alias..., apenas observe que a área de trabalho Work já está selecionada, clique em OK ou Cancel sem fazer nenhuma modificação, observe que o título da janela é SQL Editor :WORK:.
Digite o seguinte na janela:
Create Table Basico
   (
     COD_DISCO Numeric(4,0),
    NOM_DISCO VarChar(60),
    TIP_DISCO Char(3),
    FOT_CAPA Blob(3,2),
    SIG_CATEG Char(2),
    Primary Key(COD_DISCO)
    );
Clique no botão Run SQL, ou no menu SQL/Run SQL, ou ainda pressione F8, após executado o comando a tabela será criada. Salve o SQL com a opção File/Save (digite BASICO .SQL)
Abra novas janelas e crie o resto das tabelas:
Create Index SI_NomDisco on Basico (NOM_DISCO);    ? Criando o indice secundário da BASICO

Create Table CATEGOR                ? Criando a Tabela CATEGOR
   (
    SIG_CATEG Char(2),
    DES_CATEG VarChar(40),
    Primary Key(SIG_CATEG)
    );

Create Table MUSICA                ? Criando a tabela MUSICA
   (
    COD_DISCO Numeric(4,0),
    NUM_FAIXA Numeric(2,0),
    NOM_MUSICA VarChar(60),
    NOM_AUTOR  VarChar(40),
    TMP_MUSICA Char(4),
    Primary Key(COD_DISCO, NUM_FAIXA)
    );

O SQL para o Paradox não consegue executar a criação de indices referenciais (ou "Constraints") então para criar este tipo de índice crie-o através da janela de estrutura conforme mostrado anteriormente.
Observações da utilização do SQL com o dBase
Infelizmente o dBase não suporta a cláusula Primary Key que permite a criação dos índices muito menos a criação de chaves estrangeiras. Quanto as chaves estrangeiras não se preocupe pois o Delphi consegue manipular relacionamentos entre as tabelas mesmo que elas não estejem vinculadas.
Caso você esteja utilizando este tipo de base os passos para as criações das tabelas são os mesmos mas corte as cláusulas Primary Key é necessário criar os índices separadamente. Abra uma nova declaração SQL, idêntica a anterior, e digite o seguinte na janela:
Create Index PK_Unica on Basico (COD_DISCO);
? O comando correto para este índice deveria ser "Create Unique Index PK_Unica on Basico (COD_DISCO);" mas isto provoca um erro colocando que não é possível esta declaração, então coloque a cláusula UNIQUE através da janela de estrutura.
? Se você esqueceu de ativar o Select Alias coloque "Create Index Cod_Disco on "Basico.dbf" (COD_DISCO);"
As outras declarações são:
Create Index SI_NomDisco on Basico (NOM_DISCO);       ? Criando o indice secundário
Create Index FK_SigCateg_Basico on Basico (SIG_CATEG);    ? Criando a chave estrangeira
Create Index PK_Unica on Categor (SIG_CATEG);          ? Criando a chave primária
Create Index FK_CodDisco_Musica on Musica (COD_DISCO);    ? Criando a chave estrangeira
? O comando correto para a criação da chave dupla da tabela MUSICA seria "Create Index Chv_Unica on Musica (COD_DISCO, NUM_FAIXA);" mas novamente é provocado um erro mostrando a impossibilidade de execução do comando, então crie este índice através da janela de estrutura.
? É facilmente percebido que o DataBase DeskTop até que tenta colocar todas as bases de dados compatíveis com a linguagem SQL, mas infelizmente ainda não foi nesta versão.
? Para as tabelas do tipo ORACLE, INTERBASE, SYBASE e MS SQL Server a criação das tabelas podem ser feitas tanto pelo modo de estrutura quanto pelas declarações SQL mas lembre-se que a alteração das mesmas só poderá realizar-se através do modo de declarações SQL. Aqui vão alguns exemplos destas declarações:
Create Table MUSICA                   ? Criando a tabela MUSICA
   (
    COD_DISCO Numeric(4,0),
    NUM_FAIXA Numeric(2,0),
    NOM_MUSICA VarChar(60),
    TMP_MUSICA Char(4),
    Constraint PK_Unica Primary Key(COD_DISCO, NUM_FAIXA),
    Constraint FK_CodDisco_Musica Foreign Key (Cod_Disco)
        References USUARIO_AGENDA (Cod_ Disco)
   );

ALTER TABLE MUSICA ADD NOM_AUTOR VarChar(40)   ? Adiciona o campo Nom_Autor

DROP TABLE MUSICA;                ? Elimina a tabela MÚSICA
Encerre o Database Desktop e retorne ao Delphi.

Trojan

Capítulo IV
Trabalhando com o Menu
Qualquer projeto precisa de um menu, fica mais prático para o nosso usuário navegar dentro de um projeto quando este é limitado por um menu principal, iniciaremos o nosso projeto no Delphi com a criação do Menu Principal do Sistema.
Metendo a Mão na Massa
A partir deste ponto, nossa aula se transforma em receita de bolo, a única coisa que você precisa fazer e seguir as orientações passo a passo, no princípio pode parecer meio idiota, mas afinal o computador é uma máquina idiota. Bom, vamos então metendo a mão na massa.
•   Ao iniciar o Delphi, foi criado automaticamente um novo projeto, vamos descartá-lo e iniciar um novo. Para tanto:
1.   Lembre-se: no capítulo anterior criamos o diretório que abrigará o sistema a ser desenvolvido - C:\SISTEMA\CADDISCO - aprendemos o que é o Alias e estruturamos as nossas tabelas, se algum destes conceitos ficaram dispersos eu lhe aconselho que retorne ao capítulo anterior
2.   Crie um novo projeto digitando File e New Application. (Responda negativamente quaisquer mensagem para gravar o projeto atual).
Criando a janela do menu
A janela do menu principal e bem simples, como você já deve ter visto em vários aplicativos o menu é o objeto que fica servindo de pano de fundo para toda a aplicação, todo o trabalho e realizado com o auxílio de suas chamadas, em conjunto com o menu teremos três formulários gerenciadores que daremos o nome de:
?   F_Menu - Menu principal propriamente dito;
?   F_Sobre - A janela "Sobre o sistema..."; e
?   F_Inicio - Janela Splash que iniciará o nosso aplicativo.
•   Vamos criar inicialmente o nosso menu principal:
1.   Clique no botão   (Main Menu), localizado na Component Palette na página Standard, e clique dentro do objeto Form1 (não se preocupe com a posição, pois este objeto ficará invisível quando o aplicativo for executado).
•   Foi criado neste momento o objeto MainMenu1 derivado da classe de objeto TMainMenu, a partir deste objeto vamos criar nosso menu:
2.   Dê um duplo clique em cima do objeto, ou clique na propriedade Items da Object Inspector aparecerá o botão  . Clique neste botão.
•   Observe a tela de propriedades do Object Inspector, neste momento vou me conter em falar das mais significativas, mas futuramente retomaremos o assunto:
Caption - Define o nome do item de menu, quaisquer nomes são válidos, incluindo acentos, o caractere especial "&" deve ser colocado uma única vez, ele causa o sublinhado da letra, tornando-a uma letra (em conjunto com a tecla Alt) de acesso a opção.
Enabled - Define se o item está disponível ou não para o usuário.
Name - Nome interno do item (colocado automaticamente na escolha do Caption).
ShortCut - Combinação de teclas, para um rápido acesso ao item (além da letra escolhida com "&").
•   Inserindo os itens iniciais:
1.   Digite "&Arquivo" na propriedade Caption, em seguida pressione a tecla Enter.
2.   Clique no novo espaço aberto, criado lateralmente, e digite "&Consulta" na propriedade Caption, em seguida pressione a tecla Enter.
3.   Proceda da mesma forma criando as opções: "&Relatório" e "Au&xílio".
4.   Clique na opção Arquivo, aparecerá um espaço vazio abaixo, clique neste espaço e digite "&Tabela" na propriedade Caption. Ao ser dado Enter o Delphi criará mais um espaço abaixo, digite "&Cadastro" na propriedade Caption.
5.   Abaixo do Cadastro, digite "-" (sinal de menos) na propriedade Caption (o Delphi criará uma barra de separação) e altere a propriedade Enabled para False.
6.   No novo espaço criado, após a barra, digite "&Sair" na propriedade Caption e altere a propriedade ShortCut para Ctrl+X.
7.   Clique na opção Tabela, clique com o botão direito do mouse, aparecerá um menu pulldown, clique na opção Create Submenu.
8.   Digite "&Categoria" na propriedade Caption.
•   Complete os próximos itens de modo que o menu fique:
Arquivo      Consulta   Relatório   Auxílio
Tabela         ?   Categoria   CD's   Geral   Sobre o sistema
Cadastro      Música  por CD's   Capa do CD   Conteúdo
Sair     Ctrl+X         Configura Impressora   Tópicos de Ajuda
            Como usar a Ajuda
•   Saia da janela Menu Designer digitando Alt+F4, o menu já existe no objeto form1.
•   Altere as seguinte propriedades para o objeto form1:
Propriedade   Valor   Descrição
BorderStyle   Single   Estilo da borda da janela; modo simples.
Caption   Compact Disc Digital Audio   Label escrito na tarja superior da janela.
Color   clMenu   Cor da janela, clMenu é uma constante que guarda a cor padrão da janela definido pelo usuário no Windows.
Name   F_Menu   Nome do objeto interno.
WindowsState   wsMaximized   Modo de abertura da janela, modo Maximizado.
•   Salvando o formulário e o projeto:
1.   Salve o Formulário nas opções de menu File e Save (ou pressione Ctrl+S), o Delphi questionará o nome e o diretório, o diretório (conforme criado no capítulo anterior) é o C:\SISTEMA\CADDISCO e para o nome digite fMenu (note que o nome externo e o mesmo do nome interno diferenciado por "_", isto facilitará a identificação do formulário e da sua unidade).
2.   Salve o Projeto digitando File e Save Project, salve o projeto no diretório C:\SISTEMA\CADDISCO com o nome CDDA.
•   Criando no menu uma linha de status:
3.   Clique no botão   (StatusBar) na página Win95 da Component Pallete e clique em qualquer posição do objeto F_Menu.
4.   Clique no objeto criado StatusBar1 em seguida clique na propriedade Panels, para alterar esta propriedade clique no botão  , aparecerá a janela da Status Bar Panels Editor, clique sobre o botão New e para a propriedade Text coloque "Bem vindo ao sistema..." e clique no botão OK.


5.   Altere também a propriedade Name do objeto para LinhaStatus
? Caso você esteje usando o Delphi 1.0 crie a barra de status do seguinte modo:
1.   Clique no botão   (Panel) na Component Pallete na página Standard e clique em qualquer posição do objeto F_Menu.
2.   Clique no objeto criado StatusBar1 e altere as seguintes propriedades:
Propriedade   Valor   Descrição
Align   alBottom   Alinhamento dentro do form, todo no rodapé
Alignment   taLeftJustify   Alinhamento da Caption, justificado à esquerda
BevelInner   bvLowered   Borda 3D interna, tipo pressionado
BevelOuter   bvLowered   Borda 3D externa, tipo pressionado
BorderWidth   1   Tamanho da borda
Caption   Bem vindo ao sistema...   Label do objeto
Name   LinhaStatus   Nome do objeto
Font   MS Sans Serif, Estilo da fonte: Normal, Tamanho: 8, Cor: Azul Marinho   Tipo de letra a ser mostrada no objeto, para alterar esta propriedade clique no botão 
Height   22   Altura do objeto
Inserindo os Códigos Iniciais
Vamos inserir o código para o objeto LinhaStatus, este objeto receberá os conteúdos da propriedade hint dos diversos objetos, formando assim uma linha de ajuda on-line na parte inferior do menu.
•   Clique no botão   (Toggle Form/Unit) da SpeedBar, até você alternar para o Code Editor.
 Abaixo da declaração: Private insira os códigos:
private                   ? Procedures ou Funções Locais.
    { Private declarations }
    procedure ShowHint (Sender: TObject);      ? Cabeçalho de uma procedure Local.
public                  ? Procedures ou Funções Públicas.
    { Public declarations }
end;                  ? Final da seção de declaração.

Abaixo da diretiva de compilação: {$R *.DFM}
{$R *.DFM}               ? Diretiva de compilação associando o nome do                          recurso externo ao mesmo nome do objeto Form.
procedure TF_Menu.ShowHint (Sender: TObject);    ? Cabeçalho da Procedure associado ao nome do
begin                       objeto principal (TF_Menu).
    LinhaStatus.Panels.Items[0].Text := Application.hint;   ? Atribui o valor do hint da aplicacão ao end;                              Item criado do objeto LinhaStatus.

•   Clique no botão   (Toggle Form/Unit) da SpeedBar, até você alternar para o Form clique no objeto F_Menu e na página Events da Object Inspector, dê um duplo clique no evento OnCreate.
1.   O Delphi criou a procedure FormCreate a ser iniciada quando o objeto F_Menu for criado.
2.   Digite o seguinte comando abaixo do comando begin:
procedure TF_Menu.FormCreate (Sender: TObject);
begin
   Application.OnHint := ShowHint;   ? Atribui o valor da procedure ShowHint ao OnHint da
end;                   aplicação.
•   Clique no botão   (Toggle Form/Unit) da SpeedBar, até você alternar para o Form clique no objeto MainMenu1 e entre no Menu Designer, e para cada opção de Menu altere as propriedades hint e name do seguinte modo:

Opção do Menu   Hint   Name
Arquivo   Cadastro e saída do sistema.   Arquivo1
Tabela   Informações básicas do sistema.   Tabela1
Categoria   Tipos de categoria para os CD's.   ItemTabela1
Cadastro   Inclusão e manutenção dos CD's.   Cadastro1
Sair   Saída do sistema e retorno ao Windows.   Sair1
Consulta   Verificação e pesquisa dos CD's cadastrados.   Consulta1
CD's   Localização dos CD's através de um filtro estabelecido.   ItemConsulta1
CD's por música   Localiza o CD através de um título de uma música.   ItemConsulta2
Relatório   Emissões em papel dos CD's cadastrados.   Relatorio1
Geral   Impressão dos CD's por um intervalo de código.   ItemRelatorio1
Capa do CD   Impressão de capas para os CD's.   ItemRelatorio2
Configura Impressora   Verifica a impressora a qual será destinado os relatórios.   ConfImpressora1
Auxílio   Formas de ajuda direta ao sistema.   Auxilio1
Sobre o sistema   Ajuda direta com o responsável pelo desenvolvimento.   ItemAuxilio1
Conteúdo   Manual On-Line direto.   ItemAuxilio2
Tópicos de Ajuda   Exibe os tópicos de ajuda do Manual On-Line.   ItemAuxilio3
Como usar a Ajuda   Mostra como utilizar o Auxílio On-Line.   ItemAuxilio4
•   Saia do Menu Designer, salve o formulário e o projeto.
•   Rode o projeto, clicando no botão   da SpeedBar, ou no menu principal a opção Run e Run, ou ainda, digite F9.
•   Teste as opções do menu, veja na linha de Status os hints informados, saia com Alt+F4.
? Caso você esteje usando o Delphi 1.0 troque a procedure ShowHint para:
procedure TF_Menu.ShowHint (Sender: TObject);
begin
   LinhaStatus.Caption := Application.hint;      ? Atribui o valor do hint da aplicacão a Propriedade end;                      Caption do objeto LinhaStatus.
Iniciando os comandos do Menu
Com o menu pronto, começaremos a codificar os comandos que disponibilizamos ao nosso usuário:
•   Automatizando o Comando SAIR: No objeto F_Menu, clique na opção Arquivo e clique na opção Sair. O Delphi criou o evento Click para o objeto Sair1.
•   Digite o seguinte comando abaixo do begin:
procedure TF_Menu.Sair1Click (Sender: TObject);
begin
    Close;             ? proporciona o fechamento do formulário ativo
end;
Colocando os comandos para o Auxílio
O Delphi implementa o auxílio on-line de maneira prática e eficiente, não ensinarei aqui como construir um arquivo .HLP, existem diversos aplicativos que já o fazem automaticamente e fica a seu critério o modo de criá-lo, apenas mostrarei como implementá-lo em seu projeto.
•   Clique na opção Project | Options... e na página Application localize o seu arquivo com a opção Help file, aproveite também para nomear o projeto, com a opção Title e colocar um ícone para o projeto, opção Icon (clique no botão Load Icon...) e ao término clique no botão OK.

•   Automatizando o Comando CONTEÚDO: No objeto F_Menu, clique na opção Auxílio e clique na opção Conteúdo. Digite:

procedure TF_Menu. ItemAuxilio2Click(Sender: TObject);
begin
   Application.HelpCommand(HELP_CONTENTS, 0);   ? Chama o arquivo de Ajuda
end;
•   Automatizando o Comando TÓPICOS DE AJUDA: No objeto F_Menu, clique na opção Auxílio e clique na opção Tópicos de Ajuda. Digite:

procedure TF_Menu. ItemAuxilio3Click(Sender: TObject);
const
    EmptyString: pChar = '';                  ? Cria uma constante
begin
   Application.HelpCommand(HELP_PARTIALKEY, LongInt(EmptyString));   ? Tópicos do Ajuda
end;
•   Automatizando o Comando COMO USAR A AJUDA: No objeto F_Menu, clique na opção Auxílio e clique na opção Como usar a Ajuda. Digite:

procedure TF_Menu. ItemAuxilio4Click(Sender: TObject);
begin
   Application.HelpCommand(HELP_HELPONHELP, 0);   ? Chama o auxílio do Windows
end;
•   Quando fecharmos a nossa aplicação e necessário que também desativemos o auxílio, no objeto F_Menu, clique na página de Events e clique no evento Destroy. Digite:

procedure TF_Menu.FormDestroy(Sender: TObject);
begin
   Application.HelpCommand(HELP_QUIT, 0);      ? Desabilita o auxílio
end;

•   Saia do Menu Designer, salve o formulário e o projeto.
•   Rode o projeto e teste as opções do menu, saia com Ctrl+X ou utilize o comando Sair.
? Caso o F1 não ative o auxílio On-Line, provavelmente o seu menu está com a propriedade FormStyle em modo fsMDIForm, coloque-a no modo fsNormal. Se mesmo assim ainda não funcionou, mude a propriedade HelpContext do formulário para 1.
? As palavras-chaves para o comando HelpCommand são:

Comando   
                         
HELP_CONTEXT   
HELP_CONTENTS   
HELP_SETCONTENTS   
HELP_CONTEXTPOPUP   
HELP_KEY   
HELP_PARTIALKEY   
HELP_MULTIKEY   
HELP_COMMAND
HELP_SETWINPOS
HELP_FORCEFILE
HELP_HELPONHELP
HELP_QUIT

Criando a janela "Sobre o Sistema"
Em todo o sistema criado para o Windows© é incluído uma janela "Sobre o Sistema", por uma boa razão! todos os outros sistemas para o Windows© possuem uma, e quem vai querer quebrar esta maravilhosa tradição e criar um sistema sem uma janela destas ?
Criar o primeiro formulário com o Delphi não é uma tarefa assim tão difícil, mas para perdemos o medo inicial vamos criar a AboutBox (ou CaixaSobre), observe:
Criando e alterando os objetos
•   Para criar o formulário a partir do menu principal a opção File e New..., aparecerá a janela da New Items (mais informações retorne ao Capítulo II) e clique na página Forms e no objeto entitulado About box.

•   Elimine o objeto OKButton (botão de OK), clique sobre ele e pressione Delete, clique no objeto F_Sobre e click no objeto BitBtn  , encontrado na Component Palette na página Additional, e click novamente no F_Sobre
•   Dê uma organizada geral quanto a posição dos objetos para você poder ter uma idéia compare o desenho do seu formulário para ver se não ficou faltando nada
•   Salve o formulário nas opções de menu File e Save (ou pressione Ctrl+S), o Delphi questionará o nome e o diretório, o diretório é o C:\SISTEMA\CADDISCO e para o nome digite fSobre (note que novamente o nome externo e o mesmo do nome interno diferenciado por "_").

Associando o form "Sobre o Sistema" ao menu
Vamos associar o form fSobre com o fMenu:
•   Automatizando o comando SOBRE O SISTEMA: No objeto F_Menu, clique na opção Auxílio e na opção Sobre o Sistema. O Delphi criou o evento Click para o objeto item do menu ItemAuxilio1.
•   Digite o seguinte comando abaixo do begin:

procedure TF_Menu.ItemAuxilio1Click(Sender: TObject);
begin
    F_Sobre.ShowModal;       ? Abre o Objeto F_Sobre em modo Modal.
end;

•   Abaixo da diretiva de compilação: {$R *.DFM}

{$R *.DFM}

uses
    fSobre;          ? Utiliza a Unidade fSobre e todos os objetos dependentes dela.

procedure TF_Menu.ShowHint (Sender: TObject);

•   Saia do Code Editor e salve o formulário e o projeto.
•   Rode o projeto e teste o formulário Sobre o Sistema, o modo Modal não permitirá que você clique em nenhum outro lugar até a finalização desta janela, volte para o menu com o botão OK.
? Note que não foi preciso colocar nenhum código para que ao pressionar o botão OK o formulário fosse fechado, isto foi realizado graças a opção Kind, no Delphi você encontrará outros modelos de botão padrão do tipo: Cancela, Sim, Não entre outros.
Criando a janela Splash
A janela Splash é tida como a mais importante da aplicação. Esta janela aparece uma única vez (no início) durante a execução do seu sistema informando ao usuário para ter paciência e aguardar tranqüilamente enquanto o sistema é carregado, os formulários são criados, etc.
Existem vários tipos de janela Splash. O tipo mais comum é aquela que mostra o nome da aplicação, o autor, a versão, direitos autorais (Copyright) e uma imagem ou ícone que identifica a aplicação. Através da característica de herança dos objetos vamos obter facilmente esta janela:
1.   No menu principal selecione a opção File e New..., clique na página CDDA e na figura entitulada F_Sobre.
? Neste momento você obteve uma cópia da janela fSobre o problema é que a janela fSplash terá menos objetos que a janela fSobre, e por característica de herança o filho sempre deve superar os pais nunca ao contrário, então é necessário que invertamos as duas janelas.
Modificando o objeto F_Sobre
1.   Modifique a propriedade Name do F_Sobre para F_Splash e a propriedade BorderStyle para bsNone.
2.   Clique sobre objeto butOK e digite Ctrl+X, acerte o tamanho da janela.
3.   Salve o formulário nas opções de menu File e Save As..., o Delphi questionará o nome e o diretório, o diretório é o C:\SISTEMA\CADDISCO e para o nome digite fSplash.
Recriando o objeto F_Sobre
1.   Clique no objeto F_Sobre1 e note que automaticamente ele adquiriu as modificações do objeto fSplash.
2.   Aumente o tamanho da janela de modo a que caiba novamente o botão de OK e digite CTRL+V, troque a propriedade Caption do ButOK para &OK.
3.   Modifique a propriedade BorderStyle do form para bsDialog e a propriedade Caption para Sobre o Sistema.
4.   Salve o formulário nas opções de menu File e Save (ou pressione CTRL+S), o Delphi questionará o nome e o diretório, o diretório é o C:\SISTEMA\CADDISCO e para o nome digite fSobre (confirme a operação de sobescrita).
Organizando o objeto fSplash
1.   A partir do menu principal clique em Project | Options..., clique na página Forms e envie o objeto F_Splash (clicando sobre ele e clique no botão com o sinal de >) que está na lista Auto-create forms para a lista Available forms (para não ocupar espaço em memória uma janela que só será utilizada uma única vez, criaremos esta janela via comandos), clique sobre o botão OK.
2.   No menu principal selecione a opção View e Project Source (estamos agora acessando o programa principal que controla todas os outros formulários ou units).
3.   Após o comando begin adicione as seguintes linhas:
F_Splash := TF_Splash.Create(Application);    ? Cria o form como parte da aplicação.
F_Splash.Show;                ? Chama o form de modo não modal.
F_Splash.Refresh;             ? Mostra o form e devolve o controle para a
    aplicação.
   
4.   Antes do comando Application.Run; adicione a linha:
F_Splash.Free;               ? Libera o form da aplicação.

•   Saia do Code Editor e salve o formulário e o projeto.
•   Rode o projeto, qualquer problema compare com o código abaixo:

program CDDA;

uses
    Fmenu in 'FMENU.PAS' {F_Menu},
    FSobre in 'FSOBRE.PAS' {F_Sobre};

{$R *.RES}

begin
    F_Splash := TF_Splash.Create(Application);
    F_Splash.Show;
    F_Splash.Refresh;
    Application.Initialize;
    Application.HelpFile := 'C:\Sistema\CadDisco\Guia.hlp';
    Application.CreateForm(TF_Menu, F_Menu);
    Application.CreateForm(TF_Sobre, F_Sobre);
    F_Splash.Free;
    Application.Run;
end.
? Você pode mover o comando SplashScreen.Free; para o evento OnShow do form F_Menu. Isto fará com que a janela Splash só desapareça quando o menu for ativado.
? Infelizmente para os usuários do Delphi 1.0 esta característica de herança não havia sido implementada então, faz-se necessário a construção da tela fSplash através de uma cópia da tela fSobre com a utilização do comando Save As....
Criando o acesso a Base de Dados
É bem verdade que o nosso sistema se encontra na base Paradox, mas como escrevi no começo do trabalho com o Delphi é possível modificar o repositório de dados sem precisar alterar uma só linha do sistema produzido.
No capítulo a respeito das tabelas também vimos a impossibilidade de algumas ações produzidas por cláusulas SQL não serem bem vindas em base de dados não totalmente compatíveis com a estrutura do SQL, então se faz necessário identificar uma base padrão de uma base SQL.

•   Clique no botão   (Toggle Form/Unit) da SpeedBar, até você alternar para a Code Editor e localize o procedimento FormCreate associado ao evento OnCreate:
procedure TF_Menu.FormCreate(Sender: TObject);
begin
    Application.OnHint := ShowHint;   
    DBDisco.Connected := True;      ? Inicia o Banco de Dados
end;
A partir do próximo capítulo entraremos realmente no que o Delphi é capaz com tabelas, mas antes, é necessário que os conceitos ensinados anteriormente estejam bem fixados, se alguma coisa deu errada, releia o capítulo, ou então confira o código do F_Menu:

unit fMenu;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Menus, ComCtrls, DBTables, DB;

type
  TF_Menu = class(TForm)
      MainMenu1: TMainMenu;
      Arquivo1: TMenuItem;
      Consulta1: TMenuItem;
      Relatorio1: TMenuItem;
      Auxilio1: TMenuItem;
      Tabela1: TMenuItem;
      Cadastro1: TMenuItem;
      N6: TMenuItem;
      Sair1: TMenuItem;
      ItemTabela1: TMenuItem;
      ItemConsulta1: TMenuItem;
      ItemConsulta2: TMenuItem;
      ItemRelatorio1: TMenuItem;
      ItemRelatorio2: TMenuItem;
      N12: TMenuItem;
      ConfImpressora1: TMenuItem;
      ItemAuxilio2: TMenuItem;
      ItemAuxilio3: TMenuItem;
      ItemAuxilio4: TMenuItem;
      N14: TMenuItem;
      ItemAuxilio1: TMenuItem;
      LinhaStatus: TStatusBar;
      DBDisco: TDatabase;
      procedure FormCreate(Sender: TObject);
      procedure Sair1Click(Sender: TObject);
      procedure ItemAuxilio2Click(Sender: TObject);
      procedure ItemAuxilio3Click(Sender: TObject);
      procedure ItemAuxilio4Click(Sender: TObject);
      procedure FormDestroy(Sender: TObject);
      procedure ItemAuxilio1Click(Sender: TObject);
  private
      procedure ShowHint (Sender: TObject);
  public
      { Public declarations }
  end;

var
    F_Menu: TF_Menu;

implementation

{$R *.DFM}
uses
  fSobre;

procedure TF_Menu.ShowHint (Sender: TObject);
begin
    LinhaStatus.Panels.Items[0].Text := Application.hint;
end;

procedure TF_Menu.FormCreate(Sender: TObject);
begin
    Application.OnHint := ShowHint;
    DBDisco.Connected := True;
end;

procedure TF_Menu.Sair1Click(Sender: TObject);
begin
    DBDisco.Connected := False;
    Close;
end;

procedure TF_Menu.ItemAuxilio2Click(Sender: TObject);
begin
    Application.HelpCommand(HELP_CONTENTS, 0);
end;

procedure TF_Menu.ItemAuxilio3Click(Sender: TObject);
const
    EmptyString: pChar = '';
begin
    Application.HelpCommand(HELP_PARTIALKEY, LongInt(EmptyString));
end;

procedure TF_Menu.ItemAuxilio4Click(Sender: TObject);
begin
    Application.HelpCommand(HELP_HELPONHELP, 0);
end;

procedure TF_Menu.FormDestroy(Sender: TObject);
begin
    Application.HelpCommand(HELP_QUIT, 0);
end;

procedure TF_Menu.ItemAuxilio1Click(Sender: TObject);
begin
    F_Sobre.ShowModal;
end;

end.
? Caso o seu sistema não seja migrado para nenhum banco de dados no padrão SQL (do tipo ORACLE©, SYBASE©,...) não existe nenhuma necessidade em se utilizar o objeto DataBase, mas a utilização ou não do objeto não afeta o tempo de acesso ao sistema, então porque não prepará-lo para uma eventual mudança?

Trojan

Capítulo V
Janela para as Tabelas
Tabelas primárias de informação requerem entradas de dados simples, no nosso caso temos a tabela de categoria, a criação de janelas para a sua manipulação de seus dados não é um bicho de sete cabeças como você verá a seguir.
Reabrindo o seu Projeto
•   Se assim que você finalizou o capítulo anterior você saiu do Delphi, precisa agora reativar o projeto. Para tanto:
1.   No menu principal clique em File e Open....
2.   O sistema desenvolvido é encontrado no diretório C:\SISTEMA\CADDISCO, com a extensão .DPR.
•   Neste momento você está pronto para o trabalho, vamos criar a nossa janela:
3.   Clique no menu principal a opção File e New..., em New Items, mude a página para Forms e clique no objeto entitulado Database Form, agora siga a ordem:

1 - O tipo a ser criada.
Form Options: Create a simple form
Uma janela simples
DataSet Options: Create a form using TTables objects
Usando o objeto tabela
Botão Next.

2 - A tabela a ser usada para a janela.
Drive or Alias name: AliasDisco
Table Name: categor.db
Botão Next

3 - Campos a serem inseridos   
Botão ">>"
Botão Next

4 - Formação dos campos
Vertical
Botão Next

5 - Posição dos Labels
Left - A esquerda
Botão Next

6 - Completo
Gera a tela como form principal - Não
O Que gerar: Form e DataModule
Botão Finish

Alterando as Janelas Criadas
Se você seguiu direito as orientações anteriores, então você está com um belo princípio de janela em suas mãos. Digo um belo princípio porque você há de concordar comigo que a janela gerada não é nenhum pouco amigável para o nosso usuário, programando há um certo tempo com o Delphi descobri um padrão de janela que meus usuários gostaram, mas você poderá futuramente também encontrar o seu próprio padrão de janela, então vamos a algumas alterações:
? Se você está utilizando o Delphi 1.0, a única diferença será nos DataModules, não se preocupe coloque todas as instruções em um único formulário.
DataModules ?
Uma das principais novidades que acompanham o Delphi 2.0 é a possibilidade de criação de DataModules, estas janelas especiais funcionam como uma espécie de repositório de dados, não são visualizáveis em tempo de execução. É possível colocar em um único DataModule todo o modelo relacional e todos os outros formulários do sistema acessando-o.
Acesse inicialmente o objeto DataModule1 para as alterações que se seguem.
Modificando as Tabelas e as Ligações
Os objeto que contém as tabelas e as ligações de tabela são objetos invisíveis quando o aplicativo está rodando portanto não se preocupe muito com a posição que ele ocupar.
Tabela no Delphi está contida no objeto   (Table), encontrado na Component Palette na página Data Access, este objeto não é a tabela em si, mas um ponteiro para a tabela, portanto você poderá usar duplicações da mesma tabela, sem que isso afete a integridade de seu banco de dados.
•   Alterando as propriedades da Table:
1.   Altere na propriedade DataBaseName, nome do banco de dados BaseDisco, caso você não encontre na lista o BaseDisco, abra o objeto F_Menu e tente novamente.
2.   Verifique se a propriedade TableName está apontada para a tabela: CATEGOR.DB, retire o .DB (visando a compatibilidade com outras bases)
3.   Coloque a propriedade IndexFieldNames no nome do índice primário da tabela. SIG_CATEG.
4.   Altere a propriedade Name para TabCategor, ou seja, Tab + Nome da tabela externo (sem a sua extensão), isto facilitará a identificação da Table e a qual DataSource que ela pertence..
5.   Outra propriedade interessante da Table é Active, ela define se a tabela está ou não ativada para o uso. Alteraremos esta propriedade via código, portanto não se preocupe muito com ela neste instante, o ideal e deixá-la false, i.é inativa.
As Ligações da Tabela no Delphi é realizada através do objeto   (DataSource), encontrado na Component Palette na página Data Access, este objeto faz a ligação de sua tabela externa com os campos do formulário.
•   Alterando as propriedades do DataSource:
1.   Note que a propriedade DataSet está com o nome alterado (TabCategor), está propriedade define a table ou query (falemos nelas mais tarde) que será ligada.
2.   Altere a propriedade Name para DsCategor, ou seja, Ds + Nome da tabela externo (sem a sua extensão), como dito antes, isto facilitará a identificação do DataSource e a qual Table ele pertence.
Alterando os campos da tabela
Os campos da tabela deverão ser alterados para conterem as críticas, lembre-se, os campos presentes no DataModule são apenas uma "máscara" para os campos da tabela.
•   Dê um duplo clique sobre o TabCategor, será aberta a janela do FieldsEditor

? Outras propriedades importantes a serem levadas em consideração são:
?   Alignment: Alinhamento dentro do campo: Centralizado, à esquerda ou à direita;
?   DisplayWidth: Tamanho do campo disponível para inserção de dados;
?   FieldName: Nome do campo na tabela, externo;
?   Name: Nome do campo dentro do formulário, interno;
?   ReadOnly: Se é um campo só de leitura;
?   Size: Tamanho do campo na tabela; e
?   Visible: Campo é ou não visível.
? Veja mais observações sobre as máscaras no apêndice E.
•   Marque o campo DES_CATEG e altere apenas a propriedade DisplayLabel para Descrição.
? Troque a propriedade Name do objeto DataModule1 para DM_Modelo

Olhe depois como ficou!

Codificando o DataModule
Você já deve ter notado que para o Delphi a escrita de códigos é bastante reduzida e bem dividida entre os eventos e com a criação dos DataModules o código ainda fica mais reduzido, diferentemente para os usuários de Delphi 1.0. Todas as críticas e controles para as tabelas ficarão no DataModule enquanto que o formulário se preocupará com o manuseamento dos campos.
•   Código para efetivar as modificações na tabela para as bases SQL, clique no botão   (Toggle Form/Unit) da SpeedBar, até ter a visão novamente para o DM_Modelo, dê um clique simples no objeto TabCategor (marcando-o) e na Object Inspector, na página Events, dê um duplo click sobre o evento AfterPost:

procedure TDM_Modelo.TabCategorAfterPost(DataSet: TDataSet);
begin
    if F_Menu.DBDisco.IsSQLbased then      ? Se a base de dados é padrão SQL
    begin
        F_Menu.DBDisco.Commit;         ? Gravando as alterações da tabela
        F_Menu.DBDisco.StartTransaction;      ? Reinicia o modo de transações
    end;
end;
? O objeto que controla o banco de dados faz parte da Unit fMenu então é necessário fazer uso desta Unit, para tanto insira o seguinte código (abaixo da diretiva de compilação):
{$R *.DFM}

uses
   fMenu;
? Para as bases de formato SQL existem três declarações básicas:
1.   StartTransaction - Inicia um bloco de controle para as declarações;
2.   Commit - Termina o bloco de controle gravando as alterações feitas nas tabelas; e
3.   RollBack - Termina o bloco de controle cancelando quaisquer modificações feitas nas tabelas.
Controlando a duplicação dos Campos-Chave
•   É aconselhável não permitir que o usuário duplique os códigos de categoria, para tanto:
1.   Crie um novo objeto Table com as mesmas propriedades do objeto TabCategor (clique sobre o objeto e digite Ctrl+C e Ctrl+V, elimine as referências aos eventos), alterando a propriedade Name para TabCategorConf.
2.   No objeto TabCategorSIG_CATEG, localize-o através da Object Inspector, dê um duplo click sobre o evento OnValidate
procedure TDM_Modelo.TabCategorSig_CategValidate(Sender: TField);
begin
  if DSCategorState in [dsEdit, dsInsert] then      ? Verifica se o modo é de inserção ou edição de dados
    if TabCategorConf.FindKey([TabCategorSIG_CATEG]) then  ? Pesquisa o campo digit.na tab.criada
    begin
      F_Categ.EditSIG_CATEG.SetFocus;  ? Altera a posição do cursor para o objeto EditSIG_CATEG
      raise Exception.Create('Sigla da categoria duplicado'#10+                         ? Caso já exista mostra
                             'Click no botão "Localiza" em caso de dúvida');                          mensagem de erro
    end;
end;
?Note que existe uma referência para o objeto F_Categ (Será o formulário de Categoria) precisamos então fazer uso de sua Unit, para tanto coloque-a abaixo da diretiva de compilação:
{$R *.DFM}

uses
   fMenu,  { Menu Principal do Sistema }
   fCateg; { Cadastro de Categorias }
? A declaração #10, funciona como um Enter dentro da mensagem, isto fará com que esta mensagem tenha duas linhas.
?O segundo objeto Table foi criado pois a primeira tabela estará em modo de edição ou inserção de registros e não poderá ser desposicionada para a verificação, então a verificação se o registro existe será feita neste segundo objeto.
?O comando raise impede que o registro duplicado seja adicionado na tabela, no modo run-time este comando provocará um erro de classe exception que travará o projeto, não se preocupe, digite F9 e prossiga com os testes, quando o projeto for compilado e rodado através do .EXE o erro não travará o projeto mostrando somente a mensagem definida.
•   Um último detalhe para o DataModule que temos que prever que a cada novo registro o cursor deve se posicionar no primeiro campo do registro, para o início da digitação:
1.   Marque o objeto TabCategor, e dê um duplo click sobre o evento OnNewRecord:
procedure TDM_Modelo.TabCategorNewRecord(DataSet: TDataSet);
begin
    F_Categ.EditSig_Categ.SetFocus;   ? Altera a posição do cursor para o objeto EditSig_Categ
end;
Finalizando o DataModule
Salve o DataModule com o nome de DMModelo. Confira o código completo para o DataModule:
unit DMModelo;

interface

uses
  SysUtils, Windows, Classes, Graphics, Controls, Forms, Dialogs, DB, DBTables;

type                                        
   TDM_Modelo = class(TDataModule)
      TabCategorSig_Categ: TStringField;
      TabCategorDes_Categ: TStringField;
      DSCategor: TDataSource;
      TabCategor: TTable;
      TabCategorConf: TTable;
      StringField1: TStringField;
      StringField2: TStringField;
      procedure TabCategorAfterPost(DataSet: TDataSet);
      procedure TabCategorSig_CategValidate(Sender: TField);
      procedure TabCategorNewRecord(DataSet: TDataSet);
  private
      { private declarations }
  public
      { public declarations }
  end;

var
   DM_Modelo: TDM_Modelo;

implementation
 
{$R *.DFM}

uses
   fMenu,  { Menu Principal do Sistema }
   fCateg;  { Cadastro de Categorias }

procedure TDM_Modelo.TabCategorAfterPost(DataSet: TDataSet);
begin
    if F_Menu.DBDisco.IsSQLbased then
    begin
        F_Menu.DBDisco.Commit;
        F_Menu.DBDisco.StartTransaction;
    end;
end;

procedure TDM_Modelo.TabCategorSig_CategValidate(Sender: TField);
begin
    if DSCategor.State in [dsEdit, dsInsert] then
       if TabCategorConf.FindKey([TabCategorSIG_CATEG]) then
       begin
          F_Categ.EditSIG_CATEG.SetFocus;
          raise Exception.Create('Sigla da categoria duplicado'#10+
                                              'Click no botão "Localiza" em caso de dúvida');
       end;
end;

procedure TDM_Modelo.TabCategorNewRecord(DataSet: TDataSet);
begin
    F_Categ.EditSig_Categ.SetFocus;
end;

end.

Comandos e suas funções, por ordem de aparição:
Uses - Faz o uso de determinada unidade de procedimentos e biblioteca de funções.
 [DataSource].State - Define o estado em que se encontra determinado objeto DataSource.
 [Objeto].SetFocus - Posiciona o cursor no objeto definido.
raise - Cria um erro de classe exception que não permitirá que qualquer outra ação prossiga até a mesma ser resolvida.
Alterando o Formulário
Com o DataModule concluído vamos atacar a janela que será mostrada para o nosso usuário, chame objeto Form2 (chame-o através da Project Manager - opção do menu View | Project Manager).
Antes de fazermos quaisquer modificação vamos inicialmente alterar o nome da janela, para tanto pressione a tecla F11 (aparecerá a Object Inspector para o objeto Form2) altere a propriedade Name para F_Categ.
Outra modificação importante e trocar a referência do comando Uses abaixo da diretiva de compilação que estava referenciado ao antigo nome do objeto DataModule (Unit1), troque-o para:
{$R *.DFM}

uses
    DMModelo;  { Referencia ao DataModule }
Modificando os Labels e Campos
Os Labels, representados pelo objeto   (Label), encontrado na Component Palette na página Standard, são as etiquetas de cada campo que aparece a esquerda dos campos.
•   Alterando as propriedades dos Labels:
1.   Altere a propriedade Caption de SIG_CATEG e DES_CATEG para "&Sigla:" e "&Descrição:", respectivamente.
2.   Modifique a propriedade Fonte de ambos para MS Sans Serif, Negrito, 8 e Castanho; e a propriedade AutoSize para True.
? Para selecionar simultaneamente vários objetos, marque o primeiro objeto, segure a tecla SHIFT e marque os demais.
? Qualquer problema para dimensionar o tamanho de objetos use a tecla SHIFT + Setas.
? Qualquer problema para acertar a posição de objetos use a tecla CTRL + Setas.
? Uma propriedade interessante é a FocusControl ela indicará um controle para a posição do cursor. Ex.: Caso seja digitado ALT+S o cursor se posicionará no objeto EditSig_Categ ou Caso seja digitado ALT+D o cursor se posicionará no objeto EditDes_Categ.
Os Campos de Edição, representados pelo objeto   (DBEdit), encontrado na Component Palette na página Data Controls, são os que receberão o conteúdo dos campos da tabela.
•   Alterando as propriedades do campo Código:
1.   Modifique a propriedade Fonte (de ambos os campos) para MS Sans Serif, Normal, 8 e azul marinho.
2.   Verifique as propriedades DataSource e DataField, nome da ligação com DM_ Modelo.DSCategor e o nome do campo Sig_Categ, respectivamente.
3.   A propriedade Name, nome do campo, é montada com Edit + Nome externo do campo. EditSig_Categ.
•   Alterando as propriedades do campo Descrição:
4.   Verifique as propriedades DataSource e DataField, nome da ligação com DM_Modelo.DSCategor e o nome do campo Des_Categ, respectivamente.
5.   A propriedade Name, nome do campo, é montada com Edit + Nome externo do campo. EditDes_Categ.
Objeto DBNavigator
O objeto para o controle da tabela, representada pelo objeto   (DBNavigator), encontrado na Component Palette na página Data Controls, e apresentada pôr uma barra de funções que ligada ao DataSource controla a navegação dos campos, adição de novos registros, edição e exclusão de registros, o cancelamento ou a confirmação de uma modificação e a atualização do banco de dados (quando em rede):
 
Apresentada pelos botões: nbFirst (primeiro), nbPrior (anterior), nbNext (próximo), nbLast (último), ndInsert (inserir), ndDelete (excluir), nbEdit (editar), nbPost (confirmar), nbCancel (cancelar) e nbRefresh (atualizar dados).
•   Alterando as propriedades da barra de navegação:
1.   Confira a propriedade DataSource verificando para o nome da ligação com DM_Modelo.DSCategor
2.   A propriedade ConfirmDelete fará com seja exibida uma mensagem, confirmando ou não a exclusão.
3.   Altere a propriedade Hints, clicando em  , digite o nome de cada botão do seguinte modo:
Primeiro
Anterior
Próximo
Último
Inserir
Excluir
Editar
Confirmar
Cancelar
Atualizar dados

4.   Clique no botão OK e altere a propriedade ShowHint para true, isto fará com que embaixo de cada botão da barra, sobreposto pelo cursor, seja mostrado uma caixa como uma tarja amarela com a conteúdo da propriedade Hint.
5.   Você poderá definir quais botões deverão aparecer na barra utilizando a propriedade VisibleButtons, para tanto clique no sinal de + que aparece a esquerda da opção e defina true ou false para os botões que serão ou não mostrados.
Modificando os Paineis
Existem dois objetos Panel criados automaticamente: o primeiro superior, abriga o objeto DBNavigator, o segundo ocupando o restante da janela, abriga um objeto do tipo ScrollBox, labels e campos.
•   Alterando as propriedades do primeiro painel:
1.   Altere a propriedade Alignment, alinhamento da propriedade Caption do painel, para taLeftJustify.
2.   Coloque na propriedade Caption o nome Categoria.
3.   Modifique a propriedade Fonte para MS Sans Serif, Itálico, 14 e azul marinho.
? Arrume a barra de navegação de modo que não cubra a descrição, se for o caso aumente o tamanho da janela.
•   Alterando as propriedades do segundo painel:
1.   Aumente ou diminua o tamanho da janela e note que este painel diminue e aumenta com ela, isto se deve a propriedade Align estar no modo alClient, altere esta propriedade (temporariamente) para alNone.
? Para conseguir ver a tela de propriedades deste painel, clique em quaisquer das bordas, pois sobre este painel existe um outro objeto denominado ScrollBox também no modo alClient.
Modificando a Janela
A janela está um pouco escondida atrás dos objetos painéis criados, após alterar a propriedade Align do segundo painel, estique um pouco a janela para baixo e clique nela.
•   Alterando as propriedades da janela:
1.   Retire as opções biMinimize e biMaximize da propriedade BorderIcons.
2.   Altere na propriedade BorderStyle para bsSingle.
3.   Mude a propriedade Caption para Tabela.
4.   Se você não o fez, mude a propriedade Name para F_Categ, ou seja F_ + Nome da tabela externo (sem a sua extensão), isto facilitará a identificação entre o form e sua unit.
5.   Verifique a propriedade Position (posição da janela) ela deve estar com o valor ScreenCenter (centralizado).
6.   Salve o formulário com o nome fCateg e salve o projeto.
Criando o terceiro Painel
Criaremos agora um terceiro painel para comportar alguns botões
Criando e alterando o painel:
1.   Crie um objeto Panel, clique no objeto   (Panel), encontrado na Component Palette na página Standard, e clique no objeto F_Categ, altere.

Os botões que criaremos farão duas funções: 1.Sair da janela e 2.Localização rápida de um determinado registro.
Criando o primeiro botão:
1.   Marque o objeto panel3 criado, click no objeto BitBtn  , encontrado na Component Palette na página Additional, e click no panel3.

Trojan

Continuação

Programando no formulário
Agora vem a parte de código. Ao final deste tópico você observará que o trabalho maior ficou pôr conta de organizar e arrumar os objetos do que com o código em si, i.e., orientação a objetos.
Preservando as áreas de Memória
Com o Delphi é possível trabalhar de duas maneiras, a primeira é permitir que o Delphi crie todos os objetos em memória aguardando simplesmente que estes sejam chamados, mas isto implica que a máquina Client deva ter uma boa quantidade de memória para suportar os objetos que serão ali colocados, a segunda maneira e criarmos estes objetos via código permitindo que o Delphi crie o mínimo possível, o problema que isto implica e na demora quanto da chamada de um formulário, em média 50 segundos para ativar o formulário . É preferível trabalhar com o segundo modo uma vez que para entrar em determinado formulário o nosso usuário só o fará uma única vez.
Inicialmente retiraremos da área de criação automática o formulário de categoria e o formulário Sobre o sistema, para tanto, a partir do menu principal clique em Project | Options..., clique na página Forms e envie no objetos F_Categ e F_Sobre (clique sobre o primeiro, segure a tecla Shift e clique no segundo e no terceiro e em seguida clique no botão com o sinal de >) que está na lista Auto-create forms para a lista Available forms, clique sobre o botão OK (processo semelhante foi realizado para o formulário F_Splash).

•   Altere agora a instrução do formulário F_Menu, evento OnClick para o objeto ItemAuxilio1, para criarmos o objeto F_Sobre e após a sua chamada destruí-lo da área de memória:
procedure TF_Menu.ItemAuxilio1Click(Sender: TObject);
begin
    with TF_Sobre.Create(Self) do      ? Cria o formulário em memória
    begin
       ShowModal;            ? Chama o formulário através da área aberta
       Free;            ? Libera a área aberta
    end;
end;
•   Código para ativar a Base de dados e as tabelas quando no DataModule, retorne ao formulário F_Categ:
1.   Clique no botão   (Toggle Form/Unit) da SpeedBar, até você alternar para o Code Editor.

     procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    procedure inicio;          ? Criando a chamada para um procedimento público.
end;

var
  F_Categ: TF_Categ;

implementation

{$R *.DFM}
 
uses
   FMenu,   { Menu Principal do Sistema }
   DMModelo;   { Referencia ao DataModule }

procedure TF_ Categ.Inicio;          ? Inicio do procedimento
begin
    if F_Menu.DBDisco.IsSQLbased then      ? Se a base de dados é padrão SQL
       F_Menu.DBDisco.StartTransaction;      ? Inicia o modo de transações
    DM_Modelo.TabCategor.Open;         ? Ativa a Tabela
    Screen.Cursor := crDefault;         ? Faz o cursor ficar no formato de Seta
    ShowModal;               ? Mostra o formulário F_Categ
end;
? A propriedade cursor no exemplo foi atribuída a unidade Screen que atribui ao sistema o modelo do cursor, mas é possível também atribuir um determinado cursor a um objeto específico, a propriedade pode ser alterada para os diversos tipos de cursores default do windows
•   Não é necessário colocar o comando Close para o objeto butFechar pois a propriedade Kind fará isto automático.
•   Código para encerrar as tabelas do DataModule quando for dada saída no formulário, observe que o usuário não deve poder estar inserindo ou editando registros:
1.   No objeto F_Categ, localize-o através da Object Inspector, dê um duplo click sobre o evento OnClose:
procedure TF_Categ.FormClose(Sender: TObject; var Action: TCloseAction);   
begin
    if DM_Modelo.DSCategor.State in [dsEdit, dsInsert] then   ? Verifica se o estado do objeto    
    begin                          DataSource é Edição ou inserção
        MessageDlg('Cancele a edição (ou inserção) da Categoria antes de fechar!',    ? mostra mensagem
      mtInformation, [mbOK], 0);                      de informação
        Action := caNone;               ? Cancela a saída da janela
        Exit;                  ? Sai da procedure
    end;
    Screen.Cursor := crHourGlass;            ? Faz o cursor virar uma ampulheta
    TabCategor.Close;               ? Fecha a tabela
    if F_Menu.DBDisco.IsSQLbased then         ? Se a base de dados é padrão SQL
       F_Menu.DBDisco.Commit;            ? Encerra o modo de transações gravando
end;                              as alterações no banco de dados
? A função MessageDlg faz parte da Unit Dialogs então é necessário fazer uso desta Unit, para tanto insira o seguinte código (abaixo da diretiva de compilação):
{$R *.DFM}

uses
   FMenu,   { Menu Principal do Sistema }
   DMModelo,   { Referencia ao DataModule }
   Dialogs;        { Utilizado para o controle da função MessageDlg }
•   Código para localizar determinado registro, observe que se o usuário não deve estar inserindo ou editando registros:
1.   Dê um duplo Click sob o objeto ButLocalizar:
procedure TF_Categ.ButLocalizarClick(Sender: TObject);
var                ? Declaração de variáveis
   ObjPesquisa: String;          ? Cria a variável ObjPesquisa do tipo String
begin
    if DM_Modelo.DSCategor.State in [dsEdit, dsInsert] then      
    begin
        MessageDlg('Cancele a edição (ou inserção) da Categoria antes de localizar!',
                            mtInformation, [mbOK], 0);
        Exit;
    end;
    ObjPesquisa := DM_Modelo.TabCategorSig_Categ.Value;   ? Atribui a ObjPesquisa o valor do campo
   de tabela Sig_Categ
    if InputQuery('Entre com a sigla da categoria',
                          'Sigla',ObjPesquisa) then                   ? Solicita a digitação do código a ser procurado
     if not DM_Modelo.TabCategor.FindKey([ObjPesquisa]) then   ? Pesquisa o campo digitado na tabela
        MessageDlg('Sigla da Categoria não encontrada.',                  ? Caso não seja encontrado informa
                            mtInformation, [mbOK], 0);
end;
? A função InputQuery também faz parte da Unit Dialogs.
? O método FindKey faz parte do Objeto TTable.
Criando Funções Globais
Uma função ou um procedimento global e uma série de comandos comuns a um sistema como um todo, em linguagem Pascal é quase que proibido (não é proibido pois a linguagem permite) a utilização de um mesmo conjunto de comandos repetidas vezes, note que para o nosso formulário temos os mesmos comandos em chamadas diferentes:
procedure TF_Categ.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    if DM_Modelo.DSCategor.State in [dsEdit, dsInsert] then            ? Aqui
    begin
        MessageDlg('Cancele a edição (ou inserção) da Categoria antes de fechar!',    ? Aqui
                            mtInformation, [mbOK], 0);               ? Aqui
        Action := caNone;
        Exit;
    end;
    ...
end;

procedure TF_Categ.ButLocalizarClick(Sender: TObject);
var
    ObjPesquisa: String;
begin
    if DM_Modelo.DSCategor.State in [dsEdit, dsInsert] then            ? Aqui
    begin
        MessageDlg('Cancele a edição (ou inserção) da Categoria antes de localizar!',   ? Aqui
                             mtInformation, [mbOK], 0);               ? Aqui
        Exit;
    end;
    ...
end;
Podemos então retirar o trecho e criarmos uma função isolada que criticará o estado da edição devolvendo a mensagem, modificando o trecho diferente, ficando desta maneira (não esqueça de declarar a função na área PRIVATE):
  private
      function CriticaEdicao(AntesDe: String) : boolean;   ? Cria a função na área particular
  public
      procedure inicio;
  end;

var   
...
...
...
function TF_Categ.CriticaEdicao(AntesDe: String) : boolean;   ? Recebe o tipo da mensagem
begin
    if DM_Modelo.DSCategor.State in [dsEdit, dsInsert] then                 ? Verifica o estado
    begin
        MessageDlg('Cancele a edição (ou inclusão) da categoria antes de ' +
                 AntesDe, mtError, [mbOK], 0);            ? Monta e envia a mensagem   
        Result := True;                  ? Devolve que enviou a mens.
    end
    else
       Result := False;                  ? Devolve que não enviou a mens.
end;

procedure TF_Categ.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    if CriticaEdicao('fechar' ) then               ? Substitui pela chamada a função
    begin
        Action := caNone;
        Exit;
    end;
    ...
end;

procedure TF_Categ.ButLocalizarClick(Sender: TObject);
var
    ObjPesquisa: String;
begin
    if CriticaEdicao('localizar' ) then            ? Substitui pela chamada a função
      Exit;
    ...
end;
Note que já ganhamos uma certa vantagem, ao invés de termos que alterar em dois lugares diferentes só teremos que alterar em um único lugar, mas ainda não está perfeito pois devemos lembrar que um sistema normalmente não é composto por apenas uma tabela, sem contar a parte do cadastro, então se seguirmos o mesmo padrão de construção de formulários para outras tabelas continuaremos a repetir vários comandos, então vamos fazer que a nossa função sirva para a critica de edição de qualquer tabela, para isto precisamos enviar também o DataSource que pesquisará o estado e uma outra variável do tipo String para dizermos de qual tabela estamos falando para cancelar a edição, vá para o objeto F_Menu e crie a seguinte função (não esqueça de declarar na área PUBLIC):
  private
      procedure ShowHint (Sender: TObject);
  public
     function CriticaEdicao(DSOrigem: TDataSource; DoQue, AntesDe: String) : boolean;      ?  Aqui
  end;

var
...
...
{ Função Critica Edição
Recebe: DSOrigem: DataSouce para investigar o estado
   DoQue: Nome real da Tabela
   AntesDe: Função a executar do tipo Fechar, Localizar...
Devolve: True - Se o DataSource está  em estado de edição ou inserção
   False - Se o DataSource está em estado de navegação }

function TF_Menu.CriticaEdicao(DSOrigem: TDataSource; DoQue, AntesDe: String) : boolean;
begin
    if DSOrigem.State in [dsEdit, dsInsert] then
    begin
       MessageDlg('Cancele a edição (ou inclusão) ' + DoQue + ' antes de ' +
                 AntesDe, mtError, [mbOK], 0);
       Result := True;
    end
    else
       Result := False;
end;
Altere agora o objeto F_Categ eliminando a função CriticaEdicao e modificando as chamadas:
  private
      { comandos particulares }   ? Elimine
  public
      procedure inicio;
  end;

var   
  F_Categ: TF_Categ;
...
...
Elimine as linhas da função
...
...
procedure TF_Categ.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   if F_Menu.CriticaEdicao(DM_Modelo.DSCategor, 'Categoria', 'fechar' ) then   ? Substitua aqui
   begin
       Action := caNone;
       Exit;
   end;
    ...
end;

procedure TF_Categ.ButLocalizarClick(Sender: TObject);
var
    ObjPesquisa: String;
begin
    if F_Menu.CriticaEdicao(DM_Modelo.DSCategor, 'Categoria', localizar' ) then   ? Substitua aqui
      Exit;
    ...
end;
Alterando o Menu para receber o formulário
Agora finalmente vamos rodar nosso projeto mas antes precisamos chamar o formulário através do menu principal para isto:
1.   Abra o objeto F_Menu: no menu principal escolha View e Project Manager, marque o objeto F_Menu e clique sobre o botão View form.
2.   Clique em Arquivo, Tabela e Categoria, coloque o seguinte código:

procedure TF_Menu.Categoria1Click(Sender: TObject);
begin
    Screen.Cursor := crHourGlass;         ? Faz do cursor uma ampulheta
    F_Categ := TF_Categ.Create(Application);   ? Cria o formulário em memória
    F_Categ.Inicio;            ? Chama o formulário através da área aberta
    F_Categ.Free;               ? Libera a área aberta
    Screen.Cursor := crDefault;          ? Faz do cursor uma seta
end;
3.   O objeto F_Categ faz parte da Unit fCateg então é necessário fazer o uso desta Unit, para tanto insira o seguinte código (abaixo da diretiva de compilação):
{$R *.DFM}

uses
   fSobre,   { Janela do Sobre o Sistema }
   fCateg;   { Cadastro da Tabela de Categoria }
4.   Saia do Code Editor e salve o formulário e o projeto.
5.   Rode o projeto e teste o formulário de categoria, insira algumas categorias, tente provocar o erro de duplicação, tente inserir um registro com o código vazio e localizar um registro.
6.   Se alguma coisa deu errada, releia o capítulo, ou então confira todo o código:

unit fcateg;

interface

uses
    SysUtils, Windows, Messages, Classes, Graphics, Controls,
    StdCtrls, Forms, DBCtrls, DB, Mask, ExtCtrls, Buttons;

type
    TF_Categ = class(TForm)
        ScrollBox: TScrollBox;
        Label1: TLabel;
        EditSig_Categ: TDBEdit;
        Label2: TLabel;
        EditDes_Categ: TDBEdit;
        DBNavigator: TDBNavigator;
        Panel1: TPanel;
        Panel2: TPanel;
        Panel3: TPanel;
        ButFechar: TBitBtn;
        ButLocalizar: TBitBtn;
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure ButLocalizarClick(Sender: TObject);
    private
        { private declarations }
    public
        procedure inicio;
end;

var
  F_Categ: TF_Categ;

implementation

{$R *.DFM}

uses
  fMenu,      { Menu Principal do Sistema }
  DMModelo,   { Referencia ao DataModule }
  Dialogs;   { Utilizado para o controle da função MessageDlg }

procedure TF_Categ.Inicio;
begin
    if F_Menu.DBDisco.IsSQLbased then
      F_Menu.DBDisco.StartTransaction;
    DM_Modelo.TabCategor.Open;   
    Screen.Cursor := crDefault;
    ShowModal;
end;

procedure TF_Categ.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    if F_Menu.CriticaEdicao(DM_Modelo.DSCategor, 'Categoria', 'Fechar' ) then
    begin
        Action := caNone;
        Exit;
    end;
    Screen.Cursor := crHourGlass;
    DM_Modelo.TabCategor.Close;
    if F_Menu.DBDisco.IsSQLbased then
      F_Menu.DBDisco.Commit;
end;

procedure TF_Categ.ButLocalizarClick(Sender: TObject);
var
    ObjPesquisa: String;
begin
    if F_Menu.CriticaEdicao(DM_Modelo.DSCategor, 'Categoria', 'Localizar' ) then
      Exit;

    ObjPesquisa := DM_Modelo.TabCategorSig_Categ.Value;
    if InputQuery('Entre com a Sigla da categoria','Sigla',ObjPesquisa) then
       if not DM_Modelo.TabCategor.FindKey([ObjPesquisa]) then
           MessageDlg('Sigla da Categoria não encontrada.',mtInformation,[mbOK],0);
end;

end.

Comandos e suas funções, por ordem de aparição:
[Tabela].Open - Ativa um objeto Table é equivalente a Active := True.
[Form].ShowModal - Ativa o objeto Form, não permitindo que nenhum outro objeto Form anterior seja ativado, até que o mesmo seja desativado.
Exit - Sai da função ou procedimento.
[Tabela].Close - Desativa um objeto Table é equivalente a Active := False.
Var - Define uma cadeia de variáveis locais.
InputQuery - Mostra uma caixa de diálogo para leitura e entrada de variáveis do tipo String.

Trojan

Capítulo VI
Trabalhando com janela Pai X Filha
Se você até agora não sentiu dificuldade em criar e entender o trabalho com tabelas livres, não sentirá também dificuldade em criar o formulário para receber este caso, ao contrário, aconselho que você releia e refaça o capítulo anterior.
Em nosso projeto, cada registro na tabela de música só existirá se houver um correspondente na tabela básico, então a tabela básico é "pai" (mestre) da tabela música que é sua "filha" (detalhe). Esta teoria acima é explicada no conceito de modelo relacional de dados (MER). O Delphi incorpora este modelo mesmo para banco de dados não-relacionais, caso estivéssemos utilizando o dBase em nosso projeto.
Criando a janela automaticamente
•   Se assim que você finalizou o capítulo anterior você saiu do Delphi, reative o seu projeto.
•   Agora que você está pronto para o trabalho, vamos criar a nossa janela:
1.   Clique no menu principal a opção File e New..., em New Items, mude a página para Forms e clique no objeto entitulado Database Form, parece cópia do capítulo anterior? cuidado leia as instruções abaixo:


1 - O tipo a ser criada.
Form Options: Create a master/detail form
Uma janela mestre e detalhes
DataSet Options: Create a form using TTables objects
Usando o objeto tabela
Botão Next.

2 - A tabela mestre a ser usada para a janela.
Drive or Alias name: AliasDisco
Table Name: basico.dbf
Botão Next

3 - Campos a serem inseridos   
Botão ">>"

4 - Formação dos campos
Vertical

5 - Posição dos Labels
Left - A esquerda
Botão Next

6 - A tabela detalhe a ser usada para a janela.
Drive or Alias name: AliasDisco
Table Name: musica.dbf
Botão Next

7 - Campos a serem inseridos   
Botão ">>"
    Botão Next

8 - Formação dos campos
Grid
Botão Next

9 - Montagem da chave de ligação
Available Indexes : Primary
Detail Fields : COD_DISCO
Master Fields : COD_DISCO
Botão Add
Joined Fields COD_DISCO -> COD_DISCO
     Botão Next

10 - Completo
Gera a tela como form principal - Não
O Que gerar: Form e DataModule
Botão Finish


Sobre os DataModules
Como eu disse no capítulo anterior é possível criar um único DataModule abrangendo o modelo relacional completo, basta para isto você fazer o formulário que está chamando o DataModule controlar o comando Open e Close das tabelas. Não farei desta maneira pois isto ao mesmo tempo que simplificaria o meu trabalho dificultaria o seu entendimento, que é o de uma pessoa que estivesse aprendendo o Delphi neste momento, então para este trabalho adotarei um DataModule para cada cadastro.
Trabalhando com as Tabelas
Chame o objeto DataModule1 criado, a nossa primeira providência será a de alterar a propriedade Name do objeto para DM_Basico, observe que foi criado dois objetos Table, o primeiro está apontado para a tabela BASICO e o segundo para a tabela MUSICA, note que para este segundo as propriedades MasterSource e MasterFields estão "presas" pelo primeiro objeto, este é o relacionamento entre ambas. Vamos antes criarmos alguns pequenos detalhes:
•   Crie três objetos Table  , encontrado na Component Palette página Data Access, e um objeto DataSource  , encontrado na Component Palette página Data Access, e altere.

?Os objetos na hora da execução do formulário ficarão invisíveis, mas é bom colocá-los em cantos estratégicos, isto evita a confusão.
? A utilidade de cada objeto Table:
?   TabBasico - Tabela mestre principal.
?   TabBasicoConf - Tabela BASICO para realizar a validação do nome do CD.
?   TabMusica - Tabela utilizada para mostrar as músicas cadastradas de cada disco.
?   TabCategor - Tabela para mostrar a descrição da categoria.
?   TabCategorConf - Tabela para validação da sigla da categoria.
•   Crie o objeto Query  , encontrado na Component Palette página Data Access, que servirá para calcular o código automático, calculando sempre o código de maior valor, e altere.
? O campo COD_DISCO criado, servirá apenas como uma chave de ligação entre a tabela Basico e Musica, será uma chave interna do nosso sistema e sua alimentação se fará através deste objeto SQL criado pegando o maior valor e adicionando 1.
Trabalhando com os Campos
Precisamos inserir alguns campos, pois iremos precisar deles no trabalho com o código e para o objeto DBGrid1, utilize o Fields Editor para inserir os campos que faltam:
Para o objeto TabBasico:
?   COD_DISCO, Propriedade DisplayLabel: Código;
?   NOM_DISCO, Propriedade DisplayLabel: Nome;
?   TIP_DISCO, Propriedade DisplayLabel: Tipo e EditMask: >AAA;0;_
?   FOT_CAPA, Propriedade DisplayLabel: Foto; e
?   SIG_CATEG, Propriedade DisplayLabel: Categoria e EditMask: >AA;0;_
Para o objeto TabMusica:
?   COD_DISCO, Propriedade Visible: False.
?   NUM_FAIXA, Propriedade DisplayLabel: Faixa e DisplayWidth: 2;
?   NOM_MUSICA, Propriedade DisplayLabel: Música e DisplayWidth: 40; e
?   NOM_AUTOR, Propriedade DisplayLabel: Autor; e
?   TMP_MUSICA, Propriedade DisplayLabel: Tempo e EditMask: 00\:00;0;_
Para o objeto QryContador:
?   De um duplo clique sobre o objeto aparecerá a janela Fields Editor, clique com o botão direito e no menu que aparecerá clique na opção Add Fields... e adicione o campo.
Antes de iniciarmos a programação do DataModule compare como ficou o DataModule e salve-o com o nome de DMBasico.
Controlando o DataModule
Agora falta o código, note que a maior parte é uma repetição daquilo que já vimos anteriormente:
•   Ativando as tabelas ao ser chamado DataModule:
1.   Clique no objeto DMBasico e na Object Inspector na página Events dê um duplo clique sobre o evento OnCreate e altere-o do seguinte modo:

procedure TDM_Basico.DM_BasicoCreate(Sender: TObject);
begin
    if F_Menu.DBDisco.IsSQLbased then      ? Se a base de dados é padrão SQL
       F_Menu.DBDisco.StartTransaction;      ? Inicia o modo de transações
    TabCategor.Open;             ? Ativa as tabelas
    TabCategorConf.Open;
    TabMusica.Open;
    TabBasico.Open;
    TabBasicoConf.Open;
end;
•   Código para encerrar as transações com a Base de Dados e fechar as tabelas quando for encerrado o DataModule.
1.   Digite F11 e localize o objeto DM_Categ, na Object Inspector, na página Events, dê um duplo click sobre o evento OnDestroy:
procedure TDM_Basico.DM_BasicoDestroy(Sender: TObject); 
begin
    TabBasico.Close;             ? Fecha as tabelas
    TabBasicoConf.Close;
    TabMusica.Close;
    TabCategor.Close;
    TabCategorConf.Close;
    if F_Menu.DBDisco.IsSQLbased then      ? Se a base de dados é padrão SQL
       F_Menu.DBDisco.Commit;         ? Encerra o modo de transações gravando as
end;                           alterações no banco de dados
? Lembre-se da utilização do objeto F_Menu, então é preciso declarar a unidade a qual ele pertence com o comando USES (abaixo da diretiva de compilação):
{$R *.DFM}

uses
    fMenu;   { Menu Principal }
? Repare que no início desta Unit também existe uma outra declaração Uses, após a sessão interface, então por que não colocar todas essas declarações em um lugar só? 1o) O Delphi controlará (colocando ou removendo) as Units ali colocadas (dependendo dos objetos utilizados) e 2o) Todos os comandos declarados antes da declaração implementation (com exceção de eventos de criação do tipo onCreate), serão executados e objetos e units ficarão em memória esperando serem chamados, então é impraticável colocar units que só serão utilizadas em tempo de execução.
Contadores
O objeto query realiza consultas em modo SQL, no próximo capítulo o utilizaremos para criarmos nossas consultas mas, neste momento ele será utilizado para verificar qual o maior valor armazenado no campo código.
•   A cada novo registro devemos criar também um novo COD_DISCO (lembra do objeto QryContador). Além disso, precisamos nos posicionar no primeiro campo do cadastro, isto será realizado em dois eventos distintos:
1.   Marque o objeto TabBasico, e dê um duplo clique sobre o evento onNewRecord:
procedure TF_Basico.TabBasicoNewRecord(DataSet: TDataset);
begin
    F_Basico.EditNOM_DISCO.SetFocus;         ? Posiciona o cursor no objeto
end;
? Observe que foi utilizado o objeto F_Basico, então é preciso declarar a unidade a qual ele pertence com o comando USES (abaixo da diretiva de compilação):
{$R *.DFM}

uses
   fBasico;   { Cadastro do Básico }
   fMenu;   { Menu Principal }

2.   Digite F11 e dê um duplo clique sobre o evento BeforePost:
procedure TF_Basico.TabBasicoBeforePost(DataSet: TDataset);
begin
   if DSBasico.State = dsInsert then         ? Verifica se é uma inclusão na base
   begin
     QryContador.Active := False;             ? Desativa a Query
     QryContador.Active := True;            ? Ativa a Query
     with QryContador.Fields[0] do            ? Observe os lembretes
        if IsNull then                ? Se o valor do contador é nulo
           TabBasicoCOD_DISCO.Value := 1         ? Atribui 1 ao campo COD_DISCO
        else                   ? Senão
           TabBasicoCOD_DISCO.Value := AsInteger + 1;   ? Atribui ao campo COD_DISCO a adição     
   end;                         de 1 ao valor do contador campo
end;
? O comando with é utilizado como método de taquigrafia, para não escrevermos várias vezes o mesmo nome de um determinado objeto.
? Porque não colocarmos todo o código no evento onNewRecord ? Por causa do controle multi-usuário, imagine, um indivíduo A inicia a inclusão de um CD, e um indivíduo B também inicia outra inclusão, como o código do indivíduo A ainda não foi gravado no banco, será dado o mesmo código para o indivíduo B, isto não acontecerá se o código for calculado momentos antes de ser gravado o registro, com é o caso do evento BeforePost.
•   Para confirmarmos as alterações para a base SQL, pressione novamente a tecla F11 e na página Events, dê um duplo click sobre o evento AfterPost:

procedure TDM_Basico.TabBasicoAfterPost(DataSet: TDataSet);
begin
    if F_Menu.DBDisco.IsSQLbased then      ? Se a base de dados é padrão SQL
    begin
        F_Menu.DBDisco.Commit;         ? Gravando as alterações da tabela
        F_Menu.DBDisco.StartTransaction;      ? Reinicia o modo de transações
    end;
end;
Validando os Campos
Para não acontecer um duplicação dos nomes dos CD's, utilizaremos para a crítica a mesma idéia do que aconteceu com o formulário de Categoria:
1.   Marque o objeto TabBasicoNOM_DISCO, e dê um duplo clique sobre o evento OnValidate:
procedure TDM_Basico.TabBasicoNom_DiscoValidate(Sender: TField);
begin
    if DSBasico.State in [dsEdit, dsInsert] then      ? Se o modo é de inserção ou   edição
      if TabBasicoConf.FindKey([TabBasicoNOM_DISCO]) then   ? Pesquisa o campo digitado
      begin
          F_Basico.EditNOM_DISCO.SetFocus;                         ? Altera a posição do cursor
         raise Exception.Create('Nome do CD duplicado'#10+      ? Caso já exista mostra mensagem
                             'Click no botão "Localiza" em caso de dúvida');            de erro e impede o cadastro
      end;
end;
•   Para que o nosso usuário escolha somente as categorias existentes:
1.   Marque o objeto TabBasicoSIG_CATEG, e dê um duplo clique sobre o evento OnValidate:
procedure TDM_Basico.TabBasicoSig_CategValidate(Sender: TField);
begin
  if DSBasico.State in [dsEdit, dsInsert] then
    if not (TabCategorConf.FindKey([TabBasicoSIG_CATEG])) then   ? Observe o comando NOT
    begin
        F_Basico.EditSIG_CATEG.SetFocus;
        raise Exception.Create('Sigla da categoria não existe'#10+
                                             'Click no botão "Localiza Categoria" em caso de dúvida');
    end;
end;
Com o DataModule o nosso trabalho já está concluído, salve o objeto e confirme o código:

unit DMBasico;

interface

uses
   SysUtils, Windows, Classes, Graphics, Controls, Forms, Dialogs, DB, DBTables;

type
  TDM_Basico = class(TDataModule)
      TabMusicaCod_Disco: TFloatField;
      TabMusicaNum_Faixa: TFloatField;
      TabMusicaNom_Musica: TStringField;
      DSBasico: TDataSource;
      TabBasico: TTable;
      TabMusica: TTable;
      DSMusica: TDataSource;
      TabBasicoConf: TTable;
      TabCategor: TTable;
      TabCategorConf: TTable;
      DSCategor: TDataSource;
      TabBasicoCod_Disco: TFloatField;
      TabBasicoNom_Disco: TStringField;
      TabBasicoTip_Disco: TStringField;
      TabBasicoFot_Capa: TBlobField;
      TabBasicoSig_Categ: TStringField;
      QryContador: TQuery;
      QryContadorMAXOFCOD_DISCO: TFloatField;
      procedure DM_BasicoCreate(Sender: TObject);
      procedure DM_BasicoDestroy(Sender: TObject);
      procedure TabBasicoNewRecord(DataSet: TDataSet);
      procedure TabBasicoBeforePost(DataSet: TDataSet);
      procedure TabBasicoAfterPost(DataSet: TDataSet);
      procedure TabBasicoNom_DiscoValidate(Sender: TField);
      procedure TabBasicoSig_CategValidate(Sender: TField);
   private
      { private declarations }
   public
      { public declarations }
end;

var
  DM_Basico: TDM_Basico;

implementation

{$R *.DFM}

uses
    fBasico,  { Cadastro do Básico }
    fMenu;    { Menu Principal }

procedure TDM_Basico.DM_BasicoCreate(Sender: TObject);
begin
    if F_Menu.DBDisco.IsSQLbased then
       F_Menu.DBDisco.StartTransaction;
    TabCategor.Open;
    TabCategorConf.Open;
    TabMusica.Open;
    TabBasico.Open;
    TabBasicoConf.Open;
end;

procedure TDM_Basico.DM_BasicoDestroy(Sender: TObject);
begin
    TabBasico.Close;
    TabBasicoConf.Close;
    TabMusica.Close;
    TabCategor.Close;
    TabCategorConf.Close;
    if F_Menu.DBDisco.IsSQLbased then
      F_Menu.DBDisco.Commit;
end;

procedure TDM_Basico.TabBasicoNewRecord(DataSet: TDataSet);
begin
    F_Basico.EditNOM_DISCO.SetFocus;
end;

procedure TDM_Basico.TabBasicoBeforePost(DataSet: TDataSet);
begin
    if DSBasico.State = dsInsert then
    begin
       QryContador.Active := False;
       QryContador.Active := True;
       with QryContador.Fields[0] do
          if IsNull then
            TabBasicoCOD_DISCO.Value := 1
          else
            TabBasicoCOD_DISCO.Value := AsInteger + 1;
    end;
end;

procedure TDM_Basico.TabBasicoAfterPost(DataSet: TDataSet);
begin
    if F_Menu.DBDisco.IsSQLbased then
    begin
        F_Menu.DBDisco.Commit;
        F_Menu.DBDisco.StartTransaction;
    end;
end;

procedure TDM_Basico.TabBasicoNom_DiscoValidate(Sender: TField);
begin
  if DSBasico.State in [dsEdit, dsInsert] then
    if TabBasicoConf.FindKey([TabBasicoNOM_DISCO]) then
    begin
        F_Basico.EditNOM_DISCO.SetFocus;
        raise Exception.Create('Nome do CD duplicado'#10+
                                             'Click no botão "Localiza" em caso de dúvida');
    end;
end;

procedure TDM_Basico.TabBasicoSig_CategValidate(Sender: TField);
begin
    if DSBasico.State in [dsEdit, dsInsert] then
      if not (TabCategorConf.FindKey([TabBasicoSIG_CATEG])) then
      begin
          F_Basico.EditSIG_CATEG.SetFocus;
          raise Exception.Create('Sigla da categoria não existe'#10+
                                              'Click no botão "Localiza Categoria" em caso de dúvida');
    end;
end;

end.
Alterando a Janela Criada
Vamos novamente alterar a janela criada, como já foi dito, vou usar um padrão de janela que achei como ideal, mas você poderá, futuramente, também encontrará o seu próprio padrão, então vamos as alterações, antes, lembre-se, é preciso entender e compreender totalmente o capítulo anterior e o DataModule criado deve ter passado pela verificação sem erros, para verificar um objeto a partir do menu principal escolha as opções Project | Syntax Check.
Deve ocorrer um erro na cláusula Uses informando que a unidade fBasico não existe nem o objeto F_Basico não foi encontrado, então antes de qualquer passo chame o objeto Form2 e altere a propriedade Name para F_Basico e salve o formulário com o nome de fBasico, pode novamente verificar a unidade DMBasico que desta vez não haverá problemas.
? Aproveite o objeto F_Basico para alterar a cláusula uses logo abaixo da diretiva de compilação para:
{$R *.DFM}

uses
   DMBasico;  { Referência ao DataModule }
Organizando os Panels
Vamos passar para as alterações com objeto F_Basico. Os objetos da janela se encontram distribuídos em três objetos Panel, o primeiro (Panel1) guarda o objeto DBNavigator, o segundo (Panel2) guarda os labels e os campos do arquivo BASICO e o terceiro (Panel3) guarda o objeto DBGrid1 que controlará o arquivo MUSICA.
•   Altere a propriedade Align do objeto Panel3, para alNone.
•   Aumente a janela do modo que todos os campos do objeto mestre apareçam.
? Coloque os objetos label4 e ImageFOT_CAPA a direita dos outros campos.
? Depois de tudo arrumado altere a propriedade AutoScroll no objeto ScrollBox para True depois para False, isto fará com que a barra de rolagem vertical desapareça.
Crie um quarto objeto Panel   para colocar os botões, conforme as instruções do capítulo anterior, para facilitar o trabalho chame o objeto F_Categ, através do Project Manaager, clique sobre o objeto Panel3 e pressione Ctrl+C chame novamente o objeto Form2 e pressione Ctrl+V, crie um terceiro botão
•   Reorganize os três botões no objeto Panel4
Modificando os campos e Labels
•   Exclua o label (objeto Label1) e o campo (objeto EditCOD_DISCO) que faz referência ao COD_DISCO.
•   Modifique a fonte dos campos e labels conforme descrito no capítulo anterior.
•   Altere as propriedades Caption dos Labels para: "&Nome:", "&Tipo:", "Cate&goria:" e "&Capa:" respectivamente
•   Altere a propriedade AutoSize dos Labels para True
•   Modifique a propriedade Stretch do objeto ImageFOT_CAPA para true, isto fará com que a imagem da capa fique sempre de acordo com o tamanho do objeto.
Organizando os Panels
Vamos organizar cada objeto Panel por partes:
Objeto Panel1
•   Modifique o objeto DBNavigator conforme descrito no capítulo anterior.
•   Para a propriedade Hints, escreva novamente o auxílio para cada botão ou, chame o formulário F_Categ e copie as descrições da propriedade Hints com Ctrl+C e chame novamente o objeto DBNavigator e digite Ctrl+V dentro da propriedade.
•   Modifique também o objeto Panel1 conforme descrito no capítulo anterior e altere a propriedade Caption para CD's.
Objeto Panel2
•   Altere as propriedades Height e Width para 216 do objeto ImageFOT_CAPA.
•   Crie um novo objeto Label
•   Aumente o objeto Panel2 de forma a caber os outros objetos, organize os objetos da seguinte forma: Nome, Tipo, Categoria e Músicas, ao lado coloque a foto. Deixe o espaço de um campo entre Categoria e Músicas.
•   Remova o objeto EditTIP_DISCO e em seu lugar crie o objeto DBComboBox  , encontrado na Component Palette página Data Controls
•   No objeto Label3 recoloque a propriedade FocusControl apontando para o objeto ComboTIP_DISCO.
Objeto Panel3
•   Marque o objeto DBGrid1 e altere as propriedades Align para alNone e BorderStyle para bsSingle, pressione Ctrl+X marque o objeto ScrollBox e pressione Ctrl+V, acerte o objeto de forma que este caiba abaixo do objeto Label1 (Músicas:).
•   Elimine o objeto Panel3, clique sobre ele e pressione Del.

Trojan

Modificando a Janela
•   Altere as propriedades BorderIcons, BorderStyle e Position conforme descrito no capítulo anterior.
•   Mude a propriedade Caption para Cadastro.
•   Altere a propriedade Align do objeto Panel2 para alClient e acerte as posições no formulário.
•   Salve o formulário e salve o projeto.
•   No espaço deixado entre os labels de Categoria e Música, crie o objeto DBText  , encontrado na Component Palette página Data Controls, que servirá para mostrar o nome da categoria selecionada
•   Crie agora três objetos SpeedButton  , encontrado na Component Palette página Additional
? A função de cada botão está explicada na propriedade hint, para os objetos ButLocCateg e ButInsCateg iremos nos aproveitar dos formulários já construídos anteriormente.
? Provavelmente você não irá encontrar o arquivo LANTERNA.BMP solicitado para o segundo botão, teremos de criá-lo:
1.   Salve o formulário e feche o projeto, localize (no diretório demos do Delphi) e abra o projeto [DiretórioDelphi]\DEMOS\DB\MASTAPP\MASTAPP.DPR
2.   Através do Project Manager abra o formulário SearchDlg.
3.   Localize o objeto SearchButton e clique   na propriedade Glyph.
4.   Escolha o botão Save... e salve-o no diretório e nome proposto ([DiretórioDelphi]\IMAGES\BUTTONS\ e LANTERNA.BMP).
5.   Retorne ao nosso projeto descartando quaisquer aviso para salvar o MASTAPP.DPR.
Trabalhando com Grid's
Falemos agora de um objeto especial o Grid, especial por ser um dos objetos de todo o conjunto do Delphi o mais prático e fácil de usar, quem não se lembra no velho Clipper da função dbEdit( ), quem não utilizou seus recursos para mostrar registros ou realizar consultas com filtros especiais. O objeto Grid é o "neto" deste objeto com alguns recursos mais simplificados, no total são três os objetos Grid's:
1.   StringGrid   - Componente da unidade Grid sendo utilizado para, de forma simplificada, associar Strings a uma grade contendo linhas e colunas, encontrado na Component Palette página Additional.
2.   DrawGrid   - Componente da unidade Grid que permite mostrar uma estrutura de dados existentes no formato de linhas e colunas, encontrado na Component Palette página Additional.
3.   DBGrid   - Componente da unidade DBGrids que mostrar dados de um DataSet para um componente no formato de linhas e colunas, encontrado na Component Palette página Data Controls.
Por enquanto vou me deter a falar do objeto DBGrid, mais tarde voltaremos a falar dos outros, este objeto DBGrid é vinculado, ao DataSource, apresenta as seguintes propriedades (mais importantes, algumas ainda não mencionadas):
?   DataSource: Nome do objeto DataSource vinculado;
?   Font: Tipo da letra a ser mostrada no conteúdo do objeto;
?   Options: série de opções de controle (se a opção True for selecionada):
•   dgEditing: permite a edição e adição dos dados;
•   dgAlwaysShowEditor: O grid entra automaticamente em modo de edição, não havendo a necessidade de pressionar Enter ou F2 (depende que a propriedade dgEditing = True);
•   dgTitles: Viabiliza o uso do título de cada campo;
•   dgIndicator: Habilita o ponteiro de indicação da coluna;
•   dgColumnResize: A coluna pode ser redimensionada;
•   dgColLines: Habilita a separação das colunas;
•   dgRowLines: Habilita a separação das linhas;
•   dgTabs: Use o pressionamento das teclas Tab e Shif+Tab para se mover dentro das colunas;
•   dgRowSelect: Seleciona, com uma tarja azul, todas as colunas de uma linha;
•   dgAlwawsShowSelection: As células do grid são mostradas constantemente selecionadas, mesmo que este não detenha o foco.
•   dgConfirmDelete: Use as teclas Ctrl+Del, para excluir dados;
•   dgCancelOnExit: Se qualquer inclusão estiver pendente e for dado saída no grid sem a validação dos dados, a inclusão é cancelada. Previne a inclusão de registros inválidos ou em branco.
?   TitleFont: Tipo da letra a ser mostrada nos títulos do objeto.
? Os campos no objeto DBGrid são adicionados e controlados através do FieldsEditor
O nosso objeto grid mostrará apenas as músicas de cada CD.
? Não lhe aconselho usar este objeto para realizar alterações em bases de dados (apesar de isto ser possível) é mais prático utilizar uma janela separada para realizar este trabalho, as idéias ficarão mais bem ordenadas, se cada formulário controlar uma única entrada em tabela de cada vez.
•   Se você está meio perdido com isto tudo, não se desespere, simplesmente compare os formulários para ver se não falta nada
Finalmente, a programação
Agora falta apenas o código, pelo tamanho do formulário e pelo número de controles já dá para pensarmos que precisamos programar linhas e linhas de código, engano ! o maior trabalho já foi feito, observe:
•   Criando o DataModule ao ser chamado formulário:
1.   Clique no botão   (Toggle Form/Unit) da SpeedBar, até você alternar para o Code Editor.

  public
     procedure inicio;          ? Criando a chamada para um procedimento público.
end;

var
  F_Basico: TF_Basico;

implementation

{$R *.DFM}
 
procedure TF_Basico.Inicio;             ? Crie o início do procedimento
begin
    DM_Basico := TDM_Basico.Create(Application);      ? Cria o DataModule
    Screen.Cursor := crDefault;            ? Faz o cursor ficar no formato de Seta
    ShowModal;                  ? Mostra o formulário F_Basico
end;
•   Código para eliminar o DataModule, basicamente é o mesmo trabalho realizado com o objeto F_Basico:
1.   No objeto F_Basico, dê um duplo click sobre o evento OnClose:
procedure TF_Basico.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    if F_Menu.CriticaEdicao(DM_Basico.DSBasico, 'CD', 'Fechar') then    ? Lembra da Função    
    begin
        Action := caNone;               ? Cancela a saída da janela
        Exit;                  ? Sai da procedure
    end;
    Screen.Cursor := crHourGlass;            ? Faz o cursor virar uma ampulheta
    DM_Basico.Free;               ? Elimina o DataModule
end;
? Lembre-se que a função CriticaEdicao faz parte da Unit fMenu, então é preciso declarar esta unidade com o comando USES (abaixo da diretiva de compilação):
{$R *.DFM}

uses
    DMBasico,  { Referência ao DataModule }
    fMenu;        { Menu Principal do Sistema }   ? Colocado para o uso da Função CriticaEdicao
? Repare que no início desta Unit existe uma declaração Uses, após o comando interface. Então por que não colocar todas essas declarações em um lugar só? 1.O Delphi controlará (colocando ou removendo) estas Units ali colocadas (dependendo dos objetos utilizados) e 2.Todos os comandos declarados antes da declaração implementation (com exceção de eventos de criação. Ex.: onCreate), serão executados e objetos e units ficarão em memória esperando serem chamados, então é impraticável colocar units que só serão utilizadas em tempo de execução.
Consulta
•   Código para pesquisar os registros das tabelas, basicamente utilizaremos o mesmo trabalho realizado com o objeto F_Categ:
1.   Dê um duplo click sob o objeto ButLocalizar:
procedure TF_Basico.ButLocalizarClick(Sender: TObject);
var
  ObjPesquisa: String;
begin
    if F_Menu.CriticaEdicao(DM_Basico.DSBasico, 'CD', 'Localizar') then    ? Lembra da Função    
       Exit;

    ObjPesquisa := TabBasicoNOM_DISCO.Value;

    if InputQuery('Pesquisa','Entre com o nome do CD (ou parte).', ObjPesquisa) then
       TabBasico.FindNearest([ObjPesquisa]);
end;
? Lembre-se que a função InputQuery faz parte da Unit Dialogs, então é preciso declarar esta unidade com o comando USES (abaixo da diretiva de compilação):
{$R *.DFM}

uses
    DMBasico,  { Referência ao DataModule }
    fMenu,        { Menu Principal do Sistema }
    Dialogs;      { Gerente de Mensagens }      ? Colocado para o uso da Função InputQuery
? Desta vez foi utilizado o comando FindNearest, este comando consulta por parte inicial do código encontrado um código igual ou maior que o pesquisado, não é preciso ao usuário lembrar o nome completo como no comando FindKey. Atenção: o comando FindNearest não retornará uma variável boolean (True ou False como resultado da pesquisa) então não se faz a necessidade de críticas sobre o mesmo. Salvo exceção se o campo for tipo numérico ou tipo data então utilize este comando em conjunto com o comando Try. Veja no próximo capítulo como.
•   O código para o botão que localizará um registro na tabela de categoria será tratado no próximo capítulo.
•   Para inserir novos registros na tabela de categoria utilizaremos o formulário construído anteriormente, a única diferença é que desta vez devemos estar em modo de edição:
1.   Dê um duplo click sobre o objeto ButInsCateg:
procedure TF_Basico.ButInsCategClick(Sender: TObject);
begin
    if not (DSBasico.State in [dsEdit, dsInsert]) then      ? Se não estiver em estado de ediçao ou    
    begin                         inclusão
       MessageDlg('Você não está no modo de edição!',   ? Envia mensagem de erro
                           mtInformation, [mbOK], 0);
       exit;
    end

    Screen.Cursor := crHourGlass;         ? Faz o cursor virar uma ampulheta
    if F_Menu.DBDisco.IsSQLbased  then
       F_Menu.DBDisco.Commit;         ? Gravamos as alterações no banco de dados
    with TF_Categ.Create(Self) do         ? Cria o formulário na área de memória
    begin
       Inicio;                ? Chama o formulário
       Free;               ? Elimina o formulário da memória
    end;
    if F_Menu.DBDisco.IsSQLbased then      ? Se a base de dados é padrão SQL
      F_Menu.DBDisco.StartTransaction;      ? Inicia o modo de transações
    Screen.Cursor := crDefault;         ? Faz o cursor ficar no formato de Seta
end;
? Não esqueça de declarar a Unit deste formulário:
{$R *.DFM}

uses
    DMBasico,    { Referência ao DataModule }
    fMenu,          { Menu Principal do Sistema }
    Dialogs,        { Gerente de Mensagens }
    fCateg;          { Cadastro de Categorias }
Trabalhando com a área de Transferência
Na maioria dos aplicativos para Windows é comun encontrarmos os comandos Recortar, Copiar e Colar, o famoso Cut/Copy/Paste, isto é realizado utilizando a área de transferência do Windows:
São três os comandos que fazem o trabalho na área de transferência:
?   Objeto.CutToClipboard, envia o conteúdo do objeto para área de transferência; e
?   Objeto.CopyToClipboard, faz uma cópia do conteúdo do objeto na área de transferência.
?   Objeto.PasteFromClipboard, traz para o conteúdo do objeto da área de transferência;
•   Próximo passo, o código para o botão que permitirá trazer uma imagem armazenada na área de transferência do Windows (Salva com o utilitário PaintBrush, por exemplo) para o campo da Foto:
1.   Dê um duplo click sobre o objeto ButPaste:
procedure TF_Basico.ButPasteClick(Sender: TObject);
begin
    ImageFOT_CAPA.PasteFromClipboard;
end;
Utilizando o objeto OpenDialog
Um aluno uma vez me sugeriu uma outra maneira de colocar a figura, ao invés de se utilizar da área de transferência, poderíamos chamar o arquivo (.BMP) diretamente, isto é realizado com o uso de um objeto OpenDialog  , encontrado na Component Palette página Dialog, coloque-o no formulário e altere as seguintes propriedades:
Propriedade   Valor   Descrição
Filter   Arquivos bitmap|*.BMP   Seleciona os tipos de arquivo que serão abertos
Name   AbreBmp   Nome do Objeto
•   Próximo passo, o código para o botão que permitirá trazer uma imagem em arquivo .BMP para o campo da Foto:
1.   Dê um duplo click sobre o objeto ButPaste:
procedure TF_Basico.ButPasteClick(Sender: TObject);
begin
   If AbreBmp.Execute then               ? Verifica se foi clicado em OK
      ImageFot_Amostra.Picture.LoadFromFile( AbreBmp.FileName );   ? Carrega o arquivo
end;
? Escolha a maneira que mais lhe agrada.
? Outro objeto interessante é o objeto SaveDialog, veja outras utilizações sobre eles no apêndice F
Criando o formulário para o cadastro das músicas
Construiremos o formulário para cadastrar as músicas, crie o formulário com base no formulário criado para a tabela de categoria e faça as seguintes alterações:
?   Altere a propriedade name do formulário para F_MUSICA.
?   Chame o DataModule DMBasico e crie mais um objeto TTable, para fazermos as críticas das músicas duplicadas e altere as seguintes propriedades:
Propriedade   Valor   Descrição
DatabaseName   BaseDisco   Nome do Banco de Dados ou a localização do diretório das tabelas
TableName   MUSICA   Nome externo da tabela
Name   TabMusicaConf   Nome do objeto
IndexFieldNames   Cod_Disco;Num_Faixa   Nome do campo indexado
ReadOnly   True   Somente leitura
? Não esqueça de alterar o programa do DataModule para abrir e fechar a nova tabela e coloque a crítica para a tabela de música, evento OnValidate do objeto TabMusicaNum_Faixa:
procedure TDM_Basico.TabMusicaNum_FaixaValidate(Sender: TField);
begin
    if DSMusica.State in [dsEdit, dsInsert] then         
    begin
        TabMusicaConf.EditKey;
        TabMusicaConf.FieldByName('COD_DISCO').AsFloat := TabMusicaCod_Disco.Value;
        TabMusicaConf.FieldByName('NUM_FAIXA').AsFloat := TabMusicaNum_Faixa.Value;
        if TabMusicaConf.GotoKey then
        begin
            F_Musica.EditNum_Faixa.SetFocus;
            raise Exception.Create('Faixa do CD duplicada');
        end;
    end;
end;
? Repare no uso do comando GotoKey ao invés do comando FindKey, ele foi utilizado por se tratar de uma chave composta.
? Coloque também a crítica para a tabela de música, evento OnNewRecord do objeto TabMusica:
procedure TDM_Basico.TabMusicaNewRecord(DataSet: TDataSet);
begin
    F_Musica.EditNUM_FAIXA.SetFocus;
end;
? Uma última crítica será para confirmarmos as alterações para a base SQL, pressione novamente a tecla F11 e na página Events, dê um duplo click sobre o evento AfterPost:

procedure TDM_Basico.TabMusicaAfterPost(DataSet: TDataSet);
begin
    if F_Menu.DBDisco.IsSQLbased then      ? Se a base de dados é padrão SQL
    begin
        F_Menu.DBDisco.Commit;         ? Gravando as alterações da tabela
        F_Menu.DBDisco.StartTransaction;      ? Reinicia o modo de transações
    end;
end;
?   Deixe apenas o botão Fechar;
?   Remova o Label e o DBEdit do campo COD_DISCO; e
?   Mude a propriedade do BorderStyle para bsDialog.
•   Observe e compare com o desenho do formulário abaixo
•   Altere inicialmente, a cláusula uses para o DMBasico, em seguida a propriedade de todos os campos e do DBNavigator para DM_Basico.DSMusica.
•   A programação do formulário é basicamente a mesma para as tabelas, então ao invés de perder tempo e espaço falando tudo de novo, observe o código completo e note que a única mudança está em prevenir para que o formulário não seja fechado em tempo de edição ou inserção e com o estado do cursor:
unit fMusica;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,
  StdCtrls, Forms, DBCtrls, DB, Buttons, Mask, ExtCtrls;

type
  TF_Musica = class(TForm)
     ScrollBox: TScrollBox;
     Label2: TLabel;
     EditNum_Faixa: TDBEdit;
     Label3: TLabel;
     EditNom_Musica: TDBEdit;
     Label4: TLabel;
     EditNom_Autor: TDBEdit;
     Label5: TLabel;
     EditTmp_Musica: TDBEdit;
     DBNavigator: TDBNavigator;
     Panel1: TPanel;
     Panel2: TPanel;
     Panel3: TPanel;
     ButFechar: TBitBtn;
     procedure FormShow(Sender: TObject);     
     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
     { private declarations }
  public
     { public declarations }
  end;

var
   F_Musica: TF_Musica;

implementation

{$R *.DFM}

uses
  DMBasico;    { Referência ao DataModule }

procedure TF_Musica.FormShow(Sender: TObject);   
begin                     ? Evento OnShow do objeto F_Musica
  Screen.Cursor := crDefault;
end;

procedure TF_Musica.FormClose(Sender: TObject; var Action: TCloseAction);
begin                     ? Evento OnClose do objeto F_Musica
    if F_Menu.CriticaEdicao(DM_Basico.DSMusica, 'Música', 'fechar' ) then
    begin
       Action := caNone;
       exit;
    end;
    Screen.Cursor := crHourGlass;
end;

end.
? Não é preciso se preocupar com a gravação para o campo COD_DISCO, isto será feito automaticamente pelo Delphi, mantendo a integridade referencial.
•   Salve o formulário com o nome fMusica.
? Vamos agora alterar o botão do formulário principal, objeto butMusica, que será usado para chamar este segundo.
procedure TF_Basico.ButMusicaClick(Sender: TObject);
begin
    if DM_Basico.DSBasico.State in [dsEdit, dsInsert] then
    begin
        MessageDlg('Salve a edição do CD antes de Editar as músicas!',mtInformation, [mbOk], 0);
        Exit;
    end;
    Screen.Cursor := crHourGlass;      
    if F_Menu.DBDisco.IsSQLbased then   
       F_Menu.DBDisco.Commit;
    with TF_Musica.Create(Self) do   ? Criamos o formulário em memória
    begin
        ShowModal            ? Chamaremos aqui o novo formulário
        Free;            ? Eliminamos o Formulário
    end;
    if F_Menu.DBDisco.IsSQLbased then   
      F_Menu.DBDisco.StartTransaction;   
    Screen.Cursor := crDefault;      
end;
? Não esqueça de adicionar a propriedade uses
{$R *.DFM}

uses
  DMBasico,   { Referência ao DataModule }
  fMenu,      { Menu Principal do Sistema }
  Dialogs,   { Gerente de Mensagens }
  fCateg,      { Cadastro de Categorias }
  fMusica;   { Cadastro de Músicas }
? Não esqueça também de retirar os objetos F_Musica e F_Basico da criação automática, opção do menu principal clique em Options | Project..., qualquer dúvida consulte o capítulo anterior.
Criando novos Procedimentos Globais
Vamos criar mais alguns procedimentos globais, para a nosso primeiro procedimento note as chamadas aos formulários externos F_Categ e F_Musica:
Screen.Cursor := crHourGlass;
if F_Menu.DBDisco.IsSQLbased then
   F_Menu.DBDisco.Commit;
...
...
if F_Menu.DBDisco.IsSQLbased then
  F_Menu.DBDisco.StartTransaction;
Screen.Cursor := crDefault;
Os comandos listados se repetem tanto para o procedimento ButInsCategClick e para o procedimento ButMusicaClick, chame o formulário F_Menu e crie o seguinte procedimento:
  public
     procedure Prepara(Tipo: boolean);                              ?  Aqui
     function CriticaEdicao(DSOrigem: TDataSource; DoQue, AntesDe: String) : boolean;
  end;

var
...
...
procedure TF_Menu.Prepara(Tipo: boolean);
begin
    if tipo then             ?  Se o valor da variável tipo recebida for verdadeiro
    begin
        Screen.Cursor := crHourGlass;   ?  Faz a primeira parte
        if DBDisco.IsSQLbased then
           DBDisco.Commit;
   end
   else                 ?  Senão
   begin
      if DBDisco.IsSQLbased then      ?  Faz a segunda parte
        DBDisco.StartTransaction;
      Screen.Cursor := crDefault;
   end;
end;
Modifique agora ambos os procedimentos do objeto F_Basico:
procedure TF_Basico.ButInsCategClick(Sender: TObject);
begin
    ...
    ...
    F_Menu.Prepara(True);            ?  Aqui
    with TF_Categ.Create(Self) do
    begin
       Inicio;
       Free;
    end;
    F_Menu.Prepara(False);         ?  Aqui
end;

procedure TF_Basico.ButMusicaClick(Sender: TObject);
begin
    ...
    ...
    F_Menu.Prepara(True);            ?  Aqui
    with TF_Musica.Create(Self) do
    begin
        Inicio;
        Free;
    end;
    TabMusica.Refresh;
    F_Menu.Prepara(False);         ?  Aqui
end;
Um segundo procedimento global pode ser criado verificando os eventos AfterPost dos DataModules Dm_Categ e DM_Basico (este segundo em dois lugares); observamos o mesmo procedimento:
if F_Menu.DBDisco.IsSQLbased then
begin
    F_Menu.DBDisco.Commit;
    F_Menu.DBDisco.StartTransaction;
end;
Criamos então o seguinte procedimento no formulário F_Menu:
  public
     procedure GravaBanco                     ?  Aqui
     procedure Prepara(Tipo: boolean);                        
     function CriticaEdicao(DSOrigem: TDataSource; DoQue, AntesDe: String) : boolean;
  end;

var
...
...
procedure TF_Menu.GravaBanco;
begin
   if DBDisco.IsSQLbased then   ?  Embutiremos os comandos puros aqui
   begin
       DBDisco.Commit;
       DBDisco.StartTransaction;
   end;
end;
Agora substitua os eventos nos dos DataModules Dm_Categ e DM_Basico; pela seguinte chamada ao procedimento
begin
    F_Menu.GravaBanco;
end;
? Repare também que foi retirado das funções que ficaram no formulário F_Menu as referências da base de dados ao formulário (eram F_Menu.DBDisco e ficou simplesmente DBDisco).
Alterando o Menu para receber o formulário
Agora finalmente vamos rodar nosso formulário, para tanto precisamos chamá-lo através do menu principal para isto:
1.   Chame novamente o formulário F_Menu: no menu principal escolha View e Project Manager, marque o objeto e clique sobre o botão View form.
2.   Clique em Arquivo, Cadastro, coloque o seguinte código:
procedure TF_Menu.Cadastro1Click(Sender: TObject);
begin
    Screen.Cursor := crHourGlass;         ? Transforma o cursor em uma ampulheta
    F_Basico := TF_ Basico.Create(Application);   ? Cria o formulário em memória
    F_ Basico.Inicio;            ? Chama o formulário através da área aberta
    F_ Basico.Free;            ? Libera a área aberta
    Screen.Cursor := crDefault;         ? Transforma o cursor em uma seta
end;
3.   O objeto F_Basico faz parte da Unit fBasico então é necessário fazer o uso desta Unit, para tanto insira o seguinte código (abaixo da diretiva de compilação):

{$R *.DFM}

uses
   fSobre,    { Janela do Sobre o Sistema ... }
   fCateg,    { Utilizada para o cadastro de Categorias }
   fBasico;  { Utilizada para o cadastro de CD's }
? Não esqueça de retirar o formulário F_Basico da lista de formulários criados automaticamente.
4.   Saia do Code Editor e salve o formulário e o projeto.
5.   Podemos agora salvar e testar o formulário completo, para incluir algumas imagens utilize o PaintBrush do Windows, ou outro utilitário qualquer.
6.   Se alguma coisa deu errada, releia o capítulo, ou então confira todo o código:
unit fBasico;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,
  StdCtrls, Forms, DBCtrls, DB, DBGrids, Buttons, Grids, Mask, ExtCtrls;

type
  TF_Basico = class(TForm)
     ScrollBox: TScrollBox;
     Label2: TLabel;
     EditNom_Disco: TDBEdit;
     Label3: TLabel;
     Label4: TLabel;
     ImageFot_Capa: TDBImage;
     Label5: TLabel;
     EditSig_Categ: TDBEdit;
     DBNavigator: TDBNavigator;
     Panel1: TPanel;
     Panel2: TPanel;
     Panel4: TPanel;
     ButFechar: TBitBtn;
     ButLocalizar: TBitBtn;
     ButMusica: TBitBtn;
     Label1: TLabel;
     ComboTIP_DISCO: TDBComboBox;
     DBGrid1: TDBGrid;
     DBText1: TDBText;
     ButLocCateg: TSpeedButton;
     ButInsCateg: TSpeedButton;
     ButPaste: TSpeedButton;
     { AbreBmp: TOpenDialog;    ? Se você utilizou o objeto OpenDialog }
     procedure FormClose(Sender: TObject; var Action: TCloseAction);
     procedure ButLocalizarClick(Sender: TObject);
     procedure ButInsCategClick(Sender: TObject);
     procedure ButPasteClick(Sender: TObject);
     procedure ButMusicaClick(Sender: TObject);
  private
    { private declarations }
  public
    procedure inicio;
  end;

var
  F_Basico: TF_Basico;

implementation

{$R *.DFM}

uses
   DMBasico,   { Referência ao DataModule }
   fMenu,       { Menu Principal do Sistema }
   Dialogs,     { Gerente de Mensagens }
   fCateg,      { Cadastro de Categorias }
   fMusica;     { Cadastro de Músicas }

procedure TF_Basico.Inicio;
begin
    DM_Basico := TDM_Basico.Create(Application);
    Screen.Cursor := crDefault;
    ShowModal;
end;

procedure TF_Basico.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    if F_Menu.CriticaEdicao(DM_Basico.DSBasico, 'CD', 'Fechar') then
    begin
        Action := caNone;
        Exit;
    end;
    Screen.Cursor := crHourGlass;
    DM_Basico.Free;
end;

procedure TF_Basico.ButLocalizarClick(Sender: TObject);
var
  ObjPesquisa: String;
begin
  if F_Menu.CriticaEdicao(DM_Basico.DSBasico, 'CD', 'Localizar') then
     Exit;

  ObjPesquisa := DM_Basico.TabBasicoNom_Disco.Value;

  if InputQuery('Pesquisa','Entre com o nome do CD (ou parte).', ObjPesquisa) then
    DM_Basico.TabBasico.FindNearest([ObjPesquisa]);
end;

procedure TF_Basico.ButInsCategClick(Sender: TObject);
begin
    if not (DM_Basico.DSBasico.State in [dsEdit, dsInsert]) then
    begin
        MessageDlg('Você não está no modo de edição!',mtInformation,[mbOK],0);
        exit;
    end;

    F_Menu.Prepara(True);
    with TF_Categ.Create(Self) do
    begin
        Inicio;
        Free;
    end;
    F_Menu.Prepara(False);
end;

procedure TF_Basico.ButPasteClick(Sender: TObject);
begin
    ImageFOT_CAPA.PasteFromClipboard;
end;

{ Ou se você utilizou o objeto OpenDialog

procedure TF_Basico.ButPasteClick(Sender: TObject);
begin
   If AbreBmp.Execute then
      ImageFot_Amostra.Picture.LoadFromFile( AbreBmp.FileName );
end;

}

procedure TF_Basico.ButMusicaClick(Sender: TObject);
begin
    if DM_Basico.DSBasico.State in [dsEdit, dsInsert] then
    begin
       MessageDlg('Salve a edição do CD antes de Editar as músicas!',mtInformation, [mbOk], 0);
       Exit;
    end;

    F_Menu.Prepara(True);
    with TF_Musica.Create(Self) do
    begin
       Inicio;
       Free;
    end;
    F_Menu.Prepara(False);
end;

end.

Comandos e suas funções, por ordem de aparição:
with [registro ou objeto] do [comandos] - Cria um método de referência para o registro ou objeto.
[tabela].FindNearest - realiza uma pesquisa aproximada na tabela.
[objeto].PasteFromClipboard - Copia a imagem da área de transferência para o objeto selecionado.

Trojan

Pausa para descanso.

OBS: Eu peço desculpas aos moderadores e a todos que estão vendo este tópico, se tiver alguma coisa errada, ou muito absurda.

Fonte: Procurado no Google.

Trojan


sTunTzZ

bem legal... eu estou querendo começar a usa o delphi, li umas apostilas..

o seu post só li até a parte que intendi, quando fico alem da minha compreensão parei XD

meu amigo que ja usa delphi me disse que seria muito dificil aprender delphi sem fazer um curso, o que vocês acham?

Trojan

Eu concordo, mas, se vc está mesmo disposto a fazer isto, vc consegue aprender!  ;)

Boa sorte!

Be.Cool

@sTunTzZ
a mairoria dos programadores(fucadores) nunca fizeram nenhum curso!
Olhe só eu, nunca fiz nenhum curso e manjo de varias linguagens!
ta certo que eu naum sou bom em todas, a mais o que eu quero dizer, é que naum importa de vc vai fazer um curso, ou aprender fucando...o que importa e a sua forca de vontade e a sua determinacao! ;)
vlw



fui.

A sabedoria está em suas mãos

sTunTzZ

Eu tambem penso assim, eu e meu amigo quase brigamos porcausa disso aheueahuea

mas ta dificil, baixei varias apostilas, todas explicam o basico, mas por exemplo ,quando falam pra você fazer o programinha do "Sinal de transito" ou "Calculadora pra soma" não explicam os comandos a usar nem nada...

vou dar mais uma lidinha no post pra ver se aprendo algo novo hehehe

nibbles

sTunTzZ
eu acredito que fuçando, se aprenda mais do que com cursos..
eu acho muito impossível algum professor te fazer aprender qualquer linguagem
claro que eles servem para tirar duvidas, isso com certeza é extremamente útil, mas isso você consegue na internet, por exemplo aqui mesmo no fórum..
mas as dúvidas surgem do seu próprio estudo.. vários cursos de informática que fiz, não aprendi nada lá, somente estudando sozinho, de uma maneira muito mais fácil...
sem contar que é muito difícil achar uma escola boa com professores realmente bons...



"A diversão do inteligente é se fingir de burro para aquele que se finge de inteligente."
"ENGENHARIA SOCIAL. Porque não existe patch para a ignorância humana."