
Micheus
Veteranos-
Total de itens
3.189 -
Registro em
-
Última visita
Tudo que Micheus postou
-
O exemplo abaixo desliga o monitor, aguarde 5 segundos e re-liga monitor. SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, 0); Sleep(5000); { Aguarde 5 segundos } SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, -1); OBS: funciona somente para windows 95 e 98 No meu WindowsXP SP2 funciona, desde que você utilize o código adequadoDesligar: SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
-
NoNaMexD, dada a natureza da aplicação, eu me reservo ao direito de não colaborar.Quem sabe, algum outro colega se prontifique. Abraços e boa sorte.
-
Eu tentei e não tive problemas. Parece que corrompeu ao você fazer o download, mas eu o reanexei denovo. Tente novamente. Se ainda não funcionar, tente baixar do 4Share (ProjEder.zip)
-
NoNaMexD, antes um programa que se auto-copia... Agora que muda alguns dados em si próprio, que envia e-mail... O que é que você está pretendendo? <_< Porque você não grava simplesmente o e-mail no registro do windows ou em um arquivo ini, se a questão é apenas configurar este e-mail para ser enviado para pelo seu programa? Abraços
-
Bom, já que ninguém respondeu ainda e já acabou a correria do fim de ano, segue mais detalhado o que você deve fazer para chegar no que você questionou: - Criar uma variável na sessão private do seu form; - No evento OnCreate do seu form, acesse o registro do windows, baseado no que postei inicialmente e inicialize esta variável para uso durante o decorrer do programa - sem necessidade de reler o registro; - Na parte do código onde você deseja chamar sua página (p.e. ??.php), você testa se a variável está incializada. Se estiver, o FireFox está instalado e você inicializa a string de comando e ativa a página através do comando WinExec. O código na prática: type TForm1 = class(TForm) ... private FireFoxPath :String; end; var Form1: TForm1; implementation uses Registry, // uso da classe TRegistry ShellAPI; // uso a função ShellExecute procedure TForm1.FormCreate(Sender: TObject); var Reg :TRegistry; begin Reg := TRegistry.Create; try // seleciona chave de Classes Reg.RootKey := HKEY_CLASSES_ROOT; // tentamos abrir a chave referente à string de comando do FireFox if Reg.OpenKey('FirefoxURL\shell\open\command', False) then FireFoxPath := Reg.ReadString('') // lê o valor "padrão" else FireFoxPath := ''; // não está instalado finally Reg.Free; end; end; ... // para exemplificar, optei por colocar o código em um Button.OnClick procedure TForm1.Button1Click(Sender: TObject); var PageAddress :string; begin // aqui o endereço é colocado direto em uma variável local. // no seu caso, você pode adaptar para ler de um campo de tabela ou edit - fica a gosto. PageAddress := 'http://localhost/rel_sisaeg/comprovante_orcamento.php'; // se o navegador FireFox estiver instalado, a variável não estará nula // e então montamos a string de comando, substituindo o parâmetro (%1) if FireFoxPath <> '' then PageAddress := StringReplace(FireFoxPath, '%1', PageAddress, [rfReplaceAll]); // caso o FireFox não esteja instalado, estaremos passando apenas o endereço // a função ShellExecute, o que fará que o navegador padrão seja acionado. ShellExecute(0, nil, PChar(FireFoxPath), nil, nil, SW_SHOWMAXIMIZED); end; end. Espero que lhe ajude. Abraços
-
Acho que este mesmo o assunto Jhonas. Como não temos nenhuma sessão relacionada ao assunto, então, movido para Outros Assuntos.
-
No server, você dever ter a lista dos clients conectados, certo?! Sempre que uma conexão for aceita (é quando você adiciona a esta lista), você deverá enviar para a lista de client a informação de que um novo client está conectado e de modo similar, quando um client desconectar, você deverá também informar de que o client não está mais conectado.Você deverá provavelmente utilizar de algum tipo de protocolo, que indique ao client que você está informando a conexão ou desconexão de "alguém". Seria como enviar uma string com esta seqüência: CNX:Micheus:192.168.65.7; onde o ":" seira o delimitador de campo e: - CNX = conexão / DCNX = desconexão; - Micheus = nome do usuário; - 192.168.65.7 = endereço IP do client Se o servidor vai repassar ao destinatário, qual seria a finalidade do flag? Abraços
-
Acredito que tenha sim. Não utilizo Postgres, mas por analogia e de acordo com o que consta na documentação que encontrei (PostgreSQL Prático - versão 8.1.4), talvez você não precise fazer isto via programação. No FireBird, por exemplo, a função current_time, utilizada num SELECT e apresentada por uma ferramenta de consulta mostra a hora no formato hh:mm:ss (ex. 02:21:06). Mas, na verdade ainda há os milisegundos. Assim, se você fizer uso do CAST para convertê-lo para um VARCHAR, precisará lembrar disto, porque o tamanho passa a ser maior (caso contrário você obterá erro). Há, ainda, a opção da conversão "implícita" onde você faz o SELECT concatenando um string nulo à current_time e, com isto, o resultado automaticamente seria uma string. Uma vez tendo a string, bastaria pegar a substring desejada, neste caso, a partir da posição 3 dois caracteres. Estes recursos funcionam no FireBird e, como existem no Postgres, podem servir para resolver seu problema. Assim, experimente os seguintes exemplos e veja se irá funcionar no Postgres: - CAST: select substring(cast(current_time as varchar(13)) from 3 for 2) - string nulo: select substring(current_time || '' from 3 for 2) ('' são duas áspas simples) Abraços
-
bem observado. Jhonas, este "sem problemas", inclui modificar a cor de um determinado valor na série?Se sim, e o colega José Luiz não conseguir fazê-lo, pode ser que ele esteja realizando o procedimento com o dataset ainda fechado.
-
Como descobrir o usuario que está usando a maquina?
pergunta respondeu ao Arckyz de Micheus em Delphi, Kylix
mas para o programa ser 100% perfeito p/ Xp, eu preciso descobrir em q pasta no documents and Settings esta o Desktop, por exemplo na minha é Usuario, eu acredito q uma boa forma de resolver isso é descobrir qual o nome de usuario q está logado na maquina ae é so ir na pasta referente no docume~1, mas agora vem a grande duvida... com faço isso? Arckyz, para saber o nome do usuário logado (apenas), você poderia fazer uso da função API do Windows: GetUserName. Pelo o que você diz você gostaria de obter algo como: "C:\Documents and Settings\micheus" e concaternar a pasta Desktop, não é?! Talvez você possa também fazer uso de variáveis do sistema (variáveis de ambiente): USERPROFILE, retorna exatamente a pasta do usuário, como a que coloquei acima; USERNAME, retorna o nome o usuário logado. você as lé utilizando a função API: GetEnvironmentVariable, dê uma olhada no help (Windows SDK) é questão de verificar a compatibilidade (existência delas em outras versões anteriores ao XP). você poderia colocar aqui a solução encontrada? Poderia ajudar a outros. Abraços -
Eder, segue anexo a minha sugestão. O código está comentado, então não entrarei em detalhes aqui. Observe que o exemplo não é 100% à prova de falhas. Por ex., se ao invés de ENTER (o que você solicitou) o usuário teclar TAB e o edit estiver vazio, será apresentada a mensagem de que o valor não é válido. Isto porque, não adianta testar no OnKeyDown (além de Key=VK_RETURN), se a tecla pressionado foi VK_TAB porque, neste caso, o evento OnExit ocorre sem que o evento OnKeyDown seja gerado. Outro caso, poderia ser uma configuração de números no padrão americano (pouco provável), mas que no caso de utilizado um número "1,500.00" deverá resultar em erro, já que estou removendo o "." para a correta conversão via StrToFloat. Dê uma conferida e veja o que precisa ser melhorado/ajustado. Abraços
-
Muito bem. Que bom que você conseguiu. :) Apenas uma dica quanto ao uso do path do sistema: - Quando tentar endereçar as pastas do Windows, é conveniente utilizar as funções da API que retornam seus nomes visto que pode ocorrer de que não sigam o padrão. Lembre-se que a instalação do Windows, pode ter sido feita em outra pasta cujo nome não seja "windows". Por ex. , C:\WinNT, D:\Win98, ... As funções são: - GetWindowsDirectory, retorna diretório do Windows (ex. C:\Windows); - GetSystemDirectory, retorna diretório da pasta de sistema do Windows (ex. C:\Windows\System ou C:\Windows\System32). Uma correção: - quando você estiver utilizando if...then...else e não tiver o que fazer no else, então você deve o omitir. Veja esta parte final do seu código (sem os comentários): ... IF not(fileexists('C:\WINDOWS\system32\' + Nome )) then CopyFile(PChar(Origem), PChar(Destino), true) ELSE //Aqui Não Aconteçe nada se o programa Já exitir, então o mesmo não precisa ser copiado novamente! end; Você não teve qualquer problema, porque este else está realmente "nulo" (é a última instrução antes do end final da procedure). Mas, vamos supor que você, ou alguém, queira fazer um upgrade neste seu código e resolva acrescentar ao final do código mais alguma instrução. Vamos supor (só um exemplo bobo): ... IF not(fileexists('C:\WINDOWS\system32\' + Nome )) then CopyFile(PChar(Origem), PChar(Destino), true) ELSE //Aqui Não Aconteçe nada se o programa Já exitir, então o mesmo não precisa ser copiado novamente! ShowMessage('Método Create executado até o fim'); end; Você consegue perceber o que vai acontecer? Este ShowMessage que deveria ser sempre executado, na verdade, passará a fazer parte do else e, com isso, a mensagem aparecerá apenas quando o arquivo existir! Caso você julgue realmente importante colocar este else "nulo", então, coloque logo a seguir um ";" para que o compilador saiba que seu bloco (o do else) já acabou: ... IF not(fileexists('C:\WINDOWS\system32\' + Nome )) then CopyFile(PChar(Origem), PChar(Destino), true) ELSE ; //Aqui Não Aconteçe nada se o programa Já exitir, então o mesmo não precisa ser copiado novamente! ShowMessage('Método Create executado até o fim'); end; uma sugestão: - Tente observar exatamente o que cada coisa é/faz no código para que, eventualmente, quando você tentar explicar algo descritivamente (sem por o código), esteja falando de uma forma que expresse melhor o que você está pensando. Por exemplo, quando você coloca a linha: Nome:= ExtractFileName(ParamStr(0)); // Crio a Variavel Nome, Para Saber o Nome Atual do ... é comenta dizendo "Crio a variável...", na verdade neste caso você não a está criando, mas sim inicializando (atribuindo um valor a ela - o resultado da função ExtractFileName). quando coloca: reg := TRegistry.Create; // Chamo a Funão Registry Na verdade, você poderia dizer que está chamando o método Create (um constructor) da classe TRegistry ou então instanciando um objeto TRegistry. neste outro caso: reg.RootKey := HKEY_CURRENT_USER; // Esclareço O evento da Função! HKEY_CURRENT_USER refere-se a uma chave do registro e não um evento e, neste caso, você estaria simplesmente selecionando a chave do registros onde iria fazer suas leituras e escritas. São pequenos detalhes, mas que as vezes podem confundir alguém que ainda não esteja muito familiarizado com as classes/funções/..., motivo pelo qual, volta e meia falo sobre a importância do uso de termos o mais apropriados possíveis. Abraços
-
Eder, caso você tenha criado código no evento OnClick destes botões, basta que chame por este procedimento que foi criado. Tente assim no OnClick do seu XiButton1:XiButton2.OnClick(XiButton2); // chamando o evento que deve requerer o parâmetro Sender XiButton2.OnClick(XiButton3); ou XiButton2Click(XiButton2); // que é o procedimento gerado em seu form XiButton2Click(XiButton3); o parâmetro deve ser o mesmo esperado pelo botão quando é chamado - normalmente é Sender, ou seja ele próprio. Experimente.
-
respondendo assim meio na corrida... pesquise pela função ExtractFileName -> com ele você resolve a questão da troca de nome do programa pelo usuário. Daí você concatena ele com o path do destino, como você quer; Abraços e até o ano que vem. :D
-
Função para checar campos obrigatórios da tabela
pergunta respondeu ao robinhocne de Micheus em Delphi, Kylix
Faça uma função que recebe o edit como parâmetro. Daí chame esta função, passando o edit. Lá no outro forum, teve um colega que postou uma mais ou menos assim. Dê uma olhada nela. Uma vez tendo a procedure/função, você pode opinar entre chamar esta função várias vezes no momento em que você clica no botão gravar, tipo: ValidaEdit(Edit1); // suposta função ou procedure ValidaEdit(Edit2); ValidaEdit(Edit3); ... // só aque você grava os dados ou ao tentar sair do edit (no evento OnExit). O problema neste caso, é que se você por exemplo clicar em outra coisa que não seja o gravar (tipo no cancelar), acabará sendo feita a validação (e estaria errado), mas há meios de contornar isto. Para não complicar muito, eu sugiriria que você utilizasse a primeira opção - muito mais simples. Abraços -
Eder, vai ter que esperar até dia 2.O trabalho hoje estava corrido e só deu para olhar o forum agora, antes de ir para casa. Abraços e boas festas... ps.: faltou luz na sua casa hoje por volta das 18:10, durante alguns minutos? (fiquei fazendo relatórios até agora. :angry:)
-
Não sei se é exatamente a resposta, mas desde que você inclua a unit do tal form na unit onde está sua thread, e que você crie este form em run-time (não esteja em auto create) acho que você consegue fazê-lo.Acredito que a opção seja criar o form sem passar o Owner, na criação/inicialização da sua thread. Entretanto, você tem que finalizá-lo (destruí-lo) quando sua thread encerrar. Form := TForm.Create(nil); // este nil deixa o form "órfão". Eu teria que entender exatamente o que você está pretendendo e como está tratando sua thread para tentar falar algo mais sobre a questão.
-
Eder, e voce quer adicionar estes edits em run-time, ou vai colocá-los em design-time mesmo?- Uma idéia seria padronizar o nome deles, de modo que você consiga buscá-los pelo nome facilmente (usando FindComponent); - Se o procedimento de ao teclar ENTER copiar o valor do edit anterior é padrão também, dá para implementar de forma genérica apenas em um único evento; - Esta impressão, vai ser feita através de que componente? Quick ou Fortes? - Para cada Edit, provavelmente haverá um label e imagino que seu conteúdo seja também impresso. Vai pensando a respeito, veja se consegue implementar algo. Logo mais eu dou uma olhada e conforme o caso tento deixar um exemplo. Abraços
-
Função para checar campos obrigatórios da tabela
pergunta respondeu ao robinhocne de Micheus em Delphi, Kylix
Essa é a procedure: procedure TFrmCadVeiculos.ValidaCamposObrigatorios; var i: Integer; msg: string; begin msg := ''; for i := 0 to DtmIza.QryIza.Fields.Count - 1 do if DtmIza.QryIza.Fields[i].Required and DtmIza.QryIza.Fields[i].IsNull then begin if msg <> '' then msg := msg + #13 msg := msg + DtmIza.QryIza.Fields[i].DisplayName; end; if msg <> '' then raise Exception.Create('Preenchimento obrigatório!'#13+msg) end; robinhocne, basta você olhar com mais atenção que vai ver que a mensagem se refere a falta do ";" na linha anterior.Este procedimento realmente seria útil, se você estivesse utilizando componentes data-aware ligados ao dataset. Nesta situação, os valores alterados nos DBEdits ficam no buffer deste dataset e antes de você chamar o método Post para gravar os dados no banco, você chamaria este procedimento para validar os valores informados. Apenas se a função não gerasse um raise (tudo ok) é que você chamaria o Post. Mas, você lê os dados em TEdits (não é data-aware), daí você move os valores dos edits para aquela lista de valores Vvlr (um TStringList) que você irá passar para uma função que montará um SQL de UPDATE ou INSERT, cuminando com o uso do método ExecSQL - não é mesmo?! Então, pensa bem... Quando é que o seu dataset QryIza terá estes valores, digitados em edits, colocados no seu buffer para ser utilizada esta função? Eu já havia comentado lá no outro forum que esta solução não vai lhe atender. Mas, se o que eu disse acima estiver errado, então pode tentar implementar e ver no que vai dar. Esta do outro tópico também é interessante, só que está em VB. Basicamente ela varre todo o form validando os Edits. Acho até que seria a abordagem mais adequada ao seu caso. Mas, como vou estar ausente uns dias, não vou nem começar uma explicação. Espero que outro colega o faça. Abraços -
(Resolvido) Ultimo campo do ClientDataSet
pergunta respondeu ao Anderson Scinfo de Micheus em Delphi, Kylix
Anderson que componente você está utilizando? A classe base da maioria dos componentes de acesso ao banco de dados é TDataSet. Através de uma propriedade private chamada FDataLink é feita a ligação do seu dataset (seja TTable, TQuery, ...) ao DBGrid. Quando há movimentação no grid, quando por exemplo você tecla a setinha para cima/baixo, pgup/pgdown,..., o procedimento para o evento OnKeyDown do seu grid vai fazer uso desta propriedade chamando o seu método MoveBy(<deslocamento>) (mover posição baseado no deslocamento - offset). // fragmento do código da unit DBGrids.pas procedure TCustomDBGrid.KeyDown(var Key: Word; Shift: TShiftState); ... VK_NEXT: begin ClearSelection; FDataLink.MoveBy(VisibleRowCount); end; VK_PRIOR: begin ClearSelection; FDataLink.MoveBy(-VisibleRowCount); end; ... end; Este método por sua vez, simplesmente chamará o método de mesmo nome do dataset ao qual ele está vinculado: // fragmento do código da unit DB.pas function TDataLink.MoveBy(Distance: Integer): Integer; begin Result := DataSet.MoveBy(Distance); end; no dataset, esta movimentação basicamente é "seqüencial" como você poderá observa no código do método: function TDataSet.MoveBy(Distance: Integer): Integer; ... while Distance > 0 do begin if FActiveRecord < FRecordCount - 1 then Inc(FActiveRecord) else begin if FRecordCount < FBufferCount then I := 0 else I := 1; if GetNextRecord then <== *** AQUI AVANÇA PRÓXIMO begin Dec(ScrollCount, I); if FActiveRecord < FRecordCount - 1 then Inc(FActiveRecord); end else begin FEOF := True; Break; end; end; Dec(Distance); Inc(Result); end; ... end; alguns componentes podem eventualmente sobrescrever este método de modo a otimizar o acesso aos dados do banco. Como vê, acho que não haveria justificativa para sua implementação, baseado nos argumentos que você passou. Como você vê, não seriam acessados os 100.000 registros de uma só vez. A título de otimização, uma das coisas que podem ser feitas é, quando do uso de datasets do tipo query, não utilizar o "*" na cláusula SELECT. Especifique o nome das colunas - você estará trazendo apenas as informações necessárias naquele momento e evitando tráfego desnecessário na rede e recursos de memória. Mas, se ainda preferir esta abordagem, acredito que se você colocar no evento OnDataChange do seu componente DataSource ligado que liga o DBGrid ao seu dataset, você poderia testar se RecNo=50: procedure TForm1.DataSourceDataChange(Sender :TObject); begin case seuClientDataSet.RecNo of 50 : begin // Refaz a consulta dos próximos 50 registros end; 1 : begin // Refaz a consulta dos 50 registros anteriores end; end; end; é apenas uma idéia. Ainda, acho que haverão questões a serem consideradas como verificar EOF e BOF, já que o simples fato de chegar ao registro 50, não significa que irá "pular de página" (o cara parou ali, não tentou ir a diante ainda). Também, pode ser preciso algum tipo de controle, já que o evento OnDataChange muito provavelmente ocorrerá quando você manipular a nova consulta (ele sempre é gerado para cada movimentação/alteração feita no dataset). Bom, espero não ter lhe confundido mais. Abraços -
Achei este post sobre o assunto, veja se lhe ajuda. Abraços e boa sorte.
-
como chamo uma imagem de um banco em paradox para um form?
pergunta respondeu ao Greed de Micheus em Delphi, Kylix
Fireboard, acho que não é bem isto não. Neste post, está explicado como carregar uma imagem para o banco de dados.Mas, aparentemente o colega Greed já tem a imagem no banco de dados e quer mostrá-la no form. Greed, será que posse lhe questionar de onde você tirou este tipo de exemplo? É o seguinte, você tem componentes data-aware em seu form: são os TDBEdits o TDBImage; com eles corretamente configurados, você não precisa de nenhuma destas linhas de código para mostrar os dados nos DBEdits e no DBImage! ;) Com é feita esta configuração: nestes componentes existem duas propriedades importantes: - Datasource, que faz a ligação com o dataset desejado; - FieldName, que diz de qual campo no dataset, você quer obter a informação a ser mostrada. Como você utiliza datamodule, ao clicar na propriedade DataSource dos DBEdits (esta deve ser a primeira a ser setada), você deverá ver uma lista dos datasources (com seus respectivos datasets setados) lá existentes. Entretanto, faz-se necessário que você tenha acrescentado o nome da unit do seu datamodule na cláusula Uses do form onde está tentando acessá-la. Estando tudo OK, você poderá selecionar, da lista que aparece, o datasource desejado. Feito isto, na propriedade FieldName, você estará ápto a selecionar o campo que será mostrado/editado no DBEdit selecionado. Dê uma conferida no que você está fazendo, pois este é o modo correto de fazer as coisas quando utiliza os componentes data-aware (simplicidade e facilidade). Abraços -
Não tenho certeza não, mas acho pouco provável que você tenha qualquer problema mais sério, pois são versões consecutivas em nenhuma grande alteração ocorreu.O que pode ser considerado problema, neste caso, seria a impossibilidade de instalar qualquer componente (não padrão) que você possa estar fazendo uso. Mas, se for componentes freewares/open source, onde o código fonte é distribuído junto, então não deve haver problemas. não é verdade. A BPL vem mas apenas não está instalada. Mas há uma versão atualizada. Veja como instalar neste post Acho que se você utilizar as vias normais para desinstalação (painel de controle - add/remover programas) não deverá ter problemas. Mas em todos os casos, lembre-se que antes de abrir seus projetos na nova versão do Delphi, é conveniente que você faça um backup dos mesmos. Assim, se você tiver algum problema mais sério (e eu duvido que tenha), você vota com a versão 6. Abraços
-
só para não ficar qualquer confusão, setar a propriedade Active=True ou chamar o método Open resultam na mesma coisa: abrir o dataset. Acho que é difícil de afirmar isto.Mas, mais uma vez, para não deixar dúvidas quanto aos termos utilizados, este erro que você apontou não parece tratar-se de um erro de compilação, mas sim de execução. Aparentemente você pôs a executar seu programa e logo de cara recebeu este erro. Isto pressupõe aquilo que o Jhonas sugeriu: que você está com o dataset aberto em design-time, e logo ao tentar executar seu programa já estaria obtendo uma mensagem de erro associada ao banco de dados. Especificamente sobre a mensagem, ela diz que você tem um componente TDBEdit (DBEdit5) configurado com um campo (propriedade FieldName) chamado Estado que não foi encontrado no dataset vinculado ao DataSource que você ligou a esta respectiva propriedade no seu DBEdit5 (propriedade DataSource). Você esta utilizando Datamodules para acomodar seus componentes de acesso ao banco? Este dataset que você está manipulando está no form principal? Ou está em outro form ou datamodule? Este form ou datamodule está sendo criado em run-time (criado via código) ou em design-time (criado via IDE)? Abraços
-
off-topic Concordo com que a faculdade não vai ensinar nada. Mas, eu diria "nada em específico". Permitam-me fazer uma ponderação: Supondo que se estude em uma boa faculdade, com professores realmente interessados e conhecedores do assunto que professam, o que se ganhará são os horizontes do conhecimento expandidos. A maioria das pessoas vê a faculdade como um lugar semelhante ao que freqüentou antes de chegar lá - as coisas chegam prontas, basta decorá-las. Não é assim que deve ser vista, ainda mais pelo preço que se paga em algumas delas. Eu vejo a universidade como um ambiente que prepara o indivíduo para o estudo mais aprofundado (pesquisas). É o tipo de conhecimento que vai ajudar a determinar o rumo de estudos a seguir, caso resolva continuar com um mestrado, p.e.. Especificamente na área de informática, há vários setores a serem explorados e cada qual implica em conhecimentos e softwares específicos, seja para Computação Gráfica, Inteligência Artificial, Redes de Computadores, Tele-comunicação e mais um monte que tem aparecido a cada dia. Se o cara pensar que vai aprender a programar em determinada linguagem na faculdade, está enganado mesmo (melhor fazer um cursinho - mas um bom). Na verdade, vai conhecer algumas ferramentas, suas aplicações, vai ter que estudá-las por conta própria e fazer os trabalhinhos que aparecem - é a idéia de que você aprende estudando, pesquisando - não copiando e colando. Mas eu acrescentaria ainda que com muito boa vontade e perseverança, fazendo uso desta excelente ferramenta chamada internet, principalmente com o advento do Google, voce aprende tudo o que se propor. Abraços