quinta-feira, 22 de fevereiro de 2007

Animador vs animação

Olá olá olá olá.

Mais um vídeo totalmente louco que eu encontrei no YT (youtube).

Animator vs animation (animador vs aminação):



Virou favorito na hora!

Abraços.

Artigo completo (View Full Post)

Envelope

Para ter um melhor entendimento vamos falar um pouco do dB.

Decibéis

A percepção do volume está relacionada à variação de pressão gerada por uma onda sonora e, portanto, à sua intensidade.

Nosso sistema auditivo tem dois limites de audibilidade:

- limiar de audibilidade (mínima intensidade audível)
- limite de dor (máximo nível de intensidade audível sem danos fisiológicos ou dor).

Do ponto de vista auditivo, o dB é mais interessante de se estudar do que sob a matemática.

O ouvido com sua não-linearidade, oferece algumas surpresas e inocoêrencias. O interessante do lado matématico é que razões (divisões) enter potência dão origem a diferenças (subtrações) de nível.

A gama entre os 2 limites é muito grande. Para uma frequência pura de 1000 Hz, esses limites vão de 10-12 watt/m2 a 1 watt/m2, ou seja, uma razão de 1 trilhão para 1.

Numericamente, a referência em watt/m2 não é confortável. Para isso foi introduzida uma razão de compressão logarítmica, o decibel (dB).

DECIBEL é uma relação logaritmica entre duas potências ou intensidades.

dB = 10 log10 (I1/I2)


A cada 3dB a Intensidade dobra: I + I --> 10 log (2/1) = 10* 0,301= 3dB.

Percebendo os decibéis

1 dB, para volumes altos e confortável para audição, é a mínima variação de volume perceptível pela média das pessoas sadias. Mas, a volumes baixos, a mesma razão de 1 dB é totalmente imperceptível.

Ou seja, no rádio de pilha no meio da poluição sonora será imperceptível.

Sistemas de P.A(Public Address) de casas de show ou em estúdios de gravação esta variação é mínima.

Usamos escalas logarítmicas em Áudio porque a resposta do nosso mecanismo de audição é proporcional ao logarítmo da razão entre frequências e também a logarítmo da razão entre amplitudes.

Para ter um bom entendimento do envelope, precisamos endender como nosso ouvido responde as pressões sonoras.

Nosso comportamento auditivo

A extenção de níveis que somos capazes de ouvir é de 0 dBSPL a 130 dBSPL.Ou seja, a maior pressão acústica que podemos suportar é aproximadamente 32 milhões de vezes maior que a menor pressão acústica que conseguimos perceber. E, mais impressionante e que a relação entre as potências dissipada por estes extremos é de 10 trilhões.

A nosso audição reage a variações de nível em uma escala logarítmica.A cada vez que quizermos perceber uma dobra aparente no volume de um sinal de teste, teremos que aumentar a potência dissipada em dez vez.Ou seja, a intervalos interpretados como iguais pela nossa percepção, equivalem a intervalos à (razão de 10x) na potência dissipada pelo sinal.

y = 10Ex logo log y = x, na base 10

A nossa audição também reage em uma escala logarítimica a variações de frequência. A intervalos interpretados como iguais pela percepção,oitavas na escala musical, equivalem em intervalos cada vez maiores(à razão de 2x).

y = 2E logo log = y, na base 2.

Obs: 1 oitava corresponde ao dobro da frequência.

Sub-graves: até 80Hz(2 oitavas)
Graves: de 80 a 200 Hz(4/3 oitavas)
Médios-graves de 200 a 630 Hz(5/3 oitavas)
Médios: de 630 a 2 KHz(5/3 oitavas)
Médios agudos: de 2 a 6,3 KHz(1 oitava)
Super-agudos: acima de 12,5 KHz(2/3 oitavas)


O decibel, puramente, é uma medida comparativa entre duas potências. E pode ser expressa em dB, por: dB = 10.log p2/p1

Para o ouvido cada aumento de 10dB da a sensação de o dobro do volume. Então a mudança de 10 watts para 100 watts é sentida como o dobro do volume de som; para dobrar novamente, precisaríamos de mais 10 dB - isto é 1000 watts.Isso não depende de nós, e sim o que teremos que perder.
Pare e pense... 1000 watts a 1 m de distância do boneco, dissipada pelo falante.
Deve ser de ensurdecer rsrsrsr.

PMPO: Potência média para otários. Não tome como referência.

Potência máxima de alguns instrumentos
InstrumentoPotência Máxima (watt)Decibéis
clarinete0,0586
violoncelo0,1692
piano0,2794
trompete0,3194
trombone6,0107
bumbo(Kick)25,0113


Envelope

O som de cada instrumento ,voz, animal ou ruído tem sua forma peculiar de começar, se manter por algum tempo, e se extinguir.Alguns começam suavemente,se mantêm por algum tempo e terminam de forma suave. Outros começam com forte impacto, duram pouco e se extinguem rapidamente.
O conjunto dessas variações dinâmicas do som de determinada fonte é denominado envelope. Este nome faz muito sentido, pois trata-se do envoltório imaginário das ondas que fazem parte do som.
O envelope típico tem quatro fases: Ataque(Attack), decaimento(decay), Sustentação(Sustain), e Relaxamento(release). Por esta razão, sintetizadores é comun encontrar um conjunto de controles denominado ADSR, que são as inicias dos componentes do envelope.

Espero ter ajudado.

Link na Wikipedia

Pedro Motta.

Artigo completo (View Full Post)

Para quem gosta de Jazz (para quem não gosta também)

Olá queridos freqüentadores. Espero que o carnaval tenha sido ótimo.

Eu descansei um pouco, mas já ouvi várias estórias de umas figuras :D

Bem, aqui vai o post... Eu acho que o Gerson vai gostar desse; e sugiro que até aqueles que não gostam muito de Jazz vejam também porque é divertido. Aí vai:



É isso aí. Boa diversão.

Artigo completo (View Full Post)

quarta-feira, 21 de fevereiro de 2007

Editores de Partituras, Notação Musical

Um exemplo de como fazer, ou editar uma partitura no computador.

Assim como existe o Word e o Open Officce, softwares para edição de texto, existe também os voltados para edição de partituras. Os mais conhecidos e utilizados pela maioria dos músicos aqui no Brasil são o Encore, Finale e o Sibelius.

Overview

Esses softwares são ferramentas poderosas que auxiliam o trabalho de composição e construção de partituras, desde de simples partes de seção rítmica, baseadas em cifragem, até grades super-complexas para orquestra sinfônica. Ao mesmo tempo que o compositor está escrevendo (quero dizer, digitando) sua composição ele pode ouvi-la, no timbre do(s) instrumento(s) para o qual está compondo. Conta Também com recurso de transposição automática e mais um monte de funcionalidades. Basta dar uma olhada nesses links para maiores detalhes:


http://www.finalemusic.com/finale/preview_flash.aspx?mv=new_features&vers=fin2006

http://www.finalemusic.com/finale/preview.aspx

http://www.musicprep.com/sibelius/


Vamos tentar um exemplo no Encore, pois este é o único que tenho disponível na maq agora.

Tudo aqui é bem semelhante ao um editor de texto. Por exemplo, no menu “File” vc, assim como no Word, abre, fecha, ou salva um arquivo. Configura a página e impressão. Um item de menu para uma forma de exportar o arquivo, em seguida uma listagem das últimas edições que vc fez. O último item de menu é o sair.

Vou escolher a opção New do menu “File” (Costumo suar muito as teclas de atalho, “CTRL + N”, neste caso). Na configuração de página (Choose Page Layout) vc define quantas linhas deseja por página, quantos pentagramas por linha e quantos compassos por linha. Na área “Staf Format” definimos se desejamos um layout de parte de piano (dois pentagramas agregados. O de baixo, clave de Fá. E o de cima, clave de Sol) ou um layout simples. Configure como exemplificado na figura abaixo.


Na figura acima estou configurando uma página com dez linhas, um pentagrama com quatro compassos por linha. Só que para isso tive que selecionar em “Staf Format”, single staves. Após digitar os valores conforme na figura acima click “Ok”.

Eu não gosto muito do Encore, tenho sérias restrições quanto a ele. Ele é muito engessado, me parece que ele usa API do Windows 3.1.1 ainda, isso é bizarro, muito feio. Não gosto da usabilidade de também, a tela não rola com o scroll do mouse (Creeeeeedooooo). Os caras da GVox deveria estudar mais HCI.

Agora temos o novo arquivo prontinho para ser editado. Esse formatação de 4 compassos por linha torna a partitura mais legível pq na leitura musical não lemos como na leitura de textos palavra por palavra, lemos grupos de compassos que possuem um sentido completo (uma idéia completa). São raros os trechos musicais (isso, levando em consideração a música ocidental) em que essas estruturas com sentido completo não sigam sempre uma métrica de quadratura.


No menu “Measures” iremos definir a armadura (Key Signature) e fórmula de compasso (Time Signature).


A música que escolhi é uma composição bem complexa. Todavia, muita ou puco complexidade é só um detalhe sem importância no nosso caso, visto que o objetivo aqui não é ensinar música. Portanto, prosseguindo ....

Esperando, é uma composição do Helio Delmiro, que mistura elementos do Jazz moderno (modulações a la Giants Steps. veja em: http://en.wikipedia.org/wiki/Giant_Steps) com elementos do que há de melhor na música brasileira. Escolhi essa música pq trata-se de uma pérola, e outro dia, após ouví-la insistentemente resolvi escrevê-la.

Logo nos compassos iniciais, embora a melodia soe bastante intuitiva e rítmicamente simples, a chapa começa a esquentar. E começam as coçadas na cabeça logo no início da análise. Tanto harmônica, quanto melódica. Nos seis primeiros compassos, praticamente cada um está num tom diferente (já fazem mais de 5 anos que deixei a teoria musical num canto escuro da memória), o que fazer numa situação dessas? Me esqueci .... HAUHAUHAU. Pelo que me lembro, na aula do Ian ele aconselhava conservar o trecho todo no tom original, caso fossem várias modulações que, sendo esse curto, no final do trecho retornam ao tom original. Contudo não tenho certeza disso. Vou verificar mais tarde.

Essa música é dividida em duas partes: A primeira parte é modal, predominando Mi maior (E). Já na segunda parte o tonalismo é bem marcante. Embora predomine Sol maior (G) ela inicia em lá menor, tendendo pro melódico. Todavia, a partir do compasso 14 inicia novamente uma seqüência de modulações num padrão, mantendo ao mesmo tempo uma relação melódica dentro dos elementos da segunda parte, e uma relação harmônica com os elementos da primeira, no meu mo de ver, já preparando o caminho de retorno à ela.

Então, mãos a obra .... a primeira parte tem 8 compassos. Esses, inicialmente manteremos em Mi maior (3 acidentes, sustenidos #, na armadura).



Para escolher a tonalidade click na barra de rolagem (scroll bar) que marquei num círculo vermelho. Observe o número de compassos que determinei para a abrangência da armadura de Mi maior (do compasso 1 ao 8).

No campasso 12 ao 15 estaremos em Sol maior.


Uma modulação curtíssima, nos compassos 16 e 17 passa pra Si maior (B).



Mais uma modulação, nos compassos 18 e 19 passa pra Mi bemol maior (Eb).


No 20 e 21 retorna pra Sol maior.


No 22, 23 e 24 volta pra Si maior (B), preparando no último compasso (24) para Mi maior, iniciando novamente a primeira parte.


Agora, pra facilitar o trabalho vou numerar os compassos.

No menu Measures Measures Numbers.


Eu sempre configuro: Each System (entenda a cada linha), e Enclose Number in Box (o Número fica dentro de uma caixa).



Vamos definer a fórmula de compasso. no meu Measures
Time Signature. A fórmula de compasso é a razão entre a unidade de tempo e unidade de compasso

Vc precisa da fórmula de compasso para ter a referência da relação entre o valor das figuras com o todo do tempo. Para que vc possa indicar qunto um som ou silêncio vai durar. Esse link tem uma explicação excelente, boladona. Pra quem deseja aprender Música, espero que ajude.

http://www.tomdamata.org.br/cancioneiro/ritmo.asp

Como em todas as gravações dessa música, a levada adotada foi de bossa, vou escrever em 2 por 4. Depois vou colocar uma versão e "C cortado" pros gringos poderem entender. Eles não conseguem conceber o 2/4. Veja a configuração abaixo:


Pô, Felipe, vc que fica me zuando com essa parada de post micro .... hehehe ... esse eh o menor de todos. Sobre tudo, o que é um flato pra quem já ta todo .... digamos ... sujo. hehehheh

Caramba!!!! Até que em fim ... Uff!!! Vamos começar e escrever de fato essa “parti”. Para colocar a cifra, no meu Windows Palette Graphics, vc visualiza a palheta com a opção de gráficos para cifragem.

Click na palheta na célula marcada com o círculo para cifragem, em seguida click sobre o compasso 1.

Na tela Choose Chord vc monta a cifragem do acorde. Como não existe um padrão definido para cifragem, ele apresenta pra vc um padrão americano. Pelo menos esse padrão é seguido pela maioria dos Real Books. Contudo, ele não engessa totalmente, note a opçãp custom , basta que vc selecione o acorde em root e digite o complemento dele na caixa de texto ao lado da palavra custom para montar uma cifra mas adequada a sua necessidade.

http://en.wikipedia.org/wiki/Real_Book

http://www.shermusic.com/ajrb.htm

http://www.shermusic.com/


Para alguns acordes vou usar a opção de customização de cifragem. Por exemplo o segundo acorde da segunda parte (no compasso 9), Am(#5). Embora essa cifra não seja convencional, no contexto do compasso 9 ela traduz muito bem a idéia do movimento harmônico executado pelo Helio Delmiro nas diversas gravações desse tema.

No Menu Scores Text Elements, definiremos o títiulo, o compositor e alguns outros detalhes da obra.

Para o Título clique sobre a opção e digite.

Clickando em footer você pode definir número de páginas e a data da criação da partitura. Basta clickar sobre o botão correspondente ao que vc deseja.

Estamos perto do fim .... hehehheh

Já terminei a cifra.


Para colocar a melodia vc pode usar o mouse, clickando na palheta de notas e em seguida no compasso específico. No menu Windows Palette Notes










No menu Windows Tempo, você acesso um “metrêmetro” virtual que define o beat do midi gerado apartir da sua partitura. É possível ouvir o resultado do que vc está “escrevendo” imediatamente. Bata clickar no botão “Play”. Conseqüentemente, podemos concluir que se vc tiver algum instrumento Midi é possível ao tocar registrar, através do Encore, em forma de partitura o que está sendo tocado.



Pressione espaço para tocar (OBS: ele não toca cifra, pelo menos até aversão que eu tenho). Enter para gravar. Ele tem um teclado virtual que vc pode acessar pelo menu Windows Keyboard.

Pronto!!! Uff!!! Acobou está pronto.

Como no Encore não há como vc exportar para nenhum formato que preste. Fui obrigado a fazer um screenshot, levar pro Fireworks e gerar um .Gif. Não posso deixar a galera com água na boca.

Lá vai, lá vai, lá vai ... aeeeeeeeeee ..... parou chega!!!



Esperando foi gravado nos seguintes álbuns:

- Emotiva (1983)


- Symbiosis (Cleare Fischer & Helio Delmiro - 1999)

- Compassos (2005)

OBS: Na gravação do Emotiva, os gênios dos engenheiros de gravação cortaram a coda. Eles resolveram mixar sem que o Helio estivesse presente, horas de trabalho para gravar a coda foi jogado no lixo.





Artigo completo (View Full Post)

segunda-feira, 19 de fevereiro de 2007

Robustez no Delphi


O usuário, após preencher os campos de uma tela, clica no botão “Confirmar”. Inesperadamente o sistema trava, a máquina congela. Todo o trabalho foi perdido, diante de uma mensagem propagada com o seguinte conteúdo: “Ocorreram erros”, ou “Erro fatal, catastrófico”.
Quem não se deparou com essa situação? Acho que, infelizmente, isso ocorre com tanta freqüência que muitos nem dão a devida importância para este tipo de situação.
Considero que desenvolver aplicações robustas é uma questão que transcende valores como “capricho”, “elegância” e “cuidado com a qualidade”. Para mim, a robustez de um software está intrinsecamente relacionada à ética profissional. Principalmente porque o custo que esse cuidado demanda não justifica sua ausência. O que, na minha opinião, torna mais grave esse tipo de falta.
Nenhum argumento vai ter validade para o usuário, quando ele descobrir que determinada ação, equivocadamente, por ele efetuada, poderia não ter causado tanto estrago ao seu trabalho, se o programador tivesse protegido o bloco de código executado naquela funcionalidade.
Sabendo trabalhar com exceções, desenvolvedores e analistas podem otimizar seu trabalho tanto no que se refere ao custo de codificação, quanto no que tange a robustez da aplicação desenvolvida. As Exceções tornam os sistemas mais robustos porque favorecem uma padronização ao notificar e manipular possíveis erros, fluxos alternativos e situações inesperadas. Quanto ao esforço de codificação, uma boa prática de programação através das exceções, pode tornar seu programa mais simples, por isso fácil de escrever, ler, entender, e conseqüentemente, de depurar. Ou seja, o melhor dos mundos! O Desenvolvedor ganha, o projeto ganha e o usuário do produto final também ganha. Portanto, vamos gastar um tempinho pra falar sobre como tornar seus programas mais robustos.

Tentarei mostrar também como isso pode reverter pra vc com vários benefícios decorrentes das técnicas que discutiremos a seguir.

Um recurso muito importante, que é subutilizado pelos programadores no Delphi ,é o suporte a exceções. De maneira objetiva, o suporte a exceções, tanto no Delphi , quando nas demais linguagens de programação, permite que você separe o código de tratamento de erros do código que compõe o fluxo principal, no módulo que você esta programando. Melhorando a organização do seu código, conseqüentemente tornando a manutenção do mesmo muito mais fácil.
O que são Exceções? (Conceito)
Exceções são o que chamamos de erros ocorridos durante a execução de algum programa. Ou melhor, erros que podem o correr no programa, fazendo com que ele falhe ao executar uma determinada tarefa. Esses erros podem comprometer tanto o funcionamento do programa, quanto o funcionamento do sistema opercional, aumentando o transtorno sofrido pelo usuário do computador.
Pequenos detalhes que por ventura deixem de ser considerados podem ocasionar problemas de grandes proporções para uma corporação. Uma data inválida digitada por engano, pode comprometer o processamento de uma folha de pagamento se um determinado trecho de código não tiver sido preparado para evitar tal engano, por exemplo.

Evitá-las, ou tratá-las?

Em outras palavras, devemos evitar esses “erros”, essas exceções, ou devemos usá-las? Quando uma exceção é propagada, isso deve ser encarado com positivo ou negativo para o programador? Ao contrário do pensamento predominante, o mecanismo de disparo de exceções não é um inimigo, ele é aliado do desenvolvedor. De fato, em algumas situações, erros de programação podem originar exceções. Contudo, de forma alguma é correto concluir que a causa, de toda e qualquer exceção propagada, seja sempre essa. Será que em reflexo a prática de evitar erros em seus códigos, algum programador possa, por indução, ao associar a idéia do substantivo “erro”, julgar adequado evitar exceções ao ponto de evitar também trabalhar com exceções? Esse tipo de confusão não deveria acontecer. Erros de programação não são o que chama-se de “exceções”. Nem todos os erros que acontecem em programação são erros de programação. Os erros de programação não devem ser evitados. Eles não podem existir. As “exceções” também não devem ser evitadas, pois elas trabalham a seu favor. As exceções devem sim ser prevenidas e tratadas.

Como podemos, então, prevenir estes “erros” quando estamos desenvolvendo o programa, se eles só acontecerão quando o sistema for executado? Em tempo de execução, o Delphi gera mensagens de exceções quando ocorrem erros. As bibliotecas geram exceções quando algo sai errado, seja no código em execução, num componente, ou no sistema operacional. Quando isso acontece, se a linha de código, onde ocorreu o problema, não está preparada para manipular a exceção a própria VCL irá se encarregar disso exibindo uma mensagem de erro padrão. Mensagem essa quase sempre incompreensível para o usuário. Em seguida o Delphi tenta continuar o programa, sem se “preocupar” em eliminar a causa do problema. Ele tentará isso por meio da manipulação da próxima mensagem de sistema, ou solicitação do usuário. Contudo, as chances de fracasso na tentativa de continuidade do programa são consideráveis. Ainda assim, se axceção, eventualmente, não comprometer totalmente, são enormes as chances de pelo menos parte do sistema não voltar a funcionar de forma adequada.

No Delphi existem duas estruturas pelas quais podemos proteger e tratar exceções, evitando que processos sejam interrompidos de forma brusca ou resultem em operações danosas:

     
“try..finally..end;” - Para proteger um bloco de código.

“try..except..end;” - Para tratar exceções.


Elas podem ser usadas separadamente ou juntas. Vejamos agora o mecanismo de emprego dessas estruturas no intuito de tratarmos as exceções, protergermo blocos de ccódigo e com isso alcançarmos um nível de robustez satifsfatório:

try:
 
Delimita o início de um bloco de código protegido.


except:

1° Delimita o final de um bloco de código protegido
2° Delimita o inicio do bloco de código responsável por
manipular as possíveis exceções ocorridas no código
disposto entre o “try” eo “except”.
Ou seja, o except introduz as instruções de manipulação das exceções.


finally:
Garante a execução do bloco de código sempre. Ou seja, especifica o bloco de código que deverá ser executado, mesmo que ocorram exceções. A palavra reservada finally é usada para garantir finalização de processos que dispõe de recursos de sistema, como conexões abertas com SGBDs, fechamentos de arquivos ou tabelas, liberação de objetos, memória, e outros recursos alocados no mesmo fluxo de programa.


raise:
Gera uma exceção. Por meio dessa palavra reservada o desenvolvedor pode chamar o construtor da classe "Exception". para, em tempo de execução, comunicar que algo que não deveria acontecer aconteceu. Para um melhor entendimento construiremos nosso primeiro exemplo.


Exemplificando

No Delphi inicie uma nova aplicação: Menu file New Application.
No Form1 adicione os seguintes componentes e os configure conforme listado abaixo, da palheta Standard:

Edit (TEdit):
propriedade - Name = Edit1
propriedade - Text =
(vazio, sem valor algum. Apague qqr valor que esteja nela.)

Memo (TMemo):
propriedade - Name = Memo1
propriedade - Lines =
(vazio, sem valor algum. Apague qqr valor que esteja nela.)

Button (TButton):
propriedade - Name = Button1
propriedade - Caption = "Processar"





Codifique os seguintes procedimentos:
Na Seção "private" declare: procedure ProcessaNum(Numero: Integer);



Pressionte as teclas: “Ctrl+Shift+C” e codifique o corpo do procedimento.



Codifique o evento OnClick do Button1:



Neste exemplo, podemos observar que se por acaso o usuário não digitar nenhum valor e clickar no botão "Processar" será exibida uma exceção, como conseqüência o cursor do mouse ficará com a ampulheta pra sempre.



Se protegêssemos o código utilizando o “try..finally...end;” poderíamos garantir a normalização do cursor, entretanto, não evitaríamos a mensagem da VCL que não é nada amigável para o usuário. Esse é um exemplo de bloco de código protegido, contudo, sem tratamento de exceção. Veja abaixo:



O código acima não trata a exceção. O que ele faz é tornar o programa mais robusto, de modo que uma exceção não torne o funcionamento do programa irregular. Podemos acrescentar ao nosso código a estrutura “try..except” a fim de manipularmos uma eventual exceção. Neste caso, teremos que usar a palavra reservada “raise para personalizarmos uma mensagem de exceção mais amigável. Para isso teremos de utilizar “finally e “except aninhados.




Embora o código acima já apresente algum nível de proteção ele ainda está longe do ideal. Todavia, ele atende ao objetivo de entendermos como funciona esse mecanismo:

Ocorrendo qualquer exceção no fluxo de código contido no “try” o Delphi interrompe desviado para o “except”. Note que no fluxo do except, a palavra reservada “on” funciona como um desvio condicional onde podemos definir respostas para uma exceção. A estrutura “on .. do”, permite o desenvolvedor manipular a exceção podendo, em tempo de execução obter informações específicas sobre o erro ocorrido. Ora, se o recurso existente no Delphi para tratarmos as exceções é uma classe, logo, podemos concluir que, se pretendemos evocar metodos, acessar propriedades dessa classe, é lógico que precisamos instanciar um objeto dessa classe. Por isso mesmo declaramos uma variável “E” tipada da classe Exception, por isso foi possível acessar o conteúdo da propriedade “message” para exibirmos para o usuário com a função “MessageDlg”. Como isso funciona?

Uma variação da estrutura “on…do”, permite definirmos uma variável, local, temporária para criarmos uma instância da exceção. Portanto, na linha do “on..do”, testa o tipo da exceção, caso verdadeiro, cria uma instância, ou seja, aloca memória, para que possamos acessar a informação que precisamos. No nosso caso, exibindo o valor da propriedade “message” do objeto “E” (E.Message). Conseqüentemente, obtemos tratamento exclusivo para cada tipo de exceção na clausula “on do”. Por exemplo, o código abaixo trata o erro de divisão por zero, através da exceção EDivByZero:


function Divisao (Soma, Numero : Integer): double;
begin
try
Result := Soma / Numero;
except
on EDivByZero do
result 0;
end;
end;

Nesse caso, será exibido para o usuário uma mensagem padrão da VCL. Você pode tornar seu programa mais amigável criando uma mensagem específica de tratamento:


try
If Edit1.Text = ‘’ then
raise Exception.Create(‘Digite um valor.’);
A := StrToInt(Edit1.Text);
except
on Msg: EConvertError do
MessageDlg(‘Erro: ‘+Msg.Message, mtinformation,[mbOk],0);
end;


Além disso, você pode utilizar as exceções genéricas para tratar um erro, em vez de uma exceção específica. Por exemplo, se você quer tratar um erro relacionado a uma operação com inteiros, mas não sabe exatamente o erro, poderá utilizar a exceção EIntError, que é a exceção genérica da qual derivam outras exceções relacionadas a inteiros:

Dissecado a classe Exception

1.1. Seção private

A classe Exception possui dois campos privados:

  • FMessage: String; Armazena o conteúdo da mensagem que será exibida pela exceção.
  • FHelpContext: Integer; Armazena o valor que identifica o tópico do arquivo de help on-line associado a classe.

1.2. Seção public


Uma classe pode definir mais de um construtor, e esta classe possui doze métodos “Create” diferentes. Os construtores são métodos responsáveis pela alocação de memória necessária aos objetos da classe.


constructor Create(const Msg: string);


Recebe como parâmetro uma string que comporá a mensagem da caixa de diálogo exibida quando a exceção ocorrer.


constructor CreateFmt(const Msg: string; const Args: array of const);


Utiliza internamente a função “Format” para compor a mensagem com os valores passados no parâmetro “Args” e o texto passado para o parâmetro “Msg”.

constructor CreateRes(Ident: Integer); overload;


Recebe como parâmetro um inteiro que identifica uma string armazenada no arquivo de recursos (.res) do seu aplicativo. Ou seja, a string que será armazenada no campo FMessage é obtida pela função “LoadStr” que retorna um texto armazenado no arquivo de extesão “.res”.


constructor CreateRes(ResStringRec: PResStringRec); overload;


Este é a versão sobrecarregada do método anterior. O Parâmetro “ResStringRec” é um ponteiro para o Resource String. Os chamados “Resources” são arquivos que não pertencem, não fazem parte do seu projeto, entretanto, eles são ligados a aplicação quando ela é compilada.


constructor CreateResFmt(ResStringRec: PResStringRec; const Args: array of const); overload;


Este construtor é uma composição dos construtores “CreateFmt” mais o “CreateRes”. Ou seja através do valor, inteiro, passado para “Ident” carrega um texto armazenado num arquivo “.res”, e utliza a função “Format” para formatar a mensagem com os valores contidos no array “Args”.

constructor CreateResFmt(ResStringRec: PResStringRec; const Args: array of const); overload;


Versãp sobrecarregada do construtor anterior cujo aúnica diferença é: “ResStringRec” é um ponteiro para o resource string. Veja, a idéia é essa:
const sMyNewErrorMessage = 'Valor inválido: %d';

Exception.CreateResFmt(@sMyNewErrorMessage, [‘– 1’]);

O que acontece nos bastidores é isso:

constructor Exception.CreateResFmt(Ident: Integer; const Args: array of const);
begin
FMessage := Format(LoadResString(ResStringRec), Args);
end;

Ou seja: Format(LoadResString(@sMyNewErrorMessage), [‘- 1’]);

constructor CreateHelp(const Msg: string; AHelpContext: Integer);


Recebe como parâmetro uma string que comporá a mensagem da caixa de diálogo exibida quando a exceção ocorrer, além de um valor numérico inteiro, “AHelpContext”, que identifica o tópico do arquivo de Help on-line associado a classe.


constructor CreateFmtHelp(const Msg: String; const Args: array of const; AHelpContext: Integer);


Recebe como parâmetro uma string que comporá a mensagem da caixa de diálogo exibida quando a exceção ocorrer. Além de um valor numérico inteiro, “AHelpContext”, que identifica o tópico do arquivo de Help on-line associado a classe. Utiliza internamente a função “Format” para compor a mensagem com os valores passados no parâmetro “Args” e o texto passado para o parâmetro “Msg”.

constructor CreateResHelp(Ident: Integer; AHelpContext: Integer); overload;


Recebe como parâmetro um inteiro que identifica uma string armazenada no arquivo de recursos (.res) do seu aplicativo. Semelhante ao construtor “CreateRes” e um valor numérico inteiro, “AHelpContext”, que identifica o tópico do arquivo de Help on-line associado a classe.


constructor CreateResHelp(ResStringRec: PResStringRec; AHelpContext: Integer); overload;


Recebe como parâmetro um ponteiro para a resource string. Semelhante ao construtor “CreateRes” e um valor numérico inteiro, “AHelpContext”, que identifica o tópico do arquivo de Help on-line associado a classe.

constructor CreateResFmtHelp(ResStringRec: PResStringRec; const Args: array of const; AHelpContext: Integer); overload;


Recebe como parâmetro um ponteiro para a resource string. Semelhante ao construtor “CreateRes” e utliza a função “Format” para formatar a mensagem com os valores contidos no array “Args”. um valor numérico inteiro, “AHelpContext”, que identifica o tópico do arquivo de Help on-line associado a classe. Além disso, um valor numérico inteiro, “AHelpContext”, que identifica o tópico do arquivo de Help on-line associado a classe.


constructor CreateResFmtHelp(Ident: Integer; const Args: array of const; AHelpContext: Integer); overload;


Através do valor, inteiro, passado para “Ident” carrega um texto armazenado num arquivo “.res”, e utliza a função “Format” para formatar a mensagem com os valores contidos no array “Args”. Além disso, um valor numérico inteiro, “AHelpContext”, que identifica o tópico do arquivo de Help on-line associado a classe. Veja o código abaixo:






property HelpContext: Integer read FHelpContext write FHelpContext;


Como pode ser observado no código exibido na figura anterior, o campo interno “FHelpContext” armazena o valor inteiro que identifica o tópico do arquivo de Help on-line associado a classe.

property Message: string read FMessage write FMessage;


Através da propriedade “Message” podemos ler o valor do campo interno “FMessage” o qual contém o texto com a mensagem informativa sobre a exceção, a mesma que foi passada como parâmetro no construtor.


Continua no próximo artigo.

Artigo completo (View Full Post)

quinta-feira, 15 de fevereiro de 2007

Métodos? Variáveis?

Olá a todos. Este post traz algo legal: métodos chamados através de variáveis.

Métodos? Variáveis? Isso!

Primeiro vamos ver um método simples:

<?
function quadrado($numero) {
return $numero * $numero;
}
?>

Certo. método que retorna o quadrado do número informado.

Agora vamos chamar este método:

<?
$quadrado = quadrado(4);
// $quadrado será 16
?>


Assim é o padrão. vamos agora ver como chamamos este método através de variável.

O PHP permite a execução de uma variável como método desde que o conteúdo da variável corresponda a um método definido e ele tenha os parâmetros corretamente.

<?
$metodo = "quadrado";

$quadrado = $metodo(4);
// $quadrado será 16 do mesmo jeito
?>


Viu? Legal, né xD

Tá legal Felipe... mais uma coisa que só você vê utilidade... -_-

Hehe dessa vez vou mostrar uma utilidade:

Vocês já precisaram implementar uma rotina que chame um método dentro de um loop (passagem por registros de um record set por exemplo) e poder usar de forma genérica para que dê para usar a mesma rotina em situações diferentes? Então... Esta é a solução.

Hmmmmmmmm..... Tá..... ...... ...... Não entendi.

Ok, Ok. Exemplo:

Eu tenho um método que faz uma consulta no banco de dados e retorna resultados em um array multidimensional (para minha aplicação não ficar acoplada ao banco de dados). Se a consulta retornar resultados demais o buffer não agüenta e o script é abortado.

Então eu criei um método que executa o comando SQL, faz um loop no resultado e a cada passagem chama o método que foi definido no parâmetro e passa para este método o registro corrente para o método fazer o que deve fazer com o registro.

Com isso podemos definir métodos diferentes e executar ações diferentes para a mesma consulta. E sem precisar repetir os loops.

Hmmmmmmmm..........Tá quase.....

Ok, Ok.


Implementação do método chave (este fica na biblioteca principal):

<?
function executarMetodoDuranteSelecao($sql, $metodo) {
$resultado = mssql_query($sql);
while($registro = mssql_fetch_array($resultado)) {
$metodo($registro);
}
}
?>


Agora um método para uma consula específica (este fica no objeto de negócio):

<?
function consultarLivros($metodo) {
$sql = "select id, nome from livros";
executarMetodoDuranteSelecao($sql, $metodo)
}
?>


Finalmente a implementação no seu script:

<?

function mostrarLivro($registro) {
echo "<p><div>$registro[id]</div>";
echo "<div>$registro[descricao]</div></p>":
}


$instanciaObjNegocio->consultarLivros("mostrarLivro");
?>


Legal. Quando executar o método consultarLivros este vai enviar o comando SQL para o método da biblioteca executarMetodoDuranteSelecao que vai executar o comando SQL, fazer o loop e a cada passagem do loop executaro método definido na variável $metodo, que vai, a cada registro, mostrar duas div contendo os campos id e descricao.

Este assunto não é muito simples. Espero que eu tenha colocado de forma que todos possam entender. A seção de comentários é aberta para qualquer dúvida ou sugestão (nada de reclamações, por favor xD).

Abraços a todos.

Artigo completo (View Full Post)

Desculpas a todos

Olá meus queridos freqüentadores do blog.

Quero pedir desculpas a todos que todos os dias - mais de uma vez por dia - acessam o blog só para ver se eu postei alguma coisa maravilhosa!

Hehe, agora sem brincadeiras. Essa semana está um pouco pesada e eu não tenho tido muito tempo nem para tomar aquele café depois do almoço.

Vou trabalhar no resto desta semana em um post sobre um assunto maneiro.

Depois. (<<< uma piada sem graça imitando o que o pessoal em inglês escreve "Later". Se você não entendeu não tem problema xD )

Artigo completo (View Full Post)

terça-feira, 13 de fevereiro de 2007

Integrando a ReBirth com o Sonar

Ribirth com Sonar

O Sonar é um software para gravação, edição e mixagem de áudio. Com ele vc pode desenvolver projetos de CDs, trilhas sonoras, multimídia. Além de todos os recursos de gravação multipista (multrack), para edição de áudio, e do seqüenciador MIDI, já presentes na suas versões anteriores, o popular Cakewalk Pro Áudio. Essa nova versão, o Sonar, traz uma grande quantidade de inovações comparada aos seus antecessores.

Esse software é utilizando tanto a nível profissional, quanto amador (os home studios da vida) proporcionado a criação de trabalhos musicais com um resultado bem satisfatório.

Uma característica muito legal no Sonar é a fácil usabilidade. Sua interface é bem amigável, comparado a outros softwares similares, e intuitiva. Ele permite uma ótima integração com outros softwares seqüenciadores, como a ReBirth e o Rason. Funcionalidade indispensável para as produções de música digital desde das duas últimas décadas. Nosso objetivo neste post é mostrar o quanto é fácil integrar o Sonar com a ReBirth.

No sonar, vamos iniciar um novo projeto:
Quando vc abre o Sonar aparece o Quick Start, uma forma rápida de vc selecionar abrir um Projeto anteriormente iniciado, abrir o último aberto, ou iniciar um novo projeto.

Selecione “Create a New Project”. Agora, vc deverá escolher a configuração do projeto que vc está iniciando, escolha Normal.


Como vc pode notar na imagem acima, ele abre automaticamente alguns canais de audio (para gravar Wave), alguns canais de MIDI e em baixo o máster, um sub Grupo e um de Efeito. Para utilizar algum programa de Loop, como a ReBirth ou o Reason, sempre no menu principal, opção “Insert”, irá constar numa das sub-opções uma específica para o programa de sequencer que estará instalado na sua máquina. O próprio Sonar reconhece esses programas.
Nesse momento vamos utilizar a funcionalidade do Sonar que integra com a ReBirth, contudo, para que isso seja feito com sucesso, ceritifique-se que a ReBirth esteja fechada na sua máquina.
Feito isso, no menu principal:
Insert ReWire Device ReBirth Audio.


Um parêntese: Quando fiz o upload das imagens pude notar que ficaram bem
ruins aqui no blog. Mas, se vc clickar sobre elas poderá visualizá-las
com mais nitidez.

Voltando: Provavelmente, se vc nunca fez esse procedimento antes, será necessário ainda uma configuração. Defina como vc deseja que as Tracks sejam criadas (Se vc quer uma para cada instrumento da ReBirth ou todas mixadas em Stereo) e se vc vai querer que uma janela com as propriedades do Synth e/ou outra com o rack. A parte mais relevante para mim nesta configuração é que cada instrumento da ReBirth seja endereçado para um canal. Veja na figura como eu sempre trabalho. Dessa forma tenho mais flexibilidade para mixar os instrumentos. Conseqüentemente, consigo uma sonoridade que mais me agrada, embora isso dê mais trabalho.

Agora vc tem os novos tracks (canais) um para cada respectivo instrumento da ReBirth.


Agora execute a ReBirth, abra algum arquivo que vc já tenha finalizado, ou não, um loop (ou song). Retorne para o Sonar pressione Play, pronto a Rebirth ja deve estar tocando na sua máq através do Sonar.

A ReBirth vem com vários exemplos sequanciados, no diretório de instalação dela vc deve encontrar um pasta, Demo Songs:

So, then .... enjoy yourself

Artigo completo (View Full Post)

quinta-feira, 8 de fevereiro de 2007

Seu site no celular

Olá. Este post traz algo interessante: Configurar o Servidor Web Apache para usar scripts PHP em páginas WML.

Para quem ainda não sabe WML é a linguagem de marcação para WAP.

O meu exemplo é usando o Debian GNU/Linux sarge, Apache 2 e PHP 4. Acredito que em todos os sistemas operacionais que suportam Apache/PHP isso funcione.

No arquivo de configuração do Apache (/etc/apache2/apache2.conf) adicione esta linha junto de outras semelhantes (você pode colocar esta linha no fim do arquivo também, mas sempre procure organização):

AddType application/x-httpd-php .wml


O significado desta linha é que o servidor interprete extensão wml como um script PHP e use o interpretador do PHP para processar a página antes dela ir para o cliente.

Extendendo um pouquinho do assunto vou mostrar a estrutura básica de um arquivo wml:

<?xml version="1.0" encoding="iso-8859-1"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.3//EN" "http://www.wapforum.org/DTD/wml13.dtd">
<wml>
<card>
Aqui entra o conteúdo WmL que aparece no navegador WAP
</card>
</wml>


Com essa configuração do servidor esta página padrão WML não vai funcionar. Por quê?! Simples: qual é a marcação de script PHP? Hein? Isso! <? ?>. Infelizmente a tag do xml usa o mesmo ponto de interrogação; então o interpretador do PHP acha que é uma abertura de bloco, mas desconhece este "xml" que vem logo depois. Como resolver isso, então? Simples: é só fazer isso como um echo dentro de tags PHP. E não se esqueça de \"escapar\" as aspas:

<?
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>";
?>


Pronto.

Eu próprio vou começar a fazer uns módulos do site aqui da empresa em WAP. Quando tiver algo pronto eu posto aqui no blog. Abraços a todos!

Artigo completo (View Full Post)

Novidades Reloaded

Olá a todos novamente!

A mais nova novidade chegou! (ou está chegando). Acabei de achar o software para montar os posts em vídeo. Vou tentar fazer o primeiro hoje à noite.

Aguardem.

Artigo completo (View Full Post)

quarta-feira, 7 de fevereiro de 2007

Criando meus próprios toques para o Celular (.MP3).

Atende o Telemóvel, com mais estilo.

Ok, ok!!!
Estou levando pancada, vou tentar diminuir os posts ..... heheheh (Coeee, Felipe!! Bricadeira, sei que vc ta querendo mater um clima descontraido na área. Fica tranq!)
Existem toques maneiros ... mas, eu tenho idéias, embora não tenha tempo pra todas. Eu gosto da ReBirth, ela tem uma sonoridade que me agrada muito. É razoavelmente flexível e posso integrá-la tanto ao Cubase, quanto a outros, como o Nuendo ou o Sonar (veja qui!).

Acabei de sequenciar um loop, gostei do resultado, estou carregando para ser toque do cel.




Como isso funciona?

A idéia é construir patterns. Cada Banco pode ter até 8 patterns diferentes. Cada Módulo de sequencer, vou chamar assim, possui 4 bancos. Cada pattern é sub-dividido em 16 partes iguais de tempo. Cada Módulo pode tocar um som, ou não, em cada 1/16 parte do tempo. Com o slide vc liga o som de um 1/16 no outro. O accent como o próprio nome já diz acentua o som emitido na quele “step” ( Ou seja 1/16 parte do tempo). Cada 1/16 parte é ordenada e vc pode identifica - lá por um display cujo o título é “Edit Step”. Ali vc está editando um dezesseis avos qualquer do patern. Poder ser o 1°, ou o 2° ..... até o 16°.

A ReBirth vem com vário exemplos de paterns e songs seqüenciados. Os dois primeiros módulos são melódicos. A maioria dos exemplos usa sempre um deles para programar um riff de bass. Mas possui uma boa extensão possibilitando explorar sons agudos tb. Infelizmente, tem que mexer na afinação para explorar toda a extensão. Isso dificulta um pouquinho, admito.Cada um dos dois módulos melódicos possui botões para configuração da edição da afinação, timbre, acentuação e decay (não sei traduzir isso .. hehhe). Ah! Ainda pode escolher a forma da onda. Pois é, só duas eu sei mas ....

Os dois últimos módulos são rítmicos, bateria eletrônica. Cada instrumento da bateria está micro-abreviado: BD, logicamente não é banco de dados, é Bass Drum, ou seja, bumbo. SD Snare Drum, caixa. LT, Low Ton. MT, Middleton. HT, Highton (são os ton-tons da bateria, aquele som da segunda parte do message in a bottle, Os Paralamas tb exploraram esses sons em muitas levadas, alias eles copiavam o Police a rodo. Ok, ok!! Muito bem copiado. Tb acho). RS, é a clave (não lembro o nome em inglês). CP, claps. CH, Close Hi-Hat. OH, Open Hi-Hat. CC, Campana do Ride (Prato de condução, tocado na campana). RC, Ride. Chega ... acho que é isso. Não sou baterista.

Cada Módulo possui um controle de pan, volume, deley e efeitos (distorção e etc ..). Cada efeito tb pode ser configurado.

Você cria loops ou canções a partir dos patterns. Uma canção pode possuir um loop, ou ao contrário. Como vc Preferir.

O menu “edit” te permite copiar, cortar, colar (pardrão windows) nos patterns, aterá-los, shifta-los , randomizá-los automaticamente. No menu “edit” você inicia um loop ou canção apartir de um pattern criado.

È isso ai ... dá pra juntar com o sonar e adiciona guitarra, sax, teclado. Eu já fiz vários cds, quando trabalha em studio de gravação, usando a ReBirth . Muitos discos famosos usaram sequencers montados nela.

No menu “File” vc exporta para .wav depois converte para .mp3. Simples, rápido, show!

Exemplos criados por mim , postei aqui no Estação ZN.

Agora, o mais maneiro dessa história:

Vcs podem fazer douwnload da ReBirth, Mods e add-ons pra ela em: http://www.rebirthmuseum.com

Descobri essa parada agora, tem uma comunidade e tudo ... boladaum a situ.

Artigo completo (View Full Post)

Novidades a caminho!

Olá caríssimos freqüentadores do nosso blog.

Venho anunciar um plano que eu e o Gerson discutimos no almoço e que realmente vai ficar muito legal no blog.

Em vez de continuar fazendo estes posts quilométricos vamos começar a fazê-los em vídeos. Vídeos?! Isso, vídeos!

A idéia é colocar os vídeos no YouTube e exibi-los aqui também. Então, se necessário, colocaremos o arquivo de texto como anexo para download.

Estou procurando um software para isso. Como não sou muito rico preciso de um software grátis; se alguém souber ou encontrar algum por favor poste o comentário para eu começar o quanto antes.

Então é isso: Posts no blog e vídeos no YouTube - Web 2.0 na veia! Até mais!

Artigo completo (View Full Post)

Vídeo sobre Web 2.0

Olá a todos os nossos assíduos visitantes.

Estava eu no YouTube... Ia procurar um clipe do Massacration quando eu vi um link para um vídeo falando de Web 2.0 - The machine is us/ing us <<< Olha que doido! Por aí já temos uma prévia do que vem por aí. Um dos melhores vídeos que eu já vi no YouTube (acho que para mim foi o melhor):



Para quem quer ver o link no site é esse aqui:

Link para o vídeo.

Bem, é isso. grande abraço a até a próxima.

Artigo completo (View Full Post)

Extra! Extra! Novos remédios pra conjuntivite: MOST WANTED e CS!

Falae, galera!

Essa notícia vai para os viciados em games de plantão (Felipe, essa vc vai gostar):

O Videogame faz bem para os olhos!!!

Uns pesquisadores desocupados lá dos Estados Unidos, os mesmos que descobrem aqueles animais em extinção que passam no Jô, descobriram que jogar videogame faz bem para a visão.

Eles fizeram um estudo que mostrou que, durante um mês, aqueles que jogam games de ação melhoraram a sua visão em até 20%!!!

A Fonte da informação veio do site da Info e a matéria pode ser vista na íntegra clicando aqui.

Vou terminando o post por aqui pq o Most Wanted acabou de carregar e eu to querendo curar a minha conjuntivite...

Valeu, galera!

Artigo completo (View Full Post)

ASP.NET na prática: Construindo um pequeno cadastro

Olá a todos. Depois dos posts 10km de informação do Gerson vou colocar algo um pouco menor, seguindo a linha 'faça você mesmo'. Depois de ficar de blá blá blá sobre ASP.NET vamos fazer algo para sacar como a parada funciona. Usaremos o VS2005 e C#. Acredito que possa ser adaptado para a linguagem VB ou qualquer outra do VS, mas com relação à ferramente receio que só possa ser feito no VS mesmo, porque ainda não vi outra ferramenta de .NET dar suporte a .NET 2.0 ou Typed Datasets (Datasets tipados).

Faremos um programa de cadastro de produtos seguindo orientação a objetos, fazendo o máximo isolamento possível e a menor quantidade de código também :)

Vamos conhecer também os componentes ObjectDataSource, GridView e FormView entre outros.

Banco de dados: Usarei o MS SQL Server mas qualquer banco de dados suportado pela tecnologia ADO.NET pode ser usado.

Nossa tabela será chamada Produtos e terá os seguintes campos:

ProdutoID - int - not null - Chave Primária
Descricao - varchar(50) - not null
PrecoCompra - decimal(18, 2) - not null
Saldo - int - not null


O campo ProdutoID não é auto incrementado; para isso usaremos uma tabela chamada Contaores.

Tabela - varchar(50) - not null - Chave Primária
Contador - int - not null

Você até poderia usar um campo to tipo autoinc ou criar trigger, mas o objetivo aqui não é esse.

Teremos um registro nesta tabela onde o campo Tabela será Produtos e ele será incrementado a cada registro que for inserido na tabela.

Então vamos lá. Iniciaremos um novo WebSite no VS2005 em C#

Agora vamos em File > New > File e selecione DataSet. Chame de DataSetProduto.xsd

O VS irá pedir para criar uma pasta chamada App_Code e colocar o recém criado DataSet nesta pasta. Escolha sim.

No assistente do TableAdapter vamos escolher uma conexão com o banco de dados. Se ainda não tiver crie uma. Dê preferência em usar o driver OLEDB em vez do driver direto para SQL Server, porque o driver direto tem diferenças nos parâmetros e você fica acoplado ao banco, e isso não é o que queremos. Assim que criar a conexão o VS vai perguntar se você quer salvar esta string de conexão no arquivo Web.Config. Responda que sim e deixe o nome padrão de ConnectionString.

Agora selecione Use SQL statements e avance; defina o comando SQL para trazer a tabela de produtos:

SELECT ProdutoID, Descricao, PrecoCompra, Saldo
FROM Produtos
WHERE ProdutoID = ?


deixe a próxima tela como está e avance.

Nesta última tela o assistente mostra as operações que foram feitas. Clique Finish.

Com isso temos nosso TableAdapter que representa a tabela Produtos e os métodos Fil, GetData que representam a query que digitamos. No TypedDataSet temos o TableAdapter que é composto do DataTable (Produtos) e as várias queries que terão diferentes parâmetros para trazer os resultados.

Agora vamos criar a query para consultar produtos por descrição. Clique com o botão direito em ProdutosTableAdapter e escolha a opção Add Query. Deixe SQL marcado e avance. Select with return rows (select que retorna várias linhas); avance. Segue o comando:

SELECT ProdutoID, Descricao, PrecoCompra, Saldo
FROM Produtos
WHERE Descricao LIKE ?
ORDER BY Descricao


Avance. Troque os nomes dos métodos de FillBy e GetDataBy para FillByDescricao e GetDataByDescricao e avance. Finalize.

Devido a um pequeno BUG(!) na ferramente este parâmetro string não é mapeado corretamente. Então clique em FillByDescricao,GetDataByDescricao (Descricao) e abra a janela Properties.

Na propriedade Parameters clique nas reticências e procure a propriedade ProviderType do Parâmetro Descricao e troque de Char para VarChar. Dê Ok.

Aaaaarrrrrrggghghghghh BUGGGG!!!!

Sempre que você fizer uma consulta com o operador LIKE faça esta verificação com os parâmetros String que você tiver.

Agora temos nosso DataTable Produtos com duas queries: Fill/GetData e FillByDescricao/GetDataByDescricao.

Tá legal, mas qual é a diferença? Ok, eu explico: os Métodos Fill aceitam como parâmetro um objeto do tipo DataTable e o preenchem com dados; já os GetData retornam o DataTable para serem usados em métodos de objetos de negócio por exemplo. Como usaremos objetos de negócio aqui nós veremos os GetData no nosso código.

Uma vez que criamos a representação da tabela Produtos na nossa aplicação faremos agora a representação da tabela Contadores. Clique em qualquer área livre do DataSet com o botão direito e escolha Add > TableAdapter. O assistente é igual ao da criação do DataTable Produtos. Agora faremos o select na tabela Contadores. O comando SQL é:

SELECT Tabela, Contador
FROM Contadores
WHRE Tabela = ?


Deixe o resto como padrão e prossiga até terminar. Agora nós já definimos toda a nossa representação do banco de dados. Iremos agora criar o objeto de negócio para manipulação destes dados e interação com a aplicação.

É uma ótima prática separar logicamente (fisicamente também é até melhor!) as camadas de dados e apresentação (interface) para manter as partes mais isoladas e independentes e tornar as mudanças nas regras de negócios um processo mais suave.

Salve o DataSet e na janela Solution Explorer clique com o botão direito na pasta App_Code e escolha Add New Item. Selecione o ícone Class e chame o arquivo de Produto.cs.

Esta classe será responsável pela manipulação de dados na interface da aplicação. O objetivo desta classe é prover acesso e manipulação dos dados representados no DataSet, mas mantendo um isolamento e encapsulamento para que a interface tenha que somente fazer o necessário: selecionar a operação e passar os parâmetros para o objeto de negócio para este realizar as ações.

primeiro vamos fazer referência ao namespace que contém os objetos TableAdapter do nosso DataSet para não termos que digitar o seu nome toda hora. logo no começo do documento onde há várias cláusulas using vamos adicionar uma:

using DataSetProdutoTableAdapters;


Entenda namespace como um espaço onde são declarados objetos para serem usados de forma organizada. O namespace acima engloba os nossos objetos TableAdapter que estão no DataSet. É semelhante a cláusula uses do Delphi.

Agora nesta classe vamos implementar os métodos para utilizar na nossa aplicação.

Primeiro os de consulta:

    public DataTable ConsultarPorID(int ProdutoID) {
ProdutosTableAdapter ta = new ProdutosTableAdapter();
return ta.GetData(ProdutoID);
}

public DataTable ConsultarPorDescricao(string Descricao) {
ProdutosTableAdapter ta = new ProdutosTableAdapter();
return ta.GetDataByDescricao(Descricao);
}


Agora os de cadastro:

   public void Incluir(int ProdutoID, string Descricao, decimal PrecoCompra, int Saldo) {
ProdutosTableAdapter ta = new ProdutosTableAdapter();
ta.Insert(ProdutoID, Descricao, PrecoCompra, Saldo);
}

public void Alterar(int ProdutoID, string Descricao, decimal PrecoCompra, int Saldo) {
ProdutosTableAdapter ta = new ProdutosTableAdapter();
ta.Update(ProdutoID, Descricao, PrecoCompra, Saldo, ProdutoID);
}

public void Excluir(int ProdutoID) {
ProdutosTableAdapter ta = new ProdutosTableAdapter();
ta.Delete(ProdutoID);
}


Finalmente o método para gerar o contador:

   public int GerarID() {
int novoID;
string Tabela = "Produtos";
ContadoresTableAdapter ta = new ContadoresTableAdapter();
DataTable dt = ta.GetData(Tabela);
if (dt.Rows.Count > 0) {
novoID = Convert.ToInt32(dt.Rows[0]["Contador"]) + 1;
ta.Update(Tabela, novoID, Tabela);
}
else {
novoID = 1;
ta.Insert(Tabela, novoID);
}
return novoID;
}


Este método GerarID acessa a tabela contadores e incrementa o contador caso já exista algum ou inclui novo registro caso ainda não exista.

Agora nossa classe está pronta; vamos implementar as interfaces. No nosso Default.aspx vamos colocar os links para as páginas que farão o cadastro. Abra o Default.aspx. Dentro do nosso form inclua os links para as operações:

   <h1 style="border-bottom: solid 1px black">Cadastro de Produtos</h1>
<a href="Incluir.aspx">Incluir</a><br />
<a href="Consular.aspx">Consultar - Alterar e excluir</a>


segue o HTML completo:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1 style="border-bottom: solid 1px black">Cadastro de Produtos</h1>
<a href="Incluir.aspx">Incluir</a><br />
<a href="Consultar.aspx">Consultar - Alterar e excluir</a>
</div>
</form>
</body>
</html>


No Solution Explorer clique com o botão direito no Default.aspx e clique em Set as Start Page. Salve e feche Default.aspx.

Criando a página Incluir.aspx

Agora vamos criar o formulário de inclusão de registro. Clique com o botão direito no WebSite e escolha Add New Item. Escolha WebForm e chame de Incluir.aspx.

Para facilitar um pouco as coisas vamos para a visualização Design. Na parte inferior do editor há dois botões: Design e Code; clique em Design.

O Editor de HTML do VS é muito bom. Eu uso o editor até para colocar componentes ASP.NET, e ainda dá para alterar as propriedades na janela Properties clicando dentro ta tag na visualização HTML.

Na janela Toolbox na seção Data há um componente chamado ObjectDatasource. Dê um duplo clique nele para adicionar ao WebForm.

Na janela Properties mude a propriedade ID de ObjectDataSource1 para ObjDsProduto. No rodapé da janela Properties ainda há um link 'Configure Data Source...'. Clique nele.

No campo Choose your business object temos que escolher a classe Produto que nós codificamos; porém ele não aparece na lista. Devemos desmarcar a caixa ao lado 'Show only data components'. Agora, no meio de várias opções aparecerá Produto. Selecione e dê next.

Nesta página vamos incluir; então só precisamos definir os métodos de SELECT e INSERT. Na aba SELECT escolha o método ConsultarPorID e na aba INSERT escolha Incluir. Dê next.

Na próxima página o objeto nos pergunta sobre o valor padrão do parâmetro ProdutoID do método Select (nós podemos passar valores dinamicamente também). Entre com -1 para o valor. usamos este número para que a consulta não retorne registros, já que nossa operação é de INSERT e para isso não precisamos de dados neste momento. Dê Finish.

Agora que a fonte de dados está configurada vamos colocar o objeto que mostrará os campos para fazer a inserção no banco de dados. Este componente é o FormView. Deixe o cursor abaixo do ObjDsProduto e na Toolbox novamente acesse a seção Data e dê um duplo clique no FormView. Abra a janela Properties e defina as propriedades:

ID: FvwProduto
DatasourceID: ObjDsProduto
DefaultMode: Insert

Este componente nos permite criar formulários com campos diretamente ligados ao nosso DataSource (ObjDsProduto). Então vamos criar um template para o form de Insert. Clique com o botão direito no componente e escolha Edit Template > InsertItem Template. Agora tem uma área editável dentro do FormView para colocarmos os campos. Nós precisamos de 4 caixas de texto para representar os campos da tabela e um botão para confirmar e outro para cancelar. vamos um a um:

Com o cursor dentro do InsertItemTemplate vá na Toolbox e insira um TextBox:

ID: TxtProdutoID
ReadOnly: True

Agora na parte inferior da janela clique em 'Edit Databindings...'

No campo aberto para editar entre com Bind('ProdutoID') (o campo do DataSource que ele representará)

Abaixo insira outra TextBox:

ID: TxtDescricao
No 'Edit Databindings...' selecione Bind('Descricao')

Mais uma linha, mais uma TextBox:

ID: TxtPrecoCompra
'Edit Databinddings...' - Bind('PrecoCompra')

Último campo:

ID: TxtSaldo
'Edit DataBindings...' - Bind('Saldo')

Na linha de baixo insira dois botões, um ao lado do outro:

Botão 1:
ID: BtnConfirmar
Text: Confirmar
CommandName: Insert

Botão 2:
ID: BtnCancelar
Text: Cancelar

A propriedade CommandName do objeto Button serve para enviar um comando para o objeto que o está armazenando, no nosso caso o FormView. O FormView possui vários comandos para manipulação de registro, como Edit, New, Insert, Update, etc. O comando Insert chama o método de Insert do DataSource associado ao FormView (ObjDsProduto, que por sua vez chama o método Incluir definido na nossa classe Produto.

Agora digite os textos referentes a cada campo no lado esquerdo de cada um. Se você quiser pode ir até a visualização HTML e editar o html para colocar table. Meu exemplo ficou assim:


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Incluir.aspx.cs" Inherits="Incluir" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ObjectDataSource ID="ObjDsProduto" runat="server" InsertMethod="Incluir" SelectMethod="ConsultarPorID"
TypeName="Produto">
<SelectParameters>
<asp:Parameter DefaultValue="-1" Name="ProdutoID" Type="Int32" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="ProdutoID" Type="Int32" />
<asp:Parameter Name="Descricao" Type="String" />
<asp:Parameter Name="PrecoCompra" Type="Decimal" />
<asp:Parameter Name="Saldo" Type="Int32" />
</InsertParameters>
</asp:ObjectDataSource>

</div>
<asp:FormView ID="FvwProduto" runat="server" DataSourceID="ObjDsProduto" DefaultMode="Insert">
<InsertItemTemplate>
<table border="0" cellpadding="0" celllspacing="0">
<tr>
<td>ID:</td>
<td><asp:TextBox ID="TxtProdutoID" runat="server" Text="<%# Bind('ProdutoiD') %>"></asp:TextBox></td>
</tr>
<tr>
<td>Descrição:</td>
<td><asp:TextBox ID="TxtDescricao" runat="server" Text="<%# Bind('Descricao') %>"></asp:TextBox></td>
</tr>
<tr>
<td>Preço:</td>
<td><asp:TextBox ID="TxtPrecoCompra" runat="server" Text="<%# Bind('PrecoCompra') %>"></asp:TextBox></td>
</tr>
<tr>
<td>Saldo:</td>
<td><asp:TextBox ID="TxtSaldo" runat="server" Text="<%# Bind('Saldo') %>"></asp:TextBox></td>
</tr>
<tr>
<td colspan="2" align="center"><asp:Button ID="BtnConfirmar" runat="server" CommandName="Insert" Text="Confirmar" /> <asp:Button
ID="BtnCancelar" runat="server" Text="Cancelar" /></td>
</tr>
</table>
</InsertItemTemplate>
</asp:FormView>
</form>
</body>
</html>


Agora vamos codificar. Lembra como era em ASP para fazer um formulário de Inclusão? Lembra como é em JAVA? VB? Delphi? Blá? Blá???? Muito bem, aqui o modo é bem fácil. Se você rodar o programa para testar ele já funciona. Funciona? Sim, funciona!

A partir de agora vamos fazer um pequeno polimento nele. Do jeito que ele está nós temos que passar o valor do campo ProdutoID na mão; e já que ele é ReadOnly nós não conseguimos inserir. E, assim que a inclusão é realizada ele volta o formulário em branco para outra inserção. A idéia aqui é gerar um novo ID através do método GerarID da classe Produto e assim que terminar a inclusão retornar à página Default.aspx. Vamos nessa.

Vamos cuidar do mais fácil primeiro: dê um duplo clique no botão Cancelar para fazer logo o redirecionamento para a página inicial (certifique-se de que está no modo de EditTemplate):

protected void BtnCancelar_Click(object sender, EventArgs e) {
Response.Redirect("Default.aspx");
}


Ainda na página de código vamos codificar o evento Page_Load, que dispara sempre que a página carrega:

   protected void Page_Load(object sender, EventArgs e)
{
TextBox txt = (TextBox)FvwProduto.FindControl("TxtProdutoID");
if (txt.Text == "") {
Produto p = new Produto();
txt.Text = p.GerarID().ToString();
}
}


Aqui recuperamos o objeto TextBox TxtProdutoID dentro do FormView e geramos um novo ID para ele caso ainda não tenha sido definido.

Agora faremos o código para redirecionar para a página inicial quando a operação for finalizada:

Volte para o design da interface - Botão direito na página de código - View Designer e selecione o ObjDsProduto. Na janela de propriedades
há um botão que é um raio: este lista os eventos do componente. Vamos codificar o evento Inserted, que dispara depois que um item é inserido. Dê um duplo clique na área do valor:

  protected void ObjDsProduto_Inserted(object sender, ObjectDataSourceStatusEventArgs e) {
Response.Redirect("Default.aspx");
}


Por incrível que pareça, está pronto. Agora para a etapa final da nossa pequena aplicação: Tela para consultar, alterar e excluir.

Mas tudo na mesma página? Meu amigo haja código hein... Nem sempre. Temos no ASP.NET um componente muito legal: GridView. Ele em conjunto com o ObjectDataSource faz todas as operações totalmente sem código. Sem código? Sem código. :)

Salve o Incluir.aspx e feche. Agora com o botão direito no site Add New Item; WebForm e chame de Consultar.aspx.

Vamos direto para o Design e assim como na anterior insira um ObjectDataSource e defina as prorpriedades:

ID: ObjDsProduto
Clique 'Configure Data Source...' na parte inferior.
Desmarque 'Show only data components' e no campo anterior selecione Produto

Avançar

Na aba SELECT escolha ConsultarPorDescricao
Na aba UPDATE escolha Alterar
Na aba DELETE escolha Excluir

Avançar

Deixe o parâmetro em branco e Finish.

Primeiro insira um link para retornar abaixo do ObjDsProduto:

<a href="Default.aspx">Voltar</a>


Agora vamos inserir e configurar nosso GridView: Na Toolbox na parte Data duplo clique em GridView. Selecione ele e abra a janela Properties:

ID: GvwProduto
CellPadding: 4
CellSpacing: 0
DataSourceID: ObjDsProduto
DataKeyNames: ProdutoID (tem que digitar)
Columns: Clique nas reticências

Agora vamos configurar as colunas:

Selecione BoundField e clique Add

HeaderText: ID
DataField: ProdutoID
ReadOnly: True

Selecione novamente BoundField e clique Add

HeaderText: Descrição
DataField: Descricao

Outro BoundField:

HeaderText: Preço
DataField: PrecoCompra

Último BoundField:

HeaderText: Saldo
DataField: Saldo

Agora expanda CommandField e selecione Edit, Update, Cancel. Clique Add

CancelText: Cancelar
EditText: Editar
UpdateText: Atualizar

Por fim, dentro de CommandField selecione Delete e clique Add

DeleteText: Excluir.

Na parte inferior da janela desmarque a caixa 'Auto-generate fields' e dê Ok.

Rode a aplicação com Ctrl+F5. Parabéns!

Não sei vocês, mas se eu tentar fazer este grid "boladão" em PHP acho que vai ser uma boa diversão de fim de semana. Imagina em JAVA! Hehe.

É isso aí. Boa diversão para todos.

Artigo completo (View Full Post)

 
BlogBlogs.Com.Br