Ver Mensaje Individual
  #14  
Antiguo 14-09-2005
Avatar de jmariano
jmariano jmariano is offline
Miembro
 
Registrado: jul 2005
Posts: 376
Reputación: 19
jmariano Va por buen camino
Cita:
Empezado por roman
¿Cómo?

Quizá es fácil pero hasta el momento no veo como lograr esto. Cuando se usa "View as text" y luego "View as form" el constructor Create se ejecuta antes de leer el dfm creando una instancia de los paneles interiores que nunca serán las que contengan componentes insertadas en diseño.

Posiblemente redefiniendo DefineProperties, no lo sé. Creo que es demasiada complicación para algo que se resuelve con Frames (hasta ahora no he visto la razón para no usarlos).

// Saludos
Una forma de hacerlo sería buscando dos paneles en el propietario cuyo padre sea nuestro componente (ya que nuestro componente ha de poseer dos paneles). Para realizar esta operación habría que sobrecargar el método "CreateWnd", ya que si realizamos dicha operación en el constructor Create fallaría (creo que esto es debido a que "CreateWnd" debe de ejecutarse despues del constructor de la clase y despues de que fue leído el archivo de recursos .dfm, al igual que el método "Loaded" pero con la diferencia de que "CreateWnd" es llamado siempre que el control necesita "recrearse").

Pongo un ejemplo que construí para la ocasión:

Código Delphi [-]
type
  TMiPanel = class(TPanel)
  private
    FPanelSup: TPanel;
    FPanelInf: TPanel;
  protected
    procedure Loaded; override;
    procedure CreateWnd; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure CrearPanels;
  end;

procedure TMiPanel.CrearPanels;
var
  I: Integer;
begin
  { Recorremos los componentes del propietario para encontrar dos panels que
    tengan como padre nuestro componente. }
  for I := 0 to Owner.ComponentCount - 1 do
    if (Owner.Components[i] is TPanel) and (TPanel(Owner.Components[i]).Parent = Self) then
      if not Assigned(FPanelSup) then
        FPanelSup := TPanel(Owner.Components[i])
      else if not Assigned(FPanelInf) then
        FPanelInf := TPanel(Owner.Components[i])
      else Break; // Si no encontramos ningún panel salimos del bucle

  // Creamos el panel superior si no existe
  if not Assigned(FPanelSup) then
    FPanelSup := TPanel.Create(Owner);

  with FPanelSup do // Configuramos algunas propiedades
  begin
    Parent := Self;
    Align := alTop;
  end;

  // Creamos el panel inferior si no existe
  if not Assigned(FPanelInf) then
    FPanelInf := TPanel.Create(Owner);

  with FPanelInf do // Configuramos algunas propiedades
  begin
    Parent := Self;
    Align := alClient;
  end;
end;

constructor TMiPanel.Create(AOwner: TComponent);
begin
  inherited;
  Height := 100;
  Width := 250;
end;

procedure TMiPanel.CreateWnd;
begin
  inherited;
  CrearPanels; // Creamos los paneles
end;

procedure TMiPanel.Loaded;
begin
  inherited;
  CrearPanels; // Creamos los paneles
end;

Si lo probáis veréis que se crea un panel con dos paneles en su interior y que se pueden añadir controles en ambos paneles sin que se pierdan en ejecución. Tambien vereis, si visualizais el formulario como texto, que los controles añadidos forman parte del formulario (gracias a esto se mantiene la persistencia) y que, al volver a la vista de formulario normal, no ocurre el error de que tal panel ya existe (gracias a la comprobación que hacemos en el metodo "CrearPanels").

La desventaja, como ya dije, es que se pueden modificar los paneles en diseño y eliminar ( aunque siempre que la aplicación se ejecute los paneles aparecerán).


Cita:
Empezado por dec
Hola,


Esa fue una de las formas en que probé a hacerlo, y, obtenía un bonito error tal que este:

Project Project1.exe raised exception class EClassNotFound with message 'Class TPanel not found'.

Sin embargo, ahora que lo has dicho he probado de nuevo a hacerlo y he conseguido que el error no se de, añadiendo a la cláusula "initialization" de la unidad en que está el componente (que vengo probando) la instrución "RegisterClass(TPanel);". Creo que no queda sino impedir que se puedan eliminar los paneles en tiempo de diseño...
Para que esto no ocurra es necesario darle un nombre a los paneles (verás que, por defecto, Delphi los nombra como "Components[n]"), pero es mejor dárselos en tiempo de diseño (desde el mismo formulario) y no en el mismo componente a la hora de crearlos, porque puede haber problemas si se eliminan paneles y se vuelven a crear (es por eso que no les dí nombre en el método "CrearPanels"). (en verdad, podemos dejar vacía la propiedad "Name" de todos los componentes que soltamos en un formulario, pero despues será necesario registrar las diferentes clases de nuestros componentes manualmente).

Cita:
Empezado por CAOS
La verdad es que un compañero mío ha intentado crear el componente a partir de Frames y el problema es el mismo.
Eso ocurre porque, seguramente, está registrando el Frame en el IDE como un componente normal (utilizando el método "RegisterComponent"), lo que es un error porque el frame pierde, entonces, la capacidad de poder manejar el archivo de recursos .dfm relacioando.

Ten encuenta que un frame casi se comporta como si fuera un componente más. Fíjate que, incluso, cuando lo añadimos a un formulario pareciera que añadimos un control normal.

Si tu problema para usar los frames es porque necesitas propiedades en tiempo de diseño (es decir, propiedades que aparezcan en el inspector de objetos) te comento que puedes crearlas, aunque tendrás que realizar alguna operación especial (comentame si es por esto y te digo como hacerlo).

Saludos!
Responder Con Cita