Componente de la escritura, parte 3
Este artículo es la parte final de un tercera parte del artículo sobre los componentes. Esta parte final se cubre los bienes / editores de componentes, cómo escribir dedicado a los editores para su componente de propiedad, y cómo escribir 'ocultos' de los componentes.
Este artículo apareció originalmente en Desarrolladores de Delphi |
derechos de Autor Pinnacle Publishing, Inc. Todos los derechos reservados.
Componente Personalizado Editores
tan pronto Como empezamos a escribir avanzado tipos de propiedad para nuestros componentes, la vida se vuelve un poco más complicado. Aunque el inspector de objetos construidos en Delphi es capaz de reconocer la mayoría de los tipos de propiedad, es imposible para él para ser capaz de lidiar con cada posible tipo personalizado se puede escribir en nuestros componentes. A veces el inspector de objetos es capaz de lidiar con nuestro sistema personalizado de los tipos, pero la edición de un arreglo complejo de propiedades en el inspector de objetos simplemente no es lo suficientemente intuitivo. Es en este punto podemos estar obligados a escribir propiedad / editores de componentes. Delphi tiene muchos predefinidos editores ya, estos editores son en la DsgnIntf.pas archivo en el $(Delphi)/Source/ToolsAPI directorio. Usted necesita a la lista de esta unidad en la cláusula uses de cualquier componente editor / editor de la propiedad, puede escribir, también es una buena idea para mantener abierto este archivo de referencia a la hora de escribir sus propios editores.
normas de Codificación de los
Para empezar voy a cubrir algunos de los estándares de codificación que se utilizan cuando el componente de escritura o de la propiedad de los editores. Sólo hay unos pocos, pero sería una buena idea para mantener a estas normas al escribir sus propios editores, ya que hace que sea más fácil para la gente a entender su trabajo.
- Al crear un editor de propiedades, final el nombre de su editor con la palabra 'Propiedad', por ejemplo, TAngleProperty
- Al crear un editor de componentes, fin el nombre de su editor con la palabra 'Editor', por ejemplo, TPieChartEditor
- Al escribir a los editores, siempre escribo el editor en una unidad separada de su componente real. Es bueno separar el tiempo de diseño y tiempo de ejecución de código y, aparte de esto, hace el EXE resultante de tamaño más pequeño (en algunas versiones de Delphi componente pueden detener las aplicaciones de compilar si no se separan de ellos). También, aparte de los paquetes para que los usuarios puedan construir con tiempo de ejecución de los paquetes si quieren !
- el Nombre de su editor de unidad con el mismo nombre que el componente de la unidad, pero añada la palabra 'reg' al final, por ejemplo, un componente con el nombre de la unidad 'Micomponente.pas' sería el resultado en el editor de nombre de archivo que se 'MyComponentreg.pas'
- Finalmente, cuando la escritura de un componente editor / editor de propiedades para el componente, mover su RegisterComponents declaración fuera de su componente de la unidad, y en su editor de componentes de la unidad. De esta manera el componente no será registrada sin el editor también estar registrado.
El editor de propiedades
Propiedad de los editores son utilizados por el IDE para permitir la edición especial de propiedades individuales dentro de un componente. Algunos editores son muy sencillos, algunos son mucho más complicados. Delphi ya tiene un número estándar de editores de propiedades, algunas de estas son:
TIntegerProperty. Se utiliza para introducir los números enteros.
TCharProperty. Se utiliza para introducir un carácter único.
TEnumProperty. Se utiliza para el seleccionado un elemento individual de un tipo enumerado (alTop, alClient etc). TBoolProperty. Se utiliza para seleccionar 'True' o 'False' para propiedades Booleanas.
TFloatProperty. Utilizado para la introducción de números de punto flotante (Variable de tipo Float / Extendido etc. El 'Real' de tipo no debe ser utilizado para el componente de propiedades).
TStringProperty. Se utiliza para introducir cadenas de hasta un máximo de 255 caracteres.
TSetProperty. Utilizados para la inclusión / exclusión de los elementos individuales de un Conjunto de bienes. Cada elemento se muestra como un valor Booleano sub-propiedad. Ajuste el valor a 'True' incluye el elemento de la configuración a 'False' excluye de ella.
TClassProperty. Esta es la clase base para descender a partir de cuando usted desea crear un editor personalizado a ser invocada para las propiedades de una clase determinada (cuando se tiene una clase como una propiedad, como TImage.Imagen).
Todos estos editores de propiedades de descender directamente o indirectamente de TPropertyEditor. TPropertyEditor tiene muchas propiedades y métodos, los más significativos son.
función AllEqual: Boolean virtual función GetAttributes: TPropertyAttributes virtual procedimiento Editar virtual función GetValue: string virtual procedimiento GetValues(Proc: TGetStrProc) virtual |
AllEqual
Cuando varios componentes son seleccionados en el inspector de objetos filtros de su lista de propiedades para sólo los que todos los componentes seleccionados tienen en común. Si el valor de cada componente para cualquier propiedad (por ejemplo, Ancho) es el mismo, el valor se mostrará, de lo contrario no se mostrará el valor. AllEqual es la rutina que determina si cada valor es idéntico.
función TStringProperty.AllEqual: Boolean var I: Integer V: string begin Resultado := False si PropCount > 1 begin V := GetStrValue de I := 1 a PropCount - 1 si GetStrValueAt(I) <> V Salir final Resultado := True final |
En el ejemplo anterior TStringProperty compara cada valor (con GetStrValueAt) con el valor del primer elemento de la lista (utilizando GetStrValue, GetStrValueAt(0) habría hecho lo mismo). El tamaño de la lista se determina mediante el uso de PropCount, esta devuelve la cantidad total de componentes seleccionados.
GetAttributes
GetAttributes es llamado por el IDE cuando se necesita recopilar información acerca de la propiedad del editor. El inspector de objetos muestra un editor adecuado, basado en la información suministrada. El resultado de GetAttributes (TPropertyAttributes) es un conjunto, por lo que puede contener una combinación de los siguientes valores (esta no es una lista completa)
paDialog
Dice el inspector de objetos para mostrar un botón [...] después de que el nombre de la propiedad, cuando el usuario hace clic en este botón, el método de Edición está activado.
paSubProperties
Dice el inspector de objetos para mostrar un [ ] botón de expansión antes de que el nombre de la propiedad, al hacer clic en este botón, se mostrará una lista expandida de la sub propiedades (normalmente las propiedades publicadas de una propiedad de clase).
paValueList
El inspector de objetos mostrará una lista desplegable con una lista de valores, esta lista está determinado por el IDE llamando al método GetValues.
NOTA: El método GetValues, no el método GetValue que es completamente diferente
paSortList
Si se combina con paValueList, los valores mostrados se ordenarán alfabéticamente.
paMultiSelect
Esta opción especifica para la IDE de que la propiedad está permitido mostrarse cuando varios componentes seleccionados. Este elemento no está presente para los editores, un TClassProperty.
paAutoUpdate
Hace que el método SetValue para ser llamado cada vez que el valor se modifica en el inspector de objetos, en lugar de esperar a que el usuario presione o editar otra propiedad. Este se utiliza para el 'Título' y 'Texto' propiedades, para dar una representación viva de el valor que el usuario está introduciendo.
paReadOnly
Si este elemento se incluye el valor en el inspector de objetos es de sólo lectura. Esto se utiliza normalmente en conjunto con paDialog. GetValue sería reemplazado a devolver una representación descriptiva de la propiedad.
Editar
Este método es llamado cuando el botón [...] de la propiedad en el que se hace clic. Este botón aparece si el paDialog elemento se incluye en el resultado de GetAttributes.
GetValue
Este método es llamado cuando el inspector de objetos necesita saber cómo mostrar la propiedad como una cadena. Esto se utiliza normalmente cuando [paDialog, paReadOnly] se especifican en el resultado de GetAttributes.
GetValues
Este método es llamado cuando el inspector de objetos necesita para recuperar una lista de valores para mostrar cuando paValueList se especifica en el resultado de GetAttributes. GetValues pasa un parámetro llamado 'Proc' que es de tipo TGetStrProc. GetStrProc se declara como TGetStrProc = procedimiento(const: string) del objeto
El IDE de espera 'Proc' para ser llamado una vez para cada valor que debe mostrarse en el inspector de objetos para esta propiedad.
procedimiento THintProperty.GetValues(Proc: TGetStrProc) begin Proc('Primer elemento para mostrar') Proc('Segundo elemento para mostrar') final |
El siguiente ejemplo muestra cómo proporcionar una lista de valores predeterminados para la 'Sugerencia' de propiedad de todos los componentes, mientras que todavía permite que el usuario introduzca un valor no está en la lista.
tipo THintProperty = clase(TStringProperty) público función GetAttributes: TPropertyAttributes reemplazar procedimiento GetValues(Proc: TGetStrProc) reemplazar final procedimiento Registrarse aplicación procedimiento Registro begin RegisterPropertyEditor(TypeInfo(String), nil, 'Ayuda', THintProperty) final { THintProperty } función THintProperty.GetAttributes: TPropertyAttributes begin Resultado := heredado GetAttributes [paValueList, paSortList] final procedimiento THintProperty.GetValues(Proc: TGetStrProc) begin Proc('Esta es una entrada requerida') Proc( 'Pulse la tecla F1 para obtener más información' ) Proc('Este valor es de sólo lectura') final |
Primera GetAttributes es válido, y [paValueList, paSortList] se incluyen en el resultado. El próximo GetValues es ignorado y los tres valores son agregados a la lista desplegable llamando a la 'Proc' procedimiento.
Registro de la propiedad de los editores
Finalmente, el editor de propiedades se registra mediante RegisterPropertyEditor. RegisterPropertyEditor toma cuatro parámetros:
PropertyType: PTypeInfo
Requiere un puntero a un TTypeInfo registro. Esto suena mucho más complicado de lo que realmente es, todo lo que necesita hacer es agregar TypInfo a nuestros usos de la cláusula, y el uso de la TypeInfo función para recuperar el puntero para nosotros. TypeInfo(SomeVariableType)
ComponentClass: TClass
Esta es la clase base que este editor debe aplicar. El editor se aplica a esta clase y cualquiera de las clases que descienden de él. Si nil se especifica, este editor se aplican a cualquier clase.
const PropertyName: string
Si este editor sólo debe aplicarse a una propiedad específica, a continuación, el nombre de la propiedad debe ser especificado aquí. Si el editor debe aplicar a cualquier propiedad del tipo especificado en PropertyType este valor debe ser '.
EditorClass: TPropertyEditorClass
Esta es la clase que ha sido creado para tratar con la propiedad. En el ejemplo anterior, la clase es THintProperty.
el Uso de RegisterPropertyEditor incorrectamente
es importante cuando se utiliza RegisterPropertyEditor que proporcione la información correcta. El suministro de la información incorrecta podría significar que su editor afecta incorrecto propiedades (por ejemplo, Todas las propiedades de la cadena) o incorrecta de los componentes.
En el otro extremo, el ajuste de los parámetros incorrectamente podría decir que sólo una propiedad específica de un componente específico (y descendientes) se asocia con su editor. Esto no parece mucho de un problema al principio, pero descendiente de los componentes pueden poner en práctica las propiedades adicionales del mismo tipo. Como estas propiedades, obviamente, tendrá un nombre diferente que no tiene la propiedad correcta editor asignado a ellos.
Un ejemplo de mal registrado editor ya existe dentro de la VCL. El editor estándar para TCollection fue registrada para todas las clases descendientes de TComponent. El problema es que la clase más baja capaz de mostrarse en el inspector de objetos es TPersistent (la clase que TComponent desciende de).
Si un componente tiene una propiedad de tipo TPersistent (que, por defecto, expone sus sub-propiedades en una lista expandible), y una de sus propiedades es de tipo TCollection, el resultado es un [...] que se encuentra en el inspector de objetos que no hace nada cuando se hace clic (como vimos en la parte dos de este artículo de la serie).
La solución a este problema parece bastante sencillo. En lugar de nuestro sub-propiedad de ser descendientes de TPersistent podríamos descender de TComponent lugar. Sin embargo, el comportamiento por defecto para una propiedad de tipo de TComponent (Según lo determinado por el editor de la propiedad TComponentProperty editor) es para mostrar una lista de otros componentes, en lugar de la sub-propiedades de un incrustado componente.
La verdadera solución es realmente simple, pero sólo si usted sabe cómo escribir un editor de propiedades.
Paso 1:
tipo TExpandingRecord = clase(TPersistent) |
Debe cambiarse a leer
tipo TExpandingRecord = clase(TComponent) |
Paso 2: Crear un editor de propiedades como, por lo que
tipo TExpandingRecordProperty = clase(TClassProperty) público función GetAttributes : TPropertyAttributes reemplazar final |
procedimiento Registrarse
aplicación
procedimiento Registrarse
begin
RegisterComponents('Artículo', [TExpandingComponent])
RegisterPropertyEditor(TypeInfo(TExpandingRecord), nil, ', TExpandingRecordProperty)
final
{ TExpandingRecordProperty }
función TExpandingRecordProperty.GetAttributes: TPropertyAttributes
begin
Resultado := [paReadOnly, paSubProperties]
final
Paso 3: Quitar la RegisterComponents llamada desde el componente de la unidad, y registrarlo en el editor de la unidad en su lugar. De esta manera podemos asegurar que el componente no será registrada sin el componente.
Ahora nuestra propiedad de tipo TExpandingRecord mostrará como una expansión de la propiedad (debido a nuestra devolución paSubProperties de GetAttributes), y el editor predeterminado para TCollection funcionará como el propietario de la TCollection propiedad es un TComponent.
cuadro de Diálogo de editores de propiedades
la Mayoría de las veces, a la hora de crear una propiedad personalizada editor, el propósito es proporcionar una gráfica la manera de relacionarse con la propiedad.
Este primer ejemplo es una manera muy sencilla de permitir al usuario introducir varias líneas en la propiedad 'Caption' de un TLabel. Aunque en este ejemplo no es muy complicado, se muestra cómo incluir un formulario dentro de su editor.
Paso 1:
Seleccionar Archivo, Nueva Aplicación desde el menú principal. Esto creará un formulario, el nombre del formulario 'fmLabelEdit', agrega un TMemo para el formulario denominado memCaption. Agregue dos botones 'ACEPTAR' y 'Cancelar' con el ModalResult propiedades establecidas para mrOK y mrCancel respectivamente.
Paso 2:
Agregar DsgnIntf y TypInfo a la cláusula uses.
Paso 3:
Añadir la siguiente propiedad del editor de código para su unidad.
TCaptionProperty = clase(TStringProperty) público función GetAttributes: TPropertyAttributes reemplazar procedimiento Editar reemplazar final |
Y registrar el editor de la propiedad, como así
procedimiento Registrarse aplicación {$R *.DFM} procedimiento Registro begin RegisterPropertyEditor(TypeInfo(TCaption), TLabel, 'Título', TCaptionProperty) final |
Paso 4:
Agregue el código siguiente para que el inspector de objetos para mostrar la [...] botón editar después el nombre de la propiedad.
función TCaptionProperty.GetAttributes: TPropertyAttributes begin Resultado := heredado GetAttributes [paDialog] final |
Paso 5:
por último, vamos a crear una instancia de nuestro editor de formulario, establecer el contenido de la nota a la actual título y, a continuación, mostrar el formulario modal.
procedimiento TCaptionProperty.Editar var I: Integer begin con TfmLabelEdit.Crear(Aplicación) prueba memCaption.Líneas.Texto := GetStrValue ShowModal {Si el ModalResult de la forma es mrOK, tenemos que establecer la propiedad 'Caption' de cada TLabel.} si ModalResult = mrOK de I:=0 a PropCount-1 TLabel(GetComponent(I)).Caption := memCaption.Líneas.Texto finalmente Libre final final |
Paso 6:
Instalar la unidad en el paquete y, a continuación, pruebe el nuevo editor !
Avanzado editores de propiedades
Cualquiera que haya usado alguna vez TActionList o TDataSet (TTable / TQuery) tener experiencia en el ejemplo siguiente, posiblemente sin siquiera darse cuenta.
El ActionList editor es, obviamente, un editor personalizado, ya que permite la agrupación de acciones, mientras que el FieldsEditor de TDataSet puede parecer a primera vista como un editor normal, pero en una inspección más cercana tiene un menú con elementos como 'Agregar campos'. Sin embargo, la característica más notable de estos dos editores, no es que sean de diálogo personalizado editores (similar a la que hemos explicado antes), pero el hecho de que los elementos que crean se incluye en la clase principal de la declaración de la unidad actual.
tipo TForm1 = clase(TForm) ActionList1: TActionList Action1: TAction Action2: TAction privada { Private declarations } público { Public declarations } final |
El beneficio de esto es que el IDE es consciente de estos elementos, por lo tanto, lo que les permite ser seleccionado de una lista de objetos siempre que la propiedad de un componente requiere de ellos.
En la ilustración de arriba, dos acciones que se suman a una TActionList, haciendo clic en la 'Acción' de propiedad de Button1 muestra una lista que consiste en las acciones añadido. Las dos acciones se han añadido también a la clase del Formulario de declaración, y por lo tanto puede ser referido por su nombre (Action1, Action2).
El truco aquí se encuentra en su totalidad en el editor de la propiedad y no en el componente. Cuando un editor de propiedades se activa (es decir, el método de Edición que se llama) el Diseñador de la propiedad contiene una referencia válida a un IFormDesigner (TFormDesigner en Delphi 4). Muchas de las funciones de esta interfaz no están dentro del alcance de este artículo, si usted desea aprender más acerca de las capacidades de esta interfaz me gustaría recomendar un libro llamado Delphi Manual del Programador Marco Cantu.
Algunos de los métodos que se incluyen
función MethodExists(const Nombre: string): Boolean procedimiento RenameMethod(const CurName, NewName: string) procedimiento SelectComponent(Ejemplo: TPersistent) procedimiento ShowMethod(const Nombre: string) función GetComponent(const Nombre: string): TComponent función CreateComponent(ComponentClass: TComponentClass Padre: TComponent Left, Top, Width, Height: Integer): TComponent |
Algunas de las llamadas son bastante elementales, MethodExists por ejemplo devolverá True o False dependiendo de si o no un método de nombre ya existe dentro de la forma de la unidad actual (FormCreate, Button1Click etc). ShowMethod para desplazar el cursor hasta el llamado método, y RenameMethod vamos a cambiar el nombre de un método.
Los dos métodos que son de interés para el uso en este punto son:
CreateComponent
Dada una clase de componente, un padre para sujetar el componente, y la posición / dimensiones, el diseñador creará una instancia de la clase como si el desarrollador ha seleccionado de la paleta de componentes y añadido a la forma de sí mismo.
Modificado
Informa el diseñador que algo ha sido alterado (una propiedad, etc). Esto altera el estado de la unidad para que el IDE sabe, se debe guardar antes de cerrar (también habilita el botón guardar en el IDE).
Cuando la adición de elementos a nuestra matriz de todo lo que tenemos que hacer es conseguir TMyProperty.Diseñador para crear un componente en nuestro nombre. Este componente será añadido a la forma y a cualquier propiedad que se refiere a una clase de este tipo, será automáticamente conscientes de ello. En el caso de TActionList y TDataSet los componentes que se agregan a la forma no son visibles en tiempo de diseño, el propietario componente actúa como una especie de 'administrador' para los componentes.
Durante el tiempo de diseño usted no verá un TAction o un TField componente en la paleta de componentes, que posiblemente podría hacer sospechar que no están registrados, sin embargo, el IDE es todavía capaz de crear instancias de estos componentes (y que no son visibles). La respuesta no es que ellos no están registrados, este comportamiento es el resultado de un 'cómo' que el componente está registrado.
Mientras que RegisterComponents se agrega componentes de la paleta de componentes, la RegisterNoIcon método de registrar el componente sin necesidad de añadir a la paleta de componentes, registrando de esta manera también le dice a la IDE de que el componente que no se muestran durante el tiempo de diseño.
En el siguiente ejemplo vamos a crear un componente llamado TWavSound (un componente adicional llamado TWavButton se incluye en el código fuente que acompaña a este artículo como un ejemplo). TWavSound simplemente mantiene los datos de un archivo WAV, y reproducir el sonido en la demanda. Aunque sería sencillo para nosotros una gota TWavSound en nuestro formulario para cada WAV de sonido se requiere, a nuestro formulario de pronto podría empezar a ser inmanejable, por lo tanto, también vamos a crear una clase manager llamado TWavList.
Todas las técnicas utilizadas en el código fuente de estos componentes fue cubierto en la parte dos de esta serie de artículos, por lo que el código fuente no serán cubiertos en cualquier gran nivel de detalle. Sin embargo, voy a mostrar la clase de las declaraciones de estos componentes sólo para darle una idea de cómo están estructuradas.
Nota: En la parte inferior de la unidad, dentro de la sección de inicialización de la unidad puede observar el siguiente código:
inicialización
RegisterClass(TWavSound)
La razón es que RegisterNoIcon no parece hacer un trabajo completo. Aunque nos permite crear instancias de la registrada en el componente de nuestro editor de propiedades de algo parece ir mal cuando un proyecto está re-cargado que contienen estos componentes. Una 'Clase no registrada' cuadro de mensaje que aparece en pantalla y el proyecto está dañado. Además de registrar la clase de esta manera parece solucionar el problema
TWavSound
tipo PWavData = ^TWavData TWavData = empaquetado registro Tamaño: Longint Datos: array[0..0] de byte final TWavSound = clase(TComponent) privada FWavData: PWavData FWav: TWav procedimiento ReadWavData(Stream: TStream) procedimiento WriteWavData(Stream: TStream) protegido procedimiento DefineProperties(Filer: TFiler) reemplazar público destructor Destruir reemplazar procedimiento Claro procedimiento LoadFromFile(const nombre de archivo: TFilename) procedimiento LoadFromStream(Stream: TStream) procedimiento Jugar publicado final |
FWavData
se utiliza para almacenar el contenido del archivo WAV una vez que se carga una secuencia de comandos o un archivo.
Borrar
Va a liberar la memoria que contiene FWavData.
Juego
Se utiliza el sndPlaySound llamada a la API en MMSystem.pas t
Componente de la escritura, parte 3
Componente de la escritura, parte 3 : Multi-millones de consejos para hacer su vida mas facil.
Este articulo es la parte final de un tercera parte del articulo sobre los componentes. Esta parte final se cubre los bienes / editores de componentes, como escribir dedicado a los editores para su componente de propiedad, y como escribir 'ocultos' de los componentes.
Este articulo aparecio originalmente en Desarrolladores de Delphi |
derechos de Autor Pinnacle Publishing, Inc. Todos los derechos reservados.
Componente Personalizado Editores
tan pronto Como empezamos a escribir avanzado tipos de propiedad para nuestros componentes, la vida se vuelve un poco mas complicado. Aunque el inspector de objetos construidos en Delphi es capaz de reconocer la mayoria de los tipos de propiedad, es imposible para el para ser capaz de lidiar con cada posible tipo personalizado se puede escribir en nuestros componentes. A veces el inspector de objetos es capaz de lidiar con nuestro sistema personalizado de los tipos, pero la edicion de un arreglo complejo de propiedades en el inspector de objetos simplemente no es lo suficientemente intuitivo. Es en este punto podemos estar obligados a escribir propiedad / editores de componentes. Delphi tiene muchos predefinidos editores ya, estos editores son en la DsgnIntf.pas archivo en el $(Delphi)/Source/ToolsAPI directorio. Usted necesita a la lista de esta unidad en la clausula uses de cualquier componente editor / editor de la propiedad, puede escribir, tambien es una buena idea para mantener abierto este archivo de referencia a la hora de escribir sus propios editores.
normas de Codificacion de los
Para empezar voy a cubrir algunos de los estandares de codificacion que se utilizan cuando el componente de escritura o de la propiedad de los editores. Solo hay unos pocos, pero seria una buena idea para mantener a estas normas al escribir sus propios editores, ya que hace que sea mas facil para la gente a entender su trabajo.
- Al crear un editor de propiedades, final el nombre de su editor con la palabra 'Propiedad', por ejemplo, TAngleProperty
- Al crear un editor de componentes, fin el nombre de su editor con la palabra 'Editor', por ejemplo, TPieChartEditor
- Al escribir a los editores, siempre escribo el editor en una unidad separada de su componente real. Es bueno separar el tiempo de diseño y tiempo de ejecucion de codigo y, aparte de esto, hace el EXE resultante de tamaño mas pequeño (en algunas versiones de Delphi componente pueden detener las aplicaciones de compilar si no se separan de ellos). Tambien, aparte de los paquetes para que los usuarios puedan construir con tiempo de ejecucion de los paquetes si quieren !
- el Nombre de su editor de unidad con el mismo nombre que el componente de la unidad, pero añada la palabra 'reg' al final, por ejemplo, un componente con el nombre de la unidad 'Micomponente.pas' seria el resultado en el editor de nombre de archivo que se 'MyComponentreg.pas'
- Finalmente, cuando la escritura de un componente editor / editor de propiedades para el componente, mover su RegisterComponents declaracion fuera de su componente de la unidad, y en su editor de componentes de la unidad. De esta manera el componente no sera registrada sin el editor tambien estar registrado.
El editor de propiedades
Propiedad de los editores son utilizados por el IDE para permitir la edicion especial de propiedades individuales dentro de un componente. Algunos editores son muy sencillos, algunos son mucho mas complicados. Delphi ya tiene un numero estandar de editores de propiedades, algunas de estas son:
TIntegerProperty. Se utiliza para introducir los numeros enteros.
TCharProperty. Se utiliza para introducir un caracter unico.
TEnumProperty. Se utiliza para el seleccionado un elemento individual de un tipo enumerado (alTop, alClient etc). TBoolProperty. Se utiliza para seleccionar 'True' o 'False' para propiedades Booleanas.
TFloatProperty. Utilizado para la introduccion de numeros de punto flotante (Variable de tipo Float / Extendido etc. El 'Real' de tipo no debe ser utilizado para el componente de propiedades).
TStringProperty. Se utiliza para introducir cadenas de hasta un maximo de 255 caracteres.
TSetProperty. Utilizados para la inclusion / exclusion de los elementos individuales de un Conjunto de bienes. Cada elemento se muestra como un valor Booleano sub-propiedad. Ajuste el valor a 'True' incluye el elemento de la configuracion a 'False' excluye de ella.
TClassProperty. Esta es la clase base para descender a partir de cuando usted desea crear un editor personalizado a ser invocada para las propiedades de una clase determinada (cuando se tiene una clase como una propiedad, como TImage.Imagen).
Todos estos editores de propiedades de descender directamente o indirectamente de TPropertyEditor. TPropertyEditor tiene muchas propiedades y metodos, los mas significativos son.
funcion AllEqual: Boolean virtual funcion GetAttributes: TPropertyAttributes virtual procedimiento Editar virtual funcion GetValue: string virtual procedimiento GetValues(Proc: TGetStrProc) virtual |
AllEqual
Cuando varios componentes son seleccionados en el inspector de objetos filtros de su lista de propiedades para solo los que todos los componentes seleccionados tienen en comun. Si el valor de cada componente para cualquier propiedad (por ejemplo, Ancho) es el mismo, el valor se mostrara, de lo contrario no se mostrara el valor. AllEqual es la rutina que determina si cada valor es identico.
funcion TStringProperty.AllEqual: Boolean var I: Integer V: string begin Resultado := False si PropCount > 1 begin V := GetStrValue de I := 1 a PropCount - 1 si GetStrValueAt(I) <> V Salir final Resultado := True final |
En el ejemplo anterior TStringProperty compara cada valor (con GetStrValueAt) con el valor del primer elemento de la lista (utilizando GetStrValue, GetStrValueAt(0) habria hecho lo mismo). El tamaño de la lista se determina mediante el uso de PropCount, esta devuelve la cantidad total de componentes seleccionados.
GetAttributes
GetAttributes es llamado por el IDE cuando se necesita recopilar informacion acerca de la propiedad del editor. El inspector de objetos muestra un editor adecuado, basado en la informacion suministrada. El resultado de GetAttributes (TPropertyAttributes) es un conjunto, por lo que puede contener una combinacion de los siguientes valores (esta no es una lista completa)
paDialog
Dice el inspector de objetos para mostrar un boton [...] despues de que el nombre de la propiedad, cuando el usuario hace clic en este boton, el metodo de Edicion esta activado.
paSubProperties
Dice el inspector de objetos para mostrar un [ ] boton de expansion antes de que el nombre de la propiedad, al hacer clic en este boton, se mostrara una lista expandida de la sub propiedades (normalmente las propiedades publicadas de una propiedad de clase).
paValueList
El inspector de objetos mostrara una lista desplegable con una lista de valores, esta lista esta determinado por el IDE llamando al metodo GetValues.
NOTA: El metodo GetValues, no el metodo GetValue que es completamente diferente
paSortList
Si se combina con paValueList, los valores mostrados se ordenaran alfabeticamente.
paMultiSelect
Esta opcion especifica para la IDE de que la propiedad esta permitido mostrarse cuando varios componentes seleccionados. Este elemento no esta presente para los editores, un TClassProperty.
paAutoUpdate
Hace que el metodo SetValue para ser llamado cada vez que el valor se modifica en el inspector de objetos, en lugar de esperar a que el usuario presione o editar otra propiedad. Este se utiliza para el 'Titulo' y 'Texto' propiedades, para dar una representacion viva de el valor que el usuario esta introduciendo.
paReadOnly
Si este elemento se incluye el valor en el inspector de objetos es de solo lectura. Esto se utiliza normalmente en conjunto con paDialog. GetValue seria reemplazado a devolver una representacion descriptiva de la propiedad.
Editar
Este metodo es llamado cuando el boton [...] de la propiedad en el que se hace clic. Este boton aparece si el paDialog elemento se incluye en el resultado de GetAttributes.
GetValue
Este metodo es llamado cuando el inspector de objetos necesita saber como mostrar la propiedad como una cadena. Esto se utiliza normalmente cuando [paDialog, paReadOnly] se especifican en el resultado de GetAttributes.
GetValues
Este metodo es llamado cuando el inspector de objetos necesita para recuperar una lista de valores para mostrar cuando paValueList se especifica en el resultado de GetAttributes. GetValues pasa un parametro llamado 'Proc' que es de tipo TGetStrProc. GetStrProc se declara como TGetStrProc = procedimiento(const: string) del objeto
El IDE de espera 'Proc' para ser llamado una vez para cada valor que debe mostrarse en el inspector de objetos para esta propiedad.
procedimiento THintProperty.GetValues(Proc: TGetStrProc) begin Proc('Primer elemento para mostrar') Proc('Segundo elemento para mostrar') final |
El siguiente ejemplo muestra como proporcionar una lista de valores predeterminados para la 'Sugerencia' de propiedad de todos los componentes, mientras que todavia permite que el usuario introduzca un valor no esta en la lista.
tipo THintProperty = clase(TStringProperty) publico funcion GetAttributes: TPropertyAttributes reemplazar procedimiento GetValues(Proc: TGetStrProc) reemplazar final procedimiento Registrarse aplicacion procedimiento Registro begin RegisterPropertyEditor(TypeInfo(String), nil, 'Ayuda', THintProperty) final { THintProperty } funcion THintProperty.GetAttributes: TPropertyAttributes begin Resultado := heredado GetAttributes [paValueList, paSortList] final procedimiento THintProperty.GetValues(Proc: TGetStrProc) begin Proc('Esta es una entrada requerida') Proc( 'Pulse la tecla F1 para obtener mas informacion' ) Proc('Este valor es de solo lectura') final |
Primera GetAttributes es valido, y [paValueList, paSortList] se incluyen en el resultado. El proximo GetValues es ignorado y los tres valores son agregados a la lista desplegable llamando a la 'Proc' procedimiento.
Registro de la propiedad de los editores
Finalmente, el editor de propiedades se registra mediante RegisterPropertyEditor. RegisterPropertyEditor toma cuatro parametros:
PropertyType: PTypeInfo
Requiere un puntero a un TTypeInfo registro. Esto suena mucho mas complicado de lo que realmente es, todo lo que necesita hacer es agregar TypInfo a nuestros usos de la clausula, y el uso de la TypeInfo funcion para recuperar el puntero para nosotros. TypeInfo(SomeVariableType)
ComponentClass: TClass
Esta es la clase base que este editor debe aplicar. El editor se aplica a esta clase y cualquiera de las clases que descienden de el. Si nil se especifica, este editor se aplican a cualquier clase.
const PropertyName: string
Si este editor solo debe aplicarse a una propiedad especifica, a continuacion, el nombre de la propiedad debe ser especificado aqui. Si el editor debe aplicar a cualquier propiedad del tipo especificado en PropertyType este valor debe ser '.
EditorClass: TPropertyEditorClass
Esta es la clase que ha sido creado para tratar con la propiedad. En el ejemplo anterior, la clase es THintProperty.
el Uso de RegisterPropertyEditor incorrectamente
es importante cuando se utiliza RegisterPropertyEditor que proporcione la informacion correcta. El suministro de la informacion incorrecta podria significar que su editor afecta incorrecto propiedades (por ejemplo, Todas las propiedades de la cadena) o incorrecta de los componentes.
En el otro extremo, el ajuste de los parametros incorrectamente podria decir que solo una propiedad especifica de un componente especifico (y descendientes) se asocia con su editor. Esto no parece mucho de un problema al principio, pero descendiente de los componentes pueden poner en practica las propiedades adicionales del mismo tipo. Como estas propiedades, obviamente, tendra un nombre diferente que no tiene la propiedad correcta editor asignado a ellos.
Un ejemplo de mal registrado editor ya existe dentro de la VCL. El editor estandar para TCollection fue registrada para todas las clases descendientes de TComponent. El problema es que la clase mas baja capaz de mostrarse en el inspector de objetos es TPersistent (la clase que TComponent desciende de).
Si un componente tiene una propiedad de tipo TPersistent (que, por defecto, expone sus sub-propiedades en una lista expandible), y una de sus propiedades es de tipo TCollection, el resultado es un [...] que se encuentra en el inspector de objetos que no hace nada cuando se hace clic (como vimos en la parte dos de este articulo de la serie).
La solucion a este problema parece bastante sencillo. En lugar de nuestro sub-propiedad de ser descendientes de TPersistent podriamos descender de TComponent lugar. Sin embargo, el comportamiento por defecto para una propiedad de tipo de TComponent (Segun lo determinado por el editor de la propiedad TComponentProperty editor) es para mostrar una lista de otros componentes, en lugar de la sub-propiedades de un incrustado componente.
La verdadera solucion es realmente simple, pero solo si usted sabe como escribir un editor de propiedades.
Paso 1:
tipo TExpandingRecord = clase(TPersistent) |
Debe cambiarse a leer
tipo TExpandingRecord = clase(TComponent) |
Paso 2: Crear un editor de propiedades como, por lo que
tipo TExpandingRecordProperty = clase(TClassProperty) publico funcion GetAttributes : TPropertyAttributes reemplazar final |
procedimiento Registrarse
aplicacion
procedimiento Registrarse
begin
RegisterComponents('Articulo', [TExpandingComponent])
RegisterPropertyEditor(TypeInfo(TExpandingRecord), nil, ', TExpandingRecordProperty)
final
{ TExpandingRecordProperty }
funcion TExpandingRecordProperty.GetAttributes: TPropertyAttributes
begin
Resultado := [paReadOnly, paSubProperties]
final
Paso 3: Quitar la RegisterComponents llamada desde el componente de la unidad, y registrarlo en el editor de la unidad en su lugar. De esta manera podemos asegurar que el componente no sera registrada sin el componente.
Ahora nuestra propiedad de tipo TExpandingRecord mostrara como una expansion de la propiedad (debido a nuestra devolucion paSubProperties de GetAttributes), y el editor predeterminado para TCollection funcionara como el propietario de la TCollection propiedad es un TComponent.
cuadro de Dialogo de editores de propiedades
la Mayoria de las veces, a la hora de crear una propiedad personalizada editor, el proposito es proporcionar una grafica la manera de relacionarse con la propiedad.
Este primer ejemplo es una manera muy sencilla de permitir al usuario introducir varias lineas en la propiedad 'Caption' de un TLabel. Aunque en este ejemplo no es muy complicado, se muestra como incluir un formulario dentro de su editor.
Paso 1:
Seleccionar Archivo, Nueva Aplicacion desde el menu principal. Esto creara un formulario, el nombre del formulario 'fmLabelEdit', agrega un TMemo para el formulario denominado memCaption. Agregue dos botones 'ACEPTAR' y 'Cancelar' con el ModalResult propiedades establecidas para mrOK y mrCancel respectivamente.
Paso 2:
Agregar DsgnIntf y TypInfo a la clausula uses.
Paso 3:
Añadir la siguiente propiedad del editor de codigo para su unidad.
TCaptionProperty = clase(TStringProperty) publico funcion GetAttributes: TPropertyAttributes reemplazar procedimiento Editar reemplazar final |
Y registrar el editor de la propiedad, como asi
procedimiento Registrarse aplicacion {$R *.DFM} procedimiento Registro begin RegisterPropertyEditor(TypeInfo(TCaption), TLabel, 'Titulo', TCaptionProperty) final |
Paso 4:
Agregue el codigo siguiente para que el inspector de objetos para mostrar la [...] boton editar despues el nombre de la propiedad.
funcion TCaptionProperty.GetAttributes: TPropertyAttributes begin Resultado := heredado GetAttributes [paDialog] final |
Paso 5:
por ultimo, vamos a crear una instancia de nuestro editor de formulario, establecer el contenido de la nota a la actual titulo y, a continuacion, mostrar el formulario modal.
procedimiento TCaptionProperty.Editar var I: Integer begin con TfmLabelEdit.Crear(Aplicacion) prueba memCaption.Lineas.Texto := GetStrValue ShowModal {Si el ModalResult de la forma es mrOK, tenemos que establecer la propiedad 'Caption' de cada TLabel.} si ModalResult = mrOK de I:=0 a PropCount-1 TLabel(GetComponent(I)).Caption := memCaption.Lineas.Texto finalmente Libre final final |
Paso 6:
Instalar la unidad en el paquete y, a continuacion, pruebe el nuevo editor !
Avanzado editores de propiedades
Cualquiera que haya usado alguna vez TActionList o TDataSet (TTable / TQuery) tener experiencia en el ejemplo siguiente, posiblemente sin siquiera darse cuenta.
El ActionList editor es, obviamente, un editor personalizado, ya que permite la agrupacion de acciones, mientras que el FieldsEditor de TDataSet puede parecer a primera vista como un editor normal, pero en una inspeccion mas cercana tiene un menu con elementos como 'Agregar campos'. Sin embargo, la caracteristica mas notable de estos dos editores, no es que sean de dialogo personalizado editores (similar a la que hemos explicado antes), pero el hecho de que los elementos que crean se incluye en la clase principal de la declaracion de la unidad actual.
tipo TForm1 = clase(TForm) ActionList1: TActionList Action1: TAction Action2: TAction privada { Private declarations } publico { Public declarations } final |
El beneficio de esto es que el IDE es consciente de estos elementos, por lo tanto, lo que les permite ser seleccionado de una lista de objetos siempre que la propiedad de un componente requiere de ellos.
En la ilustracion de arriba, dos acciones que se suman a una TActionList, haciendo clic en la 'Accion' de propiedad de Button1 muestra una lista que consiste en las acciones añadido. Las dos acciones se han añadido tambien a la clase del Formulario de declaracion, y por lo tanto puede ser referido por su nombre (Action1, Action2).
El truco aqui se encuentra en su totalidad en el editor de la propiedad y no en el componente. Cuando un editor de propiedades se activa (es decir, el metodo de Edicion que se llama) el Diseñador de la propiedad contiene una referencia valida a un IFormDesigner (TFormDesigner en Delphi 4). Muchas de las funciones de esta interfaz no estan dentro del alcance de este articulo, si usted desea aprender mas acerca de las capacidades de esta interfaz me gustaria recomendar un libro llamado Delphi Manual del Programador Marco Cantu.
Algunos de los metodos que se incluyen
funcion MethodExists(const Nombre: string): Boolean procedimiento RenameMethod(const CurName, NewName: string) procedimiento SelectComponent(Ejemplo: TPersistent) procedimiento ShowMethod(const Nombre: string) funcion GetComponent(const Nombre: string): TComponent funcion CreateComponent(ComponentClass: TComponentClass Padre: TComponent Left, Top, Width, Height: Integer): TComponent |
Algunas de las llamadas son bastante elementales, MethodExists por ejemplo devolvera True o False dependiendo de si o no un metodo de nombre ya existe dentro de la forma de la unidad actual (FormCreate, Button1Click etc). ShowMethod para desplazar el cursor hasta el llamado metodo, y RenameMethod vamos a cambiar el nombre de un metodo.
Los dos metodos que son de interes para el uso en este punto son:
CreateComponent
Dada una clase de componente, un padre para sujetar el componente, y la posicion / dimensiones, el diseñador creara una instancia de la clase como si el desarrollador ha seleccionado de la paleta de componentes y añadido a la forma de si mismo.
Modificado
Informa el diseñador que algo ha sido alterado (una propiedad, etc). Esto altera el estado de la unidad para que el IDE sabe, se debe guardar antes de cerrar (tambien habilita el boton guardar en el IDE).
Cuando la adicion de elementos a nuestra matriz de todo lo que tenemos que hacer es conseguir TMyProperty.Diseñador para crear un componente en nuestro nombre. Este componente sera añadido a la forma y a cualquier propiedad que se refiere a una clase de este tipo, sera automaticamente conscientes de ello. En el caso de TActionList y TDataSet los componentes que se agregan a la forma no son visibles en tiempo de diseño, el propietario componente actua como una especie de 'administrador' para los componentes.
Durante el tiempo de diseño usted no vera un TAction o un TField componente en la paleta de componentes, que posiblemente podria hacer sospechar que no estan registrados, sin embargo, el IDE es todavia capaz de crear instancias de estos componentes (y que no son visibles). La respuesta no es que ellos no estan registrados, este comportamiento es el resultado de un 'como' que el componente esta registrado.
Mientras que RegisterComponents se agrega componentes de la paleta de componentes, la RegisterNoIcon metodo de registrar el componente sin necesidad de añadir a la paleta de componentes, registrando de esta manera tambien le dice a la IDE de que el componente que no se muestran durante el tiempo de diseño.
En el siguiente ejemplo vamos a crear un componente llamado TWavSound (un componente adicional llamado TWavButton se incluye en el codigo fuente que acompaña a este articulo como un ejemplo). TWavSound simplemente mantiene los datos de un archivo WAV, y reproducir el sonido en la demanda. Aunque seria sencillo para nosotros una gota TWavSound en nuestro formulario para cada WAV de sonido se requiere, a nuestro formulario de pronto podria empezar a ser inmanejable, por lo tanto, tambien vamos a crear una clase manager llamado TWavList.
Todas las tecnicas utilizadas en el codigo fuente de estos componentes fue cubierto en la parte dos de esta serie de articulos, por lo que el codigo fuente no seran cubiertos en cualquier gran nivel de detalle. Sin embargo, voy a mostrar la clase de las declaraciones de estos componentes solo para darle una idea de como estan estructuradas.
Nota: En la parte inferior de la unidad, dentro de la seccion de inicializacion de la unidad puede observar el siguiente codigo:
inicializacion
RegisterClass(TWavSound)
La razon es que RegisterNoIcon no parece hacer un trabajo completo. Aunque nos permite crear instancias de la registrada en el componente de nuestro editor de propiedades de algo parece ir mal cuando un proyecto esta re-cargado que contienen estos componentes. Una 'Clase no registrada' cuadro de mensaje que aparece en pantalla y el proyecto esta dañado. Ademas de registrar la clase de esta manera parece solucionar el problema
TWavSound
tipo PWavData = ^TWavData TWavData = empaquetado registro Tamaño: Longint Datos: array[0..0] de byte final TWavSound = clase(TComponent) privada FWavData: PWavData FWav: TWav procedimiento ReadWavData(Stream: TStream) procedimiento WriteWavData(Stream: TStream) protegido procedimiento DefineProperties(Filer: TFiler) reemplazar publico destructor Destruir reemplazar procedimiento Claro procedimiento LoadFromFile(const nombre de archivo: TFilename) procedimiento LoadFromStream(Stream: TStream) procedimiento Jugar publicado final |
FWavData
se utiliza para almacenar el contenido del archivo WAV una vez que se carga una secuencia de comandos o un archivo.
Borrar
Va a liberar la memoria que contiene FWavData.
Juego
Se utiliza el sndPlaySound llamada a la API en MMSystem.pas t
Componente de la escritura, parte 3
By Consejos Y Trucos
Componente de la escritura, parte 3 : Multi-millones de consejos para hacer su vida más fácil.