Introdução à Engenharia - Engenharia de Processamento Digital II

Transcrição

Introdução à Engenharia - Engenharia de Processamento Digital II
L
U
I
S
F
E
R
N
A
N
D
O
E
S
P
I
N
O
S
A
C
O
C
I
A
N
6. Tratamento de Exceções
As exceções são situações anómalas que requerem de um tratamento
especial e não tem porque ser consideradas como erros. Ao conseguir dominar
toda a programação a qualidade das aplicações que se desenvolvme aumenta
consideravelmente.
O funcionamento geral do mecanismo de emissão e tratamento das
exceções é o seguinte:
1. Existe um método que invoca a execução de outro.
2. O método mais interno se encontra em uma situação que pode ser
considerada como excepcional. Portanto emite uma exceção.
3. Neste momento o termina a execução do método mais interno e se
retorna imediatamente ao método invocador.
4. O método invocador deve capturar a exceção e tratá-la. Parte do
tratamento da exceção pode ser voltar a emití-la ao método que a
invocou.
A correta programação das exceções significa desenhar os algoritmos
pensando unicamente na forma habitual em que se deve executar, manipulando
as situações extraordinárias à parte. Desta forma se consegue um desenho muito
mais estuturado, legível, robusto e fácil de manter.
EXEMPLO – ALOCAÇÃO DINÂMICA DE MEMÓRIA
Quando se solicita a alocação de memória do sistema, é habitual que
exista suficiente e que náo haja nenhum problema. Mas se for necessário realizar
uma aplicação robusta deve-se levar em conta a eventualidade de que dita
memória não seja concedida o qual pode complicar enormemente o algoritmo
mais simples.
Veja a seguir uma função escrita na linguagem C que simplesmente tenta
alocar memória de forma dinâmica para três números inteiros:
#include <stdlib.h>
#include <stdio.h>
//--------------------------------------------------------------------------void SemExecoes(void);
//--------------------------------------------------------------------------void main(void)
{
140
E
N
G
E
N
H
A
R
I
A
D
E
P
R
O
C
E
S
S
A
M
E
N
T
O
D
I
G
I
T
A
L
I I
SemExecoes();
}
//--------------------------------------------------------------------------void SemExecoes(void){
int *p1, *p2, *p3;
p1 = (int*) malloc(sizeof(int));
if (p1 == NULL){
printf("Não há memória suficiente");
abort();
}
if (p2 == NULL){
printf("Não há memória suficiente");
abort();
}
if (p3 == NULL){
printf("Não há memória suficiente");
abort();
}
}
//---------------------------------------------------------------------------
Programando em C++ e fazendo uso das exeções:
#include <stdlib.h>
#include <stdio.h>
//--------------------------------------------------------------------------void ComExecoes(void);
//--------------------------------------------------------------------------void main(void){
ComExecoes();
}
//--------------------------------------------------------------------------void ComExecoes(void){
int *p1, *p2, *p3;
try {
p1 = new int; // Comportamento normal.
p2 = new int;
p3 = new int;
}
catch(...){ // Comportamento excepcional.
printf("Não há memória suficiente");
abort();
}
}
//---------------------------------------------------------------------------
A norma ANSI C++ especifica que se uma instrução new falhar (porque
não há memória disponível) deve ser emitida uma exceção bad_alloc. As
instruções que podem provocar a emissão de uma exeção ou zona crítica se
englobam dentro de um bloco try{}. Se alguma das instruções do bloco try{}
provocarem uma exeção, o fluxo do programa vai até o final do bloco buscando
um bloco catch(...){} que capture a exeção (se não a encontrar, o programa
termina). Neste caso, a instrução catch(...){} captura qualquer exeção, e em
particular, a exeção bad_alloc. O tratamento se efetua neste caso é a
apresentaçào de uma mensagem de erro e se termina a execução do programa.
141
L
U
I
F
S
E
R
N
A
N
D
O
E
S
P
I
N
O
S
A
C
O
C
I
A
N
EXEMPLO – ALOCAÇÃO DIVISÃO POR ZERO
O seguinte programa lê dois valores e calcula o quociente entre ambos. Se
o divisor for zero tenta-se fazer a divisão e o programa emite uma exeção de
divisão por zero (EZeroDivide).
Para executar este exemplo crier um novo projeto com a opção de menu
File + New Application. Usando o Gerenciador de Projetos remova os arquivos da
Unit1 com o botão direito do mouse encima da mesma, selecionar Remove from
project.
Dentro do arquivo Project1.cpp apague tudo o que estiver ali e insira o
seguinte código:
//---------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
AnsiString Valor;
float Dividendo, Divisor, Quociente;
// Lê dados de entrada: dividendo e divisor
Valor = InputBox ("Divisão", "Dividendo", ""); // Lê o dividendo e
Dividendo = StrToFloat (Valor);
// converte-o em float.
Valor = InputBox ("Divisão", "Divisor", "");
// Lê o divisor e
Divisor = StrToFloat (Valor);
// converteo em float.
// Calcula quociente. Zona critica: perigo se Divisor for igual a 0
Quociente = Dividendo / Divisor;
// Mostrar o resultado
ShowMessage ("Quociente = " + AnsiString(Quociente));
return (0);
}
//----------------------------------------------------------------
142
E
N
G
E
N
H
A
R
I
A
D
E
P
R
O
C
E
S
S
A
M
E
N
T
O
D
I
G
I
T
A
L
I I
Execute o projeto, e quando aparecer a janela de salvar, salve como
zero.bpr.
Depois de salvo, o projeto é executado abrindo duas janelas de inserção
para os valores de dividendo e divisor e uma janela de apresentação do resultado.
O programa não supõe o tratamento da exceção no caso do usuário inserir
o valor 0 no divisor. Se isto porventura venha a acontecer se produzirá uma
exeção, e por não ser tratada pelo programa, o entorno de programação (IDE do
Builder C++) se encarregará dela.
143
L
U
I
S
F
E
R
N
A
N
D
O
E
S
P
I
N
O
S
A
C
O
C
I
A
N
Figura 6-1 - Janela de erro que surge devido a uma exeção EzeroDivide não tratada.
Se for executado diretamente o arquivo executável for a do ambiente de
programação, o sistema operacional irá reagir ao erro da seguinte forma:
Se o usuário pressionar o botão Debug aparece a seguinte janela horrível
(caso ele tenha instalado o Bulder C++, Visual C++ ou algum outro software de
depuração de baixo nível):
144
E
N
G
E
N
H
A
R
I
A
D
E
P
R
O
C
E
S
S
A
M
E
N
T
O
D
I
G
I
T
A
L
I I
O Windows XP pergunta ao usuário se quiser enviar os dados do erro para
a Microsoft. Se ele quiser ver o que será enviado, ele pode selecionar a opção
click here.
145
L
U
I
S
F
E
R
N
A
N
D
O
E
S
P
I
N
O
S
A
C
O
C
I
A
N
Resumindo em poucas palavras, fica horrível para o usuário ter que se
defrontar com este tipo de problema, mais ainda se ele pagou pelo software. Um
errinho imbecil deste tipo (feito pelo próprio usuário) porém não protegido pelo
programador, pode fazer que um programa hiper complexo seja tratado como um
programa “porcaria” pelo usuário (injustamente, é claro).
Para proteger a instrução crítica, capturar e tratar a exeção, instroduzir a
seguinte modificação:
try{
Quociente = Dividendo / Divisor;
ShowMessage ("Quociente = " + AnsiString(Quociente));
}
catch (...) {
ShowMessage ("O divisor não pode ser zero.");
Application->Terminate();
}
Para ceder o controle do gerenciamento de exeções a nosso programa deve
se desabilitar a opção pela qual o entorno integrado gerencia as interrupções e
indicar que serão gerenciadas pelo programa. Para isto, selecionar a opção de
menu Tools + Debugger Options e na aba OS Exceptions modificar de acordo com
a Figura 6-2 (retirar a seleção do item Integrated debugging no canto inferior
esquerdo).
Figura 6-2 – Janela Debugger Options
146
E
N
G
E
N
H
A
R
I
A
D
E
P
R
O
C
E
S
S
A
M
E
N
T
O
D
I
G
I
T
A
L
I I
Assim, é indicado ao depurador do C++Builder que o nosso programa se
encarregará de gerenciar as exeções C++ que possam chegar a ocorrer. Agora ao
executar o programa e introduzindo o valor 0 como divisor aparecerá a janela a
seguir:
Depois disto, o programa sera encerrado.
6.1. Emissão de Exceções
A emissão de uma exceção se realiza usando a função throww(). Quando
se emite uma exceção, em realidade o que se faz é criar um objeto de uma classe
que se indique a throw() que será a própria exceção em si. Costuma ser bastante
útil criar classes de exceções próprias para controlar as situações anómalas de
nossa aplicação. Para ilustrar a emissão de exceções, usaremos o projeto POOEx.
Em ObjGraph.h coloque o seguinte código antes da declaração da classe
TObjGraf:
//--------------------------------------------------------------------------// Definição da classe EForaFaixa
// Classe de exceção por ficar “fora da faixa” de visualização:
// sair dos limites do objeto PaintBox ao calcular
// as novas coordenadas do desenho da bola.
class EForaFaixa{};
//---------------------------------------------------------------------------
Agora podem ser emitidas exceções da seguinte maneira:
throw EForaFaixa();
Mesmo que as exeções sejam classes, em C++ Builder existe a convenção
de que o seu nome comece pela letra E e não por T como o resto das classes.
Mesmo que no exemplo anterior, a classe criada para a exceção não tem nenhum
membro (propriedades e métodos), esses poderão ser adicionados. Eles servirão
para poder incorporar informações no objeto de exceção sobre a situação em que
foi produzida a exceção e poderão ser usados pela seção de código que as trate.
Por exemplo, se houver um método que emite uma exceção por falta de
memória pode ser interessante incorporar uma propriedade que indique qual foi
a máximo tamanho de memória disponível quando foi emitida a exceção.
147
L
U
I
S
F
E
R
N
A
N
D
O
E
S
P
I
N
O
S
A
C
O
C
I
A
N
6.2. Especificação de Exceções
A linguagem C++ conta com uma característica denominada especificação
de exceções, que serve para enumerar, em uma declaração, as exceções que
pode emitir um determinado método. Se quisermos que um método possa emitir
um determinado tipo de exceção deve se especificar dessa forma. Alterar como
segue em ObjGraf.h, dentro da classe TObjGraf:
//--------------------------------------------------------------------------// Definição da classe TObjGraf
//--------------------------------------------------------------------------class TObjGraf {
private:
unsigned int unFX; // foram alterados os nomes
unsigned int unFY; // de unX para unFX e unY para unFY
void SetX(unsigned int _X) throw (EForaFaixa); //
//
void SetY(unsigned int _Y) throw (EForaFaixa); //
//
Se houver algum
problema é criado
um objeto da classe
EForaFaixa
virtual int GetLargura (void) = 0; // Método virtual puro
virtual int GetAltura (void) = 0; // Método virtual puro
…
Em ObjGraf.cpp:
//--------------------------------------------------------------------------// Funções de escrita das propriedades virtuais unX e unY
void TObjGraf::SetX(unsigned int _X) throw (EForaFaixa)
{
if (_X < 0){ // Coordenada negativa
unFX = 0; // Ajustar para a margem esquerda
throw EForaFaixa(); // Emitir uma exeção
}
else{
if (_X > (PaintBox->Width - unLargo)){ // Alta demais
unFX = PaintBox->Width - unLargo;// Ajustar para a margem
// direita
throw EForaFaixa(); // Emitir uma exeção
}
else{
unFX = _X; // Correto: escrever sem modificar
}
}
}
//--------------------------------------------------------------------------void TObjGraf::SetY(unsigned int _Y) throw (EForaFaixa)
{
if (_Y < 0){ // Coordenada negativa
unFY = 0; // Ajustar a margem superior
throw EForaFaixa(); // Emitir uma exeção
}
else{
if (_Y > (PaintBox->Height - unAlto)){ // alto demais
unFY = PaintBox->Height - unAlto;// Ajustar para a margem
//inferior
throw EForaFaixa(); // Emitir uma exeção
}
else{
unFY = _Y; // Correto: escrever sem modificar
}
}
148
E
N
G
E
N
H
A
R
I
A
D
E
P
R
O
C
E
S
S
A
M
E
N
T
O
D
I
G
I
T
A
L
I I
}
//---------------------------------------------------------------------------
6.3. Captura de Exceções
O bloco suscetível de produzir alguma exceção (zona crítica) se coloca
dentro de um bloco try{}, e a captura (discriminação da exceção que foi
produzida) se efetua em uma instrução catch e o seu processamento se realiza a
continuação no bloco catch.
try{
<bloco de instruções críticas>
}
catch(<tipo exceção1> <variável>){
<manipulador1>
}
catch(<tipo exceção2> <variáve2>){
<manipulador2>
}
...
Pode se especificar tantos blocos catch para um bloco try quando forem
necessários. No momento que ocorra uma exceção se executará o bloco catch
cuja classe concorde com a da exceção. Se for expecificado catch(...) se
capturará qualquer exceção.
A exceção não tem por que ser emitida explicitamente no bloco try senão
como conseqüência da execução de uma função chamada dentro desse bloco.
Alterar em ObjGraf.cpp:
//--------------------------------------------------------------------------void TBola::Mover (void)
{
Apagar ();
try{
unX += FDirX * Velocidade;
}
catch(EForaFaixa){
FDirX = -FDirX;
}
try{
unY += FDirY * Velocidade;
}
catch(EForaFaixa){
FDirY = -FDirY;
}
Mostrar ();
}
//---------------------------------------------------------------------------
Neste exemplo, a instrução crítica:
unX += FDirX * Velocidade;
traduzida em:
149
L
U
I
F
S
E
R
N
A
N
D
O
E
S
P
I
N
O
S
A
C
O
C
I
A
N
unX = unX + FDirX * Velocidade;
e como unX é uma propriedade virtual, na realidade trata-se de fazer:
SetX(unX + FDirX * Velocidade)
Onde se observa que é o método SetX() quem pode provocar a emissão da
exceção.
Em UPrincipal.cpp colocar a seguinte declaração global:
TBola *Bola;
Modificar as funções FormCreate() e FormDestroy() para que fiquem da
seguinte maneira:
//--------------------------------------------------------------------------void __fastcall TFrmPrincipal::FormCreate(TObject *Sender)
{
Bola = new TBola (PaintBox, clYellow, 120, 70, 25);
}
//--------------------------------------------------------------------------void __fastcall TFrmPrincipal::FormDestroy(TObject *Sender)
{
delete Bola;
}
//---------------------------------------------------------------------------
Eliminar o gerenciador para o evento OnPaint do componente PaintBox
(apagando o corpo da função tão somente).
Adicionar ao FrmPrincipal um objeto TTimer (aba System) e fixar a
propriedade Interval = 100.
No evento OnTimer colocar:
//--------------------------------------------------------------------------void __fastcall TFrmPrincipal::Timer1Timer(TObject *Sender)
{
Bola->Mover();
}
//---------------------------------------------------------------------------
Neste ponto o projeto deve estar como mostra a Figura 6-310.
Figura 6-3 - Dois instantes de movimento da bola.
10 O entorno deve estar configurado para que o programa gerencie as exceções e não o entorno de programação. Se não
estiver assim configurado, selecionar Tools + Debugger Options, abrir a aba OS Exceptions e configurar como mostra a
Figura 6-2.
150
E
N
G
E
N
H
A
R
I
A
D
E
P
R
O
C
E
S
S
A
M
E
N
T
O
D
I
G
I
T
A
L
I I
Executando o programa, quando a bola chegar ao limite do componente
TPaintBox haverá a emissão de uma exceção como mostra a figura a seguir.
O entorno deve estar configurado para que o programa gerencie as
exceções e não o entorno de programação. Se não estiver assim configurado,
selecionar Tools + Debugger Options, abrir a aba OS Exceptions e configurar como
mostra a Figura 6-2.
6.4. Exceções não Tratadas
Se uma exceção que foi emitida não encontrar um manipulador apropriado,
será chamada a função terminate(), que por default realiza um abort().
Entretanto pode se definir uma função própria terminate() com set_terminate().
Uma coisa parecida ocorre se um método emite uma exceção de um tipo
não listado na especificação de exceções, então se chama a função unexpected()
que por default chama a função terminate(). Da mesma maneira que com
terminate() pode se definir a função unexpected() própria com set_unexpected().
151
L
U
I
F
S
E
R
N
A
N
D
O
E
S
P
I
N
O
S
A
C
O
C
I
A
N
6.5. Exceções da VCL
Quando se utilizam componentes da VCL as aplicações é necessário
compreender o mecanismo de tratamento de exceções da VCL. O motivo é que as
exceções estão integradas em numerosas classes e se emitem automaticamente
quando se apresenta uma situação inesperada. Se não se realiza um tratamento
da exceção , a VCL levará a cabo um tratamento default. Normalmente aparece
uma mensagem que descreve o tipo de erro que foi produzido.
6.5.1. Classes de Exceções
O C++ Builder incorpora um extenso conjunto de classes de exceção
integradas que permitem tratar automaticamente os erros de divisão por zero, de
entrada/saída de arquivos, conversões de tipos e muitas outras situações
anómalas. Todas as classes de exceção da VCL derivam de um objeto raíz
chamado Exception, que encapsula as propriedades e métodos fundamentais
para todas as exceções por parte das aplicações.
6.5.2. Tratamento de Exceções da VCL
As exceções de tipo VCL, assim como todas as classes da VCL, devem
estar localizadas no heap (criação dinâmica) e por isso deve se ter em conta o
seguinte:
As classes de exceção do tipo VCL somente podem ser capturadas por ponteiro ou
por referência (preferencialmente).
As exceções do tipo VCL devem ser emitidas com sintaxe “por valor”.
As exceções podem ser passadas a um bloco catch que toma um
parämetro do tipo Exception. Utilizar a seguinte sintaxe para capturar as
exceções da VCL:
catch(const exception_class & exception_variable)
Se especifica a classe de exceção que se deseja capturar e se proporciona
uma variável por meio da qual se faz referência à exceção. Por exemplo:
//-------------------------------------------------------#include <vcl.h>
#pragma hdrstop
//-------------------------------------------------------WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try {
throw Exception("Minha exceção VCL");
}
152
E
N
G
E
N
H
A
R
I
A
D
E
P
R
O
C
E
S
S
A
M
E
N
T
O
D
I
G
I
T
A
L
I I
catch (const Exception & E) {
ShowMessage("Classe da exceção capturada: " +
AnsiString(E.ClassName()) + "\nMessage: " + E.Message);
}
return (0);
}
//--------------------------------------------------------
A sentença throw do exemplo anterior cria uma instância da classe
Exception e chama o seu construtor. Todas as exceções que descendem de
Exception contam com uma mensagemque se pode apresentar na tela, passar aos
construtores e serem recuperadas mediante a propriedade Message. O resultado
do programa anterior é o mostrado na Figura 6-4.
Figura 6-4 - Ejemplo de lanzamiento y captura de excepción VCL.
6.5.3. Classes de Exceção Tipicas
Mesmo que as exeções não necessariamente indiquem um erro na
execução de uma aplicação, as exceções da VCL costumam ser erros sim. Veja a
seguir uma lista das classes de exceção mais utilizadas em C++ Builder.
Classe
Descrição
EAccessViolation
Erro de acceso à memoria.
EDatabaseError
Especifica um erro de aceso à base de dados.
EDBEditError
Dados incompatíveis com uma máscara especificada.
EDivByZero
Captura erros de divisão por zero (para divisão inteira e real,
EZeroDivide
respectivamente).
EInOutError
Representa um erro de E/S de arquivo.
EInvalidPointer
Operações não válidas com ponteiros.
EPrinterError
Indica um erro de impressão.
Mesmo que todas essas classes funcionem da mesma maneira, cada uma
delas possui particularidades derivadas da exceção concreta que elas indicam.
EXEMPLO – DIVISÃO POR ZERO [2]
O seguinte programa é uma ampliação do projeto de divisão anteriormente
colocado. Neste exemplo se discriminam distintas exceções.
//--------------------------------------------------------------------#include <vcl.h>
153
L
U
I
S
F
E
R
N
A
N
D
O
E
S
P
I
N
O
S
A
C
O
C
I
A
N
#pragma hdrstop
//--------------------------------------------------------------------WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
AnsiString Valor;
float Dividendo, Divisor, Quociente;
float sigo = true;
while (sigo) {
try {
// Ler e converter dividendo
Valor = InputBox ("Divisão", "Dividendo", "");
Dividendo = StrToFloat (Valor);
if (Dividendo == 0) {
sigo = false;
}
else {
// Ler e converter divisor
Valor =InputBox ("Divisão", "Divisor", "");
Divisor = StrToFloat (Valor);
Quociente = (Dividendo / Divisor);
ShowMessage ("Quociente = " + AnsiString(Quociente));
}
} // try
// Se captura se foi realizada uma divisão por zero.
catch (EZeroDivide & ) {
ShowMessage ("O divisor não pode ser zero.");
}
// Mais geral: se alcanza se não se captura a anterior.
catch (Exception & e) {
ShowMessage ("Se produziu uma exceção: " +
AnsiString(e.ClassName())+
"\n
" + e.Message);
}
} // while sigo
return (0);
}
//---------------------------------------------------------------------
Se for tentado realizar uma divisão por zero, o resultado é o indicado na
Erro! Fonte de referência não encontrada..
154
E
N
G
E
N
H
A
R
I
A
D
E
P
R
O
C
E
S
S
A
M
E
N
T
O
D
I
G
I
T
A
L
I I
Agora, se for introduzido um dado incorreto, a função StrToFloat() emite
uma exceção EConvertError que se captura no último bloco catch. Ver a Figura
6-5.
Figura 6-5 - Exemplo de entrada incorreta.
Mais ainda, se for produzido algum tipo de overflow também pode ser
controlado com o último bloco catch, como mostra a Figura 6-6.
(a)
(b)
Figura 6-6 - Exemplos de overflow: a) na entrada de dados e b) no cálculo do quociente.
155
L
U
I
S
F
E
R
N
A
N
D
O
E
S
P
I
N
O
S
A
C
O
C
I
A
N
Para finalizar, adicionar o seguinte bloco catch entre os dois anteriores e
considerar (uma parte da) a hierarquia das classes de exceções:
TObject-->Exception-->EExternal-->EMathError-->(EZeroDivide, EOverflow, ...)
catch (EMathError & e) {
ShowMessage ("Operação inválida: " + e.Message);
}
(a)
(b)
Figura 6-7 - Outra maneira de capturar overflows: a) na entrada de dados e b) no cálculo do quociente.
EXERCÍCIO – UM REPRODUTOR DE SONS
Neste exemplo se criará uma quadro que conterá um
componente MediaPlayer que servirá para reproduzir arquivos .WAV.
Será utilizado o gerenciamento de exceções para controlar a correta
execução do programa.
O primeiro passo é criar e configurar o projeto. Para isto usar a opção File
+ New Application. Salvar em nova pasta com a opção de menu File + Save
Project As... Salvar como UPrincipal.cpp (Unit1.cpp) e Som.bpr (Project1.bpr).
A seguir, configurar o quadro para aparecer como mostra a seguinte
figura:
156
E
N
G
E
N
H
A
R
I
A
D
E
P
R
O
C
E
S
S
A
M
E
N
T
O
D
I
G
I
T
A
L
I I
Alterar o título do quadro (Caption) para Sons e adicionar os seguintes
componentes:
Quatro botões normais (TButton) chamados (Name): LogoffBtn, MSSoundBtn,
ErrorBtn e OutrosBtn com o texto (Caption) como indicado na figura anterior.
Um botão BitBtn para terminar o programa.
Um controle MediaPlayer (aba System) não-visível (Visble = false).
Um quadro de diálogo OpenDialog (aba Dialogs).
A seguir, escreveremos os gerenciadores de eventos associados à pulsação
dos botões. O gerenciamento das interrupções capturadas (exceções) será
realizada com uma função comum cujo protótipo é:
void Erro(AnsiString & name, Exception & e);
Esta função é declarada acima de todas as funções em UPrincipal.cpp. Os
gerenciadores dos eventos OnClick associados aos botões serão os seguintes:
//--------------------------------------------------------------------------void __fastcall TForm1::LogoffBtnClick(TObject *Sender)
{
MediaPlayer1->FileName = "C:\\WINDOWS\\MEDIA\\Windows XP Logoff
Sound.wav";
try {
MediaPlayer1->Open();
MediaPlayer1->Wait = true;
MediaPlayer1->Play();
MediaPlayer1->Close();
}
catch (Exception & e) {
Erro(MediaPlayer1->FileName, e);
}
}
//--------------------------------------------------------------------------void __fastcall TForm1::MSSoundBtnClick(TObject *Sender)
{
MediaPlayer1->FileName = "C:\\WINDOWS\\MEDIA\\Windows XP Startup.wav";
try {
MediaPlayer1->Open();
MediaPlayer1->Wait = true;
MediaPlayer1->Play();
MediaPlayer1->Close();
}
catch (Exception & e) {
Erro(MediaPlayer1->FileName, e);
157
L
U
I
S
F
E
R
N
A
N
D
O
E
S
P
I
N
O
S
A
C
O
C
I
A
N
}
}
//--------------------------------------------------------------------------void __fastcall TForm1::ErrorBtnClick(TObject *Sender)
{
MediaPlayer1->FileName = "C:\\WINDOWS\\MEDIA\\NaoHa.wav";
try {
MediaPlayer1->Open();
MediaPlayer1->Wait = true;
MediaPlayer1->Play();
MediaPlayer1->Close();
}
catch (Exception & e) {
Erro(MediaPlayer1->FileName, e);
}
}
//--------------------------------------------------------------------------void __fastcall TForm1::OutrosBtnClick(TObject *Sender)
{
if (OpenDialog->Execute()){
MediaPlayer1->FileName = OpenDialog->FileName;
try {
MediaPlayer1->Open();
MediaPlayer1->Wait = true;
MediaPlayer1->Play();
MediaPlayer1->Close();
}
catch (Exception & e) {
Erro(MediaPlayer1->FileName, e);
}
} // if (OpenDialog1->Execute())
}
//--------------------------------------------------------------------------void Erro(AnsiString & name, Exception & e){
ShowMessage ("Falha na reprodução do arquivo de som: " + name +
"\nExceção: " + AnsiString(e.ClassName()) +
"\nDetalhes: " + AnsiString(e.Message));
}
//--------------------------------------------------------------
Quando o programa é executado e for apertado o botão Erro (supõe-se que
o arquivo não existe) aparecerá a seguinte janela de mensagem:
158

Documentos relacionados

Aula 16 - Exceções

Aula 16 - Exceções • Exceção é um desvio no fluxo de execução normal do programa • Indica que houve problema na execução de um bloco do programa • Se não for tratado, programa pode parar • O uso correto de exceções t...

Leia mais