Delphi - exploración de habilidades:
{Nº 1}
Oraciones para crear formas modales:
procedimiento de clase TMyForm.RunForm(AObj1, AObj2: TObject);
var
vForm: TMyForm;
comenzar
vForm := TMyForm.Create(aplicación);
con vForm hacer
Intentar
Formulario inicial(AObj1, AObj2);
MostrarModal;
Finalmente
Gratis;
fin;
fin;
//*ilustrar:
Las funciones declaradas a través de la clase son similares a las funciones estáticas en VC use la declaración: TMyForm.RunForm(vObj1, vObj2);
Para obtener más información específica, consulte: descripción de la clase en la Ayuda de Delphi.
El propósito de enfatizar este modismo es:
1. Si este formulario se utiliza en varios lugares, puede asegurarse de que este código se llame de manera uniforme;
2. Si se modifica la función, por ejemplo: procesamiento basado en el valor de retorno de ShowModal, solo modifique esta función.
3. El programa tiene una buena encapsulación y es fácil de mantener y transferir. *//
{No. 2}//Uso de etiqueta
Respuesta a eventos de botones de la barra de herramientas del formulario
procedimiento TMyForm.RunOperate(ATag: Integer);
comenzar
Caso ATag de
1: MiBotón.Color := clRed;
2: MiBotón.Color := clGreen;
3: MiBotón.Color := clBlack;
fin;
fin;
procedimiento TMyForm.ToolBtnClick(Remitente: TObject);
comenzar
RunOperate(TControl(Remitente).Etiqueta);
fin;
Si está en un menú desplegable y necesita realizar funciones similares,
procedimiento TMyForm.MenuItemClick(Remitente: TObject);
comenzar
RunOperate(TMenuItem(Remitente).Etiqueta);
fin;
//*ilustrar:
1. Estructura clara
2. La información relevante está concentrada, lo que facilita su verificación, modificación y mantenimiento.
3. Mejorar la adaptabilidad y escalabilidad del programa; por ejemplo, si el requisito no se implementa en el botón de la barra de herramientas, sino en diferentes botones, será fácil de modificar.
Sugerencia: Cada categoría va seguida de solo una línea o unas pocas líneas de código. Si hay mucho código, utilice una función de proceso.
Lo que es más interesante es que suelo escribir lo siguiente:
Caso btnMyButton.Visible de
{mostrar} Verdadero: ...
{No mostrar} Falso: ...
fin; *//
{ No. 3 }//Puntero de evento como parámetro
//Utiliza el puntero de eventos para leer listas, etc.
tipo
TDataSetEvent = procedimiento (DataSet: TDataSet; AIndex, ACount: Integer) de Objeto;
//Clases derivadas de TADOQuery
procedimiento TMyADOQuery.EnumRecord(AWhereStr: String; APro: TDataSetEvent);
comenzar
Cerca;
SQL.Borrar;
SQL.Add('Seleccionar * De Tabla1');
si AWhereStr <> '' entonces
SQL.Add('Dónde ' + AWhereStr);
Abierto;
Mientras no lo hagas
comenzar
si está asignado (APro), entonces APro (Self, RecNo, RecordCount);
Próximo;
fin;
Cerca;
fin;
//*ilustrar:
Este método proviene de la función API en Window para enumerar todas las ventanas secundarias actuales, EnumChildWindow.
1. Principio: intente separar la lectura de datos de la visualización de datos, el procesamiento de datos, etc., como MVC, etc., todos para este propósito;
2. Se ha mejorado la escalabilidad del programa. Si originalmente deseaba mostrar o procesar una determinada columna de información en una lista, pero luego cambió a ComboBox, al modificar el programa, no necesita leer la parte de lectura de datos. , solo necesita modificar la visualización de información, etc. Para otro ejemplo, ahora debe usar una barra de progreso para mostrar el progreso de la lectura al leer registros.
*//
{ No. 4 } // Matriz constante
{En el No.2, se implementa el siguiente contenido
procedimiento TMyForm.RunOperate(ATag: Integer);
comenzar
Caso ATag de
1: MiBotón.Color := clRed;
2: MiBotón.Color := clGreen;
3: MiBotón.Color := clBlack;
fin;
fin;
}
//Entonces sería ideal implementarlo usando una matriz.
procedimiento TMyForm.RunOperate(ATag: Integer);
constante
MiColorBotónMax := 3;
MyButtonColor: matriz [1..MyButtonColorMax] de TColor = (clRed, clGreen, clBlack);
comenzar
Caso ATag de
1..MyButtonColorMax: MyButton.Color := MyButtonColor[ATag];
101:....
fin;
fin;
//*ilustrar:
Para usar en modo de matriz, simplemente tenga en cuenta que el límite superior o inferior de la matriz se implementa mediante constantes y luego intente usar esta constante para la lectura del bucle de la matriz en usos futuros.
*//
{No 5}El mecanismo de mensajes reduce las funciones públicas de clase.
//Cómo minimizar la definición de funciones públicas en un formulario;
{Por ejemplo: si desea implementar un formulario de lista de propiedades del control de formulario actual, cuando necesite actualizar el formulario de propiedad, habrá mucha información; con el que es necesario interactuar. Si usamos funciones públicas de clase, necesitamos definir muchas funciones públicas. Al mismo tiempo, si se requiere la conversión del tipo de formulario, las funciones públicas solo se pueden usar después de convertirlas al tipo de formulario de destino. Por lo tanto, habrá situaciones en las que dos unidades deberán incluirse entre sí}
//Solución:
TfrmMyForm = clase(TForm)
FfrmProperty: TForm;
fin;
...
FfrmProperty := TfrmProperty.MyCreate(Aplicación, Auto);
...
//Cuando es necesario actualizar la ventana de propiedades
FfrmProperty.Perform(WD_REFRESHPROPERTYLIST, 0, 0);
TfrmProperty = clase(TForm)
privado
FMyForm: TForm;
procedimiento WDREFRESHPROPERTYLIST (var Mensaje: TMessage); mensaje WD_REFRESHPROPERTYLIST;
público
constructor MyCreate(Propietario: TComponent; AForm: TForm);
fin;
constructor TfrmProperty.MyCreate(Propietario: TComponent; AForm: TForm);
comenzar
heredado Crear (Propietario);
FMyForm := AForm;
fin;
//* Para la forma de utilizar los mensajes, se puede reducir la definición de funciones públicas del formulario. Al mismo tiempo, mejora la escalabilidad del programa. Si usa su formulario en su lugar, se puede convertir fácilmente, porque como máximo es su formulario y no procesa el mensaje actual*)//
{No. 6}Usar lista de registro para gestionar posibles módulos de expansión
//Proyecto: debe admitir múltiples métodos de visualización de salida para un conjunto de datos
...Se darán ejemplos más adelante.
//* ilustrar:
1. "Múltiples métodos de salida" significa que los métodos de salida se pueden ampliar con frecuencia en aplicaciones futuras, por lo que se debe tener en cuenta la fácil escalabilidad de los métodos de salida durante el diseño del programa.
2. Consulte el mecanismo de registro de control (RegisterComponents) en VCL, puede encontrar que se utilizan una gran cantidad de mecanismos de registro en VCL, el más clásico es el registro del editor de propiedades de control;
*//
{No.7}Usar la versión del programa de control predefinido
// Si está realizando un programa de plataforma de desarrollo secundario, debe involucrar problemas de control de versiones del producto y control de versiones del proyecto.
//Generalmente controlado mediante métodos predefinidos
//La declaración es relativamente simple:
{$DEFINIR JOYYUAN97}
{$IFDEF JOYYUAN97} {ELSE} {ENDIF}
{$UNDEF JOYYUAN97}
*ilustrar:
1. Divida la predefinición en varios archivos separados.
2. Al comienzo de cada unidad pero después de Unidad, use {$I...} para incluir el archivo en la unidad actual.
3. Controlar los archivos de unidad que la unidad actual puede contener en función de condiciones predefinidas.
4. Intente separar un archivo predefinido para el proyecto. Después de incluir todos los archivos predefinidos, incluya este archivo. En este archivo, algunos archivos predefinidos se pueden cancelar según las necesidades del proyecto.
*//
{No. 8}Utilice punteros de función para reducir las inclusiones de proyectos unitarios
// A menudo pienso que reducir la inclusión de unidades es el primer paso para hacer públicas las unidades, entonces, ¿cómo reducir la inclusión de unidades tanto como sea posible?
// Es decir, se deben hacer más esfuerzos sobre cómo reducir el acoplamiento de las unidades del programa.
{Descripción del escenario:
TMyFormManager: clase de gestión de formularios
TMyForm: clase base de formulario de datos
TMyFormaccess: Clase de lectura y guardado de información de formularios. Guarde la información del formulario en una base de datos o algún otro tipo de estructura.
analizar:
1. La clase base del formulario (TMyForm) y la clase de administración del formulario (TMyFormManager) deben implementarse en una unidad uManagers.
2. La unidad fMyImange de la clase de implementación específica del formulario (TMyImageForm) debe incluir la unidad uManagers para la herencia y la gestión de formularios.
3. La unidad uMyAccess de la clase de lectura de datos del formulario (TMyFormAccess) debe incluir la unidad uManagers y la unidad fMyImange
pregunta:
Si quiero guardar el formulario, debo hacerlo en un evento de botón del formulario. Cuando se trata de la unidad de formulario, debe contener la unidad de clase de acceso a datos del formulario y, si se coloca en la clase base del formulario, la unidad uManager debe contener la unidad uMyAccess.
La inclusión de celdas es un peligro cuando el acceso a los datos, es decir, los formatos de almacenamiento de datos, cambian según los requisitos y requieren escalabilidad.
Solución: utilice variables de puntero de función.
1. Defina una variable de puntero de función en la unidad uManagers para guardar información de datos.
2. Asigne un valor a esta variable de puntero de función cuando se inicialice la aplicación.
3. Cuando sea necesario guardar la información del formulario, determine si el puntero no está vacío y luego ejecute la función para guardar la información del formulario.
{No. 9}Constantes, entender constantes, usar constantes
Hay muchos libros que presentan la importancia de la definición de constantes, y a menudo pienso en ello, pero cuando miro el código fuente de VCL, me doy cuenta de que he ignorado el uso de constantes por parte de otros.
1. La definición de mensaje que usamos a menudo es: declarar una constante y luego usarla en el momento apropiado.
Comúnmente definido y utilizado:
constante
WD_MiMensaje = WM_Usuario + 101;
tipo
TMiForma = clase(TForma)
...
procedimiento WDMyMessage(var mensaje: TMessage); mensaje WD_MyMessage {posición del mensaje de respuesta}
fin;
Sin embargo, si reescribe la declaración {posición del mensaje de respuesta} como:
procedimiento WDMyMessage(var mensaje: TMessage mensaje WM_User + 101;
De manera similar, la compilación puede ser exitosa y el uso es normal. Por lo tanto, las definiciones constantes se utilizan con mucha frecuencia en las interfaces y el procesamiento del sistema Windows.
2. En Delphi, hemos definido variables de color, clRed, clGreen, etc., que también son constantes definidas para facilitar su uso futuro. A través de esta observación, descubrí que la definición de constantes debería ser parcialmente reutilizable en el proyecto. Por lo tanto, se puede definir una unidad constante estándar para que las constantes definidas se puedan reutilizar en cada proyecto.
{No 10}Una matriz de uso común en Delphi
Existe una implementación relativamente completa en Delphi para la definición y uso de matrices del tipo TIdentMapEntryd.
TIdentMapEntry = registro
Valor: entero;
Nombre: Cadena;
fin;
1. Definición de matriz: matriz [0..ArrMax] de TIdentMapEntry
Consulte: Unidad de controles:
Cursores: matriz[0..21] de TIdentMapEntry = (
...
);
2. Dos funciones que se evalúan entre sí: IntToIdent (buscar nombre a partir del valor) e IdentToInt (buscar valor a partir del nombre);
Para aplicaciones específicas, consulte: IdentToCursor y CursorToIdent.
3. Aplicación: a. Aplique directamente este método de definición de grupos de árboles y la función de manipulación de matrices; b. Aprenda a acceder y manipular matrices en la función. c.Conozca la definición de la función de acceso a la información estándar: function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean La información devuelta específica se devuelve por parámetros. se pasa a través de la función Se juzga el valor de retorno booleano.
{No. 11}De casos especiales a descubrimientos comunes
Descubrí rastreando las funciones de definición y operación de los cursores:
1. Como se introdujo en {No. 10}, generalice la definición y las operaciones generales de los Cursores.
2. Proporcionar funciones para la conversión entre Int e Ident.
3. Proporciona una función para leer información de la lista de matrices cíclicamente: GetCursorValues; entre ellos, el método de "puntero de evento como parámetro" introducido en {No.3} se utiliza para leer la información de la lista.
Suplemento del {núm. 6}:
ejemplo:
procedimiento RegisterComponents(const Página: cadena;
ComponentClasses: matriz de TComponentClass);
comenzar
si está asignado (RegisterComponentsProc), entonces
RegisterComponentsProc(Página, Clases de componentes)
demás
elevar EComponentError.CreateRes(@SRegisterError);
fin;
Interpretación:
1. Utilice el método de registro para registrar los tipos de controles que se pueden utilizar, etc.
3. Para RegisterComponentsProc, el método de "usar punteros de función para reducir la inclusión de proyectos unitarios" en {No.8} se utiliza para facilitar futuras expansiones del programa, actualizaciones de versiones, etc.
{No 11}Defina solo una función pública
// Descripción del proyecto: Ahora necesitamos implementar un sistema de dibujo CAD o Visio, que requiere buena escalabilidad y fácil mantenimiento;
//Y requiere un acoplamiento bajo, de modo que partes del sistema o del sistema ampliado puedan empaquetarse y usarse directamente en proyectos futuros.
diseño:
1. Diseñe una clase abstracta de objeto gráfico. En esta clase, defina una función abstracta CadPerform. Los parámetros de la función se refieren a la función TControl.Perform(Msg: Cardinal; WParam, LParam: Longint): Longint;
2. En la clase de gestión de gráficos, implemente la gestión de una lista de objetos gráficos. Lo que se almacena en la lista es el puntero del objeto abstracto.
3. Cuando desee controlar objetos de clase específicos, solo necesita usar la función CanPerform y luego pasar Msg de acuerdo con la categoría de la operación actual y pasar la información del parámetro correspondiente.
Implementación: TCad es la clase de control de primer nivel heredada de la clase abstracta
función TCad.CadPerform(Msg: Cardinal; WParam, LParam: Longint): Longint;
comenzar
Mensaje de caso de
Mi_Mensaje1: Resultado := MiMensaje1(WParam, LParam);
Mi_Mensaje2: Resultado := MiMensaje2(WParam, LParam);
fin;
fin;
Para TPoint hereda de TCad, la función CadPerform se implementa de la siguiente manera.
función TPoint.CadPerform(Msg: Cardinal; WParam, LParam: Longint): Longint;
comenzar
Mensaje de caso de
My_Message1: Resultado := MyMessage1(WParam, LParam); //El procesamiento de este tipo de operación en TCad está bloqueado
Mi_Mensaje3: Resultado := MiMensaje3(WParam, LParam);
else Resultado: = CadPerform heredado (Msg, WParam, LParam);
fin;
fin;
*ilustrar:
Debido a que operamos objetos gráficos con mucha frecuencia, definimos una función de interfaz pública y abierta para lograr una alta encapsulación de la clase y un fácil mantenimiento y expansión del programa.
*//
{No.12}
Los siguientes son mis requisitos de programación: (Parte de la información no tiene restricciones de idioma)
// Casi todas las siguientes soluciones se pueden encontrar en los métodos anteriores.
1. Reducir la complejidad del programa. a. Reducir la cantidad de funciones, usar métodos de caso y etiqueta y aprender a definir Perform b. Reducir las relaciones de anidamiento de unidades, usar métodos de paso de mensajes y reducir la inclusión mutua de unidades de formulario.
2. Reducir
{No. 13} Utilice la transmisión para implementar notificaciones de clases de administración a objetos de la lista de administración
// Para la descripción del proyecto {No. 12}, cuando las propiedades o el estado del control del formulario de dibujo cambian, a menudo es necesario notificar a todos los objetos gráficos y realizar los cambios correspondientes.
// Si solo se define una función de transmisión, se puede realizar la notificación entre padres e hijos, lo que también mejorará la reutilización, escalabilidad, facilidad de mantenimiento, etc. del programa y aclarará la estructura de clases.
//Por ejemplo: 1. En Visio y MapInfo, si la escala (relación de zoom) del formulario actual cambia, todos los objetos gráficos mostrados actualmente deben volver a dibujarse con la nueva escala. 2. Cuando se cambia la fuente predeterminada del formulario actual, las fuentes de texto de los objetos gráficos que usan la fuente del formulario de forma predeterminada para mostrar información de texto también deben cambiarse en consecuencia.
// Solución, consulte el mecanismo de procesamiento en TWinControl que notifica a todos los subcontroles cuando cambian los atributos o el estado:
procedimiento TWinControl.NotifyControls(Msg: Word);
var
Mensaje: TMensaje;
comenzar
Mensaje.Msg := Mensaje;
Mensaje.WParam:= 0;
Mensaje.LParam:= 0;
Mensaje.Resultado := 0;
Broadcast(Message);//Transmitir el mensaje de cambio actual
fin;
en:
procedimiento TWinControl.Broadcast(var Mensaje);
var
I: Entero;
comenzar
para I: = 0 a ControlCount - 1 hacer
comenzar
Controles[I].WindowProc(TMessage(Mensaje));
//Cambiar a: con TMessage(Message) hacer Cads[I].CadPerform(msg, WParam, LParam);
si TMessage(Mensaje).Resultado <> 0 entonces Salir;
fin;
fin;
Sin embargo, cuando tratamos con objetos gráficos, podemos llamar directamente a la función pública CanPerform de Cads.
{No. 14}Crea tus objetos dinámicamente cuando sea necesario
Por ejemplo: http://www.delphibbs.com/keylife/iblog_show.asp?xid=824
//************Opción 2: crear un formulario de propiedad cuando sea necesario
usos
...
fPropiedad;
tipo
TfrmMyMap = clase
...
procedimiento OnfrmMyMapDestroy(Remitente: TObject);
procedimiento OnMapGeoSelected(AGeo: TGeometry);
privado
Propiedad Ffrm: Propiedad Tfrm;
procedimiento ShowPropertyForm(aVisible: booleano);
público
fin;
procedimiento TfrmMyMap.ShowPropertyForm(aVisible: booleano);
comenzar
si no está asignado (FfrmProperty), entonces FfrmProperty: = TfrmProperty.Create (Aplicación);
FfrmProperty.Visible := aVisible;
fin;
procedimiento TfrmMyMap.OnfrmMyMapDestroy(Remitente: TObject);
comenzar
si está asignado (FfrmProperty), entonces FfrmProperty.Free;
fin;
procedimiento TfrmMyMap.OnMapGeoSelected(AGeo: TGeometry);
comenzar
si está asignado (FfrmProperty), entonces FfrmProperty.MyRefresh(AGeo);
fin;
Aquí se explica:
1. Cree dinámicamente su objeto FfrmProperty cuando sea necesario
2. Cuando se libere el objeto actual, determine la legalidad de su objeto y luego libere el objeto creado dinámicamente.
{No 15}Crear una interfaz o crear una estructura
// Descripción del proyecto: cuando desarrollo un control de tabla, si configuro la celda en Com, si hay demasiada información en la tabla, no se puede garantizar la velocidad de carga e incluso existe la posibilidad de que se bloquee. La razón por la que uso Com es para que el procesamiento y la información de cada celda se puedan expandir fuera del control en el futuro.
Mi solución es: crear una instancia para cada control derivado de Cell y crear dinámicamente varios objetos de estructura Registro para registrar la información de cada celda. Si necesita operar la celda, asigne el puntero del objeto de estructura al componente Cell, los resultados de la prueba son. muy satisfactorio.
Por lo tanto, si necesita utilizar una gran cantidad de instancias de un Com, intente administrar y mantener una instancia, y los datos que contiene se pueden crear y administrar dinámicamente, lo que tendrá un buen efecto en términos de velocidad.
Además, intente declarar un puntero de interfaz pMyInterface = ^IMyInterface Al pasar o usar parámetros, use el puntero de interfaz directamente. Esto puede reducir la cantidad de llamadas a la función de conteo _AddInft, etc., y también puede aumentar la velocidad. El funcionamiento es normal.