Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Como modificar todos los grids de un proyecto? (https://www.clubdelphi.com/foros/showthread.php?t=90127)

jams73 11-04-2016 18:27:14

Como modificar todos los grids de un proyecto?
 
Buenos Dias a todos, hoy me asignaron una tarea de por si tediosa, busco saber si alguien sabe si es posible Modificar el READONLY de los GRIDs existentes dentro de un proyecto, el proyecto que manejo tiene mas de 1,000 pantallas, y se esta volviendo tedioso el hecho de abrir cada una de las pantallas para ver si contienen un grid y modificar dicha propiedad, si alguien sabe de alguna manera se los voy a agradecer

Casimiro Notevi 11-04-2016 18:52:23

Depende del grid, puedes recorrer los forms (.dfm) y editarlos mediante un programita que te hagas. Aunque me parece recordar que algún "experto" tenía una utilidad para ello (gexperts o similar).

jams73 11-04-2016 18:56:53

Gracias Casimiro, voy a buscar esautilidad, si tu la tuvieras estaria excelente

Casimiro Notevi 11-04-2016 19:53:13

GExpert y CnWizards

Osorio 11-04-2016 22:36:44

Con el mismo delphi puedes ir al menu search y luego a la opcion find in files.

Alli escirbes el texto a buscar. En tu caso TGRID o TDBGrid y como resultado de ls busqueda te dirá donde estan contenidos esos componentes dentro del proyecto sin importar cuantas unidades son y en cuantas esta contenido.

Si das un doble click sobre los resultados, te lleva directamente al codigo donde esta contenido lo que buscaste.

jams73 12-04-2016 00:42:50

Ok Osorio, gracias, intentare eso

Lepe 12-04-2016 13:32:13

Lo que buscas lo tiene CnPacks, después de instalarlo en delphi:
- abres una ventana que tenga un grid, verás una barra de botones adosado al lado izquierdo de la ventana.
- das al segundo botón empezando por arriba: "Correct properties according to some rules" (corregir propiedad de acuerdo a ciertas condiciones).
- marcar "All forms in current project group" (por ejemplo).
- das al botón options (desmarcas las que no quieras que haga) y añades una nueva:
Class: TDBGrid
property: ReadOnly
Condition: <>
Value: True
Action: AutoCorrect (esto lo hace automático, puedes hacer que te pregunte "prompt" por cada grid)
Modify to: True

En palabras cristianas: busca la clase tdbgrid en todo el grupo de proyecto (puedes tener varios proyectos y hacer el cambio al unísono) y si la propiedad Readonly es distinta de True, pues la corrige automáticamente a True.

Aceptas la pantalla y le das al botón "Search" de la pantalla anterior. Te encontrará todo y puedes confirmar los cambios con "Confirm All", o desmarcando el check para el grid que no quieras que toque.

Eso usa RTTI, por eso no te aparece el nombre de las propiedades del grid, ni los valores que puedes asignar, tienes que saber lo que estás haciendo.

Después te aconsejo guardar todo y volver a abrir el proyecto, ya que el IDE en proyectos grandes se puede hacer el lío. Cuando abras los grids de nuevos, verás los cambios.

Saludos

Neftali [Germán.Estévez] 12-04-2016 16:21:49

Cita:

Empezado por jams73 (Mensaje 504296)
...si es posible Modificar el READONLY de los GRIDs existentes dentro de un proyecto

No debería ser muy difícil crear una utilidad en Delphi que:
(1) Recorra los Ficheros DFM de un directorio.
(2) Busque un elemento de la clase TDBGrid (o similar)
(3) Para ese elemento modifique la línea de ReadOnly
(4) Cree una copia de seguridad del fichero antiguo.

jams73 12-04-2016 23:12:19

Muy bien [Lepe] me sirvio mucho, gracias a todos por responder tan pronto!!

roman 14-04-2016 17:04:32

Cita:

Empezado por Neftali (Mensaje 504322)
No debería ser muy difícil crear una utilidad en Delphi que:
(1) Recorra los Ficheros DFM de un directorio.
(2) Busque un elemento de la clase TDBGrid (o similar)
(3) Para ese elemento modifique la línea de ReadOnly
(4) Cree una copia de seguridad del fichero antiguo.

Hola Neftalí, en cuanto a esto, ¿te refieres a una utilidad que lea un DFM como cualquier archivo de texto implementando un "parseo" específico, o estás pensando en algo que use RTTI, TReader, TWriter, etc?

LineComment Saludos

jams73 14-04-2016 17:19:51

Seria interesante "escuchar" al maestro Neftali que le responde al maestro roman....

Neftali [Germán.Estévez] 14-04-2016 17:57:33

Cita:

Empezado por roman (Mensaje 504388)
Hola Neftalí, en cuanto a esto, ¿te refieres a una utilidad que lea un DFM como cualquier archivo de texto implementando un "parseo" específico?

Exactamente a eso Román.

Un objeto TDBGrid en un DFM tiene una cabecera similar a esta (cambiando el nombre del componente):

Código Delphi [-]
  object DBGridClientes: TDBGrid
    ...

La parte del componente es bastante parecida a esta y siempre similar. Lo único "complejo" es si tiene o no columnas definidas.
Si tiene columnas será así:

Código Delphi [-]
object DBGrid1: TDBGrid
    Left = 48
    Top = 40
    Width = 481
    Height = 289
    TabOrder = 0
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'MS Sans Serif'
    TitleFont.Style = []
    Columns = <
      item
        Expanded = False
        Visible = True
      end
      item
        Expanded = False
        Visible = True
      end
      item
        Expanded = False
        Visible = True
      end>
  end

Si no tiene columnas así:

Código Delphi [-]
object DBGrid1: TDBGrid
    Left = 48
    Top = 40
    Width = 481
    Height = 289
    TabOrder = 0
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'MS Sans Serif'
    TitleFont.Style = []
  end

En ambos casos estará o no la propiedad ReadOnly así:

Código Delphi [-]
    ReadOnly = True

Si no está se considera a False.

No me parece complicado hacer un "parseo" de esos ficheros y modificarlos...
¿Qué os parece?

Neftali [Germán.Estévez] 14-04-2016 18:02:46

Otra opción más sencilla que se me ocurre es esta:

(1) Abrir los ficheros (DFM)
(2) Cambiar las líneas como esta:

Código Delphi [-]
  object DBGrid1: TDBGrid

Por otra como esta:

Código Delphi [-]
  object DBGrid1: TDBGridRO

Y crear un componente como este:

Código Delphi [-]
unit uDBGridRO;

interface

uses
  Windows, Messages, SysUtils, Classes, Controls, Grids, DBGrids;

type
  TDbGridRO = class(TDbGrid)
  private
    { Private declarations }
  protected
    procedure Loaded; override;
  public
    { Public declarations }
  published
    { Published declarations }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TDbGridRO]);
end;

{ TDbGridRO }

procedure TDbGridRO.Loaded;
begin
  inherited;

  Self.ReadOnly := True;
end;

end.

Neftali [Germán.Estévez] 14-04-2016 18:23:16

Ahora que has comentado lo de RTTI, se me ha ocurrido otra forma de hacerlo durante la ejecución, en la que no haría falta modificar el código fuente de los DFM.

(1) Poddemos capturar la apertura de un formulario utilizando:

Código Delphi [-]
  Screen.OnActiveFormChange := FormChange;

(2) Y en ese momento podemos modificar en ejecución todos los TDBGrid que existan en ese formulario cambiandoles la propiedad ReadOnly.

Código Delphi [-]
procedure TForm1.FormChange(Sender: TObject);
var
  f:TForm;
  i:integer;
  grid:TDBGrid;
begin
  if Assigned(Screen.Activeform) then begin
    f := Screen.Activeform;
    for i := 0 to (f.ComponentCount - 1) do begin
      if (f.Components[i] is TDBGrid) then begin
        grid := TDbGrid(f.Components[i]);
        // Modificarlo
        grid.Color := clMoneyGreen;
      end;
    end;

  end;
end;

Lo he probado con un ejemplo y en mi caso en diseño todos los DBGrid son blancos y en ejecución les cambio el color (pero podría cambiar el ReadOnly).


Casimiro Notevi 14-04-2016 18:24:06

La primera opción es más sencilla, al alcance de casi cualquiera.
La segunda opción es más profesional, aunque no sé si valdría la pena "cargar" con un nuevo componente clonado.

Desde luego, la opción sencilla y "semi" chapucera es la más cómoda :D

EDITO: La tercera opción, también bastante profesional :) puede que añada unos milisegundos más en la carga de cada Form, sobre todo si hay muchos componentes.

roman 14-04-2016 18:52:46

La segunda opción es ingeniosa, no cabe duda, pero cargaríamos con un componente de palo que sería como un invitado molesto :D. La tercera opción es la más sencilla pero, como dice maese Casimiro, un poco chapucera y quizá buena para algo temporal.

Por RTTI, pensaba yo más bien en leer un DFM como lo hace el IDE, usando un TReader, pero creo que puede complicarse el asunto al no saber de antemano las clases que deben registrarse.

La primera opción, el parseo del texto, creo que sería la más adecuada, pero de pronto no me parece tan sencilla o al alcance de cualquiera, considerando que el DBGrid puede estar anidado en otros contenedores y hay que determinar bien dónde termina la lista de sus propiedades. Vamos, creo que es algo que parece sencillo pero que presentará complicaciones a la hora de implementarlo.

Creo que es un reto interesante, y me parece que sería igual de sencillo (e igual de difícil) pensar en algo más general: parsear todo el DFM y almacenarlo en una estructura de datos manejable por código. Pero desconozco con qué detalles podemos encontrarnos. Por ejemplo, en principio había pensado que el DFM era una lista de propiedades y subobjetos

Código:

object name: class
  property = value
  property = value
  ...
  object name: class
    ..
  end
  ..

pero ahora me recuerda maese Neftali que hay elementos como las columnas, que son colecciones:

Código:

property = <
  item
    property = value
    property = value
    ...
  end
  item
    property = value
    property = value
    ...
  end
  ...

¿Con qué otras sopresas podemos encontrarnos?

LineComment Saludos

Lepe 15-04-2016 12:23:31

Las "sorpresas" que comenta román, las he vivido.

En algunos componentes, al cambiar una propiedad a cierto valor, el IDE de Delphi retoca automáticamente otras propiedades para que todo sea coherente (no recuerdo el caso concreto). La ventaja de hacerlo con Cnpacks, es que cambia la propiedad y ordena al IDE que cargue el componente, así que el IDE retoca las demás.

Un ejemplo, aunque no sea el caso, si modificas la propiedad Color de un panel, se cambia la propiedad ParentColor a False. Si el cambio lo haces tú por RTTI, tendrás que modificar ambas propiedades porque "Delphi no se entera del cambio que has hecho". Repito que este no es el caso porque lo hace la clase TControl, pero cuando tienes paquetes en tiempo de diseño de algunos componentes, ellos hacen el trabajo sucio por tí.


Por cierto, como siempre, ideas alternativas muy ingeniosas. Cuidadito con proyectos que tengan algún form guardado en Binario en lugar de "text DFM" (ya sea por error o lo que sea, también me ha pasado ;) )

Saludos!

roman 15-04-2016 16:12:27

Cita:

Empezado por Lepe (Mensaje 504418)
Cuidadito con proyectos que tengan algún form guardado en Binario en lugar de "text DFM"

Aunque en esos casos tendríamos ObjectBinaryToText. De hecho, ayer pensé que podríamos "copiar" lo que hace ObjectTextToBinary para parsear el DFM de texto, pero en lugar de escribir las propiedades a un stream binario (como hace dicho procedimiento) podríamos aprovechar para escribirlas en nuestra propia estructura de datos.

Luego, como no encontraba información acerca de la estructura del DFM, se me ocurrió googlear DfmToJson, ya que, a final de cuentas, mi intención es guardar el DFM de forma estructurada y, como quiera, eso es lo que hace Json. Y pues resulta que ya alguien pensó en eso y -para mi sorpresa- básicamente usa lo que había pensado: una copia ad hoc de ObjetTextToBinary :)

LineComment Saludos


La franja horaria es GMT +2. Ahora son las 18:37:31.

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