Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros temas > Trucos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Los mejores trucos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 01-07-2006
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Añadiendo propiedades a un formulario

Vuelvo a estar en deuda con Ray Lischner (www.tempest-sw.com) pues este truco simplemente desarrolla la técnica que describe en su propia página. De lo que se trata es de definir nuevas clases de formularios (TForm) que incorporen nuevas propiedades y eventos, de modo tal que éstas puedan ser editadas en el propio Inspector de Objetos.

Definir un nuevo componente basado en TForm. Crear un experto.

Definir un nuevo componente basado en TForm

El primer paso consiste en definir el nuevo formulario que queremos utilizar, basándonos en el tipo TForm. No es estrictamente necesario que se el ancestro sea precisamente TForm; naturalmente, puede ser también un derivado de TDataModule, pero lo interesante es que podemos utilizar con el mismo éxito cualquier derivado de TWinControl. En este ejemplo, por simplificar, solamente utilizaré formularios.

El nuevo tipo de formulario debe crearse dentro de un package de tiempo de ejecución. Podemos utilizar un package mixto, para diseño y ejecución, pero es preferible mover el código de tiempo de diseño fuera, para evitar sobrecargar de código a los programas que utilicen el formulario.

He aquí una sencilla clase que define una propiedad, un par de métodos de clase, y que intercepta eventos de modo transparente para el programador:

Código Delphi [-]
type
  TDatabaseForm = class(TForm)
  private
    FOldCloseQuery: TCloseQueryEvent;
    FOldClose: TCloseEvent;
    FDataSet: TDataSet;
    procedure SetDataSet(Value: TDataSet);
  protected
    procedure InternalClose(Sender: TObject; var Action: TCloseAction);
    procedure InternalCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure Loaded; override;
    procedure Notification(C: TComponent; Op: TOperation); override;
  public
    class procedure Mostrar;
    class function Ejecutar: TModalResult;
  published
    property DataSet: TDataSet read FDataSet write SetDataSet;
  end;

Los procedimientos de clase se implementan del siguiente modo:

Código Delphi [-]
class function TDatabaseForm.Ejecutar: TModalResult;
begin
  Result := Create(nil).ShowModal;
end;

class procedure TDatabaseForm.Mostrar;
var
  I: Integer;
  F: TForm;
begin
  LockWindowUpdate(Application.MainForm.Handle);
  try
    for I := Screen.FormCount - 1 downto 0 do
    begin
      F := Screen.Forms[i];
      if F.ClassType = Self then
      begin
        if F.WindowState = wsMinimized then
          F.WindowState := wsNormal;
        F.BringToFront;
        Exit;
      end;
      Create(Application).Show;
    end;
  finally
    LockWindowUpdate(0);
  end;
end;

El funcionamiento de estos métodos está explicada en La Cara Oculta de Delphi 4 (un poco de autobombo, ¿puedo?). Ahora los métodos relacionados con el mantenimiento del puntero al conjunto de datos:

Código Delphi [-]
procedure TDatabaseForm.SetDataSet(Value: TDataSet);
begin
  if Value <> FDataSet then
  begin
    FDataSet := Value;
    if Value <> nil then Value.FreeNotification(Self);
  end;
end;

procedure TDatabaseForm.Notification(C: TComponent; Op: TOperation);
begin
  inherited Notification(C, Op);
  if (C = FDataSet) and (Op = opRemove) then
    FDataSet := nil;
end;

Durante la ejecución del nuevo Loaded se enganchan nuestros propios manejadores de eventos:

Código Delphi [-]
procedure TDatabaseForm.Loaded;
begin
  inherited Loaded;
  FOldClose := OnClose;
  FOldCloseQuery := OnCloseQuery;
  OnClose := InternalClose;
  OnCloseQuery := InternalCloseQuery;
end;

La respuesta interna a OnClose es muy sencilla:

[delphi]
procedure TDatabaseForm.InternalClose(Sender: TObject;
var Action: TCloseAction);
begin
if Assigned(FOldClose) then FOldClose(Sender, Action);
Action := caFree;
end;
[delphi]

La respuesta a OnCloseQuery es un poco más larga:

[delphi]
procedure TDatabaseForm.InternalCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
if Assigned(FOldCloseQuery) then
begin
FOldCloseQuery(Sender, CanClose);
if not CanClose then Exit;
end;
if Assigned(FDataSet) and FDataSet.Active then
if ModalResult in [mrOk, mrNone] then
FDataSet.CheckBrowseMode
else
FDataSet.Cancel;
end;
[delphi]

Con esto terminamos la programación del package de tiempo de ejecución.

Crear un experto

Para poder aprovechar un formulario con nuevas propiedades y eventos, necesitamos un experto que cree formularios del nuevo tipo. El experto puede crearse en otro package, esta vez de tiempo de diseño, en el cual debemos además registrar el nuevo tipo de formulario a la medida. En la unidad DsgnIntf se define el siguiente método:

Código Delphi [-]
procedure RegisterCustomModule(BaseClass: TComponentClass;
  CustomModule: TCustomModuleClass);

El tipo TCustomModuleClass es una referencia a clases derivadas de TCustomModule, también definida en DsgnIntf. Para registrar un formulario personalizado debemos llamar a este procedimiento dentro de un procedimiento denominado Register:

Código Delphi [-]
procedure Register;
begin
  RegisterCustomModule(TDatabaseForm, TCustomModule);
  Aquí podemos también registrar componentes y expertos
end;

Pero podemos también definir una clase derivada de TCustomModule, si deseamos, por ejemplo, añadir comandos al menú de contexto del formulario:

Código Delphi [-]
type
  TDatabaseCustomModule = class(TCustomModule)
    function GetVerbCount: Integer; override;
    function GetVerb(Index: Integer): string; override;
    procedure ExecuteVerb(Index: Integer); override;
  end;

GetVerbCount indica el número de comandos a añadir, GetVerb debe indicar el texto del comando, y ExecuteVerb debe redefinirse para ejecutar dichos comandos:

Código Delphi [-]
function TDatabaseCustomModule.GetVerbCount: Integer;
begin
  Result := 1;
end;

function TDatabaseCustomModule.GetVerb(Index: Integer): string;
begin
  Result := '';
  if Index = 0 then
    Result := 'Alinear componentes...';
end;

procedure TDatabaseCustomModule.ExecuteVerb(Index: Integer);
begin
  AlinearComponentes(Root);
  // Esta se la debo, J
end;
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 12:15:27.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi