en Este artículo se muestra cómo los usuarios pueden modificar su interfaz gráfica de usuario en tiempo de ejecución.
| Desarrolladores de Delphi | de febrero de 1999 | derechos de Autor Pinnacle Publishing, Inc. Todos los derechos reservados.Dar a Sus Clientes el Control de la interfaz de usuario
Steve Zimmelman
¿cuántas veces has entregado lo que pensabas que era una solicitud completa, sólo para escuchar su cliente de decir, 'Gee, esto es bueno, pero realmente me gustaría el Nombre de la izquierda, y el Estado del campo debe ser de color rojo, no negro, y . . .' ¿No sería agradable si todos los usuarios tenían que hacer era a la derecha-haga clic en el ratón sobre el control, y sale un menú emergente que permite el cambio en el control de los atributos? O si se pulsa Ctrl-ArrowKey o Mayús-ArrowKey para cambiar la posición o el tamaño del control?
Dar a los usuarios el control de la interfaz gráfica de usuario es un proceso de dos pasos. Primero tienes que crear controles con las propiedades de los usuarios pueden cambiar en tiempo de ejecución y, a continuación, usted debe tener una forma de guardar y restaurar los cambios. Generalmente, el control que obtiene el mayor uso es el DBEdit. Así que en este ejemplo se centrará en la creación de un DBEdit que utiliza de una manera personalizada, PopupMenu que se activa en el clic derecho del ratón. El menú le permite al usuario cambiar el Color, tipo de letra, el Orden de Tabulación y el Texto del Caso. Además, la combinación de teclas Ctrl-Flecha y Mayús-Flecha para cambiar la posición y el tamaño del control, respectivamente.
Antes de comenzar, quiero presentarles a un nuevo texto-caso de la propiedad: ProperCase. Más adecuado-el caso de las conversiones generalmente en mayúsculas sólo la primera letra, luego la letra que sigue a un espacio. Pero esto deja un sinfín de nombres y títulos abreviados de mirar un poco torpe, como Mcdonald', O'Hara, M. D., y así sucesivamente. Así que en mi intento de crear un mejor ratón-trampa, he incluido una adecuada caso de conversión que tiene la inteligencia para manejar estos nombres especiales. Coloqué las funciones que se usan para el correcto-caso de conversión en una unidad llamada StrFunc.pas y, a continuación, se incluye la unidad de StrFunc en los Usos de la declaración de la componente.
la Creación de la variable DBEdit
La primera cosa que hice fue crear un nuevo componente mediante TDBEdit como el padre de la clase. Me llama la nueva clase TPSIDBEdit porque el nombre de la empresa en la que trabajo es PSI, y era una manera sencilla de distinguir el componente. A continuación, he creado un nuevo CharCase tipo que incluye ProperCase. Va a ser usado para reemplazar el DBEdit del TCharCase. También he cambiado el CharCase la propiedad a un nuevo tipo de TPSICharCase. En adición a la sustitución de la CharCase propiedad, me introdujo dos nuevas propiedades: AllowUserChange y PopupChangeMenu. La propiedad AllowUserChange es un Booleano simple interruptor que activa o desactiva la capacidad del usuario para cambiar cualquiera de las propiedades del componente en tiempo de ejecución, y PopupChangeMenu es un puntero a la PopupMenu que, en efecto, cuando AllowUserChange se establece en True. Una mayor parte de los componentes del cambio es realizado por el PopupChangeMenu, pero voy a hablar de eso un poco más tarde. Listado 1 se presenta la PSIDBEdit de la unidad.
Listado 1. El PSIDBEdit de la unidad.
unidad de PSIDBEdit
interfaz
usos
& nbsp & nbsp Windows, SysUtils, Classes, Controles, Formularios, cuadros de diálogo,
& nbsp & nbsp DBCtrls, Menús, db, StrFunc
tipo
& nbsp & nbsp TPSICharCase = (ecNormal, ecUpperCase,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ecLowerCase, ecProperCase)
& nbsp & nbsp TPSIDBEdit = clase(TDBEdit)
& nbsp & nbsp privada
& nbsp & nbsp & nbsp & nbsp fCharCase : TPSICharCase
& nbsp & nbsp & nbsp & nbsp fIsChanging : Boolean
& nbsp & nbsp & nbsp & nbsp fAllowUserChange : Boolean
& nbsp & nbsp & nbsp & nbsp fStartMove : Boolean
& nbsp & nbsp & nbsp & nbsp fTop : Integer
& nbsp & nbsp & nbsp & nbsp fLeft : Integer
& nbsp & nbsp & nbsp & nbsp fChangeMenu : TpopupMenu
& nbsp & nbsp & nbsp & nbsp fPopupSave : TPopupMenu
& nbsp & nbsp & nbsp & nbsp Procedimiento SetAllowUserChange(Valor:Boolean)
& nbsp & nbsp & nbsp & nbsp Procedimiento SetChangeMenu(Valor:TpopupMenu)
& nbsp & nbsp & nbsp & nbsp Procedimiento SetPopUpMenu
& nbsp & nbsp & nbsp & nbsp Procedimiento SetCharCase(Valor:TPSICharCase)
& nbsp & nbsp & nbsp & nbsp Procedimiento SetTextCase(Const bCheckState:Boolean)
& nbsp & nbsp protegido
& nbsp & nbsp pública
& nbsp & nbsp & nbsp & nbsp Procedimiento de Carga Reemplazar
& nbsp & nbsp & nbsp & nbsp Procedimiento de Cambio de Reemplazar
& nbsp & nbsp & nbsp & nbsp procedimiento KeyDown(var Key: La palabra
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Shift: TShiftState) reemplazar
& nbsp & nbsp & nbsp & nbsp Procedimiento MouseDown(Botón: TMouseButton Cambio:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp TShiftState X, Y: Integer)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Reemplazar
& nbsp & nbsp & nbsp & nbsp procedimiento MouseMove(Shift: TShiftState
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp X, Y: Integer) Reemplazar
& nbsp & nbsp & nbsp & nbsp procedimiento MouseUp(Botón: TMouseButton Cambio:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp TShiftState X, Y: Integer)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Reemplazar
& nbsp & nbsp publicado
& nbsp & nbsp & nbsp & nbsp Propiedad AllowUserChange : Boolean
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Leer fAllowUserChange
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Escribir SetAllowUserChange
& nbsp & nbsp & nbsp & nbsp Propiedad CharCase : TPSICharCase
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Leer fCharCase
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Escribir SetCharCase
& nbsp & nbsp & nbsp & nbsp Propiedad PopupChangeMenu : TPopupMenu
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Leer fChangeMenu
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Escribir SetChangeMenu
& nbsp & nbsp final
yo quería que el componente se tienen dos estados: un estado predeterminado, que se comporten igual que su antecesor, y un diseño de estado, que permitirá al usuario cambiar sus propiedades en tiempo de ejecución. La propiedad Booleana AllowUserChange que distingue a estos dos estados. Cuando AllowUserChange es True, el componente del PopupMenu es cambiado a punto para el valor almacenado en la PopupChangeMenu de la propiedad. Si es False, entonces el PopupMenu propiedad vuelve a su anterior tiempo de diseño de la asignación. También permite que el componente se mueve o cambia de tamaño. Pensé que sería agradable para que el usuario pueda ver una diferencia entre los dos estados, así que he cambiado el cursor a crHandPoint (-21) en el SetAllowUserChange método.
El PopupMenu asignación es cambiado a través de la SetPopupMenu método cuando el AllowUserChange propiedad es cambiado.
con el fin De intercambiar el PopupMenu de los punteros, el defecto PopupMenu se almacena en fPopupSave en el Cargado método (ver Listado 2). A continuación, el SetPopupMenu método es llamado para asegurarse de que el propio menú emergente se basan en el valor de AllowUserChange.
Listado 2. La Carga método.
Procedimiento TPSIDBEdit.Carga
Begin
& nbsp & nbsp & nbsp Probar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si (csDesigning en ComponentState), a Continuación, Salir
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Captura de PopupMenu Asignación
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp fPopupSave := PopupMenu
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetPopupMenu
& nbsp & nbsp & nbsp Finalmente
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp heredado Carga
& nbsp & nbsp & nbsp Final
Fin
Con la llegada del nuevo texto de caso ProperCase y el nuevo tipo de TPSICharCase, Tuve que reemplazar completamente y volver a implementar todos los demás de texto estándar-caso de las conversiones en el método de Cambio de la componente (ver Listado 3).
el Listado 3. El Cambio de método.
Procedimiento TPSIDBEdit.Cambiar
Var
& nbsp & nbsp & nbsp iSelStart : Integer
Begin
& nbsp & nbsp & nbsp Probar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si (csDesigning en ComponentState)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp O fIsChanging, a Continuación, Salir
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Captura la Posición del Cursor
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp iSelStart := SelStart
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetTextCase(Falso)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Restaurar la Posición del Cursor
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SelStart := iSelStart
& nbsp & nbsp & nbsp Finalmente
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Heredado
& nbsp & nbsp & nbsp Final
Fin
El real cambio en el Texto es un poco complicado. Si cambia el texto mediante programación cuando el objeto tiene el foco, y el conjunto de datos no está en modo de Edición o Inserción, la excepción 'conjunto de datos no está en modo de Edición o Inserción' se genera. Así que antes de cambiar el texto, el componente del conjunto de datos.El estado debe ser interrogado y cambiar si es necesario. También debemos ocuparnos de posibles multi-usuario de los conflictos que puedan producirse. El parámetro bCheckState se utiliza para determinar si el conjunto de datos.El estado tiene que ser colocado en modo de Edición o Inserción antes de cambiar el texto. Si lo hace, entonces el método también deben Publicar los cambios. El método Post se llama sólo si la variable de memoria bPost se establece en True. El listado 4 muestra donde todo esto sucede en el SetTextCase método.
el Listado 4. El SetTextCase método.
Procedimiento TPSIDBEdit.SetTextCase(Const bCheckState:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Boolean)
Var
& nbsp & nbsp & nbsp correos : Boolean
& nbsp & nbsp & nbsp Función CanChange : Boolean
& nbsp & nbsp & nbsp Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Probar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si No bCheckState, a Continuación, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := True
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Salida
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp If (origen de datos <> Nil) A continuación, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si No (origen de datos.Conjunto de datos.Estado
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp En [dsEdit, dsInsert]), a Continuación, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si el origen de datos.Conjunto de datos.Activo, a Continuación, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp origen de datos.Conjunto de datos.Editar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp correos := True
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := True
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Excepto
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := False
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp Final
Begin
& nbsp & nbsp & nbsp // Si los cambios del Texto y el conjunto de datos
& nbsp & nbsp & nbsp // no es en EditState, a continuación, una Excepción
& nbsp & nbsp & nbsp // se genera. Asegúrese de conjunto de datos es
& nbsp & nbsp & nbsp // en EditState antes de cambiar el Texto.
& nbsp & nbsp & nbsp fIsChanging := True
& nbsp & nbsp & nbsp Probar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp correos := False
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si CanChange, a Continuación, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Caso CharCase De
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ecNormal : {no Hacer Nada}
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ecUpperCase : Text := Mayúsculas(Texto)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ecLowerCase : Text := Minúsculas(Texto)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ecProperCase: Text := ToProper(Texto)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si bPost, a Continuación,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp origen de datos.Conjunto de datos.Puesto
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp End Else
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp MessageDlg('Otro usuario puede estar usando este'
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp registro del'.' #13 #13
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp 'TextCase cambios pueden no ser'
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp 'visible para este registro.' ,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp mtWarning,[mbOK],0)
& nbsp & nbsp & nbsp Finalmente
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp fIsChanging := False
& nbsp & nbsp & nbsp Final
Fin
Cambiar el CharCase propiedad ejecuta el SetCharCase método (ver Listado 5), que, a su vez, ejecuta el SetTextCase método.
Listado 5. El SetCharCase método.
Procedimiento TPSIDBEdit.SetCharCase(Valor:TPSICharCase)
Begin
& nbsp & nbsp & nbsp Si fCharCase <> Valor, a Continuación, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp fCharCase := Valor
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetTextCase(Verdadero)
& nbsp & nbsp & nbsp Final
Fin
para que el control tenga capacidad de movimiento, me sobreescribimos el método KeyDown (ver Listado 6). Endeudamiento el IDE de Delphi pulsaciones de teclas para el componente de mover y cambiar el tamaño, he utilizado la combinación de teclas Ctrl-ArrowKeys para el movimiento y el Cambio-ArrowKeys para el dimensionamiento. Pulsando estas teclas hace que el control para cambiar el tamaño o la posición de un píxel.
Listado 6. El método KeyDown.
Procedimiento TPSIDBEdit.KeyDown(var Key: Word
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Shift: TShiftState)
Begin
& nbsp & nbsp & nbsp If (Clave [vk_up,vk_down,vk_left,vk_right])
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Y AllowUserChange, a Continuación, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp If (Turno = [ssCtrl]) A continuación, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Cambiar de posición
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Caso Tecla De
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Up : parte Superior := Top - 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Down : Top := 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Left : a la Izquierda := Izquierda - 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Right: Izquierda := 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp End Else If (Turno = [ssShift]) A continuación, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Cambiar de Tamaño
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Caso Tecla De
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Up : Altura := Altura - 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Down : Altura: a= Altura 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Left : Ancho := Ancho - 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Right: Ancho := Ancho 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Clave := 0
& nbsp & nbsp & nbsp End Else Begin
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp heredado KeyDown(Tecla de Desplazamiento)
& nbsp & nbsp & nbsp Final
Fin
yo también quería que el usuario sea capaz de mover la pieza con el ratón, así que me hicieron caso omiso de los métodos MouseDown, MouseUp y MouseMove.
hasta ahora, lo que tienes es un DBEdit que permite a un usuario cambiar su posición y tamaño, pero poco más. El tipo de letra, el Color, el Orden de Tabulación, efecto 3D, y la Frontera se va a hacer con la adición del componente ChangeMenu.
La base para este componente se encuentra en la unidad de TypInfo.pas, lo que le permite tener acceso a un objeto RTTI (tiempo de ejecución tipo de información). TypInfo.pas contiene las funciones y los procedimientos que puede Obtener o Establecer un objeto de propiedad de los valores durante la ejecución de la aplicación. Algunos métodos sencillos de Establecer u Obtener un objeto de propiedad del valor en tiempo de ejecución puede ser algo como el Listado 7.
el Listado 7. Obtener y Establecer una propiedad del objeto en tiempo de ejecución.
Función GetProperty(Sender:TComponent
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp sPropName:String):Variante
Var
& nbsp & nbsp & nbsp PropInfo : PPropinfo
Begin
& nbsp & nbsp & nbsp & nbsp // a partir De la información de la clase, obtener la propiedad
& nbsp & nbsp & nbsp & nbsp PropInfo := GetPropInfo(Remitente.ClassInfo,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp sPropName)
& nbsp & nbsp & nbsp & nbsp / / ¿la propiedad existen?
& nbsp & nbsp & nbsp & nbsp Si (PropInfo <> Nil) Then Begin
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Caso propinfo^.PropType^.Tipo De
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp tkEnumeration,tkInteger:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := GetOrdProp(Remitente,PropInfo)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp tkString,tkLString,tkWString:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := GetStrProp(Remitente,PropInfo)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp End Else
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := Null
Fin
Procedimiento SetProperty(Sender:TComponent
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp sPropName:Cadena
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vValue:Variante)
Var
& nbsp & nbsp & nbsp PropInfo : PPropinfo
Begin
& nbsp & nbsp & nbsp & nbsp // a partir De la información de la clase, obtener la propiedad
& nbsp & nbsp & nbsp & nbsp PropInfo := GetPropInfo(Remitente.ClassInfo,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp sPropName)
& nbsp & nbsp & nbsp & nbsp / / ¿la propiedad existen?
& nbsp & nbsp & nbsp & nbsp Si (PropInfo <> Nil) Then Begin
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Caso propinfo^.PropType^.Tipo De
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp tkEnumeration,tkInteger:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetOrdProp(Remitente,PropInfo,vValue)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp tkString,tkLString,tkWString:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetStrProp(Remitente,PropInfo,vValue)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp Final
Fin
el Uso de estos dos métodos, se podría parecer a esto:
& nbsp & nbsp SetProperty(DBEdit1,'Ctl3D',False);
& nbsp & nbsp DBEdit2.Ctrl3D := GetProperty(DBEdit1.'Ctl3D')
Concedida, en este ejemplo es probablemente más simplificado, pero los procedimientos como estos pueden ser muy útiles si usted no sabe el nombre del componente, o incluso de su clase.
Los tres principales métodos utilizados en ChangeMenu & GetProperty(), SetProperty(), y IsProperty() & se encuentran en la unidad de PropFunc.pas que es parte de esta biblioteca. IsProperty() es una función Booleana que se comprueba la existencia de una propiedad concreta de un objeto y devuelve un valor de True si la propiedad existe. Se puede usar algo como esto:
Si IsProperty(Form1.Componentes[i],'Ctl3D'), a Continuación,
& nbsp & nbsp & nbsp Componentes[i].Ctl3D := False
TChangeMenu es una subclase de TPopupMenu con dos propiedades adicionales: FontDialog y ColorDialog, que se utilizan para cambiar el componente de Fuente y Color y puede apuntar a cualquier coincidencia de tipos de clase que están en el ámbito de la componente. Los métodos MenuClick y OnMenuPopup hacer la mayor parte del trabajo y se asignan a los OnClick y OnPopup eventos de los elementos de menú cuando se crea el componente. Todo esto sucede, por supuesto, en el ChangeMenu de la unidad (vea el Listado 8).
Listado 8. El ChangeMenu de la unidad.
unidad de ChangeMenu
interfaz
usos
& nbsp & nbsp Windows, Messages, SysUtils, Classes, Graphics,
& nbsp & nbsp Controles, Formularios, cuadros de diálogo, Menús,comctrls,
& nbsp & nbsp StdCtrls,dbctrls, db,extctrls
tipo
& nbsp & nbsp TChangeMenu = clase(TPopupMenu)
& nbsp & nbsp privada
& nbsp & nbsp & nbsp & nbsp { Private declarations }
& nbsp & nbsp & nbsp & nbsp pm_Font : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_bgColor : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_TabOrder : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Ctrl3D : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_BorderStyle: TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Columns : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Caption : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Divider1 : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_UpperCase : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_LowerCase : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_MixedCase : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_ProperCase : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Height : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Width : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Style : TMenuItem
& nbsp & nbsp & nbsp & nbsp fFontDialog :TFontDialog
& nbsp & nbsp & nbsp & nbsp fColorDialog :TColorDialog
& nbsp & nbsp & nbsp & nbsp Procedimiento SetColorDialog(Valor:TColorDialog)
& nbsp & nbsp & nbsp & nbsp Procedimiento SetFontDialog(Valor:TFontDialog)
& nbsp & nbsp & nbsp & nbsp Procedimiento MenuClick(Sender:TObject)
& nbsp & nbsp & nbsp & nbsp Procedimiento OnMenuPopup(Sender:TObject)
& nbsp & nbsp protegido
& nbsp & nbsp & nbsp & nbsp { declaraciones Protegidos }
& nbsp & nbsp pública
& nbsp & nbsp & nbsp & nbsp { Public declarations }
& nbsp & nbsp & nbsp & nbsp Procedimiento de Carga Reemplazar
& nbsp & nbsp & nbsp & nbsp Destructor destruir reemplazar
& nbsp & nbsp & nbsp & nbsp Constructor Create(AOwner: TComponent) reemplazar
& nbsp & nbsp publicado
& nbsp & nbsp & nbsp & nbsp { Publicado declaraciones }
& nbsp & nbsp & nbsp & nbsp Propiedad FontDialog :TFontDialog
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Leer fFontDialog
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Escribir SetFontDialog
& nbsp & nbsp & nbsp & nbsp Propiedad ColorDialog : TColorDialog
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Leer fColorDialog
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Escribir SetColorDialog
& nbsp & nbsp final
procedimiento de Registro
aplicación
utiliza PropFunc, col_edit
Debido al uso especializado de este menú los elementos de menú sólo se crean en tiempo de ejecución, no en tiempo de diseño en el IDE. Después de que el menú se crean los elementos, el método MenuClick() se asigna al evento OnClick de cada elemento de menú. El menú tendrá un aspecto como el de la Figura 1.
La Carga método (ver Listado 9) captura el puntero a la del componente OnPopup método, a continuación, asigna el OnPopup evento para el método OnMenuPoup(). Esto se hace para que el desarrollador del OnPopup método se ejecutará después de la OnMenuPopup método ha terminado de procesar sus propios elementos de menú.
Listado de 9. La Carga método.
Procedimiento TChangeMenu.Carga
Begin
& nbsp & nbsp & nbsp Probar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Guardar puntero del Componente OnPopup Método
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp FOtherOnPopup := OnPopup
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Asignar OnPopup Método
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp OnPopup := OnMenuPopup
& nbsp & nbsp & nbsp Finalmente
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Heredado
& nbsp & nbsp & nbsp Final
Fin
Cuando el usuario haga clic con el ratón sobre el componente, el OnMenuPopup se ejecuta el método (ver Listado 10) e inicializa los elementos del menú basados en el menú del PopupComponent de la propiedad. PopupComponent es un puntero al objeto que se encarga de activar el menú y el tipo de TComponent. Observe el uso del método IsProperty para establecer la propiedad Visible de los elementos de menú.
Listado de 10. El OnMenuPopup método.
Procedimiento TChangeMenu.OnMenuPopup(Sender:TObject)
// Inicializar los elementos de menú basado en la
// componente enfocado en el tipo y propiedades.
Var bSet : Boolean
Begin
& nbsp & nbsp & nbsp // no mostrar la Fuente de elemento si la Fuente
& nbsp & nbsp & nbsp // cuadro de Diálogo de propiedades es Nulo o la Fuente
& nbsp & nbsp & nbsp // Propiedad no existe en el centrado
& nbsp & nbsp & nbsp // componente.
& nbsp & nbsp & nbsp pm_Font.Visible :=
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp (No (FontDialog = Nil))
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Y IsProperty(PopupComponent,'Fuente')
& nbsp & nbsp & nbsp // no mostrar el elemento de Color si el ColorDialog
&
Dar a sus clientes el control de la interfaz grafica de usuario
Dar a sus clientes el control de la interfaz grafica de usuario : Multi-millones de consejos para hacer su vida mas facil.
en Este articulo se muestra como los usuarios pueden modificar su interfaz grafica de usuario en tiempo de ejecucion.
| Desarrolladores de Delphi | de febrero de 1999 | derechos de Autor Pinnacle Publishing, Inc. Todos los derechos reservados.Dar a Sus Clientes el Control de la interfaz de usuario
Steve Zimmelman
¿cuantas veces has entregado lo que pensabas que era una solicitud completa, solo para escuchar su cliente de decir, 'Gee, esto es bueno, pero realmente me gustaria el Nombre de la izquierda, y el Estado del campo debe ser de color rojo, no negro, y . . .' ¿No seria agradable si todos los usuarios tenian que hacer era a la derecha-haga clic en el raton sobre el control, y sale un menu emergente que permite el cambio en el control de los atributos? O si se pulsa Ctrl-ArrowKey o Mayus-ArrowKey para cambiar la posicion o el tamaño del control?
Dar a los usuarios el control de la interfaz grafica de usuario es un proceso de dos pasos. Primero tienes que crear controles con las propiedades de los usuarios pueden cambiar en tiempo de ejecucion y, a continuacion, usted debe tener una forma de guardar y restaurar los cambios. Generalmente, el control que obtiene el mayor uso es el DBEdit. Asi que en este ejemplo se centrara en la creacion de un DBEdit que utiliza de una manera personalizada, PopupMenu que se activa en el clic derecho del raton. El menu le permite al usuario cambiar el Color, tipo de letra, el Orden de Tabulacion y el Texto del Caso. Ademas, la combinacion de teclas Ctrl-Flecha y Mayus-Flecha para cambiar la posicion y el tamaño del control, respectivamente.
Antes de comenzar, quiero presentarles a un nuevo texto-caso de la propiedad: ProperCase. Mas adecuado-el caso de las conversiones generalmente en mayusculas solo la primera letra, luego la letra que sigue a un espacio. Pero esto deja un sinfin de nombres y titulos abreviados de mirar un poco torpe, como Mcdonald', O'Hara, M. D., y asi sucesivamente. Asi que en mi intento de crear un mejor raton-trampa, he incluido una adecuada caso de conversion que tiene la inteligencia para manejar estos nombres especiales. Coloque las funciones que se usan para el correcto-caso de conversion en una unidad llamada StrFunc.pas y, a continuacion, se incluye la unidad de StrFunc en los Usos de la declaracion de la componente.
la Creacion de la variable DBEdit
La primera cosa que hice fue crear un nuevo componente mediante TDBEdit como el padre de la clase. Me llama la nueva clase TPSIDBEdit porque el nombre de la empresa en la que trabajo es PSI, y era una manera sencilla de distinguir el componente. A continuacion, he creado un nuevo CharCase tipo que incluye ProperCase. Va a ser usado para reemplazar el DBEdit del TCharCase. Tambien he cambiado el CharCase la propiedad a un nuevo tipo de TPSICharCase. En adicion a la sustitucion de la CharCase propiedad, me introdujo dos nuevas propiedades: AllowUserChange y PopupChangeMenu. La propiedad AllowUserChange es un Booleano simple interruptor que activa o desactiva la capacidad del usuario para cambiar cualquiera de las propiedades del componente en tiempo de ejecucion, y PopupChangeMenu es un puntero a la PopupMenu que, en efecto, cuando AllowUserChange se establece en True. Una mayor parte de los componentes del cambio es realizado por el PopupChangeMenu, pero voy a hablar de eso un poco mas tarde. Listado 1 se presenta la PSIDBEdit de la unidad.
Listado 1. El PSIDBEdit de la unidad.
unidad de PSIDBEdit
interfaz
usos
& nbsp & nbsp Windows, SysUtils, Classes, Controles, Formularios, cuadros de dialogo,
& nbsp & nbsp DBCtrls, Menus, db, StrFunc
tipo
& nbsp & nbsp TPSICharCase = (ecNormal, ecUpperCase,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ecLowerCase, ecProperCase)
& nbsp & nbsp TPSIDBEdit = clase(TDBEdit)
& nbsp & nbsp privada
& nbsp & nbsp & nbsp & nbsp fCharCase : TPSICharCase
& nbsp & nbsp & nbsp & nbsp fIsChanging : Boolean
& nbsp & nbsp & nbsp & nbsp fAllowUserChange : Boolean
& nbsp & nbsp & nbsp & nbsp fStartMove : Boolean
& nbsp & nbsp & nbsp & nbsp fTop : Integer
& nbsp & nbsp & nbsp & nbsp fLeft : Integer
& nbsp & nbsp & nbsp & nbsp fChangeMenu : TpopupMenu
& nbsp & nbsp & nbsp & nbsp fPopupSave : TPopupMenu
& nbsp & nbsp & nbsp & nbsp Procedimiento SetAllowUserChange(Valor:Boolean)
& nbsp & nbsp & nbsp & nbsp Procedimiento SetChangeMenu(Valor:TpopupMenu)
& nbsp & nbsp & nbsp & nbsp Procedimiento SetPopUpMenu
& nbsp & nbsp & nbsp & nbsp Procedimiento SetCharCase(Valor:TPSICharCase)
& nbsp & nbsp & nbsp & nbsp Procedimiento SetTextCase(Const bCheckState:Boolean)
& nbsp & nbsp protegido
& nbsp & nbsp publica
& nbsp & nbsp & nbsp & nbsp Procedimiento de Carga Reemplazar
& nbsp & nbsp & nbsp & nbsp Procedimiento de Cambio de Reemplazar
& nbsp & nbsp & nbsp & nbsp procedimiento KeyDown(var Key: La palabra
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Shift: TShiftState) reemplazar
& nbsp & nbsp & nbsp & nbsp Procedimiento MouseDown(Boton: TMouseButton Cambio:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp TShiftState X, Y: Integer)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Reemplazar
& nbsp & nbsp & nbsp & nbsp procedimiento MouseMove(Shift: TShiftState
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp X, Y: Integer) Reemplazar
& nbsp & nbsp & nbsp & nbsp procedimiento MouseUp(Boton: TMouseButton Cambio:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp TShiftState X, Y: Integer)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Reemplazar
& nbsp & nbsp publicado
& nbsp & nbsp & nbsp & nbsp Propiedad AllowUserChange : Boolean
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Leer fAllowUserChange
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Escribir SetAllowUserChange
& nbsp & nbsp & nbsp & nbsp Propiedad CharCase : TPSICharCase
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Leer fCharCase
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Escribir SetCharCase
& nbsp & nbsp & nbsp & nbsp Propiedad PopupChangeMenu : TPopupMenu
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Leer fChangeMenu
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Escribir SetChangeMenu
& nbsp & nbsp final
yo queria que el componente se tienen dos estados: un estado predeterminado, que se comporten igual que su antecesor, y un diseño de estado, que permitira al usuario cambiar sus propiedades en tiempo de ejecucion. La propiedad Booleana AllowUserChange que distingue a estos dos estados. Cuando AllowUserChange es True, el componente del PopupMenu es cambiado a punto para el valor almacenado en la PopupChangeMenu de la propiedad. Si es False, entonces el PopupMenu propiedad vuelve a su anterior tiempo de diseño de la asignacion. Tambien permite que el componente se mueve o cambia de tamaño. Pense que seria agradable para que el usuario pueda ver una diferencia entre los dos estados, asi que he cambiado el cursor a crHandPoint (-21) en el SetAllowUserChange metodo.
El PopupMenu asignacion es cambiado a traves de la SetPopupMenu metodo cuando el AllowUserChange propiedad es cambiado.
con el fin De intercambiar el PopupMenu de los punteros, el defecto PopupMenu se almacena en fPopupSave en el Cargado metodo (ver Listado 2). A continuacion, el SetPopupMenu metodo es llamado para asegurarse de que el propio menu emergente se basan en el valor de AllowUserChange.
Listado 2. La Carga metodo.
Procedimiento TPSIDBEdit.Carga
Begin
& nbsp & nbsp & nbsp Probar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si (csDesigning en ComponentState), a Continuacion, Salir
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Captura de PopupMenu Asignacion
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp fPopupSave := PopupMenu
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetPopupMenu
& nbsp & nbsp & nbsp Finalmente
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp heredado Carga
& nbsp & nbsp & nbsp Final
Fin
Con la llegada del nuevo texto de caso ProperCase y el nuevo tipo de TPSICharCase, Tuve que reemplazar completamente y volver a implementar todos los demas de texto estandar-caso de las conversiones en el metodo de Cambio de la componente (ver Listado 3).
el Listado 3. El Cambio de metodo.
Procedimiento TPSIDBEdit.Cambiar
Var
& nbsp & nbsp & nbsp iSelStart : Integer
Begin
& nbsp & nbsp & nbsp Probar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si (csDesigning en ComponentState)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp O fIsChanging, a Continuacion, Salir
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Captura la Posicion del Cursor
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp iSelStart := SelStart
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetTextCase(Falso)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Restaurar la Posicion del Cursor
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SelStart := iSelStart
& nbsp & nbsp & nbsp Finalmente
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Heredado
& nbsp & nbsp & nbsp Final
Fin
El real cambio en el Texto es un poco complicado. Si cambia el texto mediante programacion cuando el objeto tiene el foco, y el conjunto de datos no esta en modo de Edicion o Insercion, la excepcion 'conjunto de datos no esta en modo de Edicion o Insercion' se genera. Asi que antes de cambiar el texto, el componente del conjunto de datos.El estado debe ser interrogado y cambiar si es necesario. Tambien debemos ocuparnos de posibles multi-usuario de los conflictos que puedan producirse. El parametro bCheckState se utiliza para determinar si el conjunto de datos.El estado tiene que ser colocado en modo de Edicion o Insercion antes de cambiar el texto. Si lo hace, entonces el metodo tambien deben Publicar los cambios. El metodo Post se llama solo si la variable de memoria bPost se establece en True. El listado 4 muestra donde todo esto sucede en el SetTextCase metodo.
el Listado 4. El SetTextCase metodo.
Procedimiento TPSIDBEdit.SetTextCase(Const bCheckState:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Boolean)
Var
& nbsp & nbsp & nbsp correos : Boolean
& nbsp & nbsp & nbsp Funcion CanChange : Boolean
& nbsp & nbsp & nbsp Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Probar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si No bCheckState, a Continuacion, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := True
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Salida
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp If (origen de datos <> Nil) A continuacion, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si No (origen de datos.Conjunto de datos.Estado
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp En [dsEdit, dsInsert]), a Continuacion, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si el origen de datos.Conjunto de datos.Activo, a Continuacion, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp origen de datos.Conjunto de datos.Editar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp correos := True
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := True
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Excepto
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := False
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp Final
Begin
& nbsp & nbsp & nbsp // Si los cambios del Texto y el conjunto de datos
& nbsp & nbsp & nbsp // no es en EditState, a continuacion, una Excepcion
& nbsp & nbsp & nbsp // se genera. Asegurese de conjunto de datos es
& nbsp & nbsp & nbsp // en EditState antes de cambiar el Texto.
& nbsp & nbsp & nbsp fIsChanging := True
& nbsp & nbsp & nbsp Probar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp correos := False
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si CanChange, a Continuacion, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Caso CharCase De
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ecNormal : {no Hacer Nada}
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ecUpperCase : Text := Mayusculas(Texto)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ecLowerCase : Text := Minusculas(Texto)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ecProperCase: Text := ToProper(Texto)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Si bPost, a Continuacion,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp origen de datos.Conjunto de datos.Puesto
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp End Else
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp MessageDlg('Otro usuario puede estar usando este'
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp registro del'.' #13 #13
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp 'TextCase cambios pueden no ser'
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp 'visible para este registro.' ,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp mtWarning,[mbOK],0)
& nbsp & nbsp & nbsp Finalmente
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp fIsChanging := False
& nbsp & nbsp & nbsp Final
Fin
Cambiar el CharCase propiedad ejecuta el SetCharCase metodo (ver Listado 5), que, a su vez, ejecuta el SetTextCase metodo.
Listado 5. El SetCharCase metodo.
Procedimiento TPSIDBEdit.SetCharCase(Valor:TPSICharCase)
Begin
& nbsp & nbsp & nbsp Si fCharCase <> Valor, a Continuacion, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp fCharCase := Valor
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetTextCase(Verdadero)
& nbsp & nbsp & nbsp Final
Fin
para que el control tenga capacidad de movimiento, me sobreescribimos el metodo KeyDown (ver Listado 6). Endeudamiento el IDE de Delphi pulsaciones de teclas para el componente de mover y cambiar el tamaño, he utilizado la combinacion de teclas Ctrl-ArrowKeys para el movimiento y el Cambio-ArrowKeys para el dimensionamiento. Pulsando estas teclas hace que el control para cambiar el tamaño o la posicion de un pixel.
Listado 6. El metodo KeyDown.
Procedimiento TPSIDBEdit.KeyDown(var Key: Word
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Shift: TShiftState)
Begin
& nbsp & nbsp & nbsp If (Clave [vk_up,vk_down,vk_left,vk_right])
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Y AllowUserChange, a Continuacion, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp If (Turno = [ssCtrl]) A continuacion, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Cambiar de posicion
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Caso Tecla De
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Up : parte Superior := Top - 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Down : Top := 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Left : a la Izquierda := Izquierda - 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Right: Izquierda := 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp End Else If (Turno = [ssShift]) A continuacion, Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Cambiar de Tamaño
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Caso Tecla De
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Up : Altura := Altura - 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Down : Altura: a= Altura 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Left : Ancho := Ancho - 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vk_Right: Ancho := Ancho 1
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Clave := 0
& nbsp & nbsp & nbsp End Else Begin
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp heredado KeyDown(Tecla de Desplazamiento)
& nbsp & nbsp & nbsp Final
Fin
yo tambien queria que el usuario sea capaz de mover la pieza con el raton, asi que me hicieron caso omiso de los metodos MouseDown, MouseUp y MouseMove.
hasta ahora, lo que tienes es un DBEdit que permite a un usuario cambiar su posicion y tamaño, pero poco mas. El tipo de letra, el Color, el Orden de Tabulacion, efecto 3D, y la Frontera se va a hacer con la adicion del componente ChangeMenu.
La base para este componente se encuentra en la unidad de TypInfo.pas, lo que le permite tener acceso a un objeto RTTI (tiempo de ejecucion tipo de informacion). TypInfo.pas contiene las funciones y los procedimientos que puede Obtener o Establecer un objeto de propiedad de los valores durante la ejecucion de la aplicacion. Algunos metodos sencillos de Establecer u Obtener un objeto de propiedad del valor en tiempo de ejecucion puede ser algo como el Listado 7.
el Listado 7. Obtener y Establecer una propiedad del objeto en tiempo de ejecucion.
Funcion GetProperty(Sender:TComponent
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp sPropName:String):Variante
Var
& nbsp & nbsp & nbsp PropInfo : PPropinfo
Begin
& nbsp & nbsp & nbsp & nbsp // a partir De la informacion de la clase, obtener la propiedad
& nbsp & nbsp & nbsp & nbsp PropInfo := GetPropInfo(Remitente.ClassInfo,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp sPropName)
& nbsp & nbsp & nbsp & nbsp / / ¿la propiedad existen?
& nbsp & nbsp & nbsp & nbsp Si (PropInfo <> Nil) Then Begin
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Caso propinfo^.PropType^.Tipo De
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp tkEnumeration,tkInteger:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := GetOrdProp(Remitente,PropInfo)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp tkString,tkLString,tkWString:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := GetStrProp(Remitente,PropInfo)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp End Else
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := Null
Fin
Procedimiento SetProperty(Sender:TComponent
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp sPropName:Cadena
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp vValue:Variante)
Var
& nbsp & nbsp & nbsp PropInfo : PPropinfo
Begin
& nbsp & nbsp & nbsp & nbsp // a partir De la informacion de la clase, obtener la propiedad
& nbsp & nbsp & nbsp & nbsp PropInfo := GetPropInfo(Remitente.ClassInfo,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp sPropName)
& nbsp & nbsp & nbsp & nbsp / / ¿la propiedad existen?
& nbsp & nbsp & nbsp & nbsp Si (PropInfo <> Nil) Then Begin
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Caso propinfo^.PropType^.Tipo De
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp tkEnumeration,tkInteger:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetOrdProp(Remitente,PropInfo,vValue)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp tkString,tkLString,tkWString:
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetStrProp(Remitente,PropInfo,vValue)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Final
& nbsp & nbsp & nbsp & nbsp Final
Fin
el Uso de estos dos metodos, se podria parecer a esto:
& nbsp & nbsp SetProperty(DBEdit1,'Ctl3D',False);
& nbsp & nbsp DBEdit2.Ctrl3D := GetProperty(DBEdit1.'Ctl3D')
Concedida, en este ejemplo es probablemente mas simplificado, pero los procedimientos como estos pueden ser muy utiles si usted no sabe el nombre del componente, o incluso de su clase.
Los tres principales metodos utilizados en ChangeMenu & GetProperty(), SetProperty(), y IsProperty() & se encuentran en la unidad de PropFunc.pas que es parte de esta biblioteca. IsProperty() es una funcion Booleana que se comprueba la existencia de una propiedad concreta de un objeto y devuelve un valor de True si la propiedad existe. Se puede usar algo como esto:
Si IsProperty(Form1.Componentes[i],'Ctl3D'), a Continuacion,
& nbsp & nbsp & nbsp Componentes[i].Ctl3D := False
TChangeMenu es una subclase de TPopupMenu con dos propiedades adicionales: FontDialog y ColorDialog, que se utilizan para cambiar el componente de Fuente y Color y puede apuntar a cualquier coincidencia de tipos de clase que estan en el ambito de la componente. Los metodos MenuClick y OnMenuPopup hacer la mayor parte del trabajo y se asignan a los OnClick y OnPopup eventos de los elementos de menu cuando se crea el componente. Todo esto sucede, por supuesto, en el ChangeMenu de la unidad (vea el Listado 8).
Listado 8. El ChangeMenu de la unidad.
unidad de ChangeMenu
interfaz
usos
& nbsp & nbsp Windows, Messages, SysUtils, Classes, Graphics,
& nbsp & nbsp Controles, Formularios, cuadros de dialogo, Menus,comctrls,
& nbsp & nbsp StdCtrls,dbctrls, db,extctrls
tipo
& nbsp & nbsp TChangeMenu = clase(TPopupMenu)
& nbsp & nbsp privada
& nbsp & nbsp & nbsp & nbsp { Private declarations }
& nbsp & nbsp & nbsp & nbsp pm_Font : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_bgColor : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_TabOrder : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Ctrl3D : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_BorderStyle: TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Columns : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Caption : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Divider1 : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_UpperCase : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_LowerCase : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_MixedCase : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_ProperCase : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Height : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Width : TMenuItem
& nbsp & nbsp & nbsp & nbsp pm_Style : TMenuItem
& nbsp & nbsp & nbsp & nbsp fFontDialog :TFontDialog
& nbsp & nbsp & nbsp & nbsp fColorDialog :TColorDialog
& nbsp & nbsp & nbsp & nbsp Procedimiento SetColorDialog(Valor:TColorDialog)
& nbsp & nbsp & nbsp & nbsp Procedimiento SetFontDialog(Valor:TFontDialog)
& nbsp & nbsp & nbsp & nbsp Procedimiento MenuClick(Sender:TObject)
& nbsp & nbsp & nbsp & nbsp Procedimiento OnMenuPopup(Sender:TObject)
& nbsp & nbsp protegido
& nbsp & nbsp & nbsp & nbsp { declaraciones Protegidos }
& nbsp & nbsp publica
& nbsp & nbsp & nbsp & nbsp { Public declarations }
& nbsp & nbsp & nbsp & nbsp Procedimiento de Carga Reemplazar
& nbsp & nbsp & nbsp & nbsp Destructor destruir reemplazar
& nbsp & nbsp & nbsp & nbsp Constructor Create(AOwner: TComponent) reemplazar
& nbsp & nbsp publicado
& nbsp & nbsp & nbsp & nbsp { Publicado declaraciones }
& nbsp & nbsp & nbsp & nbsp Propiedad FontDialog :TFontDialog
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Leer fFontDialog
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Escribir SetFontDialog
& nbsp & nbsp & nbsp & nbsp Propiedad ColorDialog : TColorDialog
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Leer fColorDialog
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Escribir SetColorDialog
& nbsp & nbsp final
procedimiento de Registro
aplicacion
utiliza PropFunc, col_edit
Debido al uso especializado de este menu los elementos de menu solo se crean en tiempo de ejecucion, no en tiempo de diseño en el IDE. Despues de que el menu se crean los elementos, el metodo MenuClick() se asigna al evento OnClick de cada elemento de menu. El menu tendra un aspecto como el de la Figura 1.
La Carga metodo (ver Listado 9) captura el puntero a la del componente OnPopup metodo, a continuacion, asigna el OnPopup evento para el metodo OnMenuPoup(). Esto se hace para que el desarrollador del OnPopup metodo se ejecutara despues de la OnMenuPopup metodo ha terminado de procesar sus propios elementos de menu.
Listado de 9. La Carga metodo.
Procedimiento TChangeMenu.Carga
Begin
& nbsp & nbsp & nbsp Probar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Guardar puntero del Componente OnPopup Metodo
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp FOtherOnPopup := OnPopup
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp // Asignar OnPopup Metodo
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp OnPopup := OnMenuPopup
& nbsp & nbsp & nbsp Finalmente
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Heredado
& nbsp & nbsp & nbsp Final
Fin
Cuando el usuario haga clic con el raton sobre el componente, el OnMenuPopup se ejecuta el metodo (ver Listado 10) e inicializa los elementos del menu basados en el menu del PopupComponent de la propiedad. PopupComponent es un puntero al objeto que se encarga de activar el menu y el tipo de TComponent. Observe el uso del metodo IsProperty para establecer la propiedad Visible de los elementos de menu.
Listado de 10. El OnMenuPopup metodo.
Procedimiento TChangeMenu.OnMenuPopup(Sender:TObject)
// Inicializar los elementos de menu basado en la
// componente enfocado en el tipo y propiedades.
Var bSet : Boolean
Begin
& nbsp & nbsp & nbsp // no mostrar la Fuente de elemento si la Fuente
& nbsp & nbsp & nbsp // cuadro de Dialogo de propiedades es Nulo o la Fuente
& nbsp & nbsp & nbsp // Propiedad no existe en el centrado
& nbsp & nbsp & nbsp // componente.
& nbsp & nbsp & nbsp pm_Font.Visible :=
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp (No (FontDialog = Nil))
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Y IsProperty(PopupComponent,'Fuente')
& nbsp & nbsp & nbsp // no mostrar el elemento de Color si el ColorDialog
&
Dar a sus clientes el control de la interfaz gráfica de usuario
By Consejos Y Trucos
Dar a sus clientes el control de la interfaz gráfica de usuario : Multi-millones de consejos para hacer su vida más fácil. Consejos Y Trucos www.consejosytrucos.net Ciempozuelos, Madrid Extramuros 82 ES-M 28350 Spain 674 192 969