Escolar Documentos
Profissional Documentos
Cultura Documentos
Curso de Extenso
MFC Bsico
PROF:
ANDR BERNARDI
andrebernardi@hotmail.com.br
Captulo 0
1 Introduo
1.1 Um pouco de Histria
Nos anos 60 lanado a Simula-67 que apresentou pela primeira vez os conceitos de
classes, rotinas correlatas e subclasses.
Na dcada de 70 a Seros-PARC cria a Smalltak at hoje considerada a mais pura das
LPOO. No final da dcada de 80 aparece a C++, uma linguagem hbrida. J a o Visual C++
surgiu no incio da dcada de 90.
Orientao a Objetos o maior avano em software destes ltimos anos. uma
forma mais natural de se analisar o mundo. Ela nos permite construir sistemas melhores e,
alm disso, de maneira mais fcil. Ser a mais importante das tecnologias emergentes na
rea de software nos anos 90.
As tcnicas estruturadas que, sem dvida, atualmente so as mais populares na
comunidade de informtica, obtiveram grande aceitao desde que foram lanadas no final
dos anos 70. Contudo a medida que foram sendo utilizadas, a decomposio funcional
mostrou-se inadequada em situaes de sistemas complexos e principalmente para
profissionais iniciantes. Os aperfeioamentos introduzidos em 1984, por Sthephen M e John
F Palmer e, mais tarde, complementados por Stephen Mellor e Paul Ward, para sistemas em
tempo real, ajudaram a anlise estruturada a se tornar mais eficiente. Contudo os sistemas
criados com as tcnicas estruturadas ainda so difceis de serem incrementados com novas
funes e as alteraes em funes j existentes, muitas vezes, provocam srios problemas
em outras partes do software.
Na prtica de programao orientada a objetos estaremos atentos em nossos
programas para pontos como:
Compatibilidade, portabilidade.
Segurana.
!" Reusabilidade.
!" Facilidade de integrao.
!" Facilidade de extenso.
!" Eficincia.
!"
!"
1.2 Reutilizao
A reutilizao est baseada na padronizao a qual adotada h longa data em toda
a indstria moderna, seja no projeto de carros, televisores, computadores, etc. A
padronizao traz inmeras vantagens, entre elas podemos citar a seguintes:
as peas padres so mais baratas;
so mais confiveis;
!" geralmente so mais fceis de serem consertadas ou substitudas.
!"
!"
Captulo 0
Captulo 0
Captulo 0
Captulo 0
pelo usurio que contm o molde, a especificao para os objetos, assim como o tipo inteiro
contm o molde para as variveis declaradas como inteiros.
Um primeiro exemplo desse relacionamento pode ser:
!" entenda o esquema eltrico e o layout de um telefone como aproximadamente
uma classe;
!" o objeto, ou instncia de uma classe, seria o telefone.
Uma classe determina as caractersticas de um objeto: propriedades, eventos e
mtodos relacionados.
Propriedades:
Um objeto tem certas propriedades, ou atributos. Para o exemplo acima, um telefone
possui cor e tamanho. Quando um telefone colocado em sua casa ou escritrio, ele ter
uma certa posio sobre uma mesa. O receptor pode estar no ou fora do gancho.
Objetos criados com o Visual C++, contm certas caractersticas que so
determinadas pela classe em que o objeto est baseado. Estas propriedades podem ser
fixadas a em seu desenvolvimento ou em tempo de execuo. Por exemplo um check box,
poder conter as seguintes propriedades, descritas na tabela abaixo:
Propriedade
Titulo
Habilitado
Esquerda
Visvel
Descrio
Um texto descritivo antes do check box
Quando o check box puder ser selecionado pelo usurio.
Alinhamento a esquerda do check box
Quando o check box est visvel na janela
Eventos:
Cada objeto reconhece e pode responder a certas aes chamadas eventos. Um
evento uma atividade especfica e pr determinada, iniciada tanto pelo usurio quanto
pelo sistema. Na maioria dos casos eventos so gerados pela interao do usurio. Por
exemplo, para o telefone, um evento disparado toda vez que o usurio retira o fone do
gancho. Eventos so gerados quando o usurio pressiona um boto para discar, etc.
Na programao para Windows, uma ao do usurio que pode provocar o disparo de
um evento pode ser um click ou movimento do mouse, ou pressionar uma tecla do teclado.
Quando um erro ocorre ao inicializar um objeto um evento do sistema disparado.
A tabela a seguir mostra alguns eventos relacionados com o check box.
Evento
Click do mouse
GotFocus
LostFocus
Descrio
Usurio pressiona o check box
Usurio seleciona o check box por um click ou tab.
Usurio seleciona outro controle
Mtodos:
Mtodos so funes que esto associadas aos objetos. Suas chamadas so feitas
atravs de mensagens. Um mtodo pode estar relacionado a um Evento. Exemplo se for
escrito um mtodo para responder ao evento de click do mouse, este ser chamado toda
vez que o boto do mouse for pressionado. Mtodos podem existir independente de
eventos, estes mtodos so chamados explicitamente dentro do cdigo.
A tabela a seguir mostra alguns mtodos relacionados com o check box.
Mtodo
Atualizar
SetFocus
Descrio
O valor do check box atualizado para refletir as alteraes que
possam Ter ocorrido na base de dados subjacente.
O foco atual passado ao check box como resultado de um
usurio pressionar a tecla TAB at o check box ser selecionado.
Captulo 0
Cliente
Venda
Atributos
id_cliente
nome_cliente
endereco
pessoa_autorizada
Status
id_cliente
id_vendedor
data_venda
produto
Mtodos
Incluir
Alterar
Excluir
Consultar
registrar
calcular_comisso
calcular_fatura
SERVIOS
Captulo 0
GENERALIZAO
ESPECIALIZAO
1-n
Objetos Parte
( 1 ) Cada parte pertence a um nico Todo
PARTE
PARTE
OBJETO 2
OBJETO 1
n
OBJETO RECEPTOR
SEVIO2
SERVIO1
SEVIO2
SERVIO1
2.7 Assunto
1 ASSUNTO 1
2 ASSUNTO 2
Notao para Assunto, quebrada
Captulo 0
10
Captulo 0
11
No faz sentido usar, chamar, esta funo membro separada de uma varivel do tipo
motor, mas ento porque na lista de argumentos no se encontra um motor? Este
pensamento reflete a maneira de associar dados e cdigo (funes) das linguagens
procedurais. Em linguagens orientadas a objetos o cdigo e os dados so ligados de forma
diferente, a prpria declarao de um tipo definido pelo usurio j engloba as declaraes
das funes inerentes a este tipo.
Note que no fornecemos o cdigo da funo, isto no importante, por hora a
preocupao com a interface definida pela classe: suas funes membro e dados membro.
Apenas pense que sua interface deve ser flexvel de modo a no apresentar entraves para a
criao do cdigo que seria feita numa outra etapa. Nesta etapa teramos que imaginar que
o valor numrico da velocidade deve ir para o conversor onde ir se transformar numa
diferena de potencial a ser aplicada nos terminais do motor, etc.
// Construtor 1
// Construtor 2
// Construtor sem parametros
Captulo 0
~CNomeClasse ( void );
// Destrutor
tipo m_dados3;
tipoRetorno funcao3( lista parametros ) { instrucoes
12
};
};
Os construtores so identificados como funes membros cujos nomes so iguais ao
nome da classe. A listagem acima mostra trs construtores para a classe CNomeClasse . A
sobrecarga do nome do construtor precisa satisfazer as mesmas exigncias das outras
funes, isto , as listas de parmetros precisam ser diferentes. Um construtor pode ter
uma lista de parmetros void. Os construtores podem fornecer valores default para um ou
mais de seus parmetros.
A funo membro ~CNomeClasse um destrutor. Ela precisa ter uma lista de
parmetros void. Pode ter um corpo de cdigo executvel se necessrio. Na listagem,
apenas prottipos so fornecidos para o Construtor1, Construtor2, Construtor3, destrutor,
funcao1 e funcao2. Tanto prottipos como definies so fornecidos para funcao3. Quando a
definio de uma funo membro est incluida na descrio de classe, ela tratada como
cdigo inline. As restries de implementao geral pedem que o cdigo inline no contenha
nenhuma construo de controle, exceto if ( como por exemplo do, for, while, break,
continue, goto, switch). Recomenda-se que o cdigo inline seja usado com ponderao e
apenas no caso de implementaes relativamente simples de funes membros.
Os detalhes relativos s definies de Construtor1, Construtor2, Construtor3,
destrutor, funcao1 e funcao2, so fornecidos fora da descrio formal da classe. Eles
pecisam ento ser identificados com suas classes, conforme indica a listagem abaixo. Estes
detalhes podem estar contidos no mesmo arquivo da descrio formal da classe ou em um
outro arquivo. Se forem implementados em um outro arquivo, o arquivo cabealho precisa
estar incluido, como mostra a listagem abaixo. As definies isoladas de funes so
identificadas com a classe apropriada colocando-se o qualificador CNomeClasse:: antes do
nome de cada funo.
Definies Externas para Funes Membros de uma Descrio de Classe
// Contedo do arquivo para definies externas de funes membros
#include NomeClasse.h
tipoRetorno CNomeClasse::funcao1( lista parametros )
{
instrucoes;
};
tipoRetorno CNomeClasse::funcao2( lista parametros )
{
instrucoes;
};
CNomeClasse::CNomeClasse ( lista parametros a)
{
instrucoes;
};
// Construtor 1
// Construtor 2
CNomeClasse::CNomeClasse ( void )
{
instrucoes;
};
CNomeClasse::~CNomeClasse ( void )
// Destrutor
Captulo 0
13
{
instrucoes;
};
Se algum tentar incluir campos de dados no arquivo externo que parte de uma
descrio de classe, ocorrer um erro. Todas as declaraes precisam estar na descrio
formal da classe. Apenas as definies das funes membros e membros de dados estticos
podem ser externas descrio formal da classe.
Captulo 0
14
Captulo 1
Microsoft Windows e Visual C++
Muito j foi escrito sobre a aceitao de Microsoft Windows e os benefcios de sua
interface grfica com o usurio (GUI). Esta introduo resume o modelo de programao
Windows (Win32 em particular) e mostra como os componentes do Visual C++ trabalham
em conjunto para lhe ajudar a escrever aplicaes para Windows. No decorrer do captulo,
voc aprender algumas coisas novas sobre o Windows.
Captulo 1
15
Captulo 1
16
Captulo 1
17
Compilao do Cdigo
Arquivos de
cabealho do
Windows
Arquivo de
recurso (RC)
Arquivos
fontes
Resource.h
Bitmap, cones, e
outros recursos
Arquivos de
Cabealhos
RunTime
Compilador de Recursos
Arquivos de
Cabealhos MFC
Arquivo RES
Compilador
Arquivos OBJ
Bibliotecas do
Windows e da MFC
Linker
Executvel
(EXE)
Captulo 1
18
workspace (com a extenso DSW) possui uma entrada para cada projeto que compe este
workspace. possvel ter vrios projetos dentro de um mesmo workspace, porm todos
exemplos deste curso tero apenas um projeto por workspace. Para trabalhar com um
projeto j existente, abra o arquivo com a extenso DSW dentro do Developer Studio e ser
possvel manipular este projeto.(editar compilar,etc.).
Arquivos intermedirios tambm so criados pelo Developer Studio. A tabela a seguir
contm uma lista dos arquivos que so gerados pelo Developer Studio para cada
workspace:
Extenso
APS
BSC
CLW
DSP
DSW
MAK
NCB
OPT
PLG
* do not delete or
Descrio
Utilizado pelo Resouce View
Arquivo de informaes do Browser
Utilizado pelo ClassWizard
Arquivo do Project*
Arquivo do Workspace*
makefile externo
Utilizado pelo ClassView
Armazena as configuraes do workspace
Arquivo de log do Build
edit in text editor.
WizardBar
Plataforma de Construo
Cdigo Fonte
Mensagens
do
Compilador e linker
Janela WorkSpace
Figura 2 Visual C++ e Developer Studio
Captulo 1
19
2.5 O Linker
O linker processa os arquivos OBJ e RES, produzidos pelo compilador C/C++ e o
compilador de recursos, e acessa os arquivos LIB para os cdigos da MFC, runtime library, e
do Windows. responsvel pela criao do arquivo executvel EXE do projeto. A opo de
link incremental minimiza o tempo de execuo quando pequenas mudanas so feitas nos
arquivos de cdigos fontes. Os cabealhos dos arquivos da MFC contm blocos especiais
#pragma (diretivas de compilao) que especificam os arquivos LIB que so necessrios,
assim voc no tem que contar explicitamente para o linker quais bibliotecas ele deve ler.
2.6 O Debugger
Caso seu programa funcione da primeira vez, no necessrio usar o debugger.
Todos ns poderiamos precisar dele de vez em quando. O debugger do Visual C++ tem
melhorado continuamente, contudo no fixa de fato os bugs. O debugger trabalha junto
com o Developer Studio para assegurar que os breakpoints so armazenados em disco.
Existem botes na barra de ferramentas para inserir e remover breakpoints e controlar a
execuo passo a passo. A Figura 3 ilustra o debugger do Visual C++ em ao. Notar que
as janelas Variables e Watch podem expandir um ponteiro de um objeto para mostrar
todos seus membros das classes derivadas e base. Se o cursor do mouse for posicionado
Prof. Andr Bernardi
Captulo 1
20
sobre uma varivel, o debugger mostra seu valor em uma pequena janela (Tooltip). Para
debugar um programa, necessrio constru-lo (build) com as opo e de compilador e
linker setadas para gerar informaes de debug.
Figura 3 O Debugger em Ao
2.7 AppWizard
O gerador de cdigo que cria todo o esqueleto de um aplicativo baseado em
Windows chamado de AppWizard. Os nomes das classes geradas, e de seus arquivos de
cdigo fonte, baseado no que foi especificado em suas caixas de dilogo. O AppWizard
ser utilizado exaustivamente por todo este curso, para gerar os programas de exemplo.
No confunda o AppWizard com os antigos geradores de cdigo, que geravam todo o cdigo
para um aplicativo. O cdigo gerado pelo AppWizard minimalista; a funcionalidade est
dentro das classes bases da application Framework. O AppWizard permite que voc inicialize
uma aplicao nova rapidamente.
2.8 ClassWizard
ClassWizard um programa (implementado como uma DLL) que est acessvel
atravs do menu View do Developer Studio. O ClassWizard o alivia da maante funo de
manter e gerar um cdigo de classe no Visual C++. Se precisar de uma classe nova, de
uma funo virtual, ou uma nova funo de manipulador de mensagem nova? O
ClassWizard escreve os prottipos, os corpos de funo, e (se necessrio) o cdigo para unir
a mensagem do Windows para a funo. ClassWizard pode atualizar cdigos de classe j
escritos, assim pode-se evitar os problemas de manuteno comum a geradores de cdigo
ordinrios. Algumas caractersticas do ClassWizard esto disponveis na WizardBar do
Developer Studio, como mostrado na Figura 2.
Prof. Andr Bernardi
Captulo 1
21
!" Call
!" Derived
!" File
!"
Captulo 1
22
!"
!"
Seja qual for o modo que o help online foi acessado, possvel copiar qualquer texto
de ajuda para o clipboard para incluso em seu programa.
2.12 A Galeria
A galeria do Developer Studio permite que se compartilhem componentes de
software entre diferentes projetos. A Galeria gerencia trs tipos de mdulos:
ActiveX controls quando instalado um controle ActiveX (OCX - OLE control),
uma entrada feita dentro do Registro do Windows. Todos os controles ActiveX
registrados aparecem na janela da Galeria, e podem ser selecionados em
qualquer projeto.
!" C++ source modules quando uma nova classe escrita, esse cdigo pode ser
adicionado na Galeria. Esse cdigo pode ser selecionado e copiado nos outros
projetos. Recursos tambm pode ser adicionados a Galeria.
!" Componentes do Developer Studio - A Galeria contm ferramentas que
podem ser usadas para adicionar caractersticas nos projetos. Tal ferramenta
pode inserir novas classes, funes, membros de dados, e recursos em um
projeto existente. Alguns componentes so fornecidos pela Microsoft
(processamento de tempo Inativo, apoio de Paleta, e Splash Screen, por
exemplo) como parte do Visual C++. Outros so fornecidos por outras firmas de
Software.
!"
DICA: Se voc decidir utilizar alguns dos componentes da Galeria Developer Studio,
experimente primeiro em um projeto bobo para ver se o que voc realmente quer.
Caso contrrio, pode ser difcil de remover o cdigo gerado de seu projeto regular.
Todos os cdigos gerados para a Galeria podem ser importados de um ou exportados
para um arquivo OCX. Estes arquivos fazem parte de um novo meio de distribuio e
compartilhamento para componentes do Visual C++.
Captulo 1
23
3 Microsoft
Foundation
Framework (Overview)
Class
Library
Application
As prximas sees:
Porque utilizar uma Estrutura de Aplicaes?
!" O que uma Estrutura de Aplicaes ?
!" Mapeamento de Mensagens na MFC Library
!" Documents e Views
!"
!"
Escrever sua prrpria biblioteca de classes em C++ para o Windows que utilize a
Win32 API,
!"
!"
Captulo 1
24
!"
!"
!"
A MFC library verso 2.0 classes (no Visual C++ 1.0) atualizou a verso 1.0 para
permitir o uso de muitas caractersticas comuns em programas baseados em Windows, alm
de introduzir o conceito de Estrutura de Aplicaes. A seguir a lista das mais importantes
caractersticas adicionadas:
Captulo 1
25
Suporte total aos itens de menu File Open, Save, and Save As, alm de permitir o
uso da lista de mais recentes usados
!" Suporte a Impresso e visualizao de impresso
!" Suporte para scrolling windows e splitter windows
!" Suporte a barra de ferramentas e barra de status
!" Acesso aos controles do Microsoft Visual Basic
!" Suporte para help sensitivo ao contexto
!" Suporte automtico para processameto de dados em uma caixa de dilogo.
!" Uma atualizao para melhor suportar OLE 1.0
!" Suporte a DLLs
!"
A MFC library 2.5 (no Visual C++ 1.5) contribuiu com o seguinte:
Suporte a ODBC (Open Database Connectivity) que permite que seus aplicativos
acessem dados armazenados com os formatos dos mais populares bancos de
dados como o Microsoft Access, FoxPro, e Microsoft SQL Server
!" Uma interface para OLE 2.01, que permite a edio de um objeto no local,
linking, arrastar e soltar, e OLE Automation
!"
O Visual C++ 2.0 foi a primeira verso em 32-bit do produto, Que inclua suporte
para Windows NT 3.5. Esta a verso 3.0 da MFC library, que incluiu as seguintes
caractersticas:
Suporte a Tab dialog (property sheet)
!" Docking control bars implementadas dentro da MFC
!" Suporte a thin-frame windows
!" Em anexo a ferramenta Control Development Kit (CDK) para construir controles
OLE (OCX) para 16 e 32 bits,
!"
A verso 2.1 do Visual C++, que inclui a MFC 3.1, adicionou o seguinte:
Suporte para os novos common controls do Microsoft Windows 95 (beta)
!" Novos drivers de ODBC para integrar com a Access jet database engine
!" Classe Winsock que permite a comunicao via TCP/IP
!"
A Microsoft decidiu pular a verso 3.0 do Visual C++ e ir diretamente a verso 4.0
com o intuito de sincronizar a verso do Visual C++ com a verso da MFC. MFC 4.0 contm
as seguintes caractersticas adicionais:
New OLE-based Data Access Objects (DAO) classes for use with the Jet engine
!" Use of the Windows 95 docking control bars instead of the MFC control bars
!" Full support for the common Controls in the released version of Windows 95, with
new tree view and richedit view classes
!"
!"
!"
Visual C++ 4.2 (subscription) inclui a MFC 4.2. As seguintes caractersticas foram
adicionadas:
Winlnet classes
ActiveX Documents server classes
!" ActiveX synchronous and asynchronous moniker classes
!" Enhanced MFC ActiveX Control classes, with features such as window less
activation, optimized drawing code, and so forth
!"
!"
Captulo 1
26
Improved MFC ODBC support, including recordset bulk fetches and data transfer
without binding
A verso 5.0 do Visual C++ com a MFC 4.21, (com alguns bugs da 4.2 corrigidos).
Dentre as principais caracterticas adicionadas ao Visual C++ 5.0 esto:
A redesigned IDE, Developer Studio 97, which includes an HTML-based online
help system and integration with other languages, including Java
!" The ActiveX Template Library (ATL) for efficient ActiveX Control construction for
the Internet
!"
Captulo 1
27
Captulo 1
28
CMyFrame::CMyFrame()
{
Create(NULL Aplicativo MYAPP) ;
}
CMyFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
TRACE(Entrando em CMyFrame::OnLButtonDown - %lx, %d, %d\n,
(long) nFlags, point.x, point.y);
}
CMyFrame::OnPaint()
{
CPaintDC dc(this);
dc.TextOut(0,0,Hello world!);
}
Aqui esto alguns elementos desse programa:
A funo WinMain Lembrar que o Windows requer que os aplicativos tenham a funo
WinMain. Aqui WinMain no visvel porque est encapsulada dentro da estrutura das
aplicaes.
A classe CMyApp Um objeto da classe CMyApp representa um aplicativo. O programa
define um objeto global do tipo CMyApp, theApp. A classe base CWinApp determina a
maioria do comportamento de theApp.
Inicializao do aplicativo Quando o usurio inicializa o aplicativo, o Windows chama a
funo WinMain interna da estrutura de aplicao, e WinMain procura pelo construtor do
objeto global do aplicativo da classe derivada de CWinApp. No esquecer que num
programa em C++, objetos globais so construdos antes do programa principal ser
executado.
A funo membro CMyApp::lnitlnstance Quando a funo WinMain procura o objeto
aplicativo, a funo membro virtual InitInstance chamada, que faz as chamadas
necessrias para construir e exibir a janela da mainframe do aplicativo. Voc tem que
sobrecarregar a InitInstance em sua classe derivada da aplicao porque o CWinApp que
a classe base no conhece que tipo de janela principal voc quer chamar.
A funo membro CWinApp::Run A funo Run est encapsulada na classe base, mas
despacha as mensagens da aplicao para suas janelas e assim mantm o funcionamento
da aplicao. WinMain chama Run depois que chama InitInstance.
A classe CMyFrame Um objeto da classe CMyFrame representa a janela da mainframe
do aplicativo. Quando o construtor chama a funo membro Create da classe base
CFrameWnd, o Windows cria a estrutura da janela e a application framework a vincula a um
objeto em C++. As funes ShowWindow e UpdateWindow, tambm membros da classe
base, devem ser chamadas para exibir a janela.
A funo CMyFrame::OnLButtonDown - Isto uma pr-estria da capacidade de
manipular mensagens da MFC. O evento pressionar o boto esquerdo do mouse mapeado
map para uma funo membro de CMyFrame. Voc aprender os detalhes das mensagens
coma a biblioteca MFC mais adiante. Por enquanto aceite que esta funo chamada
quando o usurio aperta o boto de esquerdo do mouse. A funo invoca a macro TRACE da
MFC para exibir uma mensagem na janela de depurao.
Captulo 1
29
Captulo 1
30
7 Documents e Views
O exemplo acima usou um objeto application e um objeto frame window. Muitos
aplicativos baseados na MFC library sero mais complexos. Tipicamente, contero alm das
classes application e frame, mais duas outras classes que representam o "document" e a
"view". Esta arquitetura document-view o corao da estrutura das aplicaes e est
baseado nas classes de Model/View/Controller do mundo do Smalltalk.
Um document um objeto de dados que manipulado pelo usurio em uma seo
de edio. criado pelos comando do menu File New ou Open e so tipicamente
armazenados em arquivos. Uma view um objeto janela que permite que o usurio
interaja com o documento ao qual ela est associada.
Em termos gerais, a arquitetura de document-view separa os dados, da viso pelo
usurio dos dados. Um benefcio bvio vises mltiplas dos mesmos dados. Considere um
documento que consiste no preo de um ms de citaes acionrias armazenado em disco.
Suponha que existam uma viso de tabela e uma viso grfica dos dados. O usurio
atualiza valores na janela da tabela, e a janela do grfico muda porque ambas as janelas
exibem a mesma informao (mas em vises diferentes).
Em aplicativos da MFC library, documents e views so representados por instncias
de classes C++.
A classe base do document interage com menu File Open e File Save; a classe de
document derivada faz a leitura e escrita dos dados do objeto de documento. (A estrutura
das aplicaes faz a maioria do trabalho de exibir o dilogo de abertura de Arquivos e
gravao de arquivos e abrindo, fechando, lendo, e escrevendo arquivos.) A classe base
view representa uma janela que contida dentro de uma janela de frame; a classe de viso
derivada interage com sua classe de documento associada e faz a exibio da aplicao e
impresso. As classes view derivada e base manipulam as mensagens de Windows. A MFC
libray organiza todas as interaes entre documentos, views, frame-window, e o objeto
application, principalmente por funes virtuais.
No pense que um objeto de documento deve ser associado com um arquivo de
disco que lido completamente na memria. Se um "documento" real fosse um banco de
dados, por exemplo, pode-se sobrecarregar as funes membro que servem para selecionar
o documento a funo que responde ao menu File Open para mostrar uma lista de bancos
de dados em vez de uma lista de arquivos.
Captulo 1
31
Captulo 2
Iniciando com o AppWizard
Neste Captulo abordado um dos componentes da arquitetura Document-View, a
classe view, que est intimamente relacionada com a janela. Por hora os outros trs
componentes bsicos da estrutura de um programa com a MFC no sero abordados.
Isto ser feito de forma prtica demonstrando a utilizao do AppWizard para criar
um esqueleto de um programa Windows.
claro que estes exemplos desse captulo no sero capazes de armazenar dados no
disco e no suportar mltiplas janelas, suportes estes que sero abordados nos prximos
captulos.
Como os recursos so uma parte importante de um programa para Windows, ser
abordada uma introduo do uso da ResourceView, para visualizar e explorar o programa.
Sero informadas ainda dicas de como melhorar o tempo de compilao e melhorar a
velocidade de execuo de ser programa.
2 SDI x MDI
Dois tipos de aplicativos distintos so suportados pela MFC: Single Document Interface
(SDI) e Multiple Document Interface (MDI). Um aplicativo SDI, do ponto de vista do usurio
apenas uma janela. Se este aplicativo depende de um arquivo em disco document,
apenas um ser suportado por este tipo de aplicativo. Exemplo NotePad. Um aplicativo MDI,
suporta mltiplas janelas filhas, cada uma associada a um documento correspondente.
Exemplo Word.
Quando o AppWizard executado, o tipo MDI o padro sugerido. Certifique-se de
mudar essa opo para criar os primeiros exemplos. O tipo MDI ser abordado mais tarde.
3 Exemplo Curso1a
Nesta seo ser abordado um exemplo completo de esqueleto de programa, bem
como os passos necessrios para sua criao utilizando o AppWizard. Este exemplo
apenas uma janela vazia com um menu e uma barra de ferramentas acoplada.
Quando voc criar o primeiro programa executvel MFC , voc usar o MFC
AppWizard (verso de EXE) que o conduzir por uma srie de caixas de dilogo nas quais
voc escolhe opes para a arquitetura, caractersticas, e funes de seu projeto.
Captulo 2
32
A srie um caminho ramificado: voc pode avanar pelos passos e pode fazer
mudanas s opes que voc selecionou. Ajuda est disponvel para toda opo no MFC
AppWizard: click o boto direito do mouse no controle para mais informao sobre cada
opo.
Passos para criar um programa MFC EXE usando a ferramenta AppWizard:
1. No menu File, click New e ento clique na pasta de Projects.
2. Especifique o Nome de Projeto, Localizao, Workspace, Dependncia, e opes de
Plataformas e ento click duas vezes no cone MFC AppWizard (exe).
3. Complete os passos do MFC AppWizard escolhendo as opes apropriadas para seu
programa.
4. Prepare seu programa MFC para uso. (Criar o executvel)
Captulo 2
33
Captulo 2
34
Captulo 2
35
Captulo 2
36
Passo 7
O AppWizard exibe uma tela com as informaes sobre o programa que est acabando de
ser criado.
Captulo 2
37
Quando o boto Ok do dilogo da figura acima for pressionado, o AppWizard comea a criar
o cdigo fonte de seu novo projeto. Quando o AppWizard finalizar, visualize o sub-diretrio
criado para o projeto. Os seguintes arquivos so de interesse por enquanto:
Arquivo
Curso1.dsp
Curso1.dsw
Curso1.rc
Curso1View.cpp
Curso1View.h
Curso1.opt
ReadMe.txt
Resource.h
Descrio
Arquivo de projeto que permite ao Developer Studio construir seu
aplicativo
Arquivo de WorkSpace que contm um entrada para o projeto.
Arquivo script ASCII de recursos
Arquivo de implementao da classe View, que contm as funes
membro da classe CCurso1View.
Arquivo de definio da classe View, que contm a descrio da classe
CCurso1View
Arquivo binrio que informa ao Developer Studio que arquivos foram
abertos para o projeto e como suas janelas esto arranjadas.
Arquivo texto que explica o propsito dos arquivos gerados.
Arquivo de cabealho que contm as constantes #define dos
identificadores usados pelos recursos.
A Figura 12 mostra a janela FileView do Workspace. Utilize esta janela para localizar
os arquivos que compe o projeto atual.
Captulo 2
38
Studio, possvel gerar o executvel para o aplicativo selecionando a opo Build Curso1
no menu Build ou pressionando o boto build da barra de ferramentas.
Se o processo ocorreu com sucesso, o programa executvel chamado Curso1.exe
criado no novo subdiretrio Debug dentro do diretrio de seu projeto. Nesse subdiretrio
ficam tambm armazenados os arquivos temporrios utilizados pelo compilador e linker.
NOTA: O processo de construo de um aplicativo (build), de certa forma demorado.
Este tempo de execuo pode ser reduzido com a utilizao de um computador com mais
memria(mnimo de 32MB).
Captulo 2
39
Procure a funo
Curso1aView.cpp:
OnDraw
no
arquivo
de
implementao
da
classe
view
}
A chamada da funo GetDocument pode ser seguramente retirada pois ainda no
estamos trabalhando com documentos nesse programa.
As funes TextOut, SelectStockObject, Ellipse so membros da classe de contexto de
dispositivo da Application Framework, CDC. A funo Ellipse desenha um circulo se o
retngulo que o limitar possuir dimenses iguais.
A MFC prov uma classe de til para trabalhar com retngulos no Windows, CRect. Um
objeto temporrio de CRect utilizado como parmetro da funo Ellipse para definir a
regio onde ela ser desenhada. Mais adiante voltaremos a entrar em mais detalhes sobre a
classe CRect.
Passo 2: Recompilar e Testar Curso1a
No menu Build selecione a opo Build Curso1a.exe , se nenhum erro ocorrer teste o
aplicativo novamente. Agora voc possui um programa que visivelmente faz alguma coisa.
Captulo 2
40
Descrio
Definio de teclas que simulam uma seleo do menu ou barra de
ferramentas.
Layout e contedo das caixas de dilogo. Curso1a contem apenas a caixa
de dilogo About.
Figuras de 16x16 pixels ou 32x32 pixels, como os cones que so vistos no
Windows Explorer e no dilogo About do aplicativo. Curso1a usa o logotipo
da MFC como seu icone.
O menu do aplicativo bem como seus pop-up associados.
Strings que no fazem parte do cdigo fonte em C++ do programa.
Fila de botes imediatamente abaixo do menu
Descrio do programa, numero de verso, lngua, etc.
Captulo 2
41
Captulo 2
Release Build
Debug Build
Desabilitado
Desabilitado
MFC Release Library
Mxima velocidade
Habilitado
Habilitado
MFC Debug Library
Nenhuma otimizao
42
Captulo 2
43
Captulo 3
Manipulao bsica de eventos, modos de Mapeamento e a
ScrollView
Neste captulo abordado, como a MFC realiza a chamada da funo membro virtual
OnDraw. mostrado mais uma forma de padronizao de nomes de funes membros das
classes bases da CView, onde as funes que respondem a eventos iniciam com as letras
On, como por exemplo: OnKeyDown, OnLButtonDown, a prpria OnDraw, entre outras.
Muitas dessas funes no so virtuais, o que faz com que mais passos de
programao sejam realizados. O ClassWizard, ser utilizado para facilitar a tarefa de
associar um evento a funes membros das classes derivadas. Essa conexo feita atravs
do message map, que a estrutura realizada para ligar os eventos as funes membros na
MFC.
Os dois primeiros exemplos usaro classes derivadas de CView para mostrar como
eventos do usurio podem interagir com a funo membro OnDraw, bem como o que afeta
em uma janela o modo de mapeamento de desenho utilizado. Um outro exemplo ser
utilizado para demonstrar as caractersticas da classe CScrollView, que permite que barras
de rolamento sejam conectadas a janela de vista do aplicativo.
Captulo 3
44
BEGIN_MESSAGE_MAP(CCurso3AView, CView)
ON_WM_LBUTTONDOWN()
// entrada especfica para OnLButtonDown
// outras entradas ao mapa de mensagens
END_MESSAGE_MAP()
Finalmente o arquivo de cabealho da classe tambm deve conter a declarao:
DECLARE_MESSAGE_MAP()
Todos estes passos podem ser feitos manualmente, mas o Visual C++ disponibiliza
uma ferramenta, o ClassWizard, que automatiza a gerao desses cdigos para a maiioria
das mensagens que podem ser mapeadas.
Captulo 3
45
Visualizando o guia de referncia da MFC (help), fica visvel que estas classes
possuem vrios operadores sobrecarregados, que permitem entre outras coisas:
Somar ou subtrair objetos CSize a objetos CPoint;
Subtrair um objeto CPoint de outro e armazenar em um objeto CSize;
!" Somar ou subtrair objetos CPoint e CSize de objetos CRect.
!"
!"
A classe CRect possui ainda outros membros que retornam objetos CPoint e CSize.
Neste ponto j podemos perceber que objetos do tipo CSize resultam de uma diferena
entre dois objetos CPoint, e que possvel deslocar o canto superior esquerdo de um objeto
CRect para coincidir com um objeto CPoint.
possvel ainda determinar se um ponto est dentro de um retngulo utilizando a
funo membro PtInRect. Por exemplo para trocar o estado do membro de dados m_nCor
pode ser feito um teste para determinar se o mouse est sendo pressionado dentro do
retngulo que define a elipse. O cdigo que ficaria dentro da funo OnLButtonDown seria
assim:
if (m_rectElipse.PtInRect(point))
{// se for verdadeiro o ponto pertence ao retngulo.
if (m_nCor == GRAY_BRUSH)
m_nCor = WHITE_BRUSH;
else
m_nCor = GRAY_BRUSH;
InvalidateRect(m_rectElipse)
}
Para determinar se o ponto pertence exatamente a uma regio elptica, necessrio
construir um objeto do tipo CRgn que corresponda a uma elipse utilizar um de seus
membros PtInRegion. Este seria o cdigo:
CRgn rgn;
rgn.CreateEllipticRgnIndirect(m_rectElipse);
if (rgn.PtInRegion(point))
{// se for verdadeiro o ponto pertence ao retngulo.
if (m_nCor == GRAY_BRUSH)
m_nCor = WHITE_BRUSH;
else
m_nCor = GRAY_BRUSH;
Prof. Andr Bernardi
Captulo 3
46
InvalidateRect(m_rectElipse)
}
A classe CRgn pode tamber ser utilizada para definir uma regio poligonal.
m_nCor;
m_rectElipse;
Se preferir pode digitar o cdigo acima dentro da declarao da classe que est no
arquivo Curso3AView.h.
Captulo 3
47
Captulo 3
48
2 Modos de Mapeamento
Os desenhos realizados at agora foram baseados em unidades de pixels, tambm
conhecida como Coordenadas do Dispositivo. No exemplo Curso3A, as unidades utilizadas
eram pixels devido ao Contexto de Dispositivo estar ajustado para o Modo de Mapeamento
Padro, MM_TEXT. A declarao
pDC->Rectangle(CRect(0,0,200,200));
desenha um quadrado de 200 por 200 pixels, coincidente com o canto superior esquerdo da
rea cliente. Notar que se a resoluo do monitor for alterada, para por exemplo 1024x768,
este mesmo quadrado reduzir de tamanho. Se for utilizado um contexto de Impresso
(600dpi) este quadrado aparecer com um tamanho bem pequeno.
E se meu programa tivesse que desenhar um quadrado de 4x4 cm, independente do
dispositivo que esle estivesse sendo mostrado? O Windows possui outros modos de
mapeamento, ou sistema de coordenadas, que podem ser associados a um contexto de
dispositivo. As coordenadas no modo atual de mapeamento so chamadas Coordenadas
Lgicas.
Pode parecer fcil manipular estes sistemas de coordenadas, porm no possvel
trabalhar apenas em coordenadas lgicas. O programa ter que chavear entre coordenadas
lgicas e coordenadas do dispositivo, e voc precisar conhecer quando convert-las.
Captulo 3
49
Unidade lgica
0,01 in
0,001 in
0,1 mm
0,01 mm
1/1440 in
Obs:
O modo MM_TWIPS ser utilizado preferencialmente em contexto de impresso. A
unidade twip se refere a 1/20 pontos. Um ponto uma unidade de medida que no windows
corresponde exatamente a 1/72 in. Para desenhar um caractere de tamanho 12 pontos
(fonte tamanho 12), ajuste a altura do caractere para 12*20, ou 240 twips.
50
O cdigo a seguir serve para testar se boto esquerdo do mouse foi pressionado
dentro de um retngulo:
//assumir que m_rect um membro do tipo CRect de uma classe derivada de
//CView utilizando-se do modo de mapeamento de coordenadas lgicas
//MM_LOENGLISH .
void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
{
CRect rect = m_rect;
// faz uma cpia temporria do objeto m_rect
CClientDC dc(this);
// isto como se deve pegar um contexto de
// dispositivo para o uso das funes
// SetMapMode e LPtoDP.
dc.SetMapMode(MM_LOENGLISH);
dc.LPtoDP(rect);
// rect ficou em coordenadas do dispositivo
if (rect. PtInRect(point))
TRACE(cursor do mouse est dentro do retngulo);
}
O melhor lugar para selecionar o modo de mapeamento dentro da funo virtual
OnPrepareDC membro da classe CView, ao invs de fazer isso na OnDraw.
Prof. Andr Bernardi
Captulo 3
51
Captulo 3
52
Captulo 3
53
Captulo 3
54
m_nCor;
m_rectElipse;
Se preferir pode digitar o cdigo acima dentro da declarao da classe que est no
arquivo Curso3CView.h.
Captulo 3
55
OnHScroll(SB_LINERIGHT, 0, NULL);
break;
default:
break;
}
}
cdigo
do
construtor
da
funo
OnDraw
em
ClassWizard
para
mapear
mensagem
Captulo 3
56
Captulo 3
57
Captulo 4
Interface de dispositivos grficos, cores e fontes.
Alguns elementos da GDI j foram vistos em captulos anteriores. Toda vez que um
programa desenha na tela ou na impressora est utilizando funes da GDI. A GDI possui
funes para desenhar pontos, linhas, retngulos, polgonos, elipses, bitmaps e textos. O
desenho de crculos, quadrados pode ser feito intuitivamente apenas com um breve estudo
das funes disponveis, porm a programao para o desenho de textos um pouco mais
complicada. Este captulo se destina a fornecer informaes suficientes para iniciar com o
uso da GDI efetivamente dentro do ambiente do Visual C++. Ser apresentado como
utilizar fontes efetivamente tanto na impressora como na tela.
Captulo 4
58
fcil de garantir que o objeto contexto de dispositivo seja destrudo, cri-lo na pilha
(stack). O cdigo a seguir ilustra esta operao:
void CCurso3BView::OnLButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);
// constroi um dc na pilha
CRect rectDevice = m_rectElipse;
dc.LPtoDP(rectDevice);
// converte coordenadas
}
Repare que, desta forma o construtor da classe CClientDC recebe um ponteiro para
uma janela view. O destrutor da classe CClientDC chamado quando a funo termina
(retorna).
Outra forma de conseguir um contexto em uma funo mapeada utilizando o
membro da classe me CWnd::GetDC, como mostrado no cdigo abaixo. Sempre que este
mtodo for utilizado deve-se chamar a funo ReleaseDC para destruir o contexto de
dispositivo criado.
void CCurso3BView::OnLButtonDown(UINT nFlags, CPoint point)
{
CDC* pDC = GetDC();
// ponteiro para contexto interno
CRect rectDevice = m_rectElipse;
pDC->LPtoDP(rectDevice);
// converte coordenadas
ReleaseDC(pDC);
// no deve ser esquecido.
}
NOTA: um contexto criado para ser enviado como parmetro para a funo OnDraw
no deve ser destruido, a estrutura das aplicaes se encarregar disso.
2 Objetos da GDI.
Objetos da GDI, so representados por uma classe da MFC. CGdiObject uma classe
base abstrata para encapsular os objetos da GDI, que so representados dentro do Visual
C++ por classes derivadas desta. As seguintes classes so suportadas pelo Visual C++:
Prof. Andr Bernardi
Captulo 4
59
CBitmap
CBrush
!" CFont
!" CPalette
!" CPen
!" CRgn
!"
!"
// pena desselecionada
Captulo 4
60
// pena desselecionada
Captulo 4
61
3 Cores no Windows.
A GDI proporciona uma independncia do hardware utilizado para exibir as cores. Os
programas trabalham com cores absolutas e a GDI se encarrega de fazer as combinaes
necessrias para que essas cores fiquem visveis no Windows.
Atualmente o Windows suporta 4 tipos de modalidades de cores que so processadas
pelas respectivas placas de vdeo.
Verde (G)
0
0
255
0
255
0
255
255
0
128
128
0
0
128
128
192
Azul (B)
0
255
0
0
255
255
0
255
128
0
128
0
128
0
128
192
Cor
Preto
Azul
Verde
Vermelho
Turquesa
Rosa
Amarelo
Branco
Azul escuro
Verde escuro
Turquesa escuro
Vermelho escuro
Rosa escuro
Amarelo escuro
Cinza escuro
Cinza claro
Captulo 4
62
4 Fontes.
Nos programas anteriores, quando um texto era exibido na tela ele utilizava a fonte
System, do Windows. Como comum a todos, o Windows suporta mltiplas fontes,
independentes do dispositivo e com tamanhos variveis. Fontes True-Type, so mais fceis
de ser manipuladas dentro dos programas do que as fontes que eram dependentes de
dispositivos (ex. uma fonte para impressora e outra para a tela). Aps esta introduo
terica sobre as fontes sero apresentados exemplos ao final deste captulo.
Captulo 4
63
Indice
Descrio
Valor
HORZSIZE
VERTSIZE
HORZRES
VERTRES
LOGPIXELSX
LOGPIXELSY
169
127
640
480
96
96
Captulo 4
64
5 Exemplo Curso4A
5.1 Execute o AppWizard para gerar o exemplo Curso4A
Escolha a opo File New e selecione MFC AppWizard (EXE) na pasta Project.
Selecione a opo Single Document (SDI) e desmarque a opo Print Preview, Aceite todas
outras opes padres.
As opes de criao e o nomes das classes a serem criadas est mostrada na figura
abaixo.
Captulo 4
65
Captulo 4
66
Captulo 4
67
6 Exemplo Curso4B
Este exemplo similar ao anterior porm possui duas diferenas bsicas:
1. Utiliza do modo de mapeamento MM_ANISOTROPIC com uma escala
dependente do tamanho da janela.
2. Exibe mltiplas fontes na mesma tela
Os seguintes passos deve ser seguidos para a criao desse exemplo:
Captulo 4
68
Captulo 4
69
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_MODERN, "Courier"); // not TrueType
pDC->SelectObject(&fontTest2);
TraceMetrics(pDC);
pDC->TextOut(0, 100, "This is Courier, default width");
fontTest3.CreateFont(50, 10, 0, 0, 400, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_ROMAN, NULL);
pDC->SelectObject(&fontTest3);
TraceMetrics(pDC);
pDC->TextOut(0, 200, "This is generic Roman, variable width");
fontTest4.CreateFont(50, 0, 0, 0, 400, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_MODERN, "LinePrinter");
pDC->SelectObject(&fontTest4);
TraceMetrics(pDC);
pDC->TextOut(0, 300, "This is LinePrinter, default width");
pDC->SelectObject(pOldFont);
}
Captulo 4
70
7 Exemplo Curso4C
No exemplo Curso3C, foi inciado a utilizao da classe CScrollView. Neste exemplo
ser mostrado como proceder para mover um elipse com o mouse, utilizando uma janela
rolvel com o modo de mapeamento MM_LOENGLISH. A rolagem pelo teclado foi deixada de
fora, porm se desejvel, basta utilizar os passos descritos no exemplo Curso3C para criar a
funo OnKeyDown semelhante.
Em vez de utilizar um brush do estoque, ser utilizado um brush hachurado para o
preenchimento da elipse. S h uma restrio para o uso de brushes hachurados, a origem
da janela rolante deve ser resetada, caso contrrio o efeito de preenchimento pode parecer
esquisito.
Como no programa Curso3C, este exemplo utiliza uma classe View derivada de
CScrollView. (No esquea de mudar isso no passo 6 do AppWizard) aqui esto os passos
para criar este aplicativo:
Captulo 4
71
Funo membro
OnLButtonDown
OnLButtonUp
OnMouseMove
Captulo 4
72
Captulo 4
73
m_bCaptured = FALSE;
}
// Em coordenadas do dispositivo,
// Alinhar o brush com a origem
// da janela
pDC->SelectObject(&brushHatch);
// Seleciona Brush
pDC->Ellipse(CRect(m_pointTopLeft, m_sizeElipse));
pDC->SelectStockObject(BLACK_BRUSH); // Desseleciona brushHatch
// Testa retangulo invalido
pDC->Rectangle(CRect(100, -100, 200, -200));
}
void CCurso4CView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal(800, 1050);
// 8-por-10.5 polegadas
CSize sizePage(sizeTotal.cx / 2, sizeTotal.cy / 2);
CSize sizeLine(sizeTotal.cx / 50, sizeTotal.cy / 50);
SetScrollSizes(MM_LOENGLISH, sizeTotal, sizePage, sizeLine);
}
Captulo 4
74
Captulo 4
75
Captulo 4
76
Captulo 5
Caixas de Dilogo e Controles do Windows
Quase todos os programas para o Windows possuem janelas dilogo para interagir
com o usurio. Um dilogo pode ser desde um simples Message Box com um boto OK at
um formulrio complexo para entrada de dados. Esses dilogos so elementos que se
comportam como uma verdadeira janela, recebem mensagens, podem ser movidos e
fechados, alm de aceitar elementos de desenho vistos anteriormente em seu interior.
H dois tipos de dilogos, Modal e Modeless. Estaremos abordando o tipo mais
comum que o dilogo modal. Ainda neste captulo sero implementados exemplos de
interao com dilogos atravs de controles do Windows.
2 Recursos e controles
Agora que voc j sabe que um dilogo uma janela, o que o torna diferente de
uma janela CView ser visto nessa seo. Dilogos sempre fazem parte dos recursos de um
programa Windows que conter seu identificador e o layout de como esse dilogo se
apresentar na tela. O editor de recursos poder ser utilizado para construir o layout desses
dilogos de forma amigvel e completamente visual.
Um dilogo pode conter muitos elementos em seu interior. Esses elementos recebem
o nome de Controles. Fazem parte desses controles, as caixas de texto (edit box), botes,
list box, caixas de seleo (combo box), textos estticos(labels), entre outros. Esses
controles podem ser referenciados dentro do programa por ponteiros para CWnd, bem como
pelo uso de identificadores associados aos recursos, que o meio mais comum. O controle
envia uma mensagem ao dilogo em resposta a uma interao com o usurio como por
exemplo o pressionamento de um boto.
A MFC e o ClassWizard trabalham juntos para facilitar o uso de dilogos dentro de
um programa Windows. O ClassWizard cria uma classe derivada de CDialog para cada
dialogo e permite ainda que sejam associadas variveis membros a controles do dilogo.
Podem ser especificados os limites de nmeros e tamanho de strings para as variveis
membros criadas, que o ClassWizard se encarrega criar as chamas a data validation e data
exchange que faro o controle de troca entre os dados que constam na caixa de dilogo e
as variveis membros.
Captulo 5
77
4 Exemplo Curso5A
O dilogo criado para o exemplo Curso5A.exe, no apenas uma caixa de dilogo e
sim um enorme dilogo que inclui um controle de cada tipo. Essa tarefa se torna mais fcil
utilizando o editor de dilogos do Developer Studio. O resultado final est mostrado na
Figura 24.
Captulo 5
78
Captulo 5
79
Na tela do Developer Studio ser exibido o novo dilogo que acabou de ser criado
como mostrado na Figura 27.
Captulo 5
80
Obs: para mater a janela de propriedades sempre visvel, fixe-a utilizando o boto
existente em seu canto superior esquerdo.
Prof. Andr Bernardi
Captulo 5
81
Captulo 5
82
A seguir encontra-se uma breve descrio de cada um dos controles que sero
adicionados ao novo dilogo.
!"
Controle Edit Box para o Nome. Um edit control a meio mais fcil de se
entrar com um texto dentro de um dilogo. Pressione o boto direito do mouse
sobre esse controle e selecione a opo Properties. Altere o identificador do
controle de IDC_EDIT1 para IDC_NOME. Aceite todas as outras opes padres.
!" Controle Edit Box para o RG. Este controle adicionado como o anterior
exceto que seu identificador tem que ser alterado para IDC_RG. Mais tarde esse
identificador ser utilizado pelo ClassWizard para adicionar um campo numrico.
!"
!"
Controle Edit Box para a Bio (biografia). Este um controle que deve possuir
mais de uma linha (multiline). Altere seu identificador para IDC_BIO, e selecione
suas propriedades como mostrado na Figura 32.
Controle Group Box para a categoria. Este um controle serve apenas para
separar visualmente os radio buttons das categorias. Altere seu Capition para
Categoria e aceite o identificador padro.
!" Os Radio Buttons para o Horista e Salrio. Posicione estes radio buttons
dentro do group box categoria. Altere o identificador do boto Horista para
IDC_CAT e selecione as outras propriedades como mostrado na figura abaixo:
!"
Captulo 5
83
Certifique-se que a propriedade Auto est setada (padro) na pasta Styles, e apenas
o boto horista est com a propriedade Group setada. Quando estas propriedades
esto corretamente configuradas o Windows garante que apenas um estar
selecionado ao mesmo tempo. O Group box Categoria no tem nenhum efeito sob a
operao desses botes.
!"
Controle Group Box para o Seguro. Este um controle serve apenas para
separar visualmente check box dos tipos de seguro contratados. Altere seu
Capition para Seguro e aceite o identificador padro.
Nota: Mais tarde quando for alterar a ordem de tabulao do dilogo,
certifique-se que este controle ser o posterior ao radio button do grupo das
categorias. Altere a propriedade desse controle para Group de modo que
identifique para o Windows o fim do grupo das categorias. Caso isto no seja
feito, varias mensagens de Warning sero exibidas na janela Output quando o
programa estiver rodando em modo Debug.
!"
Os check Box para Vida, Invalidez e Sade. Posicione estes controles dentro
do Group box Seguro. Aceite todos os estilos padres, porm altere os
identificadores para respectivamente, IDC_VIDA, IDC_INVALID, IDC_SAUDE.
!"
Controle Combo Box para o Cargo. Este primeiro dos trs tipos de combos
existentes. Altere seu identificador para IDC_CARGO, selecione a pasta estilo e
escolha o tipo Simple. Click na pasta Data e adicione os tres cargos como
mostrado na figura abaixo (Obs: cada final de linha no list box deve ser
informado a caixa de propriedades utilizando-se a combinao de teclas
Ctrl+Enter). Com o tipo Simple, um texto pode ser informado digitando-se um
novo valor bem como selecionado um pr-existente na lista.
!"
Controle Combo Box para o Grau. Altere seu identificador para IDC_GRAU, e
aceite todos outros estilos como o padro. Click na pasta Data e adicione os tres
nveis de instruo: Primrio, Colegial, Graduao. No estio DropDown, o usurio
Captulo 5
84
!"
Captulo 5
85
Aceite a opo padro Create a new class, e pressione Ok. Preencha os dados para a
nova classe como mostrado na figura a seguir.
Coloque o nome da classe que seja relacionado com um dilogo. Por exemplo as
ultimas trs letras do nome da classe como Dlg. E pressione Ok.
Captulo 5
86
Captulo 5
87
Digite o nome da varivel e escolha seu tipo de acordo com a tabela abaixo.
Certifique-se que os nomes das varives so exatamente como os mostrados na tabela
abaixo, pois maiusculas e minusculas afetam os nomes de variveis em C++. Pressione Ok
e repita a operao para todos os outros controles.
ID do controle
Membro de dados
Tipo
IDC_BIO
IDC_NOME
IDC_RG
IDC_CARGO
IDC_CAT
IDC_CONFIABILIDADE
IDC_LEALDADE
IDC_LANG
IDC_SAUDE
IDC_VIDA
IDC_INVALID
IDC_GRAU
IDC_DEPT
m_strBio
m_strNome
m_nRg
m_strCargo
m_nCat
m_nConfiabilidade
m_nLealdade
m_strLingua
m_bSegSaude
m_bSegVida
m_bSegInvalid
m_strGrau
m_strDepart
CString
CString
int
CString
int
int
int
CString
BOOL
BOOL
BOOL
CString
CString
Captulo 5
88
BN_CLICKED, e pressione o boto Add Function, O dilogo Add Member Function aparecer
sobre o ClassWizard como mostrado na figura abaixo:
Um nome pode ser digitado para a funo, porm o ClassWizard sempre sugere um
nome que significativo ao evento e quase sempre ser aceito sem alteraes.
Aps pressionar OK, a funo passou a ser mapeada para a classe e o boto Edit
Code pode ser usado para a edio do corpo da funo, que dever conter as seguintes
inscries:
void CCurso5ADlg::OnSpecial()
{
TRACE("CCurso5ADlg::OnSpecial\n");
}
Obs: outros membros, como por exemplo a funo que responder ao boto ok j
esto mapeadas pela classe me CDialog, portanto no necessrio que sejam
adicionadas funes para esses membros.
Captulo 5
89
BOOL CCurso5ADlg::OnInitDialog()
{
CListBox* pLB = (CListBox*) GetDlgItem(IDC_DEPT);
pLB->InsertString(-1, "Documentao");
pLB->InsertString(-1, "Contabilidade");
pLB->InsertString(-1, "Recursos Humanos");
pLB->InsertString(-1, "Segurana");
// Chame a funo aps a inicializao
return CDialog::OnInitDialog();
}
Uma inicializao para os combo boxes pode ser feita de forma semelhante ao invs
de preenche-los no momento de sua criao.
Captulo 5
90
dlg.m_bSegSaude = TRUE;
dlg.m_strDepart = "Segurana";
dlg.m_strCargo = "Programador";
dlg.m_strLingua = "Ingls";
dlg.m_strGrau
= "Graduao";
dlg.m_nConfiabilidade = dlg.m_nLealdade = 50;
int ret = dlg.DoModal();
TRACE("DoModal return = %d\n", ret);
TRACE("Nome = %s, RG = %d, Cat = %d\n",
dlg.m_strNome, dlg.m_nRg, dlg.m_nCat);
TRACE("Dept = %s, Cargo = %s, Lingua = %s, Grau = %s\n",
dlg.m_strDepart, dlg.m_strCargo, dlg.m_strLingua, dlg.m_strGrau);
TRACE("Vida = %d, Invalid = %d, Saude = %d, bio = %s\n",
dlg.m_bSegVida, dlg.m_bSegInvalid, dlg.m_bSegSaude, dlg.m_strBio);
TRACE("Confiabilidade = %d, Lealdade = %d\n",
dlg.m_nConfiabilidade, dlg.m_nLealdade);
}
Captulo 5
91
Captulo 5
92
Captulo 5
93
Captulo 5
94
Captulo 6
Separando o Documento de sua Vista
Neste captulo ser discutido como os Documentos (doc) mantm os dados do
aplicativo e como as vistas (view) apresentam esses dados ao usurio. Alm de aprender
como essas classes interagem entre si enquanto o aplicativo est em execuo.
Ainda neste captulo sero mostrados dois exemplos que utilizam a classe
CFormView como base para suas classes de vista. No primeiro exemplo a classe doc
mantm os dados de apenas um objeto do tipo CEstudante que representa um nico
registro do tipo estudante e a classe view oferece meios para a alterao desses dados. A
classe CEstudante servir como de exemplo para a implementao de classes que
representem elementos do mundo real dentro de um programa. O segundo exemplo
introduz o conceito de ponteiro para colees, atravs das classes CObList e CTypePtrList.
Agora o documento ser capaz de armazenar uma coleo de registros do tipo estudante, e
a classe view permitir o acesso individual a cada um desses registros.
Captulo 6
95
GetDocument()->UpdateAllViews(this);
O parmetro pSender no nulo, identifica para a estrutura das aplicaes que a view
atual no precisa ser notificada e assume que ela j contm os dados atualizados. Isto
previne que uma atualizao da view onde os dados foram alterados no seja realizada.
Essa funo possui ainda parmetros opcionais hint, que informam a janela como ela
dever ser atualizada. O uso desses parmetros dependente do aplicativo e constituem
um uso avanado desse tipo de funo.
Como a classe view notificada quando a funo UpdateAllViews chamada
exatamente o assunto da prxima funo membro a ser discutida, a OnUpdate.
Captulo 6
96
3 A classe CFormView
A classe CFormView uma classe view til pois contm muitas das caractersticas
das caixas de dilogos. Como uma classe derivada de CDialog, uma classe derivada de
CFormView associada a um recurso de dilogo que define as caractersticas de sua janela
alm de enumerar seus controles. A classe CFormView suporta as mesmas funes DDX e
DDV discutidas no captulo 5 para as caixas de dilogo.
OBS: Quando o AppWizard cria um dilogo que ser associado a uma
FormView, ele altera corretamente as propriedades que esse dilogo deve
obedecer. Se um recurso de dilogo for criado via o Editor de dilogos as
seguintes propriedades devem ser respeitadas para o perfeito funcionamento
desse recurso quando associado a uma FormView:
Style = Child
Border = None
Visible = desselecionado
Um objeto do tipo CFormView recebe as notificaes tanto dos controles como da
estrutura das aplicaes.
A classe CFormView derivada da classe CView e no da classe CDialog, portanto as
funes membros de CDialog OnInitDialog, OnOK e OnCancel no esto presentes nos
objetos do tipo formview. Alm da funo UpdateData e DDX no serem chamadas
automaticamente. Portanto essas funes devem ser manipuladas pelo programador no
tempo certo em resposta as notificaes dos controles e comandos.
O AppWizard pode ser utilizado para gerar um aplicativo cuja classe base para a view
seja uma CFormView. Quando A CFormView for selecionada o AppWizard gera um recurso
de dilogo com as propriedades j corretamente selecionadas. O prximo passo seria
utilizar o ClassWizard para mapear as mensagem e adicionar os membros de dados com
seus respectivos critrios de validao.
4 A classe CObject
Ao observar a hierarquia de classes da MFC, note que a classe CObject aparece bem
no topo e muitas classes so derivadas dela, o que a considerar como a classe raiz. Quando
uma classe derivada de CObject ela recebe caractersticas importantes, Muitos desses
benefcios sero mostrados em captulos posteriores.
Neste captulo sero abordadas as caractersticas de diagnstico por esvaziamento e
a opo de utilizar objetos desse tipo como elementos de colees.
Prof. Andr Bernardi
Captulo 6
97
Captulo 6
98
6 Exemplo Curso6A
Este exemplo trata de uma interao simples entre Documentos e Vistas. A classe
CCurso6ADoc, derivada de CDocument, contm um objeto do Tipo CEstudante. A classe
CEstudante representa um registro de um estudante composto por dois membros, um
CString para representar o nome e um inteiro para representar a nota. A classe
CCurso6AView, derivada de uma CFormView contm uma representao visual do
registro, com caixas de edio para representar o nome e nota. O Boto Enter, atualiza os
dados do documento com o contedo das caixas de edio. A figura a seguir mostra o
programa Curso6A em execuo:
Captulo 6
99
Captulo 6
100
Utilize
a
constante
padro
sugerida
pela
estrutura
das
aplicaes
ID_EDIT_LIMPARTUDO. Edite a caixa de texto Prompt para torn-lo igual a caixa de
propriedades abaixo:
Captulo 6
101
Controle
Identificador
IDC_NOME
IDC_NOTA
IDC_ENTER
Mensagem
IDC_ENTER
ID_EDIT_LIMPARTUDO
ID_EDIT_LIMPARTUDO
BN_CLICKED
OnEnter
COMMAND
OnEditLimpartudo
UPDATE_COMMAND_UI OnUpdateEditLimpartudo
Funo Membro
Captulo 6
102
Varivel Membro
Categoria
Tipo
IDC_NOME
IDC_NOTA
m_strNome
m_nNota
Value
Value
CString
Int
Para a varivel membro m_nNota, entre os valores 0 e 100, nas caixas de edio
Minimum Value e Maximum Value respectivamente.
prottipo
para
funo
membro
Captulo 6
103
void CCurso6AView::OnEnter()
{
CCurso6ADoc* pDoc = GetDocument();
UpdateData(TRUE);
// Retornar dados da tela
pDoc->m_estudante.m_strNome = m_strNome;
pDoc->m_estudante.m_nNota = m_nNota;
}
Em um aplicativo com mltiplas views, a funo OnEditLimpartudo deve ser
mapeada dentro da classe document, como este exemplo contm apenas uma view
associada ao documento ela pode ser mapeada dentro da view. A funo
OnUpdateEditLimpartudo chamada pela estrutura das aplicao para desabilitar a opo
do menu se o objeto estudante estiver vazio. Edite seus cdigos para torn-los como
mostrado abaixo:
void CCurso6AView::OnEditLimpartudo()
{
GetDocument()->m_estudante = CEstudante(); // cria novo objeto vazio
UpdateControlsFromDoc() ;
}
void CCurso6AView::OnUpdateEditLimpartudo(CCmdUI* pCmdUI)
{
pCmdUI->Enable( GetDocument()->m_estudante != CEstudante() );
}
Captulo 6
104
}
// Construtor de Inicializao
CEstudante(const CEstudante& s) : m_strNome(s.m_strNome)
{
m_nNota = s.m_nNota;
}
// Operador =
(Atribuio)
const CEstudante& operator =(const CEstudante& s)
{
m_strNome = s.m_strNome;
m_nNota = s.m_nNota;
return *this;
}
// Operador == (Comparao)
BOOL operator ==(const CEstudante& s) const
{
if ((m_strNome == s.m_strNome) && (m_nNota == s.m_nNota)) {
return TRUE;
}
else {
return FALSE;
}
}
// Operador != (Comparao)
BOOL operator !=(const CEstudante& s) const
{
// Basta utilizar uma negao (!) com o operador == j implementado
return !(*this == s);
}
#ifdef _DEBUG
void Dump(CDumpContext& dc) const;
#endif // _DEBUG
};
#endif // _CURSOVC_CESTUDANTE
Arquivo de implementao da Classe CEstudante, Estudante.cpp
// Arquivo de implementao da Classe CEstudante
// Estudante.cpp
#include "stdafx.h"
#include "Estudante.h"
IMPLEMENT_DYNAMIC(CEstudante, CObject)
#ifdef _DEBUG
void CEstudante::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "m_strNome = " << m_strNome << "\nm_nNota = " << m_nNota;
}
#endif // _DEBUG
Aps a edio desses arquivos selecione a opo Add To Project, no menu Project,
em seguida escolha a opo Files e selecione os arquivos Estudante.h e Estudante.cpp. O
Captulo 6
105
Developer Studio acrescenta os nomes dos arquivos ao projeto e quando ele for compilado
os arquivos tambm o sero.
Captulo 6
106
8 A funo CDocument::DeleteContents
Em algum ponto do programa ser necessrio um funo para excluir todos os dados
de seu documento. Isto poderia se conseguido atravs da escrita de uma funo membro
privada, entretanto a estrutura das aplicaes declara a funo virtual DeleteContents para
a classe CDocument. A estrutura das aplicaes faz a chamada de sua funo
sobrecarregada quando o documento fechado e em outras oportunidades que sero
comentadas no prximo captulo.
Captulo 6
107
Captulo 6
108
Para manter uma notao mais simples possvel utilizar a declarao typedef para
gerar o que mostrado a seguir:
typedef CTypedPtrList<CObList, CCEvent*> CEventList;
Agora m_pEventList pode ser declarado como a seguir:
CEventList m_pEventList;
10 Exemplo Curso6B
Este exemplo possui algumas diferenas bsicas em relao ao anterior, sendo elas:
!"
!"
Possui uma barra de ferramentas que permite o usurio navegar atravs da lista;
O aplicativo foi reformulado para permitir o uso de mltiplas views. Notar que o
comando de menu Edit Clear All, est mapeado agora para a classe doc, alm das
funes UpdateAllViews e OnUpdate serem utilizadas em conjunto.
!"
Captulo 6
Captulo 6
109
110
!"
!"
Identificador
Capition
Prompt
ID_ESTUDANTE_INICIO
ID_ESTUDANTE_FINAL
ID_ESTUDANTE_ANTERIOR
ID_ESTUDANTE_PROXIMO
ID_ESTUDANTE_INSERIR
ID_ESTUDANTE_EXCLUIR
&Incio
&Final
&Anterior
&Prximo
&Inserir
Excluir
Captulo 6
111
Identificador
ID_ESTUDANTE_INICIO
ID_ESTUDANTE_FINAL
ID_ESTUDANTE_ANTERIOR
ID_ESTUDANTE_PROXIMO
ID_ESTUDANTE_INSERIR
ID_ESTUDANTE_EXCLUIR
Boto
Prompt
Volta ao incio da lista de estudantes.\nIncio
Avana para o ultimo registro da lista.\nFinal
Retorna ao registro anterior na lista.\nAnterior
Mover para o prximo registro na lista.\nPrximo
Insere um novo registro a lista.\nInserir
Excluir o registro atual.\nExcluir
!"
Controle
Identificador
IDC_NOME
IDC_NOTA
IDC_LIMPAR
!"
10.2 Cdigo
As seguintes classes sero alteradas/criadas para atender os requisitos de cdigo
deste exemplo:
Prof. Andr Bernardi
Captulo 6
Arquivo de
cabealho
Arquivo fonte
Curso6BDoc.h
Curso6BView.h
Estudante.h
Curso6BDoc.cpp
Curso6BView.cpp
Estudante.cpp
StdAfx.h
StdAfx.cpp
Classes
CCurso6bDoc
CCurso6bView
CEstudante
CEstudanteList
112
Descrio
Interface com o documento. (Dados)
Interface com o usurio. (Janela)
Registro de um estudante.
Coleo de Registros.
Arquivos de incluso padro.
CCurso6BDoc::CCurso6BDoc()
{
TRACE("Dentro do construtor da classe CCurso6BDoc\n");
#ifdef _DEBUG
afxDump.SetDepth(1); // Garante o dump dos elementos da lista
#endif // _DEBUG
}
!"
Identificador
Mensagem
Funo Membro
ID_EDIT_LIMPARTUDO
COMMAND
OnEditLimpartudo
Captulo 6
ID_EDIT_LIMPARTUDO
!"
!"
113
UPDATE_COMMAND_UI OnUpdateEditLimpartudo
void CCurso6BDoc::DeleteContents()
{
#ifdef _DEBUG
Dump(afxDump);
#endif
// Excluindo os elementos da lista.
while (m_estudanteList.GetHeadPosition()) {
delete m_estudanteList.RemoveHead();
}
}
void CCurso6BDoc::OnEditLimpartudo()
{
DeleteContents();
UpdateAllViews(NULL);
}
// Esvaziar a lista
// Atualizar todas as janelas
!"
Captulo 6
114
Identificador
Varivel Membro
Categoria
Tipo
IDC_NOME
IDC_NOTA
m_strNome
m_nNota
Value
Value
CString
Int
!"
Identificador
Mensagem
Funo Membro
IDC_LIMPAR
BN_CLICKED
OnLimpar
!"
Utilizar o ClassWizard para mapear os comandos (COMMAND) do menu (duploclique) para as funes descritas na tabela a seguir:
Identificador
Mensagem
Funo Membro
ID_ESTUDANTE_INICIO
ID_ESTUDANTE_FINAL
ID_ESTUDANTE_ANTERIOR
ID_ESTUDANTE_PROXIMO
ID_ESTUDANTE_INSERIR
ID_ESTUDANTE_EXCLUIR
COMMAND
COMMAND
COMMAND
COMMAND
COMMAND
COMMAND
OnEstudanteInicio
OnEstudanteFinal
OnEstudanteAnterior
OnEstudanteProximo
OnEstudanteInserir
OnEstudanteExcluir
!"
Identificador
Mensagem
Funo Membro
ID_ESTUDANTE_INICIO
ID_ESTUDANTE_FINAL
ID_ESTUDANTE_ANTERIOR
ID_ESTUDANTE_PROXIMO
ID_ESTUDANTE_EXCLUIR
UPDATE_COMMAND_UI
UPDATE_COMMAND_UI
UPDATE_COMMAND_UI
UPDATE_COMMAND_UI
UPDATE_COMMAND_UI
OnUpdateEstudanteInicio
OnUpdateEstudanteFinal
OnUpdateEstudanteInicio
OnUpdateEstudanteFinal
OnEstudanteExcluir
!"
void CCurso6BView::OnLimpar()
{
TRACE("Dentro de CCurso6BView::OnLimpar\n");
LimparItem();
}
//
void CCurso6BView::OnEstudanteInicio()
{
TRACE("Dentro de CCurso6BView::OnEstudanteInicio\n");
Prof. Andr Bernardi
Captulo 6
115
Captulo 6
116
POSITION pos;
TRACE("Dentro de CCurso6BView::OnEstudanteExcluir\n");
if ((pos = m_position) != NULL)
{
m_pList->GetNext(pos); //guarda a posio do prximo elemento
if (pos == NULL)
// verifica se existe o prximo
{
pos = m_pList->GetHeadPosition();
TRACE("GetHeadPos = %ld\n", pos);
if (pos == m_position)
{
pos = NULL;
}
}
GetItem(pos);
// posiciona no novo item
CEstudante* ps = m_pList->GetAt(m_position);
m_pList->RemoveAt(m_position); // faz a excluso do item
delete ps;
// exclui o ponteiro
m_position = pos;
GetDocument()->SetModifiedFlag();
GetDocument()->UpdateAllViews(this);
}
}
//
void CCurso6BView::OnUpdateEstudanteInicio(CCmdUI* pCmdUI)
{
// chamado durante um processo idle e quando o menu Estudante aberto
POSITION pos;
// habilita o boto se a lista no estiver vazia e o no estivar no
// incio da lista.
pos = m_pList->GetHeadPosition();
pCmdUI->Enable((m_position != NULL) && (pos != m_position));
}
//
void CCurso6BView::OnUpdateEstudanteFinal(CCmdUI* pCmdUI)
{
// chamado durante um processo idle e quando o menu Estudante aberto
POSITION pos;
// habilita o boto se a lista no estiver vazia e o final da
// lista no foi atingido.
pos = m_pList->GetTailPosition();
pCmdUI->Enable((m_position != NULL) && (pos != m_position));
}
//
void CCurso6BView::OnUpdateEstudanteExcluir(CCmdUI* pCmdUI)
{
// chamado durante um processo idle e quando o menu Estudante aberto
// habilita o boto se a posio no for nula
pCmdUI->Enable(m_position != NULL);
}
!"
Captulo 6
117
protected:
POSITION
m_position; // Posio atual no documento
CEstudanteList* m_pList; // copiado do documento
2. Declarar os prottipos das funes auxiliares
protected:
virtual void LimparItem();
virtual void InserirItem(POSITION position);
virtual void GetItem(POSITION position);
!"
//
void CCurso6BView::LimparItem()
{
m_strNome
= "";
m_nNota
= 0;
UpdateData(FALSE);
}
//
void CCurso6BView::InserirItem(POSITION position)
{
if (UpdateData(TRUE))
{
// UpdateData retorna FALSE se algum erro for detectado
CEstudante* pStudent = new CEstudante;
pStudent->m_strNome
= m_strNome;
pStudent->m_nNota
= m_nNota;
m_position = m_pList->InsertAfter(m_position, pStudent);
}
}
//
void CCurso6BView::GetItem(POSITION position)
{
if (position)
// testa se a posio diferente de NULL
{
CEstudante* pStudent = m_pList->GetAt(position);
m_strNome = pStudent->m_strNome;
m_nNota = pStudent->m_nNota;
}
else
{
// se for nulo apenas limpa a tela
LimparItem();
}
UpdateData(FALSE);
}
Captulo 6
118
at $762E80
nome
at $762640
Nota 100
11 Exerccio proposto:
Modificar o programa Curso6B para permitir que ele tenha a caracterstica de alterar
um valor de um elemento da lista. Voc deve criar o item de menu bem como o boto na
barra de ferramentas para gerar este comando.
Captulo 6
119
Captulo 7
Escrevendo e lendo Documentos - SDI
Como deve Ter sido notado, todos os exemplos gerados at agora possuem um
menu File com os comandos familiares New, Open, Save e Save As. Neste captulo
mostrado como os aplicativos podem responder leitura e gravao de documentos.
O exemplo desse captulo Curso7A um aplicativo do tipo SDI (Single Document
Interface) baseado no programa Curso6B do captulo anterior. O programa utiliza o
documento de lista de alunos com uma classe view derivada a partir de CFormView. Porem
a lista de alunos poder agora ser lida e escrita no disco atravs de um processo chamado
serializao.
Captulo 7
120
Captulo 7
121
Captulo 7
122
uma referencia para o objeto CArchive. A funo Serialize da classe derivada de documento,
ento, serializa cada um dos membros de dados no-temporrios.
2 Aplicativo SDI
J vimos muitas aplicaes da SDI que possuem uma classe de documento e uma
classe de vista. Vamos manter o uso de apenas uma classe de vista neste captulo, mas
iremos explorar as inter-relaes existentes entre os elementos da estrutura das aplicaes
criados para os programas. Como por exemplo o objeto aplicativo, a janela principal
(mainframe), o documento, a vista e menu.
Captulo 7
123
3 Exemplo Curso7A
Este exemplo similar ao programa Curso6B.
!"
Alterar a string que vai ser associada aos documento do exemplo para 07A
durante o passo 4 do AppWizard, atravs do boto Advanced... que ao ser
pressionado exibe a caixa de dilogo mostrada na Figura 53.
!"
!"
3.2 Recursos
Os recursos utilizados para programa so os mesmos utilizados no exemplo Curso6B.
Utilize o editor de recursos para copi-los para o exemplo Curso7A, atravs da
abertura do arquivo curso6B.rc e explorao de seu contedo.
Captulo 7
124
Figura 53 - Dilogo para alterao das strings relacionadas com o modelo de Documento.
Captulo 7
125
3.3 Cdigo
Os requisitos de cdigo que diferem do exemplo anterior sero listados a seguir,
respeitando a notao de realado em cinza o cdigo que deve ser substitudo ou alterado
em relao ao exemplo Curso6B.
Captulo 7
126
else {
return FALSE;
}
}
// Operador !=
(Comparao)
BOOL operator !=(const CEstudante& s) const
{
// Basta utilizar uma negao (!) com o operador == j implementado
return !(*this == s);
}
virtual void Serialize(CArchive& ar);
#ifdef _DEBUG
void Dump(CDumpContext& dc) const;
#endif // _DEBUG
};
//fim da declarao da classe CEstudante
//Declarao da classe CEstudanteList
typedef CTypedPtrList<CObList, CEstudante*> CEstudanteList;
#endif // _CURSOVC_CESTUDANTE
Captulo 7
127
!"
!"
Captulo 7
128
//{{AFX_MSG(CCurso7ADoc)
afx_msg void OnEditLimpartudo();
afx_msg void OnUpdateEditLimpartudo(CCmdUI* pCmdUI);
afx_msg void OnUpdateFileSave(CCmdUI* pCmdUI);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
CEstudanteList m_estudanteList;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately
before the previous line.
#endif // AFX_CURSO7ADOC_H__5092750A_099C_11D3_B817_D53F1F592A0E__INCLUDED_
Arquivo de implementao da classe CCurso7ADoc, Curso7ADoc.cpp
/////////////////////////////////////////////////////////////////////////////
// CCurso7ADoc construction/destruction
CCurso7ADoc::CCurso7ADoc()
{
TRACE("Dentro do construtor CCurso7ADoc \n");
#ifdef _DEBUG
afxDump.SetDepth(1); // garante o esvaziamento da lista
#endif // _DEBUG
}
CCurso7ADoc::~CCurso7ADoc()
{
Prof. Andr Bernardi
Captulo 7
129
}
BOOL CCurso7ADoc::OnNewDocument()
{
TRACE("Dentro do CCurso7ADoc::OnNewDocument\n");
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CCurso7ADoc serialization
void CCurso7ADoc::Serialize(CArchive& ar)
{
TRACE("Dentro do CCurso7ADoc::Serialize\n");
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
m_estudanteList.Serialize(ar);
}
/////////////////////////////////////////////////////////////////////////////
// CCurso7ADoc diagnostics
#ifdef _DEBUG
void CCurso7ADoc::AssertValid() const
{
CDocument::AssertValid();
}
void CCurso7ADoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
dc << "\n" << m_estudanteList << "\n";
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CCurso7ADoc commands
void CCurso7ADoc::DeleteContents()
{
TRACE("Dentro de CCurso7ADoc::DeleteContents\n");
// Excluindo os elementos da lista.
while (m_estudanteList.GetHeadPosition()) {
delete m_estudanteList.RemoveHead();
}
}
Prof. Andr Bernardi
Captulo 7
130
Captulo 7
131
Captulo 7
132
Captulo 8
Escrevendo e lendo Documentos - MDI
Neste captulo introduzido um aplicativo usando a interface de mltiplos
documentos (MDI Multiple Document Interface) com o uso da MFC, explicando como sero
feitas leituras e gravaes nos arquivos de documento. Um aplicativo MDI ser
efetivamente o estilo de preferncia para um programa da biblioteca de classes. O
AppWizard permite algumas caractersticas especficas aos aplicativos MDI, como o uso do
Arrastar e Soltar, e duplo clique no Explorer. Alm disso a maior parte dos exemplos de
programa que acompanham o Visual C++ so aplicativos MDI.
Vamos abordar ainda neste captulo as similaridades e tambm as diferenas entre
aplicativos SDI(Single Document Interface) e MDI. Sugere-se que, antes de ser iniciada o
estudo dos aplicativos destinados a MDI, haja uma compreenso completa a respeito dos
Aplicativos baseados na SDI, conforme descrito no captulo anterior.
1 Aplicativo MDI
Antes de analisar o cdigo gerado pela biblioteca de classes para os aplicativos MDI,
deve haver uma certa familiaridade com a operao de programas do Windows que utilizem
a MDI. Observe com cuidado o Developer Studio. Esse um aplicativo MDI cujos "mltiplos
documentos" so arquivos contendo cdigos fontes para os programas. Contudo o
Developer Studio no representa uma das mais tpicas aplicativos MDI, porque seus
documentos so reunidos em projetos. Seria mais interessante examinar o Microsoft Word,
ou, ainda melhor, uma aplicao real da MDI da biblioteca de classes - do tipo gerado pelo
AppWizard.
Captulo 8
133
Item de Menu
Ao
New Window
Cascade
Tile
Arrange Icons
(nomes de documentos)
Se o usurio salvar e fechar as duas janela filhas (e abrir o menu file), o aplicativo
ter o aspecto da Figura 57
Captulo 8
134
primeiro arquivo novo Curso71, o segundo ser Curso72 e assim por diante. O usurio
normalmente seleciona um nome diferente ao salvar o documento.
Os aplicativos MDI geradas com o uso da MFC, assim como acontece no caso de
muitos aplicativos comerciais da MDI, iniciam suas operaes com um novo documento
vazio. Se for desejado que o aplicativo inicie com a janela mainframe em branco, pode ser
alterado o argumento da funo ProcessShellCommand chamado no arquivo de
implementao de classe do aplicativo como mostrado no exemplo Curso8A.
Captulo 8
135
Figura 59.
Em um aplicativo SDI, o objeto CMainFrame enquadrava a aplicao e continha o
objeto view. Em uma aplicao MDI estes dois papeis esto separados. Agora o Objeto
CMainFrame ser construdo em InitInstance e o objeto CMDIChildWnd ir conter a view.
A estrutura das aplicaes pode criar objetos CMDIChildWnd de forma dinmica,
porque a classe CMDIChildWnd ser passada para o construtor de CMultDocTemplate.
Classe Base
Classe gerada
pelo AppWizard
Nmero de
Objetos
Barra de
controle e
menus
Possui
uma
view
CMDIFrameWnd
CMainFrame
Apenas 1
sim
no
no
sim
CMDIChildWnd
Construo do Objeto
Na funo InitInstance
da classe do aplicativo
Pela Estrutura das
Aplicaes quando
uma nova janela filha
for aberta
2 Exemplo Curso8A
O exemplo Curso8A um aplicativo MDI baseado no exemplo anterior Curso7A. Suas
principais diferenas so as capacidades de arrastar e soltar, bem como a abertura de um
arquivo atravs do Explorer. Notar a diferena dentro da funo InitInstance da classe
CCurso8AApp.
Captulo 8
136
Captulo 8
Captulo 8
137
138
Captulo 8
139
Captulo 8
Captulo 8
140
141
Captulo 9
Introduo ao uso de banco de dados com a MFC
Neste captulo abordado uma introduo a utilizao de bancos de dados
comerciais, via ODBC (Open Database Connectivity) ou DAO (Data Access Object) utilizando
a MFC. As classes que sero utilizadas neste captulo sero derivadas de uma classe
CRecordset (CDaoRecordset) e uma classe CRecordView (CDaoRecordView).
O exemplo Curso9A mostra uma interao entre essas duas classes a ainda serve
como um visualizador de banco de dados. Durante sua criao sero mostrados os passos a
serem seguidos para criar um aplicativo simples de banco de dados utilizando a MFC.
2 A Classe CRecordset/CDaoRecordset
Um objeto de CDaoRecordset representa um conjunto de registros selecionados de
uma fonte de dados. Conhecidos como "recordsets", objetos de CDaoRecordset esto
disponveis nos trs seguintes formatos:
!" Recordsets tipo Table - representa uma tabela bsica que pode ser utilizada para
examinar, acrescentar, mudar, ou apagar registros de uma nica tabela de banco
de dados.
!" Recordsets tipo Dynaset - o resultado de uma consulta que pode conter
registros atualizveis. Este recordsets um conjunto de registros que pode ser
utilizado para examinar, acrescentar, mudar, ou apagar registros de tabelas de
um banco de dados. Podem conter campos de uma ou mais tabelas de um banco
de dados.
!" Recordsets tipo Snapshot - uma cpia esttica de um conjunto de registros que
voc pode usar, achar dados ou gerar relatrios. Estes recordsets podem conter
campos de uma ou mais tabelas em um banco de dados mas no pode ser
atualizado.
Cada formato de recordset representa um conjunto de registros definidos no
momento em que o mesmo aberto. Quando o registro alterado em recorsets do tipo
Table ou Dynaset, essas mudanas sero refletidas no registro do arquivo depois que o
recordset for aberto, ou por outros usurios ou por outro recordsets em sua aplicao. (Um
recordset de tipo Snapshot no pode ser atualizado.) Voc pode usar CDaoRecordset
diretamente ou pode derivar um recordset especfico para seu aplicativo.
Possuindo um objeto recordset no aplicativo possvel:
Navegar pelos registros.
!" Fixar um ndice e procurar registros rapidamente usando Busca (apenas para
recordsets de tipo Table).
!"
Captulo 9
142
!"
!"
!"
Ordenar o recordset.
!" Parametrizar o recordset para personalizar sua seleo com informaes somente
disponveis em tempo de execuo do programa.
!"
3 A Classe CRecordView/CDaoRecordView
Um objeto de CDaoRecordView uma view que exibe registros de banco de dados
em controles. Essa view uma form conectada diretamente um objeto de CDaoRecordset.
O layout da janela criado a partir de um recurso de modelo de dilogo e exibe os campos
do objeto CDaoRecordset em seus controles. O objeto CDaoRecordView usa dialog data
exchange (DDX) e DAO record field exchange (DFX) para automatizar o movimento de
dados entre os controles no formulrio e os campos do recordset. CDaoRecordView tambm
prov um implementao padro destinada a mover ao primeiro, prximo, prvio, ou ltimo
registro e uma interface por atualizar vista o registro corrente.
Como descrito no item anterior na MFC existem classes distintas para utilizar a
interface DAO e ODBC, sendo elas respectivamente uma CDaoRecordView e uma
CRecordView. Ambas possuem caractersticas semelhantes porm a interface DAO mais
eficiente.
A maneira mais fcil de se criar uma RecordView atravs do AppWizard. AppWizard
cria a classe RecordView e sua recordset associada como parte do esqueleto de um novo
aplicativo, ver mais a frente Exemplo Curso9A.
Para os casos em que apenas um formulrio requerido, o AppWizard oferece o
meio mais simples de implementar, entretanto necessrio mais de um formulrio para a
mesma tabela ou nos casos de vrias tabelas, o ClassWizard oferece uma opo mais
flexvel, pois possvel criar uma nova RecordView e decidir qual Recordset estar ligado a
ela no momento de sua criao. Se a classe de vista no for criada pelo o AppWizard,
possvel cri-la mais tarde utilizando o ClassWizard. Esta caracterstica tambm permite ter
mltiplas janelas associadas ao mesmo recordset.
A fim de tornar a interface com o usurio mais amigvel, e fcil de movimentar por
entre os registros o AppWizard cria recursos itens de menu (e toolbar) para mover ao
primeiro, prximo, prvio, ou ltimo registro. Se uma classe derivada de CDaoRecordView
for criada utilizando o ClassWizard, necessrio tambm criar estes recursos porm
manualmente.
CDaoRecordView mantm registrado a posio do usurio no recordset de forma que a
RecorView pode atualizar a interface de usurio. Por exemplo quando o usurio move para o
final do recordset, a RecordView desabilita a interface do usurio (as opes de menu e
botes na Toolbar) para no permitir que o usurio avance alm do final dos registros.
Captulo 9
143
Captulo 9
144
Figura 67 - Dilogo para seleo do tipo de suporte a banco de dados a ser utilizado.
Captulo 9
Captulo 9
145
146
4.2.2 Cdigo:
Utilize o ClassWizard para conectar as caixas de edio aos campos correspondentes
do banco de dados a ser exibido.
Selecione as variveis associadas (Figura 73) a tabela de dados para cada um dos
identificadores correspondentes as caixas de edio criadas no formulrio. Observe que a
varivel criada um ponteiro para um membro da classe Set, e na lista aparecem com um
indicador -> antes de seu nome.(Figura 74)
Obs: Variveis que existem apenas temporariamente, ou seja no fazem parte da
tabela ou um resultado entre elementos da tabela podem ser ainda podem ser criadas
diretamente dentro da classe View, o que permite que parte dos dados exibidos na tela
sejam resultados de clculos e no necessariamente membros de uma tabela.
Captulo 9
147
Captulo 9
148
5.1.1 Passo 1 Utilize o editor de menus para acrescentar opes ao menu Record:
Selecionar o item Menu do arquivo de recursos e escolher o identificador
IDR_MAINFRAME (duplo-clique);
!" Selecionar o submenu Record;
!" Acrescentar os itens de menu como mostrado na figura abaixo;
!"
!"
Identificador
Capition
Prompt
ID_RECORD_ADD
ID_RECORD_DELETE
ID_RECORD_REFRESH
&Add
&Delete
&Refresh
Captulo 9
149
BOOL
BOOL
BOOL
BOOL
OnMove(UINT nIDMoveCommand);
RecordAdd();
RecordRefresh();
RecordDelete();
// Implementation
public:
BOOL Gravar();
virtual ~CAddForm();
// Generated message map functions
protected:
//{{AFX_MSG(CAddForm)
afx_msg void OnRecordAdd();
afx_msg void OnRecordRefresh();
afx_msg void OnRecordDelete();
afx_msg void OnUpdateRecordFirst(CCmdUI* pCmdUI);
//}}AFX_MSG
//{{AFX_VIRTUAL(CAddForm)
virtual void OnInitialUpdate(); // called first time after construct
//}}AFX_VIRTUAL
DECLARE_MESSAGE_MAP()
};
#endif // !defined(AFX_ADDFORM_INCLUDED)
Captulo 9
#include "stdafx.h"
#include "Curso9B.h"
#include "addform.h"
//
150
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CAddForm, CDaoRecordView)
BEGIN_MESSAGE_MAP(CAddForm, CDaoRecordView)
//{{AFX_MSG_MAP(CAddForm)
ON_COMMAND(ID_RECORD_ADD, OnRecordAdd)
ON_COMMAND(ID_RECORD_REFRESH, OnRecordRefresh)
ON_COMMAND(ID_RECORD_DELETE, OnRecordDelete)
ON_UPDATE_COMMAND_UI(ID_RECORD_FIRST, OnUpdateRecordFirst)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CAddForm::CAddForm(UINT nIDTemplate)
: CDaoRecordView(nIDTemplate)
{
//{{AFX_DATA_INIT(CAddForm)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_bAddMode = FALSE;
}
CAddForm::~CAddForm()
{
}
BOOL CAddForm::OnMove(UINT nIDMoveCommand)
{
CDaoRecordset* pRecordset = OnGetRecordset();
if (m_bAddMode)
{
if (!UpdateData())
return FALSE;
try
{
pRecordset->Update();
}
catch (CDaoException* e)
{
e->ReportError();
e->Delete();
return FALSE;
}
pRecordset->Requery();
UpdateData(FALSE);
m_bAddMode = FALSE;
return TRUE;
}
else
{
return CDaoRecordView::OnMove(nIDMoveCommand);
}
Prof. Andr Bernardi
Captulo 9
151
}
BOOL CAddForm::RecordAdd()
{
// If already in add mode, then complete previous new record
if (m_bAddMode)
OnMove(ID_RECORD_FIRST);
OnGetRecordset()->AddNew();
m_bAddMode = TRUE;
UpdateData(FALSE);
return TRUE;
}
BOOL CAddForm::RecordDelete()
{
if (IDYES==AfxMessageBox("Voc tem certeza que deseja prosseguir a
excluso?", MB_ICONQUESTION|MB_YESNO))
{
CDaoRecordset* pRecordset = OnGetRecordset();
try
{
pRecordset->Delete();
}
catch (CDaoException* e)
{
e->ReportError();
e->Delete();
return FALSE;
}
// Move to the next record after the one just deleted
pRecordset->MoveNext();
// If we moved off the end of file, then move back to last record
if (pRecordset->IsEOF())
try
{
pRecordset->MoveLast();
}
catch (CDaoException* e)
{
pRecordset->SetFieldNull(NULL);
e->ReportError();
e->Delete();
return FALSE;
}
// If the recordset is now empty, then clear the fields
// left over from the deleted record
if (pRecordset->IsBOF())
{
pRecordset->SetFieldNull(NULL);
}
UpdateData(FALSE);
}
return TRUE;
}
BOOL CAddForm::RecordRefresh()
{
if (m_bAddMode == TRUE)
Prof. Andr Bernardi
Captulo 9
{
OnGetRecordset()->CancelUpdate();
OnGetRecordset()->Move(0);
m_bAddMode = FALSE;
}
// Copy fields from recordset to form, thus
// overwriting any changes user may have made
// on the form
UpdateData(FALSE);
return TRUE;
}
void CAddForm::OnRecordAdd()
{
RecordAdd();
}
void CAddForm::OnUpdateRecordFirst(CCmdUI* pCmdUI)
{
if (m_bAddMode)
pCmdUI->Enable(TRUE);
else
CDaoRecordView::OnUpdateRecordFirst(pCmdUI);
}
void CAddForm::OnRecordRefresh()
{
RecordRefresh();
}
void CAddForm::OnRecordDelete()
{
RecordDelete();
}
BOOL CAddForm::Gravar()
{
CDaoRecordset* pRecordset = OnGetRecordset();
if (m_bAddMode)
{
OnMove(ID_RECORD_LAST);
return OnMove(ID_RECORD_LAST);
}
if (pRecordset->IsBOF() || pRecordset->IsEOF())
return FALSE;
pRecordset->Edit();
if (!UpdateData())
return FALSE;
try
{
pRecordset->Update();
}
catch (CDaoException* e)
{
e->ReportError();
e->Delete();
return FALSE;
}
return TRUE;
}
Prof. Andr Bernardi
Captulo 9
152
153
void CAddForm::OnInitialUpdate()
{
CDaoRecordView::OnInitialUpdate();
}
Captulo 9
154
2 Observaes
1. As mdias devem ser calculadas utilizando as frmulas que so obtidas no
manual do aluno.
2. Utilizar os exemplos do curso como base para a criao desse programa.
3. Gerar uma verso Release do programa para entrega.
155
Bibliografia
1
Bibliografia consultada
Os seguintes referncia foram utilizadas como base para a construo dessa apostila:
Bibliografia