CategoríaDesarrollo

Guardar posición y tamaño de formularios

Una de las tareas habituales que utilizo en casi cualquier aplicación de windows forms es guardar la posición y el tamaño de los formularios entre ejecuciones. Para facilitar la incorporación de esta funcionalidad en cualqueira de mis programas he creado un par de clases que se encargan de los pormenores.

Los requisitos para este desarrollo son:

  • Minimizar el código de inicialización y uso en cualquier formulario de cualquier aplicación.
  • Guardar la posición, el tamaño y, opcionalmente, el estado de la ventana (maximizada, normal, minimizada).
  • Guardar los datos para cada usuario independientemente.

Para facilitar la inicialización la clase TGBFormState hereda de la clase Component. De esta manera al compilar el proyecto aparece en la barra de herramientas. Arrastrando este componente en un formulario cualquiera en tiempo de diseño, parte de la inicialización del componente se realiza sola. Solamente será necesario establecer dos propiedades del componente agregado al formulario (puede hacerse en la ventana de propiedades del componente en tiempo de diseño):

  • Parent: debe ser establecido al formulario que contiene el componente. De esta manera el componente se suscribe a los eventos de carga y cierre del formulario para cargar y guardar el estado respectivamente.
  • AllowSaveState: Si está establecido a true en el momento de restablecer el estado del formulario se tendrá en cuenta si está maximizado, minimizado o en estado normal. En caso contrario, siempre se restablece en un estado normal y se utilizan la posición y el tamaño guardados.

Para realizar el guardado, utilizo una clase intermedia FormState que se serializa a un archivo xml con varias propiedades del formulario: ancho, alto, posición superior, posición izquierda, estado de la ventana y nombre del formulario.

El archivo serializado se guarda utilizando un almacenamiento aislado o IsolatedStorage basado en la identidad del usuario y en el assembly. Para cada formulario, se guardará un archivo con su nombre en dicha ubicación.

Código de TGBFormState

#region Copyright
/***************************************************************************
 *   Copyright (C) 2008 by Tony G. Bolaño                                  *
 *   Contact:  tonybolanyo@gmail.com                                       *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License v.3.             *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                  *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License v.3 *
 *   along with this program; if not, write to the tonybolanyo@gmail.com   *
 ***************************************************************************/
#endregion

using System;
using System.ComponentModel;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace TGBComponents {
    /// <summary>
    /// Al agregarlo a un formulario añade la funcionalidad
    /// de persistencia de la posición, estado y tamaño del formulario.
    /// </summary>
    public class TGBFormState : Component {

        /// <summary>
        /// Almacén personal de datos para el usuario
        /// </summary>
        IsolatedStorageFile _isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null);

        /// <summary>
        /// Inicializa una nueva instancia de la clase TGBFormState.
        /// </summary>
        public TGBFormState() {
            _allowSaveState = true;
        }

        #region Properties

        private bool _allowSaveState;
        /// <summary>
        /// Establece o devuelve si el estado del formulario también
        /// se restablece desde las configuraciones guardadas
        /// </summary>
        [Category("Behavior"),
        Description("Establece o devuelve si el estado del formulario también se restablece desde las configuraciones guardadas")]
        public bool AllowSaveState {
            get { return _allowSaveState; }
            set {
                _allowSaveState = value;
            }
        }

        private Form _parent;
        /// <summary>
        /// Establece o devuelve el formulario padre del componente.
        /// Debe ser establecido para al formulario del que se van a guardar
        /// las configuraciones de posició y tamaño.
        /// </summary>
        /// 
        ///
Al establecer el formulario sobre el que se va a actuar
        /// el componente se suscribe al evento FormClosing
        /// para guardar el estado del formulario en ese momento. Y al evento
        /// Load para restablecer el estado guardado.
        /// 
        [Category("Behavior"),
        Description("Establece o devuelve el formulario padre del componente.")]
        public Form Parent {
            get { return _parent; }
            set {
                if (value==null &amp;&amp; _parent!=null) {
                    _parent.FormClosing -= new FormClosingEventHandler(_parent_FormClosing);
                    _parent.Load -= new EventHandler(_parent_Load);
                }
                _parent = value;
                if (_parent != null) {
                    _parent.FormClosing += new FormClosingEventHandler(_parent_FormClosing);
                    _parent.Load += new EventHandler(_parent_Load);
                }
            }
        }

        #endregion

        #region Events suscriptions

        /// <summary>
        /// Responde al evento Load del formulario.
        /// </summary>
        ///
Formulario que lanza el evento
        ///
Datos del evento
        void _parent_Load(object sender, EventArgs e) {
            LoadFormState();
        }

        /// <summary>
        /// Responde al evento FormClosing del formulario
        /// </summary>
        ///
Formulario que lanza el evento
        ///
Datos del evento
        void _parent_FormClosing(object sender, FormClosingEventArgs e) {
            SaveFormState();
        }

        #endregion

        #region Methods

        /// <summary>
        /// Guarda el estado actual del formulario.
        /// </summary>
        public void SaveFormState() {
            if (_parent == null)
                return;
            string filename = _parent.Name;
            try {
                IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filename, FileMode.Create, _isoStore);
                FormState state = new FormState(_parent);
                XmlSerializer serializer = new XmlSerializer(typeof(FormState));
                TextWriter writer = new StreamWriter(stream);
                serializer.Serialize(writer, state);
                writer.Close();
            } catch (Exception) {
                // Se ignoran los errores
            }
        }

        /// <summary>
        /// Restablece el estado del formulario según el estado guardado.
        /// </summary>
        public void LoadFormState() {
            if (_parent==null)
                return;
            string filename = _parent.Name;
            string[] fileNames = _isoStore.GetFileNames(filename);
            if (fileNames.Length==0)
                return;
            bool isOk = true;
            FormState state = null;
            try {
                IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filename, FileMode.Open, _isoStore);
                XmlSerializer serializer = new XmlSerializer(typeof(FormState));
                TextReader reader = new StreamReader(stream);
                state = (FormState)serializer.Deserialize(reader);
                reader.Close();
            } catch (Exception) {
                isOk = false;
            }
            if (!isOk)
                return;
            _parent.Width = state.Width;
            _parent.Height = state.Height;
            _parent.Top = state.top;
            _parent.Left = state.Left;
            if (_allowSaveState)
                _parent.WindowState = state.WindowState;
        }

        #endregion

    }
}

Código de FormState

#region Copyright
/***************************************************************************
 *   Copyright (C) 2008 by Tony G. Bolaño                                  *
 *   Contact:  tonybolanyo@gmail.com                                       *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License v.3.             *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                  *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License v.3 *
 *    along with this program; if not, write to the tonybolanyo@gmail.com  *
 ***************************************************************************/
#endregion

using System.Windows.Forms;
using System.Xml.Serialization;

namespace TGBComponents {
    /// <summary>
    /// Clase para serializar las propiedades de un formulario
    /// que se van a guardar a través del componente 
    /// </summary>
    [XmlRoot("form")]
    public class FormState {
        private int _width;
        /// <summary>
        /// Ancho en pixeles del formulario
        /// </summary>
        [XmlElement("width")]
        public int Width {
            get { return _width; }
            set {
                _width = value;
            }
        }

        private int _height;
        /// <summary>
        /// Alto en pixeles del formulario
        /// </summary>
        [XmlElement("height")]
        public int Height {
            get { return _height; }
            set {
                _height = value;
            }
        }

        private int _left;
        /// <summary>
        /// Posición izquierda del formulario
        /// </summary>
        [XmlElement("left")]
        public int Left {
            get { return _left; }
            set {
                _left = value;
            }
        }

        private int _top;
        /// <summary>
        /// Posición superior del formulario
        /// </summary>
        [XmlElement("top")]
        public int top {
            get { return _top; }
            set {
                _top = value;
            }
        }

        private string _formName;
        /// <summary>
        /// Nombre del formulario
        /// </summary>
        [XmlAttribute("name")]
        public string FormName {
            get { return _formName; }
            set {
                _formName = value;
            }
        }

        private System.Windows.Forms.FormWindowState _windowState;
        /// <summary>
        /// Estado del formulario
        /// </summary>
        [XmlElement("state")]
        public System.Windows.Forms.FormWindowState WindowState {
            get { return _windowState; }
            set { _windowState = value; }
        }

        /// <summary>
        /// Inicializa una nueva instancia de la clase FormState.
        /// </summary>
        public FormState() {
        }

        /// <summary>
        /// Inicializa una nueva instancia de la clase FormState.
        /// </summary>
        ///
Formulario del que se van a guardar las propiedades.
        public FormState(Form form) {
            _height = form.Height;
            _width = form.Width;
            _top = form.Top;
            _left = form.Left;
            _windowState = form.WindowState;
            _formName = form.Name;
        }

    }
}

Descargar código fuente

Ejecutar un paquete DTS desde .net

Es posible ejecutar un paquete DTS de SQL Server 2000 desde .net. Para ello es necesario utilizar una dll que se puede encontrar en la carpeta de instalación de SQL Server

<Unidad:>\Archivos de programa\Microsoft SQL Server\80\Tools\Binn\dtspkg.dll

La forma más sencilla de ejecutar un paquete DTS se compone de tres pasos fundamentalmente:

  1. Cargar el paquete
  2. Ejecutarlo
  3. Descargar el paquete

Cargar el paquete

Lo primero es saber desde dónde hay que cargar el DTS. Los paquetes DTS pueden guardarse en tres diferentes localizaciones o formatos y para cada uno de ellos existe un método diferente dentro de la clase Package:

  1. LoadFromStorageFile permite la carga cuando se ha guardado en un archivo. Este archivo en realidad es un archivo estructurado que puede albergar varios paquetes y varias versiones de un mismo paquete.
  2. LoadFromSQLServer si el paquete se guarda en la base de datos de sistema del propio SQL Server (en la tabla msdb.dbo.sysdtspackages). Dentro de la tabla el paquete propiamente dicho se almacena en la columna packagedata, que contiene una única versión del paquete. Las versiones en este caso son guardadas en diferentes filas de la tabla.
  3. La última posibilidad es que esté guardado en el repositorio (Microsoft Repository) o Microsoft Meta Data Services. En este caso la ejecución se realiza mediante el método LoadFromRepository.

Ejecutar el paquete

Después de cargarlo, simplemente hay que llamar al método Execute del objeto Package que ejecutará el paquete de forma síncrona. Para seguir el proceso será necesario responder a los eventos del paquete.

Descargar el paquete

Después de la ejecución del paquete es necesario limpiar el estado de la ejecución mediante el método Uninitialize, aunque antes de llamarlo es posible analizar el resultado de cada paso de ejecución del paquete y comprobar los mensajes de error. Una vez descargado esto no será posible.

A %d blogueros les gusta esto: