Borland DevCon - USA
Report #10
VCL.NET
Criado - 9 de Novembro de 2005 – 09:45 p.m. (local time)
Atualizado – 9 de Novembro de 2005 – 09:45 p.m. (local time)
Marco Cantu, personagem que dispensa apresentações, ministrou uma excelente palestra sobre a VCL.NET, a versão adaptada da nossa conhecida VCL para o .NET Framework. Marco falou da arquitetura geral da VCL.NET, diferenças para a VCL Win32 e apresentou cuidados na migração de aplicações Win32 para .NET. A seguir mostro um sumário do que foi apresentado.
Antes de sua palestra, fiquei honrado em almoçar com Marco Cantu. Quando comecei a trabalhar com o Delphi, há uns 10 anos, lembro-me que foi através das “Bíblias” que consegui todo o progresso e aprendizado na ferramenta, sempre tive o Marco como um ídolo! Jamais imaginaria que um dia poderia compartilhar a mesma mesa de almoço com uma pessoa que considero ser uma das maiores celebridades Delphi do planeta. Coisas que só a DevCon poderia proporcionar.
O que é VCL.NET?
A VCL.NET é um subconjunto das classes da “VCL Win32” adaptadas para o .NET. Um dos principais objetivos é permitir que desenvolvedores se adaptem à nova plataforma fazendo uso do conhecimento adquirido durante anos com o desenvolvimento Delphi, e que possam realizar de forma mais suave a migração para o .NET. É possível recompilar suas aplicações criadas em versões antigas do Delphi com alterações mínimas (ou mesmo com nenhuma mudança).
Para criar aplicações VCL.NET no Delphi 8/2005/2006, acesse a opção VCL Forms Application dentro do grupo Delphi for .NET Projects no Object Repository.
Por que VCL.NET?
Vamos responder a pergunta, por que usar VCL.NET?
· Preservar seu código-fonte existente, porém fazendo uso da nova plataforma .NET;
· Preservar seu conhecimento - não é somente a Delphi Language ou o IDE que ajudam você desenvolver no futuro mantendo seu conhecimento do passado, mas um rico e produtivo conjunto de classes usado por todos;
· Um framework maduro: a VCL tem 10 anos, enquanto a FCL tem apenas 5;
· E minha opinião pessoal: A Borland firmou um compromisso com a VCL para os próximos anos: teremos a VCL adaptada para o Compact Framework, de forma que aplicações possam rodar em Pocket PCs por exemplo; VCL para Avalon e .NET 2.0, mesmo código usando novas tecnologias em novas versões do Windows e .NET Framework;
· Com a VCL.NET, basicamente você pode abrir seus projetos Win32 no Delphi 8/2005/2006 e recompilar, fazendo mudanças mínimas, conforme destacarei a seguir.
VCL.NET Overview
As classes da VCL.NET estão no namespace Borland.Vcl. Classes relacionadas a banco de dados estão no namespace Borland.Vcl.DB, enquanto as da RTL (Runtime Library) podem ser encontradas no namespace Borland.Vcl.Rtl. No entanto, você não precisa especificar o nome completo do namespace ao incluí-lo em uma cláusula uses, por exemplo, o que ajuda muito na migração de aplicações (defina o namespace default para o projeto).
A VCL para o .NET, ao contrário do que estava previsto no primeiro Preview que veio no compilador do Delphi 7, não é uma “casca fina” sobre a biblioteca de classes do .NET Framework. As primeiras versões da VCL adaptada consistiam basicamente de aliases de tipo, como:
TForm = Sistem.Windows.Forms.Form;
A Borland decidiu manter sua hierarquia de classes, preservando nomenclatura de métodos, propriedades, tipos e eventos. Para que qualquer objeto da VCL pudesse ser considerado um objeto .NET, TObject na VCL.NET é um alias de tipo para a classe System.Object, declarado em Borland.Delphi.System.pas:
TObject = System.Object;
Existe um Class Helper (TObjectHelper) que adiciona os métodos padrão de TObject para compatibilidade com código já existente. De forma semelhante, TPersistent e TComponent (declarados em Borland.Vcl.Classes) também são aliases para classes do .NET Framework (e também possuem class-helpers):
TPersistent = System.MarshalByRefObject;
TComponent = System.ComponentModel.Component;
Wrappers
Existem algumas classes, no entanto, que não mantém a sua hierarquia e funcionalidade da VCL, porém fazem uso de classes do .NET Framework “por baixo” para simular sua funcionalidade original. Como fazem uso de uma classe interna, permitindo o mesmo acesso através de membros públicos que mapeiam para métodos do objeto interno, são classes “wrappers”. Alguns exemplos desse tipo de classe na VCL.NET:
· TList é um Wrapper, veja que internamente temos um FList de um tipo nativo da FCL (System.Collections.ArrayList)
TList = class(TObject)
private
FList: System.Collections.ArrayList;
protected
function Get(Index: Integer): TObject;
function GetCount: Integer;
function GetCapacity: Integer;
procedure Grow; virtual;
procedure Put(Index: Integer; Item: TObject);
procedure Notify(Instance: TObject; Action: TListNotification); virtual;
procedure SetCapacity(NewCapacity: Integer);
procedure SetCount(NewCount: Integer);
public
constructor Create;
function Add(Item: TObject): Integer;
procedure Clear; virtual;
procedure Delete(Index: Integer);
class procedure Error(const Msg: string; Data: Integer); overload; //virtual;
procedure Exchange(Index1, Index2: Integer);
function Expand: TList;
function Extract(Item: TObject): TObject;
function First: TObject;
function GetEnumerator: TListEnumerator;
function IndexOf(Item: TObject): Integer;
procedure Insert(Index: Integer; Item: TObject);
function Last: TObject;
procedure Move(CurIndex, NewIndex: Integer);
function Remove(Item: TObject): Integer;
procedure Pack;
procedure Sort(Compare: TListSortCompare);
procedure Assign(ListA: TList; AOperator: TListAssignOp = laCopy; ListB: TList = nil);
property Capacity: Integer read GetCapacity write SetCapacity;
property Count: Integer read GetCount write SetCount;
property Items[Index: Integer]: TObject read Get write Put; default;
property List: System.Collections.ArrayList read FList;
end;
· TThread é um Wrapper para System.Threading.Thread, veja:
TThread = class
private
FHandle: System.Threading.Thread;
FCreateSuspended: Boolean;
FStarted: Boolean;
FSuspendCount: Integer;
FTerminated: Boolean;
FSuspended: Boolean;
FFreeOnTerminate: Boolean;
FFinished: Boolean;
FReturnValue: Integer;
FOnTerminate: TNotifyEvent;
FSynchronize: TSynchronizeRecord;
FFatalException: TObject;
procedure ThreadError(O: TObject);
procedure CallOnTerminate;
function GetPriority: TThreadPriority;
procedure SetPriority(Value: TThreadPriority);
{$IFNDEF CF}
procedure SetSuspended(Value: Boolean);
{$ENDIF}
class procedure Synchronize(ASyncRec: TSynchronizeRecord; QueueEvent: Boolean = False); overload;
protected
procedure Initialize; virtual;
procedure DoTerminate; virtual;
procedure Execute; virtual; abstract;
procedure Queue(AMethod: TThreadMethod); overload;
procedure Synchronize(Method: TThreadMethod); overload;
property ReturnValue: Integer read FReturnValue write FReturnValue;
property Terminated: Boolean read FTerminated;
public
constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
{$IFNDEF CF}
procedure Resume;
procedure Suspend;
{$ENDIF}
procedure Terminate;
function WaitFor: LongWord; overload;
function WaitFor(TimeOut: Integer; var ReturnValue: LongWord): Boolean; overload;
class procedure Queue(AThread: TThread; AMethod: TThreadMethod); overload;
class procedure RemoveQueuedEvents(AThread: TThread; AMethod: TThreadMethod);
class procedure StaticQueue(AThread: TThread; AMethod: TThreadMethod);
property FatalException: TObject read FFatalException;
property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;
property Handle: System.Threading.Thread read FHandle;
property Priority: TThreadPriority read GetPriority write SetPriority;
{$IFNDEF CF}
property Suspended: Boolean read FSuspended write SetSuspended;
{$ENDIF}
property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
end;
Migração
Algumas dicas para migração de aplicações de VCL Win32 para VCL.NET:
· Consulte as muitas dicas disponíveis no tópico “Porting VCL Applications” do Help do Delphi;
· Use o “Upgrade Wizard” da IDE, disparado quando abrimos um projeto Win32;
· Será necessário converter os arquivos .DFM para .NFM (basicamente renomear);
· Use um “Default Project Namespace” para não modificar cláusulas uses;
Cuidados
Na migração, atentar para alguns detalhes diferentes entre .NET e Win32:
· Gerenciamento de Memória é diferente, temos um Garbage Collector;
· Chamadas a API são feitas de forma diferente. Saiba usar o DLLImport;
· Procure não usar Pointers e classes “Hacks”;
· A propriedade Tag é um Variant e não Integer;
· OldCreateOrder não existe mais;
· Use StringBuilder para concatenar strings, aqui tem um exemplo:
procedure TWebForm1.Button2_Click(sender: System.Object; e: System.EventArgs);
var
sb: StringBuilder;
begin
sb := StringBuilder.Create;
sb.Append('Teste 1');
sb.Append('Teste 2');
sb.Append('Teste 3');
Label2.Text := sb.ToString();
end;
Um código-fonte, duas plataformas
Usando VCL, você pode ter um único código-fonte que pode ser compilado tanto para Win32 quanto .NET. Coloquei um exemplo abaixo de como usar diretivas de compilação caso você precise detectar se o seu código está sendo compilado em Win32 ou .NET:
{$IFDEF MSWINDOWS} // Delphi/Windows
// Código Win32
{$ENDIF}
{$IFDEF CLR} // Delphi for .NET
// Código .NET
{$ENDIF};
Windows Forms
Marco depois comparou Windows Forms com a VCL:
· É similiar VCL, um conjunto de classes sobre a API Win32;
· Tem muitos menos recursos e classes visuais, se comparado a VCL;
· Não tem o conceito de arquivo DFM;
· Componentes não-visuais aparecem em parte separada do formulário;
· Uma exclusividade: WinForms tem controles de validação;
· Vantagem do WinForms: todos os controles são “Data-Aware” (data-bound), através do uso da propriedade DataBindings;
· Existe a propriedade Language, para feitos de tradução para outros idiomas.
O que só existe na VCL.NET
· ActionList;
· Data Modules;
· A capacidade de referenciar componentes em outros formulários/DataModules em tempo de design;
· Suporte a Docking;
· Conceito de TGraphicControl;
· A VCL.NET permite o uso de WinForms controls, caso queira;
· DFMS e component Streaming;
· É distribuída com o código-fonte;
Novidades no Delphi 2005/2006
· TButtonGroup, TCategoryButtons;
· TCaptionedDockTree, TDockTabSheet;
· OnMouseActive;
· PopupParent e PopupMode para formulários;
· TGridPanel, TFlowPanel;
· Componente TTrayIcon! (finalmente);
Links
Why VCL for .NET? - by Danny Thorpe
http://bdn.borland.com/article/0,1410,31983,00.html
Overview of the VCL for .NET - by John Kaster
http://bdn.borland.com/article/0,1410,29460,00.html
Marco Cantu Web Site
Dominando a VCL.NET com Marco Cantu
Guinther Pauli
Editor Geral Revista ClubeDelphi