Boletim Pascal #49
Os exemplos do código fonte desta edição estão disponíveis para download.
![]() |
![]() |
Boletim Pascal #49 - 09 DE FEVEREIRO DE 2004 Índice 1. Algumas Palavras dos Editores 2. Atributos de Classe - O Jeito Delphi 3. Criando um Expert Delphi A forma mais simples de criar um Expert Delphi 4. Por Dentro das Classes e Interfaces do Delphi (I) 5. Fóruns / Listas 6. Delphi na Rede - Sites em português - Componentes, Bibliotecas e Utilidades · Shareware/Commercial · Freeware · Atualizações do Delphi e Produtos Borland - Artigos, Dicas e Truques · White Papers / Estudos de Caso - Tutoriais e Treinamento - Outros Links - Notícias ________________________________________________________________________ 1. Algumas Palavras dos Editores Editorial da Versão em Português -------------------------------- Mais uma edição do Boletim Pascal está pronta! Ao contrário do último número, esse não sofreu atrasos. Espero poder, de agora em diante, manter o ritmo de publicações em uma freqüência quase mensal. Gostaria, uma vez mais, de convidar a comunidade para apresentar artigos para o boletim- vocês podem ser traduzidos e publicados para um grupo de quase 10000 assinantes do Boletim nos vários idiomas- nada mal, hein? Só a versão em português já conta com mais de 1600 membros! Isso sem contar que ainda podem ser premiados com um dos vários softwares distribuídos mensalmente pelo Boletim. Agora chega de conversa. Divirtam-se com nosso boletim! Demian Lessa demian@knowhow-online.com.br Editor da versão em português ________________________________________________________________________ Junte-se ao maior e mais influente grupo de discussão Delphi em língua portuguesa. http://groups.yahoo.com/group/delphi-br ________________________________________________________________________ Editorial da Versão em Inglês ----------------------------- Fico feliz em anunciar que o boletim alcançou 10.000 assinantes. Meu especial agradecimento a todos os assinantes que nos possibilitaram alcançar essa marca, indicando o Boletim para seus colegas e também com webmasters que trocaram links consco, permitindo que o site ficasse bem conhecido na comunidade Delphi. Nesse número, temos um artigo por Demian Lessa mostrando como implementar atributos de classe em Object Pascal, um artigo por Daniel Wischnewski explicando como criar um Expert simples no Delphi e um atrigo por Ezra Hoch revelando o funcionamento interno de classes e interfaces. Agradeço aos autores por suas contribuições ao mesmo tempo em que anuncio os prêmios para: * Demian Lessa ("Atributos de Classe - O Jeito Delphi") . NTTools 7 For Delphi - por i-tivity (US$49.95) Para de debater-se com a API de segurança do Windows NT! Tenha sua cópia do NTTools 7 para Delphi 4/5/6/7 agora e economize incontáveis horas com essa coleção de 40 componentes VCL escritos especificamente para lidar com as funções de segurança do Windows NT. Código fonte complete está incluído com o produto. http://www.i-tivity.biz/nttools.htm * Daniel Wischnewski ("Criando um Expert no Delphi") . LMD SearchPack 2.0 - por LMD Innovative (EUR 39) LMD SearchPack inclui 3 controles que permitem a integração de capacidades avançadas de pesquisas sobre texto nos seus projetos, com suporte aos operadores AND, OR, NEAR e NOT. Código fonte completo e vários projetos de exemplo estão incluídos. http://www.ceberus.com/lmd/products/index.php3#P6 Para o próximo número, temos os seguintes prêmios disponíveis para dois de nossos colaboradores: * EurekaLog v4.1.1 - por Fabio Dell'Aria (Std $24, Pro $49, Ent $99) EurekaLog permite que sua aplicação (GUI, Console, Web, etc.) capture todas as exceções ocorridas, gere um registro detalhado (com informações de unidade, classe, método e número de linha) da execeção e o envie por e-mail. Totalmente integrado no IDE, você só precisa fazer um Rebuild de seu projeto para acrescentar a funcionalidade a sua aplicação. Não interfere com a performance e aumenta o tamanho do executável final em apenas 0,5%-4%. Compatível com Delphi 3-7 e todas as plataformas Windows. http://www.eurekalog.com/bannerclick.php?id=15 * SMExport v4.30 - por Scalabium Software ($20 standard, $35 com fontes) Conjunto nativo da VCL para exportação a partir de diversas fontes (dataset, grids, decision cube, memória, árvores DevExp, etc). Suporta exportação para MS Excel, MS Access, MS Word, PDF, Text/CSV, HTML, XML, dBase, RTF, SQL, Lotus 1-2-3, QuattroPro e mais. http://www.scalabium.com/ O link para as atualizações mais recentes do Kylix 3 publicados na última edição estavam incompletos. Agradeço a Chris Nye por nos indicar o link correto: http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=20136 Após a publicação de meu artigo "Reproduzindo sons com o PC speaker" na última edição, muitos leitores me perguntaram sobre a reprodução de sons pelo speaker nos Windows NT/2000/XP. Nesses sistemas operacionais, a API do Windows Beep aceita como argumentos a freqüência do som (em hertz) e a duração (em milisegundos), que são ignorados nos Windows 95/98/Me. Então é isso. Espero que curtam essa edição. Cordialmente, Ernesto De Spirito pascal-newsletter-owner@yahoogroups.com __________________ Collaborated in this issue: Dave Murray ________________________________________________________________________ Help & Manual 3, by EC Software - Shareware ($ 279) - Help & Manual is a WYSIWYG help authoring tool that will aid you in creating standard WinHelp files (.HLP), Adobe PDF files, HTML pages and the new HTML HELP (.CHM) files introduced in Windows 98, as well as other file formats and printed documentation, everything from a single source. This is a must- have for any software developer. http://www.helpandmanual.com/hmpage.htm ________________________________________________________________________ 2. Atributos de Classe - O Jeito Delphi Por Demian Lessa <demian @ knowhow-online.com.br> Recentemente, numa discussão na lista delphi-br do Yahoo! Grupos sobre atributos de classe, tive a chance de aprender uma nova técnica que permite implementar na prática atributos de classe em Delphi. Mas o que são mesmo atributos de classe? Atributos de classe são valores associados a uma classe e não às instâncias dessa classe. Ou seja, para toda instância da classe, o valor do atributo é o mesmo. E qual a utilidade dos atributos de classe? Posso apresentar duas bastante óbvias: contagem da quantidade de instâncias de uma classe e criação de uma instância de objeto associada à classe (um objeto gerenciador, por exemplo). Quando se deseja manter a contagem da quantidade de instâncias de uma determinada classe pode se fazer isso através de uma variável global da unidade, na seção de implementação- isso garante que ela não é alterada por código externo à unidade. Ainda assim, outras porções de código da unidade (mesmo fora da classe) podem alterar o valor dessa variável. Encapsulando o valor da contagem em um atributo de classe, esse problema é resolvido e o valor da contagem só é alterado através de chamadas específicas a métodos dessa classe. Outra importante aplicação de atributos de classe é na instanciação de objetos gerenciadores ou auxiliares. Imagine, por exemplo que, ao invés da contagem de instâncias, queiramos manter uma lista das instâncias ativas de uma determinada classe. Se utilizarmos um atributo de classe contendo a lista de instâncias o problema estará resolvido. Essa lista pode ser instanciada apenas quando necessária e destruída, por exemplo, na finalização da unidade. A implementação de atributos de classe em Delphi será apresentada abaixo. O valor do atributo de classe é encapsulado na classe e a única forma de alterar seu valor é chamando o método de atribuição do valor. O truque de como encapsular o valor do atributo na própria classe foi apresentado pelo Marcelo Almeida, um dos moderadores do grupo. Abaixo, apresento uma solução completa para utilização desses atributos. type TMyClass = class private class function Attribute: PInteger; class function InstanceList: Pointer; class procedure DestroyInstanceList; public constructor Create; class function GetAttribute: Integer; class function GetInstanceList: TObjectList; class procedure SetAttribute(Value: Integer); end; class function TMyClass.Attribute: PInteger; {$J+} const placeholder: Integer = 0; {$J-} begin Result := @placeholder; end; class function TMyClass.InstanceList: Pointer; {$J+} const placeholder: TObjectList = nil; {$J-} begin if (TObjectList(Pointer(@placeholder)^) = nil) then placeholder := TObjectList.Create(false); // nós destruímos nossos // objetos Result := @placeholder; end; class procedure TMyClass.DestroyInstanceList; begin if (GetInstanceList <> nil) then begin GetInstanceList.Free; TObjectList(InstanceList^) := nil; end; end; class function TMyClass.GetAttribute: Integer; begin Result := Attribute^; end; class function TMyClass.GetInstanceList: TObjectList; begin Result := TObjectList(InstanceList^); end; class procedure TMyClass.SetAttribute(Value: Integer); begin Attribute^ := Value; end; constructor TMyClass.Create; begin inherited Create; SetAttribute(GetAttribute + 1); GetInstanceList.Add(Self); end; destructor TMyClass.Destroy; begin SetAttribute(GetAttribute - 1); GetInstanceList.Remove(Self); if (GetInstanceList.Count = 0) then DestroyInstanceList; inherited Destroy; end; Na classe TMyClass acima, os métodos de classe Attribute e InstanceList são responsáveis pelo encapsulamento dos valores dos atributos de classe. Nesses métodos, constantes tipadas locais (diretiva $J+) são utilizadas para reservar o espaço de armazenamento dos valores dos atributos. Constantes tipadas podem ter seus valores alterados em tempo de execução da mesma forma como variáveis. Mas essas constantes são locais- como elas podem armazenar valores globais para a classe? A resposta é simples: não utilizamos os valores das constantes propriamente ditas. As constantes são declaradas apenas para que o compilador reserve o espaço de memória para o tipo associado à constante. Apesar de locais, o espaço reservado para o armazenamento dessas constantes (representado por um ponteiro simples) não é alterado ao longo da execução do programa e, portanto, podemos aproveitar esse fato para implementar os atributos de classe. Esperto, não? Os métodos Attribute e InstanceList retornam ponteiros para o espaço de armazenamento reservado pelo compilador para as constantes tipadas locais. É esse o grande truque! No código que acompanha o artigo, além da implementação completa de TMyClass, foi incluído um pequeno aplicativo exemplificando o resultado do uso dos atributos de classe de TMyClass. ________________________________________________________________________ When was the last time you voted for the Pascal Newsletter? Please support this initiative voting for us in The Programming Top 100! http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium ________________________________________________________________________ 3. Criando um Expert Delphi A forma mais simples de criar um Expert Delphi Copyright © 2003 Daniel Wischnewski. Visite minha empresa http://www.gatenetwork.com Versão em almão desse artigo disponível em http://www.delphipraxis.net/referenzen.php Traduzido por: Demian Lessa Introdução ========== Por vezes, você quer definir algumas rotinas para facilitar sua vida no uso do Delphi. Uma forma simples de fazer isso é criando um Expert. Esse primeiro artigo mostra a parte básica. Esse artigo introduz o mundo dos Experts Delphi. Experts Delphi são DLLs que são carregadas durante a inicialização do Delphi. Esse artigo foi publicado pela primeira vez em alemão, na Delphi-PRAXiS: http://www.delphipraxis.net/viewtopic.php?t=5300 NOTA: As técnicas exibidas nesse artigo são válidas a começar pelos Delphi 3 ou 4 e, desde o Delphi 7 estão obsoletas, ainda que totalmente suportadas pelo IDE do Delphi. Instalação de um Expert Delphi no IDE ===================================== Todo Expert Delphi deve ser registrado no Registro do Windows. Para cada versão do Delphi instalada na máquina, assim como para cada usuário da máquina, o Expert deve ser registrado separadamente. No Registro, o Expert Delphi deve ser registrado sob a seguinte chave: HKCU\Software\Borland\Delphi\X.0\Experts onde X deve ser substituído pela versão apropriada do Delphi suportada pelo Expert. Pode acontecer que a chave do registro do Expert não esteja instalada e, em tal caso, você deve criá-la. Abaixo da chave do Expert você deve criar uma entrada do tipo string para o Expert. O nome deve ser único e o valor deve apontar para a DLL do Expert, com o caminho completo e o nome do arquvo do Expert. Na próxima vez que o Delphi iniciar, o Expert será carregado automaticamente. A interface do Expert Delphi ============================ Para que o Expert interaja com o IDE do Delphi, ele deve exportar uma função com o nome ExpertEntryPoint, usando os seguintes parâmetros: function InitExpert( ToolServices: TIToolServices; RegisterProc: TExpertRegisterProc; var Terminate: TExpertTerminateProc): Boolean; export; stdcall; O primeiro parâmetro ToolServices fornece todas as interfaces "documentadas" do IDE do Delphi. O segundo parâmetro RegisterProc é utilizado para carregar o Expert no IDE. O terceiro parâmetro Terminate é utilizado para notificar a DLL do Expert quando ela estiver prestes a ser descarregada do IDE. O método InitExpert retorna True se o Expert foi carregado com sucesso; se não for este o caso, ele poderá retornar False ou então gerar uma exceção para forçar que a DLL seja descarregada do IDE (veja o código para uma solução exemplo). A classe PlugIn TIExpert ======================== Qualquer Expert Delphi deve ser derivado da classe TIExpert, que está declarada na unidade ExptIntf. Essa classe define métodos abstratos que devem ser implementados em cada PlugIn: GetName, GetAuthor, GetComment, GetPage, GetGlyph (diferente para Windows e Linux), GetStyle, GetState, GetIDString, GetMenuText e Execute. O objetivo de cada método é explicado no código fonte anexado. O mais simples Expert Delphi ============================ O Expert de exemplo não faz nada de mais; contudo, ele demonstra os aspectos básicos de como fazer um Expert. Ele mostra uma entrada no menu Help (comportamento padrão). Quando o usuário seleciona o item de menu, o método Execute do Expert é chamado. As restrições abaixo devem ser respeitadas para que o Expert funcione conforme esperado: * O método GetState deve retornar [esEnabled] * O método GetStyle deve retornar esStandard * O método GetMenuText retorna o texto a exibir no menu Help * O método Execute define a ação do Expert no instante de sua ativação O código fonte competo desse Expert pode ser encontrado no código em anexo. ________________________________________________________________________ Delphi-PRAXiS· Community for German-speaking Delphi programmers. We are not just (one of) the fastest growing German Delphi-forums, but we also offer some unique services like our "Delphi-PRAXiS Expert" (a Delphi add-on which allows access to our libraries directly from within the IDE). In the "code library" you can find several tips, tricks and snippets ready to use. Our database contains more than 50,000 articles for searches of any kind. >>>>>>>> http://www.delphipraxis.net <<<<<<<< ________________________________________________________________________ 4. Por Dentro das Classes e Interfaces do Delphi (I) Por Ezra Hoch Traduzido por: Demian Lessa Algumas palavras antes de começarmos: - Primeiro, gostaria de inciar esse artigo dizendo que toda a informação contida neste documento é derivada da visualização do código desmontado gerado pelo Delphi 5. Assim, tudo escrito aqui vale apenas para o Delphi 5; pode ser diferente em outras versões. - Segundo, para entender completamente o que foi escrito neste artigo, é preciso mergulhar em algum código assembler. Eu vou explicar o que o código assembler faz mas, esteja preparado, pois pode ficar confuso. Então vamos começar. No Delphi, uma instância de classe é simplesmente um ponteiro. Isso pode parecer estranho para alguns, já que vocês vêm usando instâncias no Delphi por muito tempo mas nunca tentaram tratá-las como ponteiros. Isso está correto mas somente porque a Borland foi gentil o suficiente para empacotar esses ponteiros de forma inteligente. Esses ponteiros na verdade, apontam para uma estrutura complicada na memória que tentaremos entender. Primeiramente, vamos olhar para uma definição simples de classe: TBoo1 = class FDataA, FDataB : Integer; end; var Boo1 : TBoo1; begin Boo1 := TBoo1.Create; end; Agora vamos ver para onde Boo1 aponta (Boo1 é um ponteiro, lembra?). Boo1 aponta para os seguintes valores, cada um com 4 bytes: um ponteiro para a VMT de TBoo1 FDataA FDataB Vamos agora examinar um descendente de TBoo1: TBoo2 = class(TBoo1) FDataC, FDataD : Integer; end; var Boo2 : TBoo2; begin Boo2 := TBoo2.Create; end; Boo2 aponta para os seguintes valores na memória: a Pointer to TBoo2's VMT FDataA FDataB FDataC FDataD Note que os valores para os quais Boo2 aponta incluem alguns dos valores para os quais Boo1 aponta. Isso é muito fácio de explicar- TBoo2 herda de TBoo1 e, portanto, deve apontar para todos os campos que TBoo1 aponta. Como regra geral, podemos dizer que cada instância de classe aponta para os seguintes valores: um ponteiro para a VMT da classe uma lista de campos da classe base uma lista de campos da própria classe Agora é hora de investigar as interfaces. Antes que possamos entender por completo como as interfaces funcionam, devemos entender a forma como o Delphi faz chamadas a métodos de uma instância de classe. O que o Delphi faz é chamar a rotina com um parâmetro adicional além daqueles declarados-esse parâmetro é a própria instância. Vejamos um exemplo: TMoo = class FData: Integer; procedure Act(Value: Integer); end; procedure TMoo.Act(Value: Integer); begin if Self.FData = Value then Self.FData := FData + 1 else Self.FData := Value; end; var Moo: TMoo; begin Moo := TMoo.Create; Moo.Act(15); end; Mas como o Delphi implementa isso? Simples, 'TMoo.Act' é, na verdade, compilado como uma rotina que aceita dois (!) parâmetros. Um é aquele definido no cabeçalho da rotina- 'Value', do tipo Integer. O outro é uma instância da classe TMoo. Toda vez que o Delphi chama 'Moo.Act' ele passa a instância de TMoo responsável pela chamada. Basicamente, você pode dizer que toda chamada a um método de um objeto é traduzida para uma chamada a uma função/procedimento regular que aceita o objeto fazendo a chamada como um dos parâmetros. No exemplo anterior, 'TMoo.Act' é na verdade compilada para algo como isso: procedure TMoo_Act(Self: TMoo; Value: Integer); begin if Self.FData = Value then Self.FData := FData + 1 else Self.FData := Value; end; Agora é hora de voltar às interfaces. Considere o código a seguir: IKoo = interface function Calculate(Value: Integer): Double; end; function Evaluate(Koo: IKoo; Value: Integer): Double; begin Result := Koo.Calculate(Value); end; TKooA = class(TInterfacedObject, IKoo) function Calculate(Value: Integer) : Double; end; TKooB = class(TInterfacedObject, IKoo) procedure DoNothing; function Calculate(Value: Integer): Double; end; Qualquer classe que suporte IKoo pode ser passada como uma variável à função 'Evaluate'. Quando passamos uma instância de TKooA para 'Evaluate' precisamos chamar o primeiro método de TKooA mas passamos uma instância de TKooB precisamos chamar o segundo método de TKooB! Como o Delphi sabe qual função chamar em cada caso?! Para entender a resposta, precisamos revisar o que é uma interface e como ela é implementada no Delphi. Uma interface é simplesmente uma lista de métodos que uma classe declara implementar. Ou seja, cada método na interface é implementado na classe. A forma como o Delphi implementa isso é a seguinte: Cada interface que uma classe implementa é, na verdade, uma lista de ponteiros de métodos. Assim, cada vez que uma chamada de método é feita para uma interface, a interface encaminha a chamada para um de seus ponteiros de método, dando ao objeto que na verdade implementa o método a chance de executar. Vou explicar usando o exemplo 'Koo' acima: Cada vez que a função 'Evaluate' recebe um parâmetro do tipo IKoo, ela na verdade recebe uma lista (com 4 itens- IKoo herda de IUnknown) de ponteiros de método. Se ela recebe uma interface IKoo implementada por TKooA, então o quarto item na lista estaria apontando para a método 'TKooA.Calcualte'. De outra forma, apontaria para 'TKooB.Calcualte'. Assim, quando uma chamada é feita para 'IKoo.Calculate', o que realmente é chamado é o método para o qual 'IKoo.Calcualte' aponta ('TKooA.Calculate' ou 'TKooB.Calculate'). É assim que o Delphi implementa interfaces. E agora vejamos como o Delphi armazena interfaces na memória. Para cada instância de classe que suporta 'N' interfaces, precisamos de 'N' listas de ponteiros de métodos diferentes, uma para cada interface. Mas essas listas são as mesmas no escopo de classe e, por isso, para economizar memória, apenas 'N' ponteiros de lista são mantidos para cada instância (ao invés das próprias listas). Considere o código a seguir: ILooA = interface end; ILooB = interface end; TLoo = class(TInterfacedObject, ILooA, ILooB) FLooA, FLooB: Integer; end; A instância de TLoo ficaria assim na memória: a pointer to TLoo's VMT FRefcount IUnknown FLooA FLooB ILooB ILooA Em geral, uma instância de classe teria a seguinte estrutura: ponteiro para a VMT da classe a estrutura da classe base (exceto pelo ponteiro da VMT) primeiro membro de dados da classe . . último membro de dados da classe última interface na lista de interfaces da classe . . primeira interface na lista de interfaces da classe Como disse no início do artigo, para entender como o Delphi implementa classes e interfaces, temos que olhar o código assembler produzido pelo compilador. Primeiramente, aprendemos um pouco de assembler para entender o código que segue. Em assembler existem elementos chamados 'Registros'. Um registro é um espaço de armazenamento na CPU que pode manter um valor de 32 bits. Em uma CPU Pentium, existem 8 registros principais (EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP). A maioria das ações realizadas em assembler ocorrem sobre registros. A seguir, alguns comandos em assembler: (Copia o valor para o registro) Mov Register, Value (Copia o valor de Register2 em Register1) Mov Register1, Register2 (Copia o valor apontado por Register2 em Register1. É o mesmo que "Register1 := Register2^;") Mov Register1, [Register2] (Copia o valor que apontado por (Register2 + Value) em Register1. É o mesmo que "Register1 := Pointer(Integer(Register2) + Value)^;") Mov Register1, [Register2 + Value] Examplos: MOV EAX, 10 MOV EBX, EAX MOV EAX, [EBX + 6] EBX terá o valor 10 e EAX terá o valor contido no endereço $10. Apenas para ter certeza que essa parte foi entendida, apresento um exemplo de como o Delphi atribui um valor a um membro de dados de uma instância. TGoo = class FDataA, FDataB: Integer; end; var Goo: TGoo; begin Goo := TGoo.Create; Goo.FDataA := 5; Goo.FDataB := 7; end; Se você abrir a janela de disassembler do Delphi, você veria o código: // Goo.FDataA := 5; mov eax, [ebp-$08] mov [eax + $04], $00000005 // Goo.FDataB := 7; mov eax, [ebp-$08] mov [eax + $08], $00000007 Por que copiar o valor apontado por "ebp-$08"? Simples- é nesse endereço que a variável Goo está armazenada. Note que acessar FDataA é o mesmo que acessar o endereço "eax+$04" e que acessar FDataB é o mesmo que acessar o endereço "eax+$08". Isso porque "eax" aponta para a VMT de TGoo e (como mencionei anteriormente) os valores seguintes na memória são os membros de dados de TGoo. Voltemos às interfaces. Vejam o código abaixo: IRoo = interface end; TRoo = class(TInterfacedObject, IRoo) end; var Roo: TRoo; RooIntf: IRoo; begin Roo := TRoo.Create; RooIntf := Roo; RooIntf._AddRef; end; O código assembler abaixo não é exatamente o código gerado pelo Delphi mas realiza a mesma tarefa e serve para nossos propósitos: // RooIntf := Roo; // eax contém o valor retornado por TRoo.Create, ou seja, a variável // Roo // ecx contém o valor que deve será atribuído mais tarde à RooIntf mov ecx, eax // o mesmo que: "ecx := ecx + $0C;" add ecx, $0C // RooIntf._AddRef // coloque "ecx" na pilha da CPU push ecx mov ecx, [ecx] // "call ecx" diz à CPU para saltar para o endereço armazenado como // valor em "ecx" call ecx Vamos inspecionar o código ao qual "call ecx" nos levou: // retire o valor colocado na pilha de volta em "ecx" pop ecx // o mesmo que: "ecx := ecx - $0c;" sub ecx, $0C // chame o método "_AddRef" com "ecx" como variável call TInterfacedObject._AddRef(ecx) Alguma explicação é devida aqui. Por que o Delphi adicionou "$0C" a "ecx"? Lembre que Roo é armazenado na memória (um ponteiro para a VMT, FRefCount do InterfacedObject, IUnknown de TInterfacedObject, IRoo). IRoo é o quarto valor na lista para a qual "ecx" aponta. Cada valor possui 4 bytes então IRoo é 12 (4*4) bytes após "ecx" e "$0C" é 12 na notação hexadecimal. Então, basicamente, adicionar "$0C" a "ecx" apenas fez que "ecx" apontasse para o valor correto, isto é, para IRoo de Roo (instância de TRoo). Por que coloccamos ecx na pilha? Porque precisaríamos utilizar seu valor mais tarde, quando da chamada do método "_AddRef". Lembre-se, "ecx" aponta para Roo + 12. Após isso, copiamos para "ecx" o valor para o qual "ecx" apontava. Lembre-se que eu disse que, ao invés de guardar as listas de ponteiros de métodos, o Delphi armazena apenas os ponteiros para essas listas (para economizar memória)? É por isso que "ecx" era um ponteiro e, depois, recebeu o valor para o qual ele mesmo apontava anteriormente (o mesmo que "p := p^;"). O próximo comando é chamar o método que "ecx" aponta. Agora então, olhamos para esse método. É bem curto. A única coisa que ele faz é alterar o valor de "ecx" (após recuperá-lo da pilha) de forma que seja igual ao valor de Roo (ou seja, aponte para a variável Roo). Então o método 'TInterfacedObject._AddRef' é chamado com "ecx" (Roo) como parâmetro. Isso é o mesmo que quando disse que o Delphi compila um método como uma função/procedimento regular que recebe um parâmetro extra- a instância de classe. E para que serviu isso? Acrescentamos um valor a um ponteiro, saltamos pela memória, subtraímos o mesmo valor do ponteiro e chamamos a função para a qual o ponteiro apontava! Por que preocupar-se? Poderíamos apenas ter chamado a função sem acrescentar ou subtrair esses valores! Esse é o momento em que o poder da indireção entra em cena. Note que a chamada a 'RooIntf._AddRef' não sabia que RooIntf era na verdade uma instância de TRoo. O método foi apenas chamado por estar lá para ser chamado. A implementação desse método é onde a reatribuição do ponteiro ocorreu. Isto é, somente a implementação para a qual RooIntf aponta (IRoo de TRoo) sabia quanto havia sido somado ou subtraído do ponteiro colocado na pilha. Se tivéssemos outra variável do tipo TRoo2 que também implementasse IRoo, tivéssemos feito a atribuição 'RooIntf := variável do tipo TRoo2', em seguida chamado o método 'RooIntf._AddRef', então um valor diferente seria subtraído da pilha, fazendo a chamada de método ir para a posição correta na classe TRoo2. __________________ O autor pode ser contatado através de ezra.hoch@saad.org.il ________________________________________________________________________ Vote for the Pascal Newsletter in The Programming Pages! http://www.programmingpages.com/topsite.asp?r=latium&Language=29 ________________________________________________________________________ Delphi BUGS? Catch & Log every BUG showing Unit, Class, Method, Line #. Now with support for IntraWeb applications and Anti-Freeze feature. http://www.eurekalog.com/bannerclick.php?id=15 ________________________________________________________________________ 5. Fóruns / Listas Tradução: Demian Lessa Para juntar-se a qualquer um de nossos fóruns de discussão, a melhor forma é assinar através da web, já que dessa forma você poderá acessar todas as funcionalidades disponíveis no site (como alterar suas opções de assinatura, visualizar mensagens passadas, baixar arquivos, etc.). Um ID Yahoo! é necessário para isso e você pode adquirir o seu de forma gratuita registrando-se como um usuário Yahoo! Mas se você não deseja registrar-se ou se não tem acesso completo à Internet, você pode fazer sua assinatura por e-mail (basta ter acesso a uma conta de e-mail). * Delphi: Todos os usuários de língua portuguesa são bem-vindos ao grupo de discussão; se você é um novato ou um guru, essa lista é para você. Essa é a maior e mais bem conceituada lista de discussão Delphi em língua portuguesa! http://br.groups.yahoo.com/group/delphi-br/ Assinatura: http://br.groups.yahoo.com/group/delphi-br/ delphi-br-subscribe@yahoogroups.com * Delphi (inglês): Um grupo sobre Delphi aberto a todos os níveis de usuários. http://groups.yahoo.com/group/delphi-all/ Assinatura: http://groups.yahoo.com/group/delphi-all/join delphi-all-subscribe@yahoogroups.com * Kylix (inglês): Programação Kylix. http://groups.yahoo.com/group/KylixGroup/ Assinatura: http://groups.yahoo.com/group/KylixGroup/join KylixGroup-subscribe@yahoogroups.com * Componentes (inglês): Esse é um fórum para pesquisa/recomendação de componentes de software (componetes VCL e CLX, objetos ActiveX, DLLs, SOs, etc.), assim como utilitários, tutoriais, informações, etc. http://groups.yahoo.com/group/components/ Assinatura: http://groups.yahoo.com/group/components/join components-subscribe@yahoogroups.com * Desenvolvedores de Software (inglês): Esse é um fórum para discussões sobre o desenvolvimento de software e para a troca de experiências de trabalho em ambientes profissionais e comerciais. Esse não é um fórum sobre programação; os assuntos abordados são mais gerais e independentes de linguagem de programação. http://groups.yahoo.com/group/software-developers/ Assinatura: http://groups.yahoo.com/group/software-developers/join software-developers-subscribe@yahoogroups.com ________________________________________________________________________ Merlin's Delphi Forge Delphi and Kylix news, FAQ, downloads, links, forums and more. Accepting uploads and submissions. http://www.delphifaq.net/ ________________________________________________________________________ 6. Delphi na Rede Por Dave Murray <irongut @ vodafone.net> Sites em português ================== * Comunidade Delphi de Rio Preto Portal com componentes, novidades, artigos, links e mais. http://www.delphirp.com.br/ * Planet Delphi Site brasileiro especializado em componentes para Delphi. Download grátis. http://www.fprass.hpg.ig.com.br/ * Delphi Company Site do Fernando Gonçalves dedicado ao mundo Delphi http://www.delphicompany.hpg.ig.com.br/ * IntereSite Tudo sobre Delphi http://www.ulbrajp.com.br/~tecnobyte/ * Advanced Developers Delphi, productos, novidades, consultoria... http://www.adev.com.br * Fórum Delphi-BR http://br.groups.yahoo.com/group/delphi-br/ * Fórum Delphi !! http://www.qualyinf.com.br/forum/delphi/delphi.html Componentes, Bibliotecas e Utilidades ===================================== Shareware / Comercial --------------------- * LMD SearchPack 2.0 - by LMD Innovative (EUR 39) LMD SearchPack includes 3 controls for integrating advanced text search capabilities into your projects including support of AND, OR, NEAR and NOT operators. Full source code and extensive demo projects included. http://www.ceberus.com/lmd/products/index.php3#P6 * EurekaLog v4.2 - by Fabio Dell'Aria (Std $24, Pro $49, Ent $99) Gives your application the ability to catch every exception, generate a detailed log and send it via email. Integrated with Delphi 3 - 7, a single rebuild adds EurekaLog to your app. NEW: save modified files on exception; detailed Log when the application freezes; customizable email for every exception; speed and stability improvements. http://www.eurekalog.com/bannerclick.php?id=15 Freeware -------- * WinDowse v5.1 - by Greatis Software (free for non-commercial use) Unique windows analyzer, best Borland's WinSight replacement. Greatis WinDowse is an extremely convenient tool for obtaining necessary technical information about any window. Place a mouse cursor on a window, and WinDowse will show all parameters of the window and window class. Full Delphi 3-7 source code available after 100 Euro donation. http://www.greatis.com/windowse.htm * Inno Setup v4.0.8 - by JR Software (with source) A free installer for Windows that rivals commercial installers in features and stability. Features include: all 32-bit Windows versions; create a single EXE or disk spanning; standard interface; customizable setup types; complete uninstall capabilities; zip / bzip2 compression; create shortcuts, registry + .INI entries; silent install / uninstall; register DLL, OCX and type libraries; install fonts; Pascal Script. http://www.jrsoftware.org/isinfo.php * TPages v1.2 - by Angus Johnson (with source) Visual component for simple, non-data-aware reports. Features include: text wrapped between margins, in columns or at specific offsets; multiple alignment options; multi-line page headers, footers and column headers; angled text; bitmaps, lines, boxes and arrows; page numbering; prevent blocks of text spanning across pages. http://www.users.on.net/johnson/delphi/ Atualizações do Delphi e Produtos Borland ----------------------------------------- * Fixes for Kylix 3 Issues on Newer Distros (updated) - Andrés Colubri Kylix 3 (particularly C++) on newer Linux distros (eg. RedHat 8+, Madrake 9+, SuSE 8.2) has a number of bugs: compilation errors with STL, unresolved references when linking, installer and IDE hangs, etc. This package contains a collection of fixes to address these issues. http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=20136 Artigos, Dicas e Truques ======================== * Come learn about Octane! Sneak peeks around the world! - by A Ohlsson First Octane sighting at Entwickler Konferenz in Frankfurt, Germany. http://bdn.borland.com/article/0,1410,30387,00.html * Using D7 to Consume Web Services and Transform XML - by Anders Ohlsson In this BDNtv episode, Anders shows how you can consume web services that return XML data. Anders uses Delphi 7 Enterprise to create a simple application that consumes an XML web service, transforms the result and displays custom picked data in a regular DBGrid. Format(s): Flash, Duration: 9:34. http://community.borland.com/article/0,1410,30379,00.html * Customizing the DBNavigator Enhancing the TDBNavigator component with modified graphics (glyphs), custom button captions, and more. Exposing the OnMouseUp/Down event for every button. http://delphi.about.com/library/weekly/aa090203a.htm * Accessing and managing MS Excel sheets with Delphi - by Zarko Gajic How to retrieve, display and edit Microsoft Excel spreadsheets with ADO (dbGO) and Delphi. This step-by-step article describes how to connect to Excel, retrieve sheet data, and enable editing of data (using the DBGrid). You'll also find a list of most common errors (and how to deal with them) that might pop up in the process. http://delphi.about.com/library/weekly/aa090903a.htm * Delphi History: from Pascal to Octane - by Zarko Gajic Concise descriptions of Delphi's versions and its history, along with a brief list of features and notes. Find out how Delphi evolved from Pascal to a RAD tool that can help you solve development problems not only for Windows but also for Linux and .NET. http://delphi.about.com/cs/azindex/a/dhistory.htm * Drop Down List Inside a DBGrid: Part 1 - by Zarko Gajic Here's how to place a drop down pick list into a DBGrid. Create visually more attractive user interfaces for editing lookup fields inside a DBGrid - using the PickList property of a DBGrid column. http://delphi.about.com/library/weekly/aa092703a.htm * How to Darken or Lighten TColor? http://www.swissdelphicenter.ch/en/showcode.php?id=1411 * How to execute a Javascript function in a Webbrowser / IE Document? http://www.swissdelphicenter.ch/en/showcode.php?id=1732 * How to display the items in a listview control as a group? (WinXP) http://www.swissdelphicenter.ch/en/showcode.php?id=1782 * How to detect if an Application is running within VMware? http://www.swissdelphicenter.ch/en/showcode.php?id=1819 * How to mix two colors using transparency coefficient? http://www.swissdelphicenter.ch/en/showcode.php?id=1832 * THvHQuery for exporting query to CSV file - by Henk van Hoek Export a query to a Comma Separated CSV File. http://www.delphi3000.com/articles/article_3763.asp * TEdit and EConvertError - by Andrew Kennaugh Checking TEdit for StrToFloat using OnKeyPress not OnChange. http://www.delphi3000.com/articles/article_3765.asp * Inline Assembler in Delphi (I): Introduction - by Ernesto De Spirito Reprinted from this newsletter, Ernesto's Assembler tutorial. http://www.delphi3000.com/articles/article_3766.asp * Inline Assembler in Delphi (II): ANSI strings - by Ernesto De Spirito http://www.delphi3000.com/articles/article_3767.asp * Inline Assembler in Delphi (III): Static Arrays - Ernesto De Spirito http://www.delphi3000.com/articles/article_3768.asp * Inline Assembler in Delphi (IV): Records - by Ernesto De Spirito http://www.delphi3000.com/articles/article_3769.asp * Inline Assembler in Delphi (V): Objects - by Ernesto De Spirito http://www.delphi3000.com/articles/article_3770.asp * Inline Assembler in Delphi (VI): Calling External Procedures - by Ernesto De Spirito http://www.delphi3000.com/articles/article_3771.asp * Inline Assembler in Delphi (VII): 128-bit Integer Arithmetic - by Ernesto De Spirito http://www.delphi3000.com/articles/article_3772.asp * Playing Sounds Thru The Built-In PC Speaker - by Ernesto De Spirito Using inline assembler to play sounds with the built-in PC speaker. http://www.delphi3000.com/article.asp?id=3773 * Determining if a Logical Drive Exists - by Ernesto De Spirito How to know if there is a drive assigned to a letter. http://www.delphi3000.com/articles/article_3774.asp * Using TList's and Pointers in delphi (Part II) - by Stewart Moss Demonstration of how to create records on a TList object. http://www.delphi3000.com/articles/article_3775.asp * Adding HTML Resources to DLL/EXE that IE can Reference - Matt Harrison Creating an RC file to store HTML and Images as resources that works with IE's res:// format. http://www.delphi3000.com/articles/article_3776.asp * Horizontal Modularization - by Hang Liu This article introduces a modular approach to building large applications. http://www.delphi3000.com/articles/article_3777.asp * Borland DataSnap vs Microsof ADO.NET - by Pablo Reyes A comparison between the tools provided by these technologies for building data aware applications. http://www.delphi3000.com/articles/article_3778.asp * Simple Winsock Component for Console App - by J3N7iL Jones How can I create a TCP/IP internet connection in a console application using winsock? http://www.delphi3000.com/articles/article_3779.asp * PageControl Without Border - by Tommy Andersen http://www.delphi3000.com/articles/article_3783.asp * Adding new Standard Actions - by Andreas Schmidt http://www.delphi3000.com/articles/article_3784.asp * Create a Sizeable Dialog - by Terrance Hui How to create a sizable dialog (with sizegrip) without using any 3rd party components. http://www.delphi3000.com/articles/article_3785.asp * Selecting Files - by Teun Spaans In which ways can you let your user choose a file or directory? http://www.delphi3000.com/articles/article_3786.asp * Debugging Tricks - by Andreas Schmidt How to read the content of a TStrings in the integrated debugger. http://www.delphi3000.com/articles/article_3787.asp Tutoriais e Treinamento ======================= * BorCon 2003 to be be held in San Jose, California November 1-5, 2003 http://info.borland.com/conf2003/ Outros Links ============ * Public Beta: QualityCentral Java Client - by John Kaster Use a smart client for Borland QualityCentral from wherever you can run JDK 1.4.x. http://community.borland.com/article/0,1410,30348,00.html * San Francisco East Bay Delphi User Group Our goal is to connect the Delphi developers in the Bay Area. We meet the 1st Wednesday of every month and have great speakers and sessions. We organize Delphi events with the help of eBig - the East Bay IT Group (www.ebig.org). The group will explore Delphi and how Borland's Delphi 7-8 Studio provides a migration path to Microsoft .NET for developers as well as Delphi and Linux (Kylix). http://www.ebig.org/sig/sig.aspx?SIGid=20 Notícias ======== * Altova XMLSPY to be Included in Borland Development Tools Special Edition of Altova XMLSPY Available in Borland Delphi Studio, C++ Builder, and C# Builder for the Microsoft .NET Framework. http://www.altova.com/press/2003-08-28_borland.pdf ________________________________________________________________________ Vote for the Pascal Newsletter in The Delphi Top 200! http://top200.jazarsoft.com/delphi/rank.php3?id=latium ________________________________________________________________________ VOCÊ PODE NOS AJUDAR Nós precisamos de sua ajuda para manter esse boletim ativo e cada vez maior. Você pode ajudar indicando o boletim a seus amigos e colegas: http://www.latiumsoftware.com/br/pascal/index.php Você também pode votar para nós em um ou todos esses rankings para dar maior visibilidade a nosso site e assim aumentar o número de assinantes do boletim: http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E http://www.programmingpages.com/?r=latiumsoftwarecomenpascal http://www.top219.org/cgi-bin/vote.cgi?delphi&83 http://top100borland.com/in.php?who=20 http://top200.jazarsoft.com/delphi/rank.php3?id=latium http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80 São alguns segundos para você que REALMENTE significam muito para nós. Não esqueça que também precisamos de artigos para os boletins e que existe um prêmio para um dos autores em cada número (em inglês). Todos os artigos serão considerados mas nós estamos particularmente interessados em artigos sobre Kylix já que existe pouco material disponível online. * Envie seu artigo em inglês para pascal-newsletter-owner@yahoogroups.com * Envie seu artigo em português para boletim-pascal-owner@yahoogrupos.com.br ________________________________________________________________________ Se você não recebeu o código fonte completo dos exemplos neste número, você pode obtê-los em http://www.latiumsoftware.com/br/pascal/p0049.zip ________________________________________________________________________ Esse boletim é fornecido "COMO ESTÁ" sem garantias de qualquer tipo. Seu uso implica na aceitação dos termos de licença e isenção de garantia que podem ser lidos em http://www.latiumsoftware.com/br/pascal/index.php Os artigos são propriedade e copyright de seus respectivos autores e foram reproduzidos aqui com sua permissão. Você pode redistribuir esse boletim desde que na sua íntegra (incluindo notas de propriedade e copyright), sem alterações e de forma gratuita. ________________________________________________________________________ Página principal.....: http://www.latiumsoftware.com/br/pascal/index.php Página do grupo:.....: http://br.groups.yahoo.com/group/boletim-pascal/ Assinar..............: boletim-pascal-subscribe@yahoogrupos.com.br Cancelar assinatura..: boletim-pascal-unsubscribe@yahoogrupos.com.br Assinar/cancelar.....: http://groups.yahoo.com/group/boletim-pascal/join Problemas com sua assinatura? boletim-pascal-owner@yahoogrupos.com.br ________________________________________________________________________ Boletim Pascal http://www.latiumsoftware.com/br/pascal/index.php Copyright (c) 2003 por Ernesto De Spirito. Todos os direitos reservados. ________________________________________________________________________ |
Os exemplos do código fonte desta edição estão disponíveis para download.
![]() |
Erros? Omissões? Comentários? Por favor contate-nos!






