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.lmdinnovative.com/products/vcl/lmdsearchpack/
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.
________________________________________________________________________
Support us! Vote for the Pascal Newsletter in The Programming Top 100!
http://top100borland.com/in.php?who=20
________________________________________________________________________
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/?r=latiumsoftwarecomenpascal&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://tech.groups.yahoo.com/group/components/
Assinatura:
http://tech.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://tech.groups.yahoo.com/group/software-developers/
Assinatura:
http://tech.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.lmdinnovative.com/products/vcl/lmdsearchpack/
* 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
________________________________________________________________________
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.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
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.
________________________________________________________________________
|