Prévia do material em texto
Tutorial: Utilizando o Formulário DataModule Faculdade de Filosofia Santa Dorotéia Tecnologia em Informática – Programação IV Autor: Márcio Gil Maldonado Atualização: 12/04/2004 2 Índice I. Objetivo ....................................................................................................................................................... 4 II. Pré-requisitos ............................................................................................................................................. 4 III. Notação ..................................................................................................................................................... 4 IV. Dicionário de dados..................................................................................................................................4 V. Criando o Programa................................................................................................................................... 5 VI. Componentes do DataModule .................................................................................................................. 5 A. O Componente TDatabase..................................................................................................................... 6 B. O Componente TUpdateSQL................................................................................................................. 6 C. O Componente TQuery.......................................................................................................................... 7 D. O Componente TDataSource ................................................................................................................. 7 VII. Inserindo Campos....................................................................................................................................7 A. A Classe TField ..................................................................................................................................... 8 VIII. Codificando os Eventos da Tabela......................................................................................................... 8 A. O Evento TabUf→BeforeInsert ............................................................................................................. 8 B. O Evento TabUf→BeforeEdit................................................................................................................ 8 C. O Evento TabUf→BeforeDelete............................................................................................................ 9 D. O Evento TabUf→BeforePost ............................................................................................................... 9 E. O Evento TabUf→AfterPost ................................................................................................................ 10 IX. A Janela de Detalhes .............................................................................................................................. 10 A. O Componente DBEdit........................................................................................................................ 11 X. Codificando os Eventos da Janela de Detalhes........................................................................................ 11 A. O Evento DetUf→OnShow ................................................................................................................. 11 B. O Evento BitBtn1→OnClick ............................................................................................................... 11 C. O Evento BitBtn2→OnClick ............................................................................................................... 12 D. O Evento DetUf→OnClose ................................................................................................................. 12 XI. A Janela de Cadastro .............................................................................................................................. 12 A. O Componente TDBGrid..................................................................................................................... 13 XII. Codificando os Eventos da Janela de Cadastro..................................................................................... 13 A. O Evento CadUf→OnShow................................................................................................................. 13 B. O Evento Button1→OnClick ............................................................................................................... 13 C. O Evento Button2→OnClick ............................................................................................................... 13 D. O Evento Button3→OnClick............................................................................................................... 14 E. O Evento Button4→OnClick ............................................................................................................... 14 F. O Evento CadUf→OnKeyDown.......................................................................................................... 14 XIII. O Menu Principal................................................................................................................................. 14 XIV. Codificando os Eventos do Menu Principal ........................................................................................ 15 A. O Evento MainCad→OnShow ............................................................................................................ 15 B. O Evento MainCad→OnClose ............................................................................................................ 15 C. O Evento Button4→OnClick ............................................................................................................... 15 D. O Evento Button1→OnClick............................................................................................................... 16 XV. Compilando o Programa ....................................................................................................................... 16 XVI. Inserindo os Outros Formulários ......................................................................................................... 16 A. No formulário DMCad......................................................................................................................... 16 B. Nos formulários DetCidade e DetBairro............................................................................................. 16 C. Nos formulários CadCidade e CadBairro........................................................................................... 17 D. No formulário MainCad...................................................................................................................... 17 XVII. Incluindo Referências Entre as Tabelas ............................................................................................. 17 A. Referência por Código para Edição ..................................................................................................... 17 B. Referência Via SQL para Consultas .................................................................................................... 17 3 XVIII. O Componente TDBLookupComboBox .......................................................................................... 18 XIX. Finalizando .......................................................................................................................................... 18 4 Tutorial: Utilizando o Formulário DataModule I. Objetivo Exemplificar a utilização de um formulário DataModule no Borland C++ Builder (versão 5.0) com um banco de dados SQL relacional, de modo que o gerenciamento da base de dados fique centralizado ao máximo no programa. II. Pré-requisitos O servidor de banco de dadosdeve estar instalado ou acessível da sua máquina. O driver ODBC, bem como o DSN da sua base de dados, devem estar devidamente instalados e configurados, ou seja, este não é um guia de instalação e configuração de banco de dados. Você pode utilizar qualquer gerenciador de banco de dados compatível com a linguagem SQL e acessível via ODBC, tal como MySQL , PostgreSQL, InterBase, etc. III. Notação Neste tutorial utilizaremos o nome “dbCad” para a base de dados, que poderá ser trocado por qualquer outro nome. Por convenção, todos os nomes escritos em itálico podem ser trocados por qualquer outro nome. Utilizaremos como exemplo um cadastro de cidades e bairros, principalmente por ser este um exemplo simples e de poucos campos. Veja a notação utilizada: a) Os nomes dos formulários recebem um prefixo de acordo com sua finalidade: Cad para as janelas de cadastro, Det para as janelas de detalhe, entre outros, exemplo: CadUf e DetUf; b) O nome do arquivo fonte (.cpp) e do formulário (propriedade Name) devem ser sempre diferentes, por isso invertemos o nome do formulário para o nome do arquivo, exemplo: formulário DMCad, arquivo CadDM.cpp; formulário CadUf, arquivo UfCad.cpp, etc.; motivo: todos os arquivos ficam agrupados por módulo, exemplo: todos os arquivos de unidade federativa ficarão juntos (Uf*.* ); c) Os nomes dos componentes recebem um prefixo distinto para cada tipo de componente: Tab para componentes TQuery; Upd para componentes TUpdateSQL, etc; d) Os componentes do tipo TField recebem o mesmo nome do campo, mas com a inicial maiúscula, exemplo: uf_cod vira Uf_cod; IV. Dicionário de dados Abaixo estão descritas as tabelas utilizadas como exemplo neste tutorial: CREATE TABLE uf ( uf_cod INT PRIMARY KEY, -- Código da unidade federativa uf_nome VARCHAR( 20), -- Nome da unidade federativa uf_sigla VARCHAR( 2) -- Sigla da unidade federativa ); CREATE TABLE cidade ( cid_cod INT PRIMARY KEY, -- Código da cidade cid_nome VARCHAR( 20), -- Nome da cidade cid_ufcod INT REFERENCES uf( uf_cod) -- Código da unidade federativa ); CREATE TABLE bairro ( bai_cod INT PRIMARY KEY, -- Código do bair ro bai_nome VARCHAR( 20), -- Nome do bairro bai_cidcod INT REFERENCES cidade( cid_cod) -- Código da cidade ); OBS: Utilizamos aqui a opção REFERENCES do PostgreSQL para indicar as chaves estrangeiras. Se você utilizar outro gerenciador, pode remove-la sem problemas. 5 V. Criando o Programa 1. Se você não abriu o C++ Builder agora, escolha File – New Application; 2. Abra File – New... e insira um formulário Data Module e dois formulários comuns (Form), atribuindo suas propriedades conforme descrito na tabela abaixo; 3. Escolha File – Save All, nomeando os arquivos conforme indicado abaixo: Item Arquivo Propriedade Valor Comentário Application CadProj.cpp Arquivo de projeto Name MainCad Janela principal Form CadMain.cpp Caption Menu Principal Título da janela Data Module CadDM.cpp Name DMCad Módulo de dados Form UfDet.cpp Name DetUf Detalhes da unidade federativa Name CadUf Cadastro de unidade federativa Caption Cadastro de Unidade Federativa Título da janela Form UfCad.cpp KeyPreview true Para utilizar teclas especiais OBS: a) Não é preciso definir o título da janela de detalhes (propriedade Caption), pois o mesmo será atribuído nos eventos BeforeInsert e BeforeEdit. Veja o capítulo VIII. A. (página 8); b) Para o formulário de cadastro, sempre modificamos a propriedade KeyPreview para true. É isso que faz o evento OnFormKeyDown funcionar. Veja o capítulo XII. F. (página 14). VI. Componentes do DataModule 4. Abra View – Forms..., escolha DMCad e confirme; 5. Insira os componentes listados abaixo, atribuindo suas respectivas propriedades: Guia Componente Propriedade Valor Comentário Name DataCad Componente de acesso à base de dados AliasName dbCad Alias ODBC Database DatabaseName DataCad Alias interno Name UpdUf Componente de atualização de tabela ModifySQL UPDATE uf SET uf_nome = : uf_nome, uf_sigla = : uf_sigla WHERE uf_cod = :OLD_ uf_cod Código SQL para alterar registro. Ver parte B. (página 6) InsertSQL INSERT INTO uf ( uf_cod, uf_nome, uf_sigla ) VALUES ( : uf_cod, : uf_nome, : uf_sigla ) Código SQL para inserir registro. Ver parte B. (página 6) UpdateSQL DeleteSQL DELETE FROM uf WHERE uf_cod = :OLD _uf_cod Código SQL para excluir registro. Idem Name TabUf Componente de consulta à base de dados Data Access Query DatabaseName DataCad Nome da base de dados (alias interno) 6 RequestLive true Permite editar os dados da tabela SQL SELECT * FROM uf ORDER BY uf_nome Consulta SQL UpdateObject UpdUf Componente de atualização de tabela Name DSUf Componente de acesso à tabela DataSource DataSet TabUf Componente de consulta à base de dados A. O Componente TDatabase Controla o acesso ao servidor de banco de dados. A princípio este componente poderia ser eliminado do projeto, já que a propriedade DatabaseName do componente TQuery pode ser atribuído diretamente ao alias OBDC (dbCad), porém este componente permite uma série de configurações e maior controle de acesso à base de dados. Um exemplo é a propriedade Params, que permite configurar os parâmetros de acesso ao servidor SQL. Você pode clicar no botão da propriedade Params e inserir as seguintes linhas, com os valores corretos para usuário e senha preenchidos: user_name= password= Agora mude a propriedade LoginPrompt para false e o programa não irá mais pedir usuário e senha ao ser aberto. Porém, não é muito seguro deixar sua senha em aberto e, portanto, se você tem uma senha, procure preencher somente a propriedade user_name , mantendo LoginPrompt como true. B. O Componente TUpdateSQL Permite entrar com comandos SQL para a manutenção da base de dados. Torna o componente TQuery, que a princípio é somente para leitura, em uma tabela onde se pode fazer inclusão, exclusão e alteração de registros. Basicamente, o TQuery guarda os valores digitados pelo usuário e uma cópia do valor original em componentes TField; quando o método Post é chamado, o TUpdateSQL substitui os nomes pré- fixados com “:” (dois pontos) pelo valor atualizado dos campos indicados e os precedidos por “:OLD_” pelo valor original, executando o comando resultante no servidor. Este componente também contém um utilitário para gerar todo o código SQL para você, como você pode ver no exemplo da figura abaixo: Para que este utilitário funcione, é preciso que o componente TQuery esteja configurado e conectado, pela propriedade UpdateObject, ao UpdateSQL. Após criar a consulta, de um clique duplo no UpdateSQL 7 e irá aparecer uma janela com o campo Table Name preenchido com o nome da tabela e duas colunas, Key Fields e Update Fields, contendo a lista dos campos. Na primeira coluna, selecione o campo ou campos chave; na segunda deixe todos os campos selecionados ou desmarque aqueles que não serão atualizados pelo programa, como os campos de auto-incremento. Clique no botão Generate SQL e os campos ModifySQL , InsertSQL e DeleteSQL serão preenchidos; confira o código gerado nos itens Modify , Insert e Delete da aba SQL e confirme. C. O Componente TQuery Possibilita a realização de consultas no banco de dados e a sua navegação em estilo de tabela. Tal navegação pode ser realizada por métodos tais como: First() (primeiro registro), Last() (último registro), Next() (próximo registro) e Prior() (registro anterior), ou pelo componente DBNavigator da guia Data Controls. A princípio, qualquer consulta reconhecível pelo servidor pode ser escrita na propriedade SQL, mas, se a propriedade RequestLive for mudada para true, uma série de restrições é imposta a sua consulta. A primeira restrição é que você só poderá codificar consultas em SQL padrão (SQL/92); qualquer recurso específico do seu servidor irá provocar um erro de execução.A segunda restrição é para abrir a consulta para leitura e gravação; você não poderá utilizar nem junção de tabelas (INNER JOIN), nem agrupamentos (GROUP BY) ou funções de agregação (count(), sum(), etc.). Caso contrário, a tabela será aberta somente para leitura (read only). Expressões de filtragem (WHERE) e ordenação (ORDER BY) são permitidas. Tal como o TUpdateSQL, este componente também tem um utilitário para ajuda-lo a construir suas consultas. Clique com o botão direito sobre o TQuery e escolha SQL Builder... Você pode selecionar os campos a serem visualizados, definir critérios, agrupamento, ordem, junção de tabelas, tudo isso usando apenas o mouse. Muito útil se você não está muito familiarizado com a linguagem SQL, ou simplesmente para testar suas consultas (pelo menu Query – Run Query). Como você verá a seguir, este componente contém os principais eventos que permitem controlar as alterações feitas na tabela. D. O Componente TDataSource Este componente é necessário para ligar a interface de usuário com a consulta SQL (TQuery). Você pode verificar que praticamente todos os componentes da guia Data Controls têm uma propriedade DataSource a fim de serem conectados à tabela. VII. Inserindo Campos 6. De um clique duplo sobre o componente TabUf ou clique com o botão direito e escolha Fields Editor...; deve aparecer uma pequena janela de título DMCad→TabUf. Clique com o botão direito do mouse sobre a janela e escolha Add all fields. Deverá abrir uma janela Database login, digite o seu login e a sua senha, se tiver, ou simplesmente clique no botão OK . O resultado deverá ser este: OBS: Em alguns servidores de banco de dados, o nome de tabelas e campos é sensível ao caso, provocando erros do tipo: “Table does not exist”. Pode ser que o nome da sua tabela tenha sido convertido para minúsculo, de “Uf” para “uf”, por exemplo, e você precise corrigir sua consulta SQL. 7. Modifique as propriedades dos campos conforme indicado abaixo: Campo Propriedade Valor Comentário uf_cod Name Uf_cod Nome de acesso 8 DisplayLabel Código Título na tabela Name Uf_nome Nome de acesso uf_nome DisplayLabel Nome Título na tabela Name Uf_sigla Nome de acesso uf_sigla DisplayLabel Sigla Título na tabela 8. Feche o editor de campos, clique sobre o componente DataCad e altere sua propriedade Connected para false. Com isso você evita problemas mais tarde, ao abrir novamente seu projeto, se o banco de dados não estiver acessível. A. A Classe TField Cada um destes campos que você inseriu acima é um objeto de uma classe descendente da classe TField. Alguns exemplos são as classes TIntegerField para campos numéricos e TStringField pata campos caracter. A principal vantagem de se criar estes objetos é o uso de nomes alternativos para os campos (Uf_cod é melhor de escrever que TabUf->FieldByName(“uf_cod”) ), além da possibilidade de se entrar com parâmetros para a visualização e edição dos campos. Um exemplo é a propriedade DisplayLabel, onde se define o título do campo na grade de consulta. Outros exemplos são as propriedades EditFormat , para campos numéricos, e EditMask , para campos caracter. Por exemplo: podemos atribuir o EditMask do campo Uf_sigla para “>LL;0; ” e assim a sigla só aceitará duas letras (L ) convertidas em maiúsculo (>). Os dois parâmetros restantes (;0; ) indicam a não utilização de caracteres fixos (0) e a visualização dos caracteres não preenchidos como espaços. VIII. Codificando os Eventos da Tabela 9. Escolha File – Include Unit Hdr... , clique em UfDet e confirme; 10. Clique no componente TabUf, abra a guia Events do Object Inspector e insira os seguintes eventos: A. O Evento TabUf→BeforeInsert Sempre antes de inserir um registro na base de dados (método Insert()), o componente TQuery chama este evento. Esta implementação abre uma janela (DetUf) para que o usuário entre com os dados. //------------------------------------------------- -------------------------- void __fastcall TDMCad:: TabUfBeforeInsert(TDataSet *DataSet) { DetUf->Caption = "Inserindo Unidade Federativa" ; DetUf->Show(); } B. O Evento TabUf→BeforeEdit Este evento é chamado sempre antes da tabela passar para o modo de edição (método Edit() ). Esta implementação abre então uma janela (DetUf) para que o usuário possa alterar os dados. //------------------------------------------------- -------------------------- void __fastcall TDMCad:: TabUfBeforeEdit(TDataSet *DataSet) { DetUf->Caption = "Alterando Unidade Federativa" ; DetUf->Show(); } 9 C. O Evento TabUf→BeforeDelete Sempre que houver uma tentativa de exclusão de registro (método Delete()), o componente TQuery chama este evento que, por sua vez, pedirá a confirmação do usuário. Caso o usuário não confirme a exclusão, a operação é cancelada pela função Abort() . //------------------------------------------------- -------------------------- void __fastcall TDMCad:: TabUfBeforeDelete(TDataSet *DataSet) { if (Application->MessageBox( "Deseja realmente excluir o registro?" , "Atenção!" , MB_YESNO|MB_ICONQUESTION ) == IDNO) { ShowMessage( "Exclusão cancelada" ); Abort(); } } D. O Evento TabUf→BeforePost Antes de o registro ser efetivamente gravado na tabela (método Post()), este evento é chamado, de modo que podemos fazer todas as checagens básicas necessárias e impedimos, na maior parte dos casos, que o usuário receba mensagens de erro vindas do gerenciador de banco de dados, geralmente muito pouco amigáveis. Também implementamos o auto-incremento de código que, embora pudesse estar no evento BeforeInsert (antes de inserir), aqui permite que dois usuários, em terminais diferentes, possam cadastrar dados, ao mesmo tempo, na mesma tabela. //------------------------------------------------- -------------------------- void __fastcall TDMCad:: TabUfBeforePost(TDataSet *DataSet) { int ncod; TQuery *sql; // Checagem básica de erro if ( Uf_nome->AsString.IsEmpty()) { ShowMessage( "Favor informar o nome da UF" ); Abort(); } else if ( Uf_sigla->AsString.IsEmpty()) { ShowMessage( "Favor informar a sigla da UF" ); Abort(); } // Auto-incremento do código if ( TabUf->State == dsInsert) { sql = new TQuery( DMCad); sql->DatabaseName = " DataCad" ; sql->SQL->SetText( "SELECT MAX( uf_cod) as uf_cod FROM uf" ); sql->Open(); sql->Last(); ncod = sql->FieldByName( " uf_cod" )->AsInteger + 1; Uf_cod->AsInteger = ncod; sql->Close(); delete sql; } } OBS: A vantagem do auto-incremento por código e que este reutiliza a numeração de registros recentemente excluídos. Mas, se o seu banco de dados suportar a opção AUTOINCREMENT (MySQL ), SERIAL (PostgreSQL) 10 ou algo equivalente, e você quiser utiliza-la, então elimine o bloco “if ( TabUf->State == dsInsert) ”. Veja o código alternativo: //------------------------------------------------- -------------------------- void __fastcall TDMCad:: TabUfBeforePost(TDataSet *DataSet) { // Checagem básica de erro if ( Uf_nome->AsString.IsEmpty()) { ShowMessage( "Favor informar o nome da UF" ); Abort(); } else if ( Uf_sigla->AsString.IsEmpty()) { ShowMessage( "Favor informar a sigla da UF" ); Abort(); } } OBS: Caso use este código alternativo, altere a propriedade InsertSQL do componente TabUf para: INSERT INTO uf ( uf_nome, uf_sigla ) VALUES ( : uf_nome, : uf_sigla ) E. O Evento TabUf→AfterPost Um dos detalhes mais problemáticos ao se trabalhar no C++ Builder com SQL é a atualização. Uma solução simples é que, após qualquer alteração na tabela, guardamos o código original, fechamos e abrimos a tabela e, finalmente, localizamos o registro anterior. //------------------------------------------------- -------------------------- void __fastcall TDMCad:: TabUfAfterPost(TDataSet *DataSet) { int cod; cod = Uf_cod->AsInteger; TabUf->Close();TabUf->Open(); TabUf->Locate( " uf_cod" , cod, TLocateOptions() ); } IX. A Janela de Detalhes 11. Abra View – Forms..., escolha DetUf e confirme; 12. Escolha File – Include Unit Hdr... , clique em CadDM e confirme; 13. Insira os componentes listados abaixo: Guia Componente Propriedade Valor Comentário Alignment taRightJustify Font→Style→fsBold true Label Caption Código: Inserir no canto superior esquerdo Alignment taRightJustify Font→Style→fsBold true Label Caption Nome: Inserir abaixo do label anterior Alignment taRightJustify Font→Style→fsBold true Standard Label Caption Sigla: Inserir abaixo do label anterior DataSource DMCad→DSUf Origem dos dados DataField uf_cod Nome do campo Data controls DBEdit Enabled false Somente leitura 11 DataSource DMCad→DSUf Origem dos dados DBEdit DataField uf_nome Nome do campo DataSource DMCad→DSUf Origem dos dados DBEdit DataField uf_sigla Nome do campo BitBtn Kind bkOK Inserir no canto inferior esquerdo Kind bkCancel Additional BitBtn Caption Cancelar Inserir à direita do botão anterior O resultado deverá ser mais ou menos este: A. O Componente DBEdit Permite editar os campos do registro. A caixa de edição para o campo Uf_cod foi desabilitada porque o código é auto-incrementado e não pode ser alterado. X. Codificando os Eventos da Janela de Detalhes A. O Evento DetUf→OnShow Ao abrir o formulário, posicionamos o foco do teclado no primeiro campo a ser digitado (DBEdit2). //------------------------------------------------- -------------------------- void __fastcall TDetUf::FormShow(TObject *Sender) { ActiveControl = DBEdit2; } B. O Evento BitBtn1 →OnClick Neste evento chamamos o método Post() se o registro estiver no estado de edição ou inserção (dsEdit ou dsInsert). Se passar para o modo de consulta (dsBrowse), fechamos o formulário. //------------------------------------------------- -------------------------- void __fastcall TDetUf::BitBtn1Click(TObject *Sender) { if ( DMCad-> TabUf->State == dsEdit || DMCad-> TabUf->State == dsInsert) { DMCad-> TabUf->Post(); if ( DMCad-> TabUf->State == dsBrowse) Close(); } } 12 C. O Evento BitBtn2 →OnClick Ao cancelar, verificamos se o registro está no estado de edição ou inserção (dsEdit ou dsInsert). Não é necessário checar se a operação foi bem sucedida. //------------------------------------------------- -------------------------- void __fastcall TDetUf::BitBtn2Click(TObject *Sender) { if ( DMCad-> TabUf->State == dsEdit || DMCad-> TabUf->State == dsInsert) { DMCad-> TabUf->Cancel(); Close(); } } D. O Evento DetUf→OnClose Neste evento, verificamos se o formulário foi fechado pelos botões OK e Cancelar. Para isso, checamos se o registro está no estado de edição ou inserção (dsEdit ou dsInsert), neste caso o usuário clicou no x do formulário ou teclou Alt+F4 , e assim pedimos a confirmação dele. //------------------------------------------------- -------------------------- void __fastcall TDetUf::FormClose(TObject *Sender, TCloseAction &Action) { int res; if ( DMCad-> TabUf->State == dsEdit || DMCad-> TabUf->State == dsInsert) { res = Application->MessageBox( "Gravar Registro?" , "Atenção!" , MB_YESNOCANCEL|MB_ICONQUESTION ); if (res == IDYES) { DMCad-> TabUf->Post(); if ( DMCad-> TabUf->State != dsBrowse) Action = caNone; } else if (res == IDNO) DMCad-> TabUf->Cancel(); else Action = caNone; } } XI. A Janela de Cadastro 14. Abra View – Forms..., escolha CadUf e confirme; 15. Escolha File – Include Unit Hdr... , clique em CadDM e confirme; 16. Insira os componentes listados abaixo: Guia Componente Propriedade Valor Comentário Align alTop Na parte superior Standard Panel Caption Limpe este campo Align alClient No resto da tela DataSource DMCad→DSUf Origem dos dados Data Controls DBGrid Options→dgEditing false Não permite edição direta no formulário. Standard Button (em Panel1) Caption Incluir No canto superior esquerdo 13 Button (em Panel1) Caption Excluir À direita do botão anterior Button (em Panel1) Caption Alterar À direita do botão anterior Button (em Panel1) Caption Fechar À direita do botão anterior A. O Componente TDBGrid Aqui o usuário pode visualizar toda a consulta de uma só vez. As colunas com seus títulos são acessados, automaticamente, do componente TQuery. Porém, você pode configurar quais campos devem aparecer. Para isso de um clique duplo no DBGrid , clique com o botão direito na janela que foi aberta e escolha Add All Fields; agora você pode excluir, mover colunas, ou atribuir uma série de parâmetros adicionais. Desabilitamos a propriedade Options→dgEditing pois a edição será feita na janela de detalhes. Porém, se você não quiser utilizar uma tabela de detalhes, elimine os eventos TabUf→BeforeInsert e TabUf→BeforeEdit e deixe o dgEditing habilitado. XII. Codificando os Eventos da Janela de Cadastro A. O Evento CadUf→OnShow Ao abrir o formulário, garantimos que a tabela está ativa e o foco do teclado está na grade. O bloco “try ... catch” impede que a função seja interrompida no caso de haver erro. //------------------------------------------------- -------------------------- void __fastcall TCadUf::FormShow(TObject *Sender) { try { DMCad-> TabUf->Open(); } catch (Exception &exception) { Application->ShowException(&exception); } if (! DMCad-> TabUf->Active) { ShowMessage( "Falha abrindo tabela" ); Close(); } ActiveControl = DBGrid1; } B. O Evento Button1 →OnClick Insere um registro na tabela. //------------------------------------------------- -------------------------- void __fastcall TCadUf::Button1Click(TObject *Sender) { DMCad-> TabUf->Insert(); } C. O Evento Button2 →OnClick Exclui o registro selecionado da tabela. 14 //------------------------------------------------- -------------------------- void __fastcall TCadUf::Button2Click(TObject *Sender) { DMCad-> TabUf->Delete(); } D. O Evento Button3 →OnClick Altera o registro atual. Um duplo clique no registro também deve altera-lo. Para isso, selecione o evento DBGrid1→DblClick e escolha Button3Click . //------------------------------------------------- -------------------------- void __fastcall TCadUf::Button3Click(TObject *Sender) { DMCad-> TabUf->Edit(); } E. O Evento Button4 →OnClick Fecha o formulário de cadastro. //------------------------------------------------- -------------------------- void __fastcall TCadUf::Button4Click(TObject *Sender) { Close(); } F. O Evento CadUf→OnKeyDown Implementa atalhos de teclado para os comandos: incluir (Ins), excluir (Del), alterar (Enter) e sair (Esc). Se o valor da propriedade KeyPreview do formulário não for true, este método não irá funcionar. //------------------------------------------------- -------------------------- void __fastcall TCadUf::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { switch (Key) { case VK_INSERT: DMCad-> TabUf->Insert(); break; case VK_DELETE: DMCad-> TabUf->Delete(); break; case VK_RETURN: DMCad-> TabUf->Edit(); break; case VK_ESCAPE: Close(); break; } } XIII. O Menu Principal 17. Abra View – Forms..., escolha MainCad e confirme; 18. Escolha File – Include Unit Hdr... , clique em CadDM e em UfCad com a tecla Control pressionada e confirme; 19. Insira os componentes listados abaixo: 15 Guia Componente Propriedade Valor Comentário Button Caption Cadastro de UF No canto superior esquerdo Button Caption Cadastro de Cidade Abaixo do botão anterior Button Caption Cadastro de Bairro Abaixo do botão anterior Additional Button Caption Sair Abaixo do botão anterior XIV. Codificandoos Eventos do Menu Principal A. O Evento MainCad→OnShow Ao entrar no programa, tentamos abrir o banco de dados. O bloco “try ... catch” impede que a função seja interrompida no caso de haver erro e assim podemos checar se a operação foi bem sucedida, não permitindo o acesso ao sistema se o acesso à base de dados for negado. //------------------------------------------------- -------------------------- void __fastcall TMainCad::FormShow(TObject *Sender) { try { DMCad-> DataCad->Open(); } catch (Exception &exception) { Application->ShowException(&exception); } if (! DMCad-> DataCad->Connected) { ShowMessage( "Falha acessando a base de dados" ); Close(); } } B. O Evento MainCad→OnClose Implementamos um diálogo simples para confirmar a saída do programa. //------------------------------------------------- -------------------------- void __fastcall TMainCad::FormClose(TObject *Sender, TCloseAction &Action) { if (Application->MessageBox( "Deseja realmente sair do sistema?" , "Atenção!" , MB_YESNO|MB_ICONQUESTION ) == IDNO) Action = caNone; else if ( DMCad-> DataCad->Connected) DMCad-> DataCad->Close(); } C. O Evento Button4 →OnClick Botão sair. //------------------------------------------------- -------------------------- void __fastcall TMainCad::Button4Click(TObject *Sender) { Close(); } 16 D. O Evento Button1 →OnClick Chama o cadastro de unidade federativa. //------------------------------------------------- -------------------------- void __fastcall TMainCad::Button1Click(TObject *Sender) { CadUf->Show(); } XV. Compilando o Programa Agora o programa está pronto para rodar. Abra o menu Run - Run e veja o resultado. Se não funcionar, certifique-se que a base de dados está acessível e revise calmamente as propriedades de todos os componentes e o código de todos os eventos listados acima. XVI. Inserindo os Outros Formulários Podemos, afinal, inserir os formulários que estão faltando: 20. Abra File – New... e insira quatro formulários comuns (Form), atribuindo suas propriedades conforme descrito na tabela abaixo; 21. Escolha File – Save All, nomeando os arquivos conforme indicado abaixo: Item Arquivo Propriedade Valor Comentário Form CidadeDet.cpp Name DetCidade Detalhes de cidade Name CadCidade Cadastro de cidade Caption Cadastro de Cidade Título da janela Form CidadeCad.cpp KeyPreview true Para utilizar teclas especiais Form BairroDet.cpp Name DetBairro Detalhes de bairro Name CadBairro Cadastro de bairro Caption Cadastro de Bairro Título da janela Form BairroCad.cpp KeyPreview true Para utilizar teclas especiais O que ainda falta ser implementado é bastante similar ao que já foi feito com a tabela de unidade federativa, exceto pelo fato da UF não conter referências às outras tabelas. Abaixo você tem um resumo das inclusões necessárias para implementar os cadastros de cidade e bairro, volte aos capítulos indicados, substituindo os nomes em itálico, referentes à UF, para os nomes correspondentes para Cidade e Bairro. Nos capítulos seguintes (XVII. e XVIII. ) você verá como implementar referências entre as tabelas. A. No formulário DMCad a) Os componentes TUpdateSQL: UpdCidade e UpdBairro. Capítulo VI. (página 5); b) Os componentes TQuery: TabCidade e TabBairro. Ibidem; c) Os componentes TDataSource: DSCidade e DSBairro. Ibidem; d) Os campos das tabelas TabCidade e TabBairro. Capítulo VII. (página 7); e) Os campos referência Cid_ufnome e Bai_cidnome. Capítulo XVII. (página 17); f) Os eventos das tabela TabCidade e TabBairro. Capítulo VIII. (página 8). B. Nos formulários DetCidade e DetBairro a) Os componentes TLabel e TDBEdit para código e nome. Capítulo IX. (página 10); b) Os componentes TLabel e TDBLookupComboBox para editar as referências entre as tabelas TabCidade e TabUf e entre as tabelas TabBairro e TabCidade. Capítulo XVIII. (página 18); c) Os botões de controle Ok e Cancelar. Capítulo IX. (página 10); 17 d) Os eventos da janela e dos botões. Capítulo X. (página 11). C. Nos formulários CadCidade e CadBairro a) Os componentes TPanel, TDBGrid e os botões de controle. Capítulo XI. (página 12); b) Os eventos da janela e dos botões. Capítulo XII. (página 13). D. No formulário MainCad Codifique os eventos dos botões Button2 e Button3 para chamar os formulários CadCidade e CadBairro, respectivamente, conforme exemplificado no capítulo XIV. D. (página 16). XVII. Incluindo Referências Entre as Tabelas Freqüentemente precisamos mostrar dados de tabelas diferentes em uma mesma consulta. Em bancos de dados relacionais, usamos chaves estrangeiras para isso. Asseguir mostramos duas formas de implementar referências entre tabelas, uma para edição e outra, mais simples, para consultas. A. Referência por Código para Edição 22. Ainda no editor de campos, clique com o botão direito e escolha New Field...; 23. Deve aparecer uma janela de título New Field. Agora preencha os campos conforme indicado na tabela: Propriedade Valor Comentário Name cid_ufnome Nome do novo campo Component Cid_ufnome Nome de acesso ao novo campo Type String Tipo de dado para visualização Field type Lookup Tipo de campo KeyFields cid_ufcod A chave estrangeira Dataset TabUf A tabela alvo Lookup Keys uf_cod Campo chave na tabela alvo Result Field uf_nome Campo para visualização Veja como fica o exemplo: B. Referência Via SQL para Consultas Uma forma mais simples de incluir campos de referência é codificando-o diretamente na consulta SQL. Exemplo: SELECT cid_cod, cid_nome, cid_ufcod, uf_nome AS cid_ufnome FROM cidade, uf WHERE cid_ufcod = uf_cod ORDER BY cid_nome 18 Porém, esta forma só é permitida em consultas. Se você tentar incluir os campos, conforme o capítulo VII. (página 7), estando a opção RequestLive igual a true, você receberá uma mensagem de erro do tipo “Table is read only” (Tabela é somente para leitura). Porém, se RequestLive for false, você conseguirá inserir os campos sem problemas, mas também não conseguirá cadastrar os dados através do seu programa. XVIII. O Componente TDBLookupComboBox 24. Além das caixas de textos para código e nome de cidade, conforme exemplificado no capítulo IX. (página 10), insira os componentes listados abaixo para a edição do campo cid_ufcod: Guia Componente Propriedade Valor Comentário Alignment TaRightJustify Font→Style→fsBold True Standard Label Caption Uf: Abaixo do label para nome. DataSource DSCidade Origem dos dados DataField cid_ufcod A chave estrangeira ListSource DSUf Origem do alvo KeyField uf_cod Chave na tabela alvo Data controls DBLookupComboBox ListField uf_nome Campo visualização O Componente TDBLookupComboBox mantém uma lista atualizada de itens para campos de referência (chaves estrangeiras). Esconde do usuário todos os códigos da base de dados e assim, por exemplo, ele poderá entrar com “Rio de Janeiro” ao invés de “1” para informar a unidade federativa de uma cidade. Dica: Você pode incluir um pequeno botão ao lado do DBLookupComboBox, com Caption = “&Novo...”, de modo que o usuário não precise acessar o menu a fim de incluir uma referência que esqueceu de cadastrar. Basta codificar o evento OnClick deste botão com a linha: //------------------------------------------------- -------------------------- void __fastcall TDetCidade::BitBtn3Click(TObject *Sender) { DMCad-> TabUf->Insert(); } XIX. Finalizando Agora rode o programa clicando no botão Run e veja o resultado. Você pode utilizar este tutorial para implementar seus projetos, bastando trocar os nomes em itálico pelos nomes corretos.