Mostrando las entradas con la etiqueta Clases. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Clases. Mostrar todas las entradas

2 de octubre de 2021

Mejoras en el control Grid de Visual FoxPro

Artículo original: Visual FoxPro Grid Enhancements
https://www.sweetpotatosoftware.com/blog/index.php/2008/11/25/visual-foxpro-grid-enhancements
Autor: Craig Boyd
Traductor: Luis María Guayán

El control grid de Visual FoxPro

A menudo me han escuchado decir que el Grid de Visual FoxPro es uno de los mejores controles jamás ideados. Sigo sintiéndome así, pero ¿no sería bueno si algunas de las funciones que nuestros clientes quieren implementar en el control Grid ya estuvieran disponibles? Ya sabes, características como: ordenado, filtrado, búsqueda incremental, guardar las preferencias del usuario y exportar a Excel. Sería aún mejor si este tipo de funcionalidades pudiera implementarse en cualquier control Grid de Visual FoxPro (independientemente del origen de los registros) simplemente colocando una clase en un formulario, estableciendo una sola propiedad y escribiendo una sola línea de código. Bueno, eso es lo que me he propuesto crear con la clase que presento en esta publicación.

Pueden ver la funcionalidad básica proporcionada por GridExtras en las imágenes que aparecen al final de la publicación.

Cómo usar la clase

Les proporciono la aplicación Sample.exe en la descarga para que puedan probarla y ver cómo se implementa. Sin embargo, los pasos básicos son:

  • Coloque una instancia de GridExtras en su formulario o contenedor (un GridExtras para cada control Grid que desee mejorar).
  • Establezca la propiedad GridExpression de GridExtras en una cadena que se evaluará en tiempo de ejecución al control Grid que está mejorando: "Thisform.Grid1" es el valor predeterminado para esta propiedad.
  • Llame al método Setup() de GridExtras cuando su control Grid esté listo para funcionar. No tengo forma de saber si está configurando el origen de registros en tiempo de ejecución, o si está agregando columnas en el código, por lo que este método se proporciona como una forma de controlar cuándo GridExtras comenzará a interactuar con el control Grid
  • .

Eso es todo lo que hay que hacer para poner GridExtras en funcionamiento para un control Grid en su aplicación. Como digo, he incluido un ejemplo en la descarga, así que si tiene alguna pregunta sobre cómo se hace esto, simplemente revise el ejemplo.

Otras propiedades de la clase

Hay algunas otras propiedades de GridExtras de las que es posible que desee tomar nota y utilizar, como:

  • CompanyName y ProductName: estas propiedades se utilizan para determinar dónde guardar el archivo de preferencias del control Grid del usuario que está separado por perfil (Ej: "C:\Users\Craig\AppData\Roaming\MyCompany\MyProduct\gridprefs.tmp").
  • AllowGridExport, AllowGridFilter, AllowGridPreferences, AllowGridSort: estas propiedades le permiten activar o desactivar ciertas características de la clase según sus necesidades.
  • TemplateTable: esta propiedad determina dónde GridExtras busca gridextras.dbf que se usa para guardar las plantillas de Grid que crea el usuario (el usuario puede guardar sus filtros y ordenaciones para poder recrearlos fácilmente en un momento posterior). Es posible que deba establecer esta propiedad si planea mantener la tabla gridextras en una ruta de red, como con la carpeta de base de datos compartida para su aplicación.

Que sigue

Simplemente juegue con GridExtras y vea si es útil para usted y sus aplicaciones. En un mundo perfecto, encontraría alguna forma de mejorarlo (agregar formatos de exportación adicionales, proporcionar una función de bloqueo de columna, etc.). Si mejora GridExtras, le agradecería que se ponga en contacto conmigo y comparta las mejoras que ha implementado. Gracias de antemano a aquellos de ustedes que decidan hacerlo.

Hasta la próxima!

Descargar GridExtras y ejemplos (aproximadamente 223 KB)


Figura 1: GridExtras proporciona capacidades de ordenamiento, búsqueda incremental y filtrado a cualquier control Grid de Visual FoxPro.


Figura 2: GridExtras tiene características adicionales como la capacidad de volverse semitransparente y la capacidad de guardar las preferencias del usuario (orden de columna y ancho).


Figura 3: Además de las funciones proporcionadas por GridExtras a través de los encabezados de columna de un coltrol Grid, también hay un icono agregado en la parte inferior derecha de la clase que permite al usuario acceder a la pantalla "Plantillas de cuadrícula y exportación" que se ve en la Figura 4.


Figura 4: Las plantillas de Grids ayudan al usuario a guardar las vistas del Grid para poder recrearlas rápidamente en el futuro. La función de exportación de GridExtras puede crear formatos de Excel XLS, XLSX, XLB y XLM. Los títulos de encabezado del control Grid se utilizan para nombrar las columnas de Excel cuando se exportan los datos.

3 de junio de 2021

Alcance (rango) de propiedades

Titulo: Ver o no ver
Original: To See or Not To See
Autor: Jim Booth
Traducido por: Roberto Alfredo Moré


En esta columna investigaremos la visibilidad de propiedades y métodos. Visual FoxPro nos da tres: Pública, Protegida y Oculta. ¿Que son exactamente cada una de estas y dónde deberíamos usar una en lugar de la otra?.

Una pequeña clase.

Uno de los objetivos del desarrollo orientado a Objetos es aislar los datos y el comportamiento requerido en una clase particular a esa clase misma, para reducir el nivel de dependencia que esa clase particular tiene sobre otras clases no relacionadas. Estas dependencias incluso pueden ser un problema dentro del mismo árbol de la clase, afectando como la superclase (parent) y las subclases interactúan.

Para examinar la visibilidad de propiedades y métodos usaremos un pequeño ejemplo de una estructura de clases. El siguiente diagrama describe el ejemplo.

En este ejemplo hay dos definiciones de clase txtBase y txtSubClass. TxtSubClass es una subclase de txtBase. Hay allí un formulario con una instancia de txtSubClass, txtSubClass1, en él. La clase txtBase tiene una propiedad, Prop1, agregada en ella y marcada como Oculta. TxtSubClass tiene agregada una propiedad, Prop2, marcada como protegida.

Pública

La primer visibilidad a discutir es el valor de Pública. Al crear una propiedad o método que es Público causa que aquella propiedad o método sea visible, o sea que se la pueda leer, escribir o ejecutar desde cualquier otro objeto o clase sin limitación.

Protegida

Un método o propiedad Protegida es accesible solamente por la clase que creó dicha propiedad o método y para las subclases de esa clase. La visibilidad se extiende a lo largo del árbol de subclases si hay varios niveles hacia abajo (Prop2 en el diagrama de arriba es visible a txtSubClass, pero no puede ser direccionada en el código que esté en el objeto txtSubClass1 o en el objeto Formulario).

Nota del Traductor: se ha respetado en forma literal al autor, pero en realidad la propiedad Prop2 es visible en txtSubClass1 y se puede hacer referencia a ella en el formulario, pero no se puede modificar. Únicamente la clase que creó la propiedad lo puede hacer.

Oculta

Un método o propiedad Oculta es visible ÚNICAMENTE para la clase que la ha creado. Las subclases no ven esta propiedad/método en su hoja de propiedades y no pueden acceder a la misma (ocurre un error de VFP). (Prop1 en el diagrama de arriba es accesible SÓLO por la clase txtBase, txtSubClass no puede direccionar la propiedad y el nombre de la propiedad no aparece en la hoja de propiedades de la clase txtSubClass)

¿Por qué debería preocuparme?

Una de las características subyacentes del Diseño Orientado a Objetos es "Ocultar la implementación de un objeto". Esto significa ocultar completamente el mecanismo exacto que un objeto particular o clase usa para cumplir con su responsabilidad.

A menudo, un objeto puede necesitar datos internos o funcionalidad que no tiene ningún significado fuera del alcance de dicho objeto. Si estas porpiedades y métodos fueran visibles para el mundo exterior, existe la posibilidad de que puedan ser accedidos por algún código que no debería estar haciendo eso. Usando la visibilidad se puede controlar absolutamente qué puede y qué no puede acceder a propiedades y métodos.

Nota: También se puede cambiar la visibilidad de las propiedades y métodos de Visual FoxPro usando el diálogo de Edición de Métodos y Propiedades.

Un ejemplo para Oculta.

Usted está diseñando una clase formulario que será utilizada por otros desarrolladores a través de subclases. Uno de los comportamientos de la clase se cumpliría mejor si estuviera repartido en múltiples métodos en lugar de uno grande. No obstante, estos sub-métodos no son útiles fuera de la clase y un desarrollador que sobreescriba uno de ellos convertiría en no funcional a la clase. Usted puede definir un médodo como Público, aquel que será llamado por los desarrolladores para iniciar el comportamiento, pero los restantes sub-métodos como Oculto de manera que los otros desarrolladores ni siquiera sabrán que existen.

Un ejemplo para Protegida.

Usted está creando una clase utilitaria que necesita algún almacenamiento interno para su estado. Para ello crea un conjunto de propiedades. Si algún objeto fuera de la clase modifica estas propiedades, el estado del objeto se pierde. Usted puede definir estas propiedades como Protegidas y nada fuera del objeto puede direccionarlas.

Usando los métodos Access y Assign.

Usted podría estar pensando que usando los métodos Access y Assign se hace esencialmente la misma cosa que con popiedades protegidas. No exactamente. Los métodos Access y Assign permiten responder a algo que se direcciona a una propiedad, pero no previenen el acceso. En algunas situaciones, usted podría querer permitir a objetos externos actualizar o leer una propiedad y necesita hacer algo basado en el valor asignado o leído. En ese caso, los médodos Access y Assign son la vía para hacerlo.

No obstante, creando un método Assign que siempre descarte la asignación, es como ayudar a una persona que se está quemando manteniéndola bajo agua por 30 minutos.

7 de enero de 2021

Guía de uso del Control Ribbon similar a Microsoft Office 365

Traducción libre de la documentación del Control Ribbon similar a Microsoft Office 365 de Doug Hennig.

El proyecto proporciona un Control Ribbon similar al de Microsoft Office 365 para ser usado en formularios VFP

El código fuente del proyecto y la documentación en inglés se encuentra en: https://github.com/DougHennig/Ribbon

Nota: la traducción se hizo con la documentación al día 06 de enero de 2021.


Usando el Control Ribbon

Para agregar un control ribbon a un formulario, suelte una instancia de la clase SFRibbon de SFRibbon.vcx en el formulario y luego escriba el código en algún método del formulario o quizás en el método Init del objeto del ribbon, para agregar pestañas, secciones y botones; consulte la sección "Componentes" para obtener más detalles.

Para implementar el control ribbon en su aplicación, agregue lo siguiente al proyecto:

  • SFRibbon.vcx
  • SFGDIMeasureString.prg
  • SFRibbonDown.png
  • SFRibbonRight.png
  • RibbonThemes.xml

Además, incluya System.app con los archivos instalados de su aplicación.

Componentes

El control ribbon consta de varios componentes, todos los cuales están definidos en la biblioteca de clases visuales SFRibbon.vcx:

  • Una pestaña (la clase SFRibbonTab) es un elemento del menú en la parte superior, como "Home" y "Send/Receive" de la imagen de arriba. Para agregar una pestaña al ribbon, llame al método AddTab, pasando opcionalmente el nombre de la pestaña (si no se pasa, AddTab asigna un nombre único). Establezca la propiedad "Caption" del objeto Tab devuelto por AddTab.

        loTab = Thisform.oRibbon.AddTab('Home')
        loTab.Caption = 'Home'
    

    Las pestañas tienen una propiedad "Selected" que es .T. para la pestaña seleccionada y .F. para todas las demás pestañas. Establezca esta propiedad en .T. para seleccionar una pestaña mediante programación:

        Thisform.oRibbon.Home.Selected = .T.
    
  • Cada pestaña tiene una barra de herramientas (una instancia de la clase SFRibbonToolbar) debajo. No necesita preocuparse por las barras de herramientas, ya que están allí solo para su comodidad: cuando se selecciona una pestaña, su barra de herramientas se hace visible y las barras de herramientas de las otras pestañas están ocultas.

  • Una sección (la clase SFRibbonToolbarSection) es un conjunto de botones con una barra separadora a la derecha y un título en la parte inferior. Puede haber varias secciones en una barra de herramientas. Para agregar una sección, llame al método AddSection de una pestaña (que en realidad agrega una sección a la barra de herramientas de una pestaña), pasando opcionalmente el nombre de la sección (si no se pasa, AddSection asigna un nombre único). Establezca la propiedad Caption del objeto de sección devuelto por AddSection

        loSection = loTab.AddSection()
        loSection.Caption = 'New'
    
  • Hay dos tipos de botones: normales (la clase SFRibbonToolbarButton) y horizontales (la clase SFRibbonToolbarButtonHorizontal). La diferencia es que los botones normales están dispuestos de izquierda a derecha y tienen una imagen de 32 x 32 con un título debajo, mientras que los botones horizontales se apilan uno encima del otro y tienen una imagen de 16 x 16 con un título a la derecha. Puede haber varios botones en una sección. Al hacer clic en un botón, se ejecuta un comando o se muestra un menú desplegable (que se explica a continuación).

    Para agregar un botón normal, llame al método AddButton de una sección, pasando opcionalmente el nombre del botón (si no se pasa, AddButton asigna un nombre único).

    Para agregar un botón horizontal, llame al método AddHorizontalButton de una sección, pasando opcionalmente el nombre del botón (si no se pasa, AddHorizontalButton asigna un nombre único).

    Establezca las propiedades Caption, Image, Command y EnabledExpression del objeto  botón devuelto por AddButton o AddHorizontalButton. Para utilizar un título de varias líneas, incluya un retorno de carro (carácter CHR(13)) en el texto del título. El código en Command se ejecuta a través de la función EXECSCRIPT(), por lo que puede constar de varias declaraciones separadas por retornos de carro si es necesario. EnabledExpression contiene opcionalmente una expresión (como una cadena) que el método Refresh evalúa para determinar si el botón está habilitado.

          loButton = loSection.AddButton()
          with loButton
              .Caption = 'New' + chr(13) + 'Email'
              .Image   = 'newmail.png'
              .Command = 'Thisform.NewMail()' + chr(13) + 'Thisform.Refresh()'
              .EnabledExpression = 'Thisform.IsButtonEnabled()'
          endwith
          loButton = .AddHorizontalButton()
          with loButton
              .Caption = 'Ignore'
              .Image   = 'ignore.png'
              .Command = 'Thisform.Ignore()'
          endwith
    
  • Un botón puede tener un menú desplegable; si es así, aparece una pequeña flecha hacia abajo en el título del botón. El botón tiene un menú si tiene barras. Para agregar una barra al menú, llame al método AddBar del botón, pasando el título de la barra (use "\<" delante del carácter utilizado como tecla de acceso rápido para la barra tal como lo haría con un menú de VFP) , el comando a ejecutar, opcionalmente una imagen para la barra (16 x 16), y opcionalmente una expresión que determina cuando la barra está habilitada (si no se pasa, la barra siempre está habilitada).

    Para agregar una barra separadora, no pase ningún parámetro al método AddBar.

    Para agregar un submenú a una barra de menú, llame al método AddBar del objeto de barra devuelto por AddBar. Por ejemplo, en el código siguiente, el botón "New Items" tiene un menú con cuatro barras: "E-mail Message", "Appointment", un separador y "E-mail Message Using", el último de los cuales tiene un submenú con "More Stationery...", un separador, y barras de "Plain Text", "Rich Text" y "HTML".

          loButton = .AddButton('NewItems')
          with loButton
              .Caption = 'New' + chr(13) + 'Items'
              .Image   = 'newitems.png'
              .AddBar('E-\<mail Message', 'Thisform.Email()', 'newemailsmall.png')
              .AddBar('\<Appointment', 'Thisform.Appointment()', 'appointmentsmall.png')
              .AddBar()
              loBar = .AddBar('E-mail Message \<Using')
              loBar.AddBar('\<More Stationery...', 'Thisform.MoreStationery()')
              loBar.AddBar()
              loBar.AddBar('\<Plain Text')
              loBar.AddBar('\<Rich Text')
              loBar.AddBar('\<HTML')
          endwith
    
  • El control ribbon también puede tener un menú desplegable, que se muestra al hacer clic con el botón derecho en la parte del ribbon que no está cubierta con botones. Para agregar barras al menú del ribbon, llame al método AddBar del ribbon utilizando los mismos parámetros descritos anteriormente. Los submenús también se admiten de la misma manera que se discutió anteriormente.

          Thisform.oRibbon.AddBar('Change Theme to Colorful', ;
              "Thisform.oRibbon.Theme = 'Colorful'" + chr(13) + ;
              "Thisform.Refresh()", , ;
              "Thisform.oRibbon.Theme <> 'Colorful'")
          Thisform.oRibbon.AddBar('Change Theme to Dark Grey', ;
              "Thisform.oRibbon.Theme = 'Dark Grey'" + chr(13) + ;
              "Thisform.Refresh()", , ;
              "Thisform.oRibbon.Theme <> 'Dark Grey'")
    
  • Puede agregar otros tipos de controles además de botones a una sección: llame a AddControl, pasando el nombre (opcional), la clase y la biblioteca para el control. Asegúrese de llamar al método CalculateWidth para la sección, para que el ancho de la sección se ajuste en consecuencia. Por ejemplo, este código agrega un cuadro de texto:

          loControl = loSection.AddControl('Test', 'textbox', '')
          with loControl
            .FontName = 'Segoe UI'
            .Width    = 200
    		.Height   = 24
    		.Top      = int((loSection.Height - .Height)/2) && center it vertically
    	endwith
    	.CalculateWidth()
    
  • Puede hacer referencia a objetos jerárquicamente por el nombre, comenzando desde el ribbon. Por ejemplo, Thisform.oRibbon.Home.Toolbar.New.NewEmail, puede hacer referencia al botón NewEmail en la sección "New" de la barra de herramientas de la pestaña Home" en el ribbon. Esta es la razón principal para pasar un nombre a los distintos métodos Add*; de lo contrario, tiene que usar los nombres asignados automáticamente al objeto, algo como Thisform.oRibbon.Tab1.Toolbar.Section1.Button1.

Comportamiento

El control ribbon tiene el siguiente comportamiento:

  • La pestaña actualmente seleccionada tiene una barra debajo (una barra azul en la primera captura de pantalla anterior; el color se especifica usando el color "tabbordercolor" en el tema actual; consulte la sección "Temas" a continuación) y su título está en negrita.
  • Al pasar el mouse sobre una pestaña, se resalta la pestaña en el color "tabhighlightcolor" especificado por el tema actual y, si es la pestaña seleccionada, se alarga la barra debajo de la pestaña.
  • Hacer clic en una pestaña la convierte en la seleccionada y muestra la barra de herramientas para esa pestaña.
  • Al pasar el mouse sobre un botón, se resalta el botón en el color "buttonhighlightcolor" especificado por el tema actual.
  • Al hacer clic en un botón se ejecuta el comando para ese botón. Si no se especificó ningún comando y no hay un menú para el botón (consulte el siguiente punto), aparece un cuadro de mensaje con "No implementado".
  • Aparece una flecha hacia abajo en el título de un botón si tiene un menú. Al hacer clic en el botón, se muestra el menú. Al hacer clic en el botón nuevamente, hacer clic fuera del menú o mover el mouse fuera del formulario, se oculta el menú.
  • Al pasar el mouse sobre una barra de menú, se resalta la barra en el color "menuitemhighlightcolor" especificado por el tema actual.
  • Al hacer clic en una barra se ejecuta el comando para esa barra. Si no se especificó ningún comando y no hay un submenú para la barra (ver el siguiente punto), aparece un cuadro de mensaje con "No implementado".
  • Aparece una flecha hacia la derecha en el título de una barra si tiene un submenú. Los submenús se comportan como menús.

Temas

Un tema define un conjunto de colores para el control ribbon. El tema predeterminado es el tema "Colorido" (Colorful)

Aquí está el tema "Gris oscuro" (Darkgrey):

Los temas se definen en el archivo RibbonThemes.xml:

<themes>
	<theme name="Colorful" 
		ribbonbackcolor="243,242,241" 
		ribbonbordercolor="210,208,206" 
		ribbonshadowcolor1="234,234,234"
		ribbonshadowcolor2="238,238,238"
		ribbonshadowcolor3="243,243,243"
		ribbonshadowcolor4="247,247,247"
		ribbonshadowcolor5="251,251,251"
		menuitembackcolor="255,255,255"
		menuitemhighlightcolor="210,208,206"
		menuseparatorcolor="225,223,221"
		buttonhighlightcolor="200,198,196"
		tabhighlightcolor="250,249,248"
		tabbordercolor="16,110,190"
		sectionseparatorcolor="179,176,173"
	/>
	<theme name="Dark Grey" 
		ribbonbackcolor="190,187,184" 
		ribbonbordercolor="68,68,68" 
		ribbonshadowcolor1="75,75,75"
		ribbonshadowcolor2="82,82,82"
		ribbonshadowcolor3="88,88,88"
		ribbonshadowcolor4="95,95,95"
		ribbonshadowcolor5="102,102,102"
		menuitembackcolor="243,242,241"
		menuitemhighlightcolor="200,198,196"
		menuseparatorcolor="210,208,206"
		buttonhighlightcolor="151,149,147"
		tabhighlightcolor="200,198,196"
		tabbordercolor="32,31,30"
		sectionseparatorcolor="121,119,117"
	/>
</themes>

Los valores numéricos son colores RGB.

Los atributos del XML son:

  • ribbonbackcolor: El color de fondo del ribbon.
  • ribbonbordercolor: el color de la línea del borde en la parte inferior del ribbon.
  • ribbonshadowcolor1, ribbonshadowcolor2, ribbonshadowcolor3, ribbonshadowcolor4 y ribbonshadowcolor5: Hay una "sombra" debajo de la línea del borde en la parte inferior del ribbon. Esta sombra en realidad consta de cinco líneas de un píxel de altura. Estos atributos especifican los colores de esas líneas.
  • menuitembackcolor: El color de fondo de una barra en un menú.
  • menuitemhighlightcolor: El color de fondo de una barra cuando se mueve el mouse.
  • menuseparatorcolor: el color de una barra separadora en un menú.
  • buttonhighlightcolor: El color de fondo de un botón cuando el mouse está sobre él.
  • tabhighlightcolor: El color de fondo de una pestaña cuando el mouse está sobre él.
  • tabbordercolor: el color de la línea del borde debajo de una pestaña.
  • sectionseparatorcolor: El color de la línea de separación a la derecha de una sección.

Para establecer el tema del ribbon, establezca la propiedad "Theme" con el nombre del tema deseado (actualmente solo "Colorido" y "Gris oscuro"). La propiedad "Theme" del ribbon contiene una colección de los nombres de temas disponibles. El formulario Sample.scx incluido con este proyecto utiliza un cuadro combinado con Thisform.oRibbon.Themes como RowSource y Thisform.oRibbon.Theme como ControlSource para elegir el tema del ribbon.

Clases

Todas las clases de los componentes del control ribbon están en SFRibbon.vcx.

  • SFRibbonBase: la clase principal para la mayoría de los componentes del ribbon, excepto como se muestra; una subclase de Container.
  • SFRibbon: la clase de ribbon.
  • SFRibbonTab: la clase de Tab.
  • SFRibbonToolbar: la barra de herramientas de una pestaña.
  • SFRibbonToolbarSection: la clase de sección.
  • SFRibbonToolbarButton: una clase de botón normal.
  • SFRibbonToolbarButtonHorizontal: una clase de botón horizontal; una subclase de SFRibbonToolbarButton.
  • SFRibbonMenu: una clase utilizada para definir menús; una subclase de Custom.
  • SFRibbonMenuBar: la clase de la barra de menú; una subclase de SFRibbonToolbarButtonHorizontal.
  • SFRibbonMenuSeparator: la clase de barra separadora de menú.
  • SFRibbonMenuForm: una clase de formulario que proporciona un menú desplegable; una subclase de Form.

5 de enero de 2021

Control Ribbon similar a Microsoft Office 365

Artículo original: Microsoft Office 365-like Ribbon Control
https://doughennig.blogspot.com/2020/12/microsoft-office-365-like-ribbon-control.html
Autor: Doug Hennig
Traducido por: Luis María Guayán


¡Felices Fiestas! Cada año, entre Navidad y Año Nuevo, me gusta trabajar en algún proyecto divertido, como aprender una nueva técnica o escribir alguna utilidad interesante. El año pasado, trabajé en la versión de código abierto de Hacker's Guide to Visual FoxPro. Este año, he creado un control ribbon de código abierto similar a Microsoft Office 365 para formularios VFP: Microsoft Office 365-like ribbon control.

Aquí hay un formulario de ejemplo que contiene el control ribbon similar a Microsoft Outlook. Tiene dos pestañas: "Inicio" y "Enviar / Recibir". Al hacer clic en una pestaña, se muestra la barra de herramientas de dicha pestaña.

Aquí está la pestaña "Enviar / Recibir":

Hasta ahora, he incluido dos temas: "Colorido" (arriba) y "Gris oscuro" (abajo):

Los temas se definen como colores RGB en un archivo XML, por lo que agregar otro tema es muy sencillo.

El control ribbon es 100% código VFP. Pruébelo y avíseme de cualquier mejora que desee, o cualquier problema que encuentre en el repositorio del proyecto en GitHub: Microsoft Office 365-like ribbon control.

Descarga directa del código del control ribbon: https://github.com/DougHennig/Ribbon/archive/master.zip


Consulte la traducción al español de la documentación del Control Ribbon en:

"Guía de uso del Control Ribbon similar a Microsoft Office 365"

https://comunidadvfp.blogspot.com/2021/01/guia-de-uso-del-control-ribbon-similar.html


17 de diciembre de 2020

AddProperty() no necesita comprobar la existencia de la propiedad

Puede no ser obvio, pero el método AddProperty() (y la función ADDPROPERTY() agregada en VFP 8.0) es bastante "lista" para no colisionar o para no generar un error cuando usted añade con .AddProperty() una propiedad que ya exista.

En vez de un código semejante a esto:

IF NOT PEMSTATUS(THIS,"AlgunaPropiedad",5)
  THIS.AddProperty("AlgunaPropiedad", AlgunValor)
ENDIF

usted puede escribir esta sola línea de código:

THIS.AddProperty("AlgunaPropiedad", AlgunValor)

Con lo cual VFP agrega la propiedad "AlgunaPropiedad" si no existe ya, y le asigna "AlgunValor" a ésta.

VFP Tips & Tricks - Drew Speedie

1 de diciembre de 2020

Controles Unicode en Visual FoxPro: Un nuevo enfoque más rápido y eficiente

Articulo original: Unicode Controls in Visual FoxPro - A new faster and efficient aproach
https://vfpimaging.blogspot.com/2020/11/unicode-controls-in-visual-foxpro-new.html
Autor: Cesar Ch.
Traducido por: Luis María Guayán


Como continuación de mi último artículo publicado: Iconos Unicode en botones de Visual FoxPro, decidí seguir probando diferentes soluciones para llevar Unicodes a nuestros controles, especialmente como iconos en botones.

La opción más natural sería usar botones de Windows reales como el ejemplo que tenemos en dicho artículo: https://comunidadvfp.blogspot.com/2020/11/iconos-unicode-en-botones-de-visual.html

Pero esto trae la desventaja de que tendríamos que hacer varios cambios en nuestros formularios heredados para adaptar todos los códigos relacionados con el evento Click y otros.

Entonces, decidí probar una solución híbrida - "Dibujar" un control Win32 "Estático", similar a nuestro control Label de VFP sobre CommandButtons y Labels comunes. Estos controles "estáticos" de Win32 permiten Unicodes, y nos permitirían mantener todos nuestros códigos heredados como están.

Así que aquí está FoxyObjects, una clase de VFP personalizada que se puede incluir en nuestros formularios y que "convertirá" todos los botones y etiquetas que tienen contenido entre las etiquetas <UC> </UC> a Unicodes, al igual que el artículo anterior. Esta vez unas 4 ó 5 veces más rápido que GradObjects, con el mismo resultado.

Si no leíste el artículo anterior, mi objetivo es traer algunos íconos atractivos, los mismos que vemos en la interfaz de usuario de Windows 10, especialmente los de "SEGOE MDL2 ASSETS", como se muestra en el siguiente CharMap:

El uso de esta nueva clase es realmente muy simple:

  • Abra el proyecto FoxyObjects
  • Lance una instancia de FoxyObjects a tu formulario
  • Establezca la propiedad FontName del botón de comando en "SEGOE MDL2 ASSETS" o cualquier otra fuente que desee. Configure la propiedad Caption del botón para aceptar unicodes, introduciendo los unicodes entre las etiquetas , por ejemplo:
    • griego <UC> 03b5 03b9 03c1 03ae 03bd 03b7 </UC> - Esto mostrará la palabra "Paz" en caracteres griegos, en cualquier fuente regular, como Arial, Tahoma, Segoe UI, etc.
    • Para obtener el icono de la impresora de la fuente SEGOE MDL2 ASSETS, establezca la propiedad FontName del botón de comando y agregue lo siguiente a la propiedad Caption: "<UC> E749 </UC>"

FoxyObjects trae algunas propiedades, que se aplicarán a todos los controles CommandButton y Label que están en el mismo nivel de objeto que el nivel de FoxyObjects. Por ejemplo, si desea que FoxyObjects aplique cambios a algunos objetos seleccionados, puede insertarlos en un contenedor y agregarle una instancia de la clase. De esta forma, el resto de objetos no se verán afectados.

De forma predeterminada, se aplicará cambios solo a los objetos que tengan la etiqueta <UC> en sus propiedades Caption.

  • BackColor: Numérico, especifica el color de fondo utilizado para mostrar texto y gráficos en un objeto.
  • DisabledForeColor: Numérico, especifica el color utilizado para mostrar el texto cuando el objeto está desactivado.
  • ForeColor: Numérico, especifica el color utilizado para mostrar el texto.
  • MouseOverForeColor: Numérico, especifica el color en el que se convertirá el texto del objeto (y el icono) cuando el mouse esté sobre el objeto especificado. Si no desea este efecto, especifique el valor -1
  • lBindAll: Logical, determina que todos los objetos se verán afectados, incluso si no tienen el en el Caption. Esto significa que puede cambiar el Caption en tiempo de ejecución, y se respetarán los Unicodes
  • lBindLabels: Lógico, determina que tanto los CommandButtons como los Labels se verán afectados
  • lBindResize: Lógico, determina que siempre que se cambie el tamaño o se mueva cualquier control, la máscara de etiqueta también se actualizará.
  • lBindVisible: Lógico, determina que siempre que cualquier control esté oculto o visible, la máscara de etiqueta también se actualizará..

Los Unicodes se pueden obtener directamente a través de CharMap.EXE o en toda la web. Aquí hay un excelente punto de partida: https://docs.microsoft.com/en-us/windows/uwp/design/style/segoe-ui-symbol-font

La fuente "SEGOE MDL2 ASSETS" viene con Windows 10, pero no se permite su distribución a otros sistemas operativos. Esto no es gran cosa, porque Tahoma también nos trae varias opciones, y siempre podemos trabajar con algunas de las fuentes gratuitas disponibles en la web, como "Material.io". Traen toneladas de iconos modernos y hermosos de forma gratuita. Realmente vale la pena una visita: https://material.io/resources/icons/?style=outline

AGRADECIMIENTOS ESPECIALES a Mustapha Bihmuten de Marruecos y Leandro Walfrans de Brasil por probar la versión Pre-Alpha de la clase y por brindar valiosas sugerencias

Descargar de FoxyObjects v.0.4


10 de abril de 2019

Clase ctl32_statusbar

ctl32_statusbar

Por Carlos Alloatti

Descarga

Descripción general
Esta clase proporciona un control de barra de estado que se puede usar para reemplazar la barra de estado VFP9 nativa. Si usa un formulario de nivel superior como formulario principal de su programa, también puede usar esta barra de estado en su formulario de nivel superior.

Esta clase usa las funciones de la API de Windows para crear un verdadero control común de control de Windows Barra de estado.

Esta clase es un proyecto VFPX.

VFPX: un esfuerzo de la Comunidad de Visual FoxPro para crear complementos de código abierto para Visual FoxPro 9.0. El código, las clases y las bibliotecas disponibles aquí complementarán los esfuerzos continuos de Microsoft para mejorar y extender Visual FoxPro con el código llamado proyecto Sedna que se describe en la Hoja de ruta de Visual FoxPro.


Jerarquía de clases
ctl32
ctl32_statusbar


Principales características
Puede usar esta barra de estado en todo su potencial, usando la barra de progreso, los paneles, los íconos de configuración, los títulos, etc. O simplemente puede colocarlo en su proyecto y no hacer nada más que crear una instancia al inicio de su programa, y dejarlo simplemente conviértase en un sustituto más agradable de la barra de herramientas nativa, o suelte una en su formulario principal de nivel superior y disfrute de una barra de estado en su formulario de nivel superior. Todos los textos mostrados por las opciones de menú y la propiedad StatusBarText de los controles se mostrarán en la barra de estado ctl32.

Así que ahora no más "así que usas esa cosa de FoxPro ... ¿es eso todavía? ¿Y por qué la Barra de estado se ve tan fea, diferente de todos mis otros programas de Windows? Debe ser porque FoxPro es viejo ..."


Imágenes
Así es como se ve la barra de estado VFP nativa. No es muy bueno para una aplicación de Windows XP.
Así es como se ve la barra de estado ctl32 en un formulario de nivel superior o en la pantalla VFP, con todos sus paneles en uso.
Así es como se ve ctl32_statusbar en Vista Beta 2 Build 5384.

Descripción de los paneles
El primer panel (desde la izquierda) muestra un icono opcional y los mensajes normales de la barra de estado de VFP, los que normalmente se muestran en la barra de estado nativa de VFP. No muestra el recuento de registros / posición de registro para las tablas abiertas, etc. Si configura un mensaje en este panel, anula todos los mensajes de la barra de estado generados por el sistema VFP, hasta que borre el mensaje personalizado.

El segundo panel contiene una barra de progreso, una clase por sí misma, que se puede controlar completamente, su ancho se puede ajustar, etc.

Los siguientes paneles son los paneles personalizados (tantos como desee en la versión 3 o superior). Estos paneles se pueden utilizar para mostrar un icono y un título. Los paneles personalizados se pueden consultar por nombre: Panel1, Panel2 ... o por su índice: Panels(1), Panels(2), etc.

Los siguientes paneles son los 3 paneles indicadores, que muestran el estado de las teclas Insertar, Bloqueo de teclas y Bloqueo de números. El texto que se muestra es configurable por el usuario y se pueden ocultar.

Luego, hay un Panel de fechas que puede mostrar la fecha del sistema en formato corto o largo, según los formatos y el idioma del sistema operativo.

El último panel no se usa, es solo un divisor para el área de agarre de tamaño.

Todos los paneles, excepto el primero, el Panel de mensajes, se pueden mostrar/ocultar.

Aquí todos los paneles están ocultos.

Inicio rápido: uso en un formulario
Si desea un ctl32_statusbar en un formulario, arrastre el control ctl32_statusbar desde la ventana del Project Manager y suéltelo en el formulario. Por supuesto que hay otras formas de hacer esto. Tamaño y posición en la parte inferior del formulario. Este último paso no es necesario, el control cambia de tamaño y se coloca en la parte inferior en el tiempo de ejecución, hágalo solo por razones estéticas en el momento del diseño. O puede instalar el constructor, haciendo clic en constructores \ ctl32_statusbar_builder.app Luego, si hace clic con el botón derecho en el control de la barra de estado en el diseñador de formularios y elige el creador del menú de acceso directo, la barra de estado se posicionará y dimensionará.

NOTA: Si su formulario es un Formulario de nivel superior, ctl32_statusbar usará los 24 píxeles inferiores de su formulario para sí mismo, por lo que su formulario será 24 píxeles más corto. Si también tienes un menú de formulario de nivel superior, eso es 20 píxeles más que pierdes. Compruebe cómo distribuir los controles y use la propiedad Ancla de ellos.

Las únicas propiedades que debe cambiar en el momento del diseño son Nombre y PanelCount.


Inicio rápido: uso en la pantalla principal de VFP
Agregue las siguientes líneas a su código:

If Not Pemstatus(_Screen,"StatusBar", 5) Then

   _Screen.Newobject("StatusBar", "ctl32_statusbar", "ctl32.vcx")

Endif
O, si desea especificar un cierto número de paneles personalizados (el valor predeterminado es 5):

If Not Pemstatus(_Screen,"StatusBar", 5) Then

   _Screen.Newobject("StatusBar", "ctl32_statusbar", "ctl32.vcx", null, 3)

Endif
Para eliminar el ctl32_statusbar:

_Screen.RemoveObject("StatusBar")
Eso es todo. No tiene que configurar nada más si solo desea un reemplazo básico de la barra de estado VFP nativa. La barra de estado ctl32 sondeará el valor de _vfp.StatusBar y el estado de Capslock(), NumLock() e Insmode() en un evento de temporizador, y actualizará el mensaje.

NOTA: La barra de estado de VFP nativa no debe configurarse como DESACTIVADA o _VFP.StatusBar no devolverá ningún valor.


Control de barra de progreso
Hay un control ctl32_progressbar en ctl32_statusbar, invisible por defecto. Hay un archivo de ayuda para ello (en español, lo siento). Verifique las propiedades allí, en su mayoría son autoexplicativas, y en los proyectos de muestra. Para un inicio rápido, para verlo en acción haga esto:

oStatusBar.ProgressBar.Repeat = .T.

oStatusBar.ProgressBar.Play = .T.

oStatusBar.ProgressBar.Visible = .T.
Simplemente reemplace oStatusBar con la referencia de objeto correcta. Esta barra de progreso se puede usar sola en cualquier formulario, verifique el proyecto de ejemplo ctl32_progressbar.


Proyecto de ejemplo
Vea el proyecto de muestra incluido en la carpeta de muestra para ver ejemplos de cómo usar el control y qué se puede hacer.


BindEvent
Esta clase hace Bindevents a las siguientes ventanas y mensajes de ventana:
_VFP.hWnd, WM_THEMECHANGED
_Screen, WM_SIZE
Si se conecta a esos mismos pares de ventana / evento en alguna otra parte de su código, recuerde lo que dice el archivo de Ayuda:

"Al vincular eventos de mensaje de Windows (Mensaje de Windows), solo puede existir un emparejamiento de mensajes hWnd a Windows".

Los archivos de iconos utilizados deben incluirse en el proyecto. No es necesario redistribuir los archivos de iconos a los usuarios finales. Los archivos de iconos deben contener un icono de 16x16 256 colores, que se usa para mostrar en la barra de estado.

¿Por qué un temporizador? Intenté usar Bindevent con la propiedad _Vfp.StatusBar, para detectar cambios en su valor y actualizar el texto para mostrar, pero hay un error en VFP, los cambios _Vfp.StatusBar no siempre activan el método enlazado, por lo que no siempre se actualiza correctamente . No había otra manera que usar un temporizador. Para leer más sobre esto, y una solución parcial, consulte el Blog de Calvin Hsia, pero el problema para la propiedad StatusBarText de los controles permanece. (Y sí, es un error).

Si tiene un botón de comando en un formulario que cierra el formulario haciendo, por ejemplo, Thisform.Release(), y ese botón tiene la propiedad StatusBarText establecida en algún valor, cuando se cierra el formulario, StatusBarText permanecerá en la barra de estado, y tipo de colgar para mostrarse en función de dónde apunta el mouse.

Para resolver esto, usa el siguiente truco:

Procedure cmdClose.Click

   This.StatusBarText = " "

Thisform.Release()
Por cierto, este es un error de VFP ...


Errores
Version 3 20060522
Andrew Nickless estaba teniendo un problema extraño al acceder a todos los controles de una forma en un método de formulario. Cuando su método llegó a la barra de estado, se generó un error, e incluso al intentar obtener la propiedad de nombre del objeto con el problema surgió un error.

Lo que descubrí es que la etiqueta y el control del temporizador contenidos en la barra de estado de alguna manera tienen la mayoría de sus propiedades configuradas como protegidas u ocultas. Para resolver esto, corta cada objeto, guarda la clase, abre y pega nuevamente. Haga esto con la etiqueta y el temporizador. Insecto realmente oscuro, quién sabe cómo sucedió eso.

Si la barra de estado se usa en un formulario estándar con ShowWindow = 0 y el formulario se redimensiona en su evento inicial, parece que el evento de cambio de tamaño del formulario no se dispara, por lo que la barra de estado no tiene la posibilidad de reposicionarse. Para solucionar esto rápidamente, agregue el siguiente código al método ctl32_BindEvents de la clase ctl32_statusbar:

*!* When host is a Standard Form and the form is resized in its Init event,

*!* the Resize event of the form does not fire, so we bind to the form Visible property:

If This.ctl32_FormType = CTL32_FORMTYPE_DEFAULT Then

    Bindevent(Thisform, [Visible], This, [ctl32_Resize], 1)

Endif
Gracias, Andrew Nickless por informar de este error (VFP).

Versión 3 20060510

Para evitar que la barra de herramientas auxiliar parpadee en máquinas lentas, cambie el código en ctl32_statusbar_toolbar Init a esto (solo intercambia el dock y las líneas visibles)
This.ctl32_DeclareDlls()
*!* Hide the toolbar thru API so its still there but invisible
With This
    *!* 20060519 swaped lines //Doru Constantin//
    .Dock(TOOL_BOTTOM, 0, 0)
    .Visible = TRUE
    ShowWindowAPI(.HWnd, SW_HIDE)
Endwith
Un error en ctl32_ResizePanels tiene el efecto de no mostrar el título del panel de mensajes cuando todos los paneles están ocultos. En ctl32_Resizepanels encuentra esta línea:

.SetAll([ctl32_Right], -1, [ctl32_StatusBar_Panel])
Y cambiarlo a esto:

.SetAll([ctl32_Right], 0xFFFFFF, [ctl32_StatusBar_Panel])
En ctl32_Width_Access, las barras de herramientas acopladas por el lado no se consideraron al calcular el ancho deseado de la barra de estado en una forma de nivel superior. Reemplace ctl32_Width_Access con este código:
*!* RETURN desired Width for StatusBar proxy Window
*!* Width from _Screen is no good, space taken by toolbars on both
*!* sides is subtracted from total Width, so we use _vfp Hwnd
*!* Modified 20060513
Local lnHwnd, lnWidth, lcRect, lnLeft, lnRight
With This
    If .ctl32_FormType = CTL32_FORMTYPE_SCREEN
        m.lnHwnd = _vfp.HWnd
    Else
        m.lnHwnd = Thisform.HWnd
    Endif
    m.lcRect = Space(16)
    GetClientRect(m.lnHwnd, @m.lcRect)
    m.lnLeft = .uStrToLong(Substr(m.lcRect, 1,4))
    *!* m.lnTop = .uStrToLong(Substr(m.lcRect, 5,4))
    m.lnRight = .uStrToLong(Substr(m.lcRect, 9,4))
    *!* m.lnBottom = .uStrToLong(Substr(m.lcRect, 13,4))
    m.lnWidth = m.lnRight - m.lnLeft
Endwith
*!* Width is off by one pixel
m.lnWidth = m.lnWidth + 1
Return m.lnWidth
Los problemas se notificaron con la pantalla que no se actualizaba correctamente en ciertas máquinas. Resuelto al comentar la primera línea de tmrUpdater.Timer:

*!* DoEvents
Debo confesar que ni siquiera sé por qué estaba allí DoEvents.

Si está acoplando programáticamente una barra de herramientas en la parte inferior izquierda de un formulario de nivel superior con una barra de estado, debe hacer esto:

oToolbar.Dock(3)

oToolbar.Dock(3)
De esa manera el toobar no cubrirá la barra de estado. No hay ningún problema si la barra de herramientas se acopla con el mouse.

Versión 2:

Al configurar la propiedad de icono de cualquier panel en una cadena vacía, borrará el icono del primer panel. Para corregir esto, en la clase ctl32_statusbar_panel, método icon_assign, cambie esta línea:

SendMessageN(This.Parent.HWnd, SB_SETICON, 0, 0)
Por esto:

SendMessageN(This.Parent.HWnd, SB_SETICON, This.Index - 1, 0)

Problemas conocidos

Registro de cambios
2006XXXX
Algunos errores corregidos.

Añadido ctlSizeGrip.

Se agregó ctlInit que se ejecuta después de crear la barra de estado, para permitir personalizar la barra de estado cuando se usa en un formulario de nivel superior, donde se crea en el evento de activación de formulario.

Se ha corregido el pinzamiento de tamaño que se muestra en la barra de estado de _Screen maximizada cuando se selecciona _Screen.Themes. nOldWindowState se establece en -1.

La barra de estado _Screen de muestra fija, los eventos, dblclick y clic derecho no funcionan.

Se eliminaron todos "With This" de la clase ctl32_statusbar.

Se agregó el código en ctl32_FormActivate para actualizar las leyendas e íconos del panel cuando se usa la barra de estado en un formulario de nivel superior y las leyendas e íconos se configuran en el control de inicio, vea el nuevo formulario ctl32_statusbar_sample_toplevelform2.scx Los iconos e leyendas no se muestran sin este código, y No entiendo por qué.

Se eliminaron todos "Con esto" de la clase ctl32_statusbar_panel. Refactored todos los métodos de asignación de esa clase. Se agregó control para el control Hwnd <> 0.

Se modificaron las funciones _ThemeStatus, _HostHWnd, _FormType en _util de ctl32_common. Eliminó todas las referencias a ThisForm, ahora el formulario se determina a partir del control que se pasa como parámetro a estas funciones.

Se modificó la forma en que se agrega el objeto _Util al control, de newobject a addproperty, para que no cuente como otro control.

Se agregó la verificación para la asignación de la variable numérica a la propiedad lógica panel.ctlAutosize

Agregado ctlVcxProgressBar, especifica el nombre / ubicación de la clase ctl32_progressbar.

Añadidos ctlVcxStructs y ctlVcxCommon, especifican el nombre / ubicación de las clases ctl32_structs y ctl32_common.

Movió y renombró las propiedades del objeto de uso interno a ctl32_addproperties()

Se agregó el método ctlUpdatePanels() y la propiedad ctlUpdateStyle

Código movido para determinar el idioma a la clase _util

Propiedad ctlLangId agregada

Movió el método ctlos a la clase _util.

Elimine el método ctlTheme, utilizando _ThemeStatus de _util

Se agregó una verificación de ancho para evitar que los paneles se vuelvan a dibujar cuando el ancho no haya cambiado.
20060627
  • Restablecer las propiedades del contenedor VFP nativo a público.
  • Se corrigió un error en el que las propiedades de los objetos contenidos se configuraban como ocultas / protegidas.
  • Se agregó la clase ctl32_structs.vcx para manejar estructuras en llamadas de funciones API.


Bajo el capó
Cuando decidí crear un control de barra de estado para VFP9, me puse los siguientes objetivos:
  • Tenía que ser un reemplazo directo de la Barra de estado nativa, no debería haber necesidad de cambiar nada en un proyecto que usa la Barra de estado nativa para mostrar los mensajes.
  • Debería estar disponible en la pantalla principal, o en cualquier formulario estándar o de nivel superior.
  • No debería ser necesario realizar ninguna configuración especial de la barra de estado para poder usarla, no hay opciones de paneles o cualquier otra cosa.
  • Las formas secundarias deben maximizar sin superponerse a la barra de estado, al igual que la barra de estado nativa se comporta.
  • La apariencia de la barra de estado debe ser como cualquier otra barra de estado estándar de Windows y seguir el tema en uso en Windows XP.
También quería poder mostrar la fecha actual en la barra de estado y una barra de progreso, al igual que la barra de progreso que se muestra en la barra de estado de Internet Explorer o Mozilla Firefox.

Algunos de los siguientes pueden estar desactualizados ahora, ya que he cambiado algunos detalles en la implementación, pero es una buena referencia "histórica".

Paso 1: Decida cómo crear una barra de estado estándar.

La primera pregunta fue cómo crear una barra de estado que siga las convenciones estándar de Windows para una barra de estado. Por supuesto, la forma más sencilla es usar el control de la barra de estado de Windows, como se describe en Barras de estado. Este control se ajusta a la parte inferior (u opcionalmente superior) de una ventana principal, y también ajusta su ancho al ancho de la ventana principal. Su apariencia sigue las convenciones estándar de Windows.

Paso 2: Cómo obtener nuestra propia barra de estado para mostrar en VFP.

El siguiente paso es encontrar cómo colocar una barra de estado en un formulario estándar, en un formulario de nivel superior y en la ventana principal de VFP, y cómo hacer que los formularios secundarios en los últimos 2 casos sean conscientes de la existencia del estado. Barra, por lo que no se superponen cuando se maximiza.

Sabía por MSDN que un control de la Barra de estado de Windows ajusta su posición y ancho en relación a su ventana principal, así que tuve que encontrar una manera de manejar los 3 casos.

a) Barra de estado en un formulario estándar

En una forma normal es fácil, solo use la ventana de Formulario como la ventana principal para el control de la Barra de Estado, no hay mucho más que hacer aquí, solo intercepte el evento de Cambio de Tamaño del Formulario con un BINDEVENT, y diga al Control de Windows de la Barra de Estado que Tiene que redimensionarse y luego redimensionar los paneles.

El evento ctl32_resize de la barra de estado Ctl32 hace precisamente eso, en el caso de un formulario VFP estándar.

Envía un mensaje WM_SIZE al control de Windows de la barra de estado, vuelve a calcular la posición y el tamaño de los paneles y envía un mensaje SB_SETPARTS con los parámetros necesarios.

b) Barra de estado en un formulario de nivel superior (TLF)

En un formulario de nivel superior, las cosas se vuelven un poco más complejas, ya que un formulario de nivel superior en VFP es en realidad 2 ventanas:

Aquí puede ver la ventana del cliente de un formulario de nivel superior de VFP resaltado (Winspector). Así que empecé a pensar cómo podría lograr poner una Barra de estado allí y hacer que el niño se diera cuenta. Decido explorar primero cómo VFP muestra su barra de estado nativa.

c) Barra de estado en la ventana principal de VFP

Comencé por investigar cómo VFP muestra su propia barra de estado, para obtener algunas pistas sobre cómo hacerlo yo mismo.

Esta es la ventana principal de VFP, resaltada en rojo por Winspector, con un tamaño de 800 x 600 píxeles.

Aquí se resalta la ventana de pantalla de VFP. El espacio de la ventana de la pantalla es utilizado por formularios secundarios.

Esta es la ventana que VFP crea para contener la ventana de la Barra de estado nativa de VFP y las ventanas de barras de herramientas que están acopladas en la parte inferior. Observe el ancho de la ventana: 32767 píxeles. Supongo que el tamaño de esta ventana es así, por lo que las barras de herramientas acopladas verticalmente se extienden hasta la parte superior de esta ventana. Como el control de la Barra de estado de Windows ajusta su ancho a la ventana principal, no podemos ubicarlo aquí directamente, ¡o su ancho será de 32767 píxeles!

Aquí se resalta una ventana de la barra de herramientas. Sabemos que una ventana de la barra de herramientas de VFP ajusta su ancho al ancho de su contenido, por lo que no podemos usar una barra de herramientas para mantener nuestro control de la Barra de estado, que ajusta el ancho a su ventana principal.

Aquí se resalta la ventana de la barra de estado de VFP. La barra de estado de VFP ajusta su ancho a la ventana principal de VFP, por lo que quizás podamos colocar nuestra propia ventana de control de la barra de estado de Windows aquí. Al principio intenté esto, pero luego, al intentar colocar un control de Barra de estado en un formulario de nivel superior, encontré una manera más conveniente, que funcionó para ambos casos, los formularios de nivel superior y la ventana principal de VFP. Lo que hice fue crear una ventana proxy, una ventana cuyo único propósito es servir como un contenedor de la ventana de control de la barra de estado.

Después de ver lo que hace VFP para mostrar su propia barra de estado, se me ocurrió la idea de agregar una barra de herramientas de VFP a un formulario de nivel superior y acoplarla en la parte inferior del formulario, de esta manera el propio VFP creará para mí una ventana que Podría usar.

Así que creo una barra de herramientas simple con solo una forma que dará como resultado una barra de herramientas de 24 píxeles de alto. Establecí su propiedad ShowWindow en 1 (en el formulario de nivel superior). En la etapa de creación de la barra de estado Ctl32, creo una instancia de esta barra de herramientas y la acoplo a la parte inferior de la ventana principal de VFP o al formulario de nivel superior según sea necesario. También utilizando la API, la ventana de la barra de herramientas se oculta. Lo que ocurre aquí es que una barra de herramientas no se puede agregar a un formulario de nivel superior hasta que el formulario esté visible, por lo tanto, evito el evento de activación del formulario para ejecutar un procedimiento que agregue la barra de herramientas y luego se desenlace.

Esta es una imagen de la barra de estado en un formulario de nivel superior, con un "recorte" donde puede ver la barra de herramientas subyacente utilizada para crear el "espacio" para mantener la barra de estado.

Al usar la propiedad hwnd de la barra de herramientas y la función de API GetParent, puedo obtener el hwnd de la ventana principal de la barra de herramientas, que usaré como principal del control de la Barra de estado de Windows. Pero espere, esta ventana principal tiene 32767 píxeles de ancho, por lo que no puedo usarla directamente, por lo que primero creo una estática (actualización: ahora creo una ventana usando la misma clase que las ventanas VFP, "tomo prestada" la clase de ventana de VFP) ventana como proxy, con un ancho igual al ancho de la ventana de Formulario / VFP, y usarlo como elemento primario para el control de la Barra de estado de Windows.

Tal vez esta lista de ventanas de Winspector puede ayudar a obtener una imagen de lo que está pasando:
  • La línea 1 en la lista es una ventana de formulario de nivel superior de VFP.
  • La línea 2 es la ventana creada por la barra de herramientas, la que tiene un ancho de 32767 píxeles. Yo lo llamo la "ventana de host"
  • La línea 3 es la ventana que creé para contener la ventana de la barra de estado de Windows. (ACTUALIZACIÓN: ahora creo una ventana utilizando la misma clase que las ventanas de VFP, "tomo prestada" la clase de ventanas de VFP, ¡y obtengo el ícono de cabeza de zorro gratis!). Yo lo llamo la "ventana Proxy"
  • La línea 4 es la propia ventana de la barra de estado ctl32. Yo lo llamo la "ventana de control"
  • La línea 5 es la ventana de la barra de progreso ctl32
  • La línea 6 es la ventana de la barra de herramientas VFP que agrego.
  • La línea 7 es la ventana del cliente del formulario de nivel superior. Vea la imagen del formulario de fondo amarillo en la parte superior de esta sección.
Todo lo que queda es hacer algo de magia en el evento de cambio de tamaño de la ventana de Formulario / VFP, y todo está configurado. Por ejemplo, la Barra de estado de Windows no mostrará un control de tamaño cuando su ventana principal esté maximizada, pero en este caso su ventana principal es una ventana estática, por lo que tuve que agregar un código para lidiar con eso.

ACTUALIZACIÓN 2006-05-07

Me he esforzado por proporcionar soporte para tratar con _Screen.Themes, Thisform.Themes y el cambio de tema en el nivel de Windows. Tomó más tiempo lidiar con estos problemas que programar todo en primer lugar. Creo que finalmente lo hice bien. Ahora puede configurar la propiedad de Temas de la barra de estado, cambiar Thisform.Themes, cambiar _Screen.Themes, o cambiar los temas en las Propiedades de Pantalla de Windows, y todo se verá como está supuestamente.

Por ahora me di por vencido al tratar de lidiar con SYS (2700,0) y SYS (2700,1). No hay forma de detectar el estado de ese interruptor, ya que SYS(2700) devuelve 1 si un tema está habilitado en Windows. También he visto interacciones extrañas cuando hago SYS(2700,0 / 1) y _Screen.Themes .T ./. F. muchas veces.

También he notado extrañas interacciones entre la pantalla del monitor y mis ojos después de cambiar de tema más de un millón de veces ...

He realizado algunas reformas al alcalde y me he movido bastante por las cosas, pero solo por el funcionamiento interno, así que todo es un poco más organizado y comprensible.

Propiedades, Eventos y Métodos
 ctlCaption
Property.
Value Type: Character
Default Value: None
R/W: Read/Write
Esta propiedad es un acceso directo a StatusBar.PanelMessage.ctlCaption

El texto que se mostrará en el primer panel de la izquierda, el Panel de mensajes. Si está configurado, anula cualquier otro conjunto de texto de Menús y controla StatusBarText. Establézcalo en una cadena vacía para continuar mostrando los mensajes de la barra de estado normal.


 ctlClick
Evento. 
Ocurre cuando el usuario hace clic en la barra de estado con el botón izquierdo del ratón.


 ctlDblClick
Evento.
Ocurre cuando el usuario hace clic dos veces en la barra de estado en una sucesión rápida, también dispara un evento Click / Right Click antes.

 ctlGetStringSize(cExpression, cFlags)
Método.

Devuelve el Ancho o el Alto de la cadena de caracteres de cExpression especificada, calculada con las propiedades de fuente de la fuente StatusBar (Nombre, Tamaño, etc.) Útil al configurar la propiedad ctlAutosize de un Panel en .F. y necesitamos saber qué ancho es una expresión de caracteres para establecer la propiedad ctlWidth del Panel.

cFlag = "W" devuelve Ancho (predeterminado)

cFlag = "H" devuelve Altura

 ctlHWnd
Property.
Value Type: Numeric
Default Value: 0
R/W: Read
Devuelve un identificador de ventana al control.

El entorno operativo de Microsoft Windows identifica cada formulario en una aplicación asignándole un identificador, o hWnd. La propiedad hWnd se usa con las llamadas a la API de Windows. Muchas funciones del entorno operativo de Windows requieren el hWnd de la ventana activa como argumento.

 ctlIcon
Property.
Value Type: Character
Default Value: None
R/W: Read/Write
cFileName especifica el nombre del archivo y la ruta del icono que se mostrará en el panel de mensajes. El archivo de iconos debe tener un icono de 16x16 256 colores.

Esta propiedad es un acceso directo a StatusBar.PanelMessage.ctlIcon

Si el archivo que especifica no existe, no se genera ningún error y el icono anterior, si se definió, se elimina.

Para eliminar un icono, establezca el valor en una cadena vacía. Los archivos de iconos deben incluirse en el proyecto. No es necesario copiar los archivos de íconos al implementar la aplicación.

 ctlInit
Evento.

Este evento es útil cuando se utiliza una barra de estado en un formulario de nivel superior. El código en este evento se ejecuta después de que se haya creado la barra de estado, por lo que puede personalizarlo aquí

 ctlLangID
Property.
Value Type: Numeric
Default Value: 0
R/W: Read/Write
Cuando se establece en un valor distinto de 0x0, reemplaza el idioma de la configuración regional del sistema para las cadenas de idioma del control. En la barra de estado, el texto de los indicadores Bloq Mayús, Bloq Num y Insertar.

Consulte http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_61df.asp para obtener los códigos de configuración regional.

 ctlMessage
Property.
Value Type: Character
Default Value: None
R/W: Read/Write
Esta propiedad es un acceso directo a StatusBar.PanelMessage.ctlCaption

El texto que se mostrará en el primer panel de la izquierda, el Panel de mensajes. Si está configurado, anula cualquier otro conjunto de texto de Menús y controla StatusBarText. Establézcalo en una cadena vacía para continuar mostrando los mensajes de la barra de estado normal.

 nButton
Property.
Value Type: Numeric
Default Value: 0
R/W: Read
Devuelve un número que especifica en qué botón del mouse se hizo clic en el último clic, DblClick o RightClick

1: botón izquierdo del ratón

2: botón derecho del ratón

 nPanel
Property.
Value Type: Numeric
Default Value: 0
R/W: Read
Devuelve un número que especifica en qué panel se hizo clic en el último evento Click, DblClick o RightClick.

-2: sin panel, clic en bordes o área de agarre de tamaño

-1: PanelMessage

0: PanelProgressBar (El panel, no la barra de progreso en sí)

n: Paneles (n) Donde n es un número de panel personalizado de 1 a 100

101: PanelOvr

102: PanelCaps

103: PanelNum

104: PanelDate

 nXCoord
Property.
Value Type: Numeric
Default Value: 0
R/W: Read
La posición horizontal (nXCoord) del puntero del mouse en el último evento Click o DblClick, en relación con la esquina superior izquierda o la barra de estado.

 nYCoord
Property.
Value Type: Numeric
Default Value: 0
R/W: Read
La posición vertical (nYCoord) del puntero del mouse en el último evento Click o DblClick, en relación con la esquina superior izquierda o la barra de estado.

 ctlPanelCount
Property.
Value Type: Numeric
Default Value: 5
R/W: Read/Write
Especifica el número de objetos del Panel, disponibles en tiempo de diseño y de solo lectura en tiempo de ejecución. Al crear una instancia de una barra de estado en el código, el número de paneles debe pasarse como un parámetro. El número máximo de paneles personalizados es 100. (creo que más que suficiente). El valor de PanelCount no debe cambiarse en el tiempo de ejecución.

 ctlPanels(nPanel)
Propiedad.

Una matriz para acceder a objetos individuales personalizados del Panel en el control por número de panel. Sólo lectura en tiempo de ejecución.

Los paneles personalizados pueden ser referenciados por esta matriz. Si tiene 3 paneles personalizados en la barra de estado, entonces tendrá:

StatusBar.Panels (1)

StatusBar.Panels (2)

StatusBar.Panels (3)

Los paneles integrados no se pueden referenciar de esta manera, no forman parte de esta matriz.

El debe ser referenciado por sus nombres.

 ctlRightClick
Evento.
Ocurre cuando el usuario hace clic en la barra de estado con el botón derecho del ratón

 ctlSizeGrip
Property.
Value Type: Logical
Default Value: .T.
R/W: Read/Write
Specifies whether a sizing grip will be shown in the status bar. The sizing grip will be disabled when a form is maximized or its border style is not sizable.

 ctlThemes
Property.
Value Type: Logical
Default Value: .T.
R/W: Read/Write
Specifies whether Windows XP Themes are enabled or disabled for a control. Read/write at design and run time.

 ctlUpdatePanels() 2006XXXX
Method.
Updates the updatable panels: PanelMessage, PanelOvr, PanelNum. PanelCaps, PanelDate

 ctlVcxCommon
Property.
Value Type: Character
Default Value: ctl32_common.vcx
R/W: Read/Write
Specifies the location and file name of the ctl32_common vcx file

 ctlVcxProgressBar
Property.
Value Type: Character
Default Value: ctl32_progressbar.vcx
R/W: Read/Write
Specifies the location and file name of the ctl32_progressbar vcx file

 ctlVcxStructs
Property.
Value Type: Character
Default Value: ctl32_structs.vcx
R/W: Read/Write
Specifies the location and file name of the ctl32_sctrucs vcx file

 ctlUpdateStyle
Property.
Value Type: Numeric
Default Value: 1
R/W: Read/Write
Indicates the update method to use to update the panels (PanelMessage, PanelOvr, PanelNum. PanelCaps, PanelDate)
1: Update with VFP timer
When using ctlUpateStyle = 2 the status bar will only display messages from the menu options, if the menu options have any message text set. The statusbar will not display the text of controls with StatusBarText property set.
3: No automatic update, the updates will be done using ctlUpdatePanels()

Panel Objects (only available at run time)
This is the list of the names of the available panels:
PanelMessage
PanelProgressBar
Paneln or Panels(n)
n is the panel number of the custom panel, for example, if we have 3 custom panels, panel number two can be referred to as "Panel2" or Panels(2) or we can change its Name property and call it what we want, "PanelUser" for example.
PanelOvr
PanelCaps
PanelNum
PanelDate

Panel Properties:
 ctlAlignment
Property.
Value Type: Numeric
Default Value:
R/W:
0 Left
1 Right
2 Center

 ctlAutosize
Property.
Value Type: Logical
Default Value:
R/W:
True / False

 ctlCaption
Property.
Value Type: Character
Default Value:
R/W:
The text to display in the Panel.

 ctlFormat
Property.
Value Type: Numeric
Default Value:
R/W:
Sets date format for PanelDate
0 Nothing
1 Short date
2 Long date.
The date is shown in the Windows formats set in Control Panel.
Applies to: PanelDate panel only.

 ctlIcon
Property.
Value Type: Character
Default Value:
R/W:
Full path and name to a 16x16 256 color icon (".ico") file to display in the Panel. Set to an empty string to clear the Icon.

 ctlIndex
Property.
Value Type: Numeric
Default Value:
R/W:
Returns the index number of the custom Panel. This is the index used by the statusbar, it is 0 based. Used internally by class to send messages to statusbar window control.

 ctlName
Property.
Value Type: Character
Default Value:
R/W:
The name of each Panel. You can change the names of the custom panels from Paneln to what you want.
Remarks:
Property "Name" can still be used, this property was added to be consistent in the naming conventions.

 ctlToolTipText
Property.
Value Type: Character
Default Value:
R/W:
The text to display in the Panel ToolTip. This text will display if any of this conditions is true:
There is only an Icon with no Caption text.
ctlAutosize is .F.: when the Caption text does not fit in the Panel, or Alignment is Left.
ctlAutosize is .T.

 ctlVisible
Property.
Value Type: Logical
Default Value:
R/W:
Specifies whether a Panel is visible or hidden. True/False, 0/1. The first panel, PanelMessage is always visible.

 ctlWidth
Property.
Value Type: Numeric
Default Value:
R/W:
Sets the Width of a Panel when its ctlAutosize property is set to False
Remarks:
Property "Width" can still be used, this property was added to be consistent in the naming conventions.

Note
Todas las propiedades y métodos con un nombre que comienzan con "_" son solo para uso interno de la clase.

Descarga