.net - leer - setting file c#
Guardar y restaurar la posición y el tamaño de la forma (8)
Puede crear una clase de formulario base con funciones comunes, como recordar la posición y el tamaño, y heredar de esa clase base.
public class myForm : Form {
protected override void OnLoad(){
//load the settings and apply them
base.OnLoad();
}
protected override void OnClose(){
//save the settings
base.OnClose();
}
}
then for the other forms:
public class frmMainScreen : myForm {
// you get the settings for free ;)
}
Bueno, algo así;)
En una aplicación WinForms 2.0 C #, ¿cuál es el método típico utilizado para guardar y restaurar la posición y el tamaño del formulario en una aplicación?
Relacionado, ¿es posible agregar nuevas configuraciones de la aplicación del alcance del usuario AT RUNTIME? Veo totalmente cómo agregar configuraciones en el momento del diseño, eso no es un problema. Pero, ¿y si quiero crear uno en tiempo de ejecución?
Más detalles:
Mi aplicación es una conversión de una aplicación existente de Visual FoxPro. He estado tratando de leer todo lo que puedo sobre la configuración de la aplicación, la configuración del usuario, etc. y me he dejado claro sobre la manera de hacer las cosas en .Net, pero todavía hay varias cosas en las que estoy confundido.
En la aplicación Fox, la configuración guardada se almacena en el registro. Mis formularios tienen una subclase y tengo un código de clase base que guarda automáticamente la posición y el tamaño del formulario en el registro con la clave del nombre del formulario. Cada vez que creo un formulario nuevo, no tengo que hacer nada especial para obtener este comportamiento; está integrado en la clase base. Mis formularios .Net también tienen una subclase, esa parte funciona bien.
En .Net, tengo la impresión de que se supone que debo usar la configuración de ámbito del usuario para cosas como las preferencias del usuario. El tamaño y la ubicación de un formulario definitivamente parecen preferencias del usuario. Pero no veo ninguna forma de agregar automáticamente estas configuraciones al proyecto. En otras palabras, cada vez que agrego un formulario nuevo a mi proyecto (y son cientos de formularios), debo recordar agregar una configuración de aplicación de ámbito de usuario y asegurarme de darle el mismo nombre que el formulario, es decir, " FormMySpecialSizePosition "para mantener el tamaño y la posición. Prefiero no tener que recordar hacer eso. ¿Es esto solo una mala suerte? ¿O estoy ladrando completamente al árbol equivocado al tratar de usar la configuración de ámbito del Usuario? ¿Debo crear mi propio archivo XML para mantener la configuración, de modo que pueda hacer lo que quiera (es decir, agregar una nueva configuración en tiempo de ejecución)? ¿O algo mas?
Sin duda, esto es muy común y alguien puede decir la forma "correcta" de hacerlo. ¡Gracias por adelantado!
Estoy en el mismo barco que tú, ya que tengo varios formularios (MDI secundarios, en mi caso) que deseo conservar la posición y el tamaño de cada usuario. De mi investigación, la creación de configuraciones de aplicaciones en tiempo de ejecución no es compatible. (mira esta entrada en el blog ) Sin embargo, no tienes que pegar todo en el archivo de configuración principal. Puede agregar un archivo de Configuraciones a su proyecto ( explicado aquí en MSDN ) y usarlo a través del objeto Properties.Settings. Esto no aliviará el dolor de tener que recordar crear nuevas configuraciones para cada formulario, pero al menos las mantendrá unidas y no saturará la configuración principal de la aplicación.
En cuanto a usar la clase base para recuperar la configuración ... No sé si puedes hacerlo allí. Lo que haría (y probablemente haré) es nombrar cada atributo, luego usar Me.GetType (). ToString () (estoy trabajando en VB) para componer los nombres de los atributos que deseo recuperar en el evento Load () de cada forma.
Simplemente lo transfiero a un archivo xml separado, rápido y sucio, y probablemente no lo que buscas:
Dim winRect As String() = util.ConfigFile.GetUserConfigInstance().GetValue("appWindow.rect").Split(",")
Dim winState As String = util.ConfigFile.GetUserConfigInstance().GetValue("appWindow.state")
''
Me.WindowState = FormWindowState.Normal
''
Me.Left = CType(winRect(0), Integer)
Me.Top = CType(winRect(1), Integer)
Me.Width = CType(winRect(2), Integer)
Me.Height = CType(winRect(3), Integer)
''
If winState = "maximised" Then
Me.WindowState = FormWindowState.Maximized
End If
y
Dim winState As String = "normal"
If Me.WindowState = FormWindowState.Maximized Then
winState = "maximised"
ElseIf Me.WindowState = FormWindowState.Minimized Then
winState = "minimised"
End If
''
If Me.WindowState = FormWindowState.Normal Then
''
Dim winRect As String = CType(Me.Left, String) & "," & CType(Me.Top, String) & "," & CType(Me.Width, String) & "," & CType(Me.Height, String)
'' only save window rectangle if its not maximised/minimised
util.ConfigFile.GetUserConfigInstance().SetValue("appWindow.rect", winRect)
End If
''
util.ConfigFile.GetUserConfigInstance().SetValue("appWindow.state", winState)
Recibí este código de alguna parte, pero desafortunadamente en ese momento (hace mucho tiempo) no hice ningún comentario acerca de dónde lo obtuve.
Esto guarda la información del formulario en el registro HKCU del usuario:
using System;
using System.Windows.Forms;
using Microsoft.Win32;
/// <summary>Summary description for FormPlacement.</summary>
public class PersistentForm : System.Windows.Forms.Form
{
private const string DIALOGKEY = "Dialogs";
/// <summary></summary>
protected override void OnCreateControl()
{
LoadSettings();
base.OnCreateControl ();
}
/// <summary></summary>
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
SaveSettings();
base.OnClosing(e);
}
/// <summary>Saves the form''s settings.</summary>
public void SaveSettings()
{
RegistryKey dialogKey = Application.UserAppDataRegistry.CreateSubKey(DIALOGKEY);
if (dialogKey != null)
{
RegistryKey formKey = dialogKey.CreateSubKey(this.GetType().ToString());
if (formKey != null)
{
formKey.SetValue("Left", this.Left);
formKey.SetValue("Top", this.Top);
formKey.Close();
}
dialogKey.Close();
}
}
/// <summary></summary>
public void LoadSettings()
{
RegistryKey dialogKey = Application.UserAppDataRegistry.OpenSubKey(DIALOGKEY);
if (dialogKey != null)
{
RegistryKey formKey = dialogKey.OpenSubKey(this.GetType().ToString());
if (formKey != null)
{
this.Left = (int)formKey.GetValue("Left");
this.Top = (int)formKey.GetValue("Top");
formKey.Close();
}
dialogKey.Close();
}
}
}
En realidad, existe una verdadera falta de una solución única que funcione de esta manera en cualquier parte de Internet, así que aquí está mi propia creación:
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Win32;
using System.ComponentModel;
using System.Security.Cryptography;
namespace nedprod
{
abstract public class WindowSettings
{
private Form form;
public FormWindowState state;
public Point location;
public Size size;
public WindowSettings(Form _form)
{
this.form = _form;
}
internal class MD5Sum
{
static MD5CryptoServiceProvider engine = new MD5CryptoServiceProvider();
private byte[] sum = engine.ComputeHash(BitConverter.GetBytes(0));
public MD5Sum() { }
public MD5Sum(string s)
{
for (var i = 0; i < sum.Length; i++)
sum[i] = byte.Parse(s.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
}
public void Add(byte[] data)
{
byte[] temp = new byte[sum.Length + data.Length];
var i=0;
for (; i < sum.Length; i++)
temp[i] = sum[i];
for (; i < temp.Length; i++)
temp[i] = data[i - sum.Length];
sum=engine.ComputeHash(temp);
}
public void Add(int data)
{
Add(BitConverter.GetBytes(data));
}
public void Add(string data)
{
Add(Encoding.UTF8.GetBytes(data));
}
public static bool operator ==(MD5Sum a, MD5Sum b)
{
if (a.sum == b.sum) return true;
if (a.sum.Length != b.sum.Length) return false;
for (var i = 0; i < a.sum.Length; i++)
if (a.sum[i] != b.sum[i]) return false;
return true;
}
public static bool operator !=(MD5Sum a, MD5Sum b)
{
return !(a == b);
}
public override bool Equals(object obj)
{
try
{
return (bool)(this == (MD5Sum)obj);
}
catch
{
return false;
}
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
for (var i = 0; i < sum.Length; i++)
sb.Append(sum[i].ToString("x2"));
return sb.ToString();
}
}
private MD5Sum screenconfig()
{
MD5Sum md5=new MD5Sum();
md5.Add(Screen.AllScreens.Length); // Hash the number of screens
for(var i=0; i<Screen.AllScreens.Length; i++)
{
md5.Add(Screen.AllScreens[i].Bounds.ToString()); // Hash the dimensions of this screen
}
return md5;
}
public void load()
{
using (RegistryKey r = Registry.CurrentUser.OpenSubKey(@"Software/" + CompanyId() + @"/" + AppId() + @"/Window State/" + form.Name))
{
if (r != null)
{
try
{
string _location = (string)r.GetValue("location"), _size = (string)r.GetValue("size");
state = (FormWindowState)r.GetValue("state");
location = (Point)TypeDescriptor.GetConverter(typeof(Point)).ConvertFromInvariantString(_location);
size = (Size)TypeDescriptor.GetConverter(typeof(Size)).ConvertFromInvariantString(_size);
// Don''t do anything if the screen config has since changed (otherwise windows vanish off the side)
if (screenconfig() == new MD5Sum((string) r.GetValue("screenconfig")))
{
form.Location = location;
form.Size = size;
// Don''t restore if miminised (it''s unhelpful as the user misses the fact it''s opened)
if (state != FormWindowState.Minimized)
form.WindowState = state;
}
}
catch (Exception)
{
}
}
}
}
public void save()
{
state = form.WindowState;
if (form.WindowState == FormWindowState.Normal)
{
size = form.Size;
location = form.Location;
}
else
{
size = form.RestoreBounds.Size;
location = form.RestoreBounds.Location;
}
using (RegistryKey r = Registry.CurrentUser.CreateSubKey(@"Software/" + CompanyId()+@"/"+AppId() + @"/Window State/" + form.Name, RegistryKeyPermissionCheck.ReadWriteSubTree))
{
r.SetValue("state", (int) state, RegistryValueKind.DWord);
r.SetValue("location", location.X.ToString() + "," + location.Y.ToString(), RegistryValueKind.String);
r.SetValue("size", size.Width.ToString()+","+size.Height.ToString(), RegistryValueKind.String);
r.SetValue("screenconfig", screenconfig().ToString(), RegistryValueKind.String);
}
}
abstract protected string CompanyId();
abstract protected string AppId();
}
}
Esta implementación almacena la posición y el tamaño de un formulario en HKCU / Software / <CompanyId ()> / <AppId ()> / Window State / <form name>. No restaurará la configuración si la configuración del monitor cambia para evitar que las ventanas se restauren fuera de la pantalla.
Obviamente, esto no puede manejar múltiples instancias de la misma forma. También deshabilité específicamente la restauración minimizada, pero esa es una solución fácil de la fuente.
Lo anterior está diseñado para ser soltado en su propio archivo .cs y nunca volver a tocar. Debe instanciar una copia de espacio de nombres local como esta (en Program.cs o su archivo .cs principal del complemento o donde sea):
namespace <your app/plugin namespace name>
{
public class WindowSettings : nedprod.WindowSettings
{
public WindowSettings(Form form) : base(form) { }
protected override string CompanyId() { return "<your company name>"; }
protected override string AppId() { return "<your app name>"; }
}
....
Ahora tiene una instanciación no abstracta en el espacio de nombres principal. Entonces, para usar, agregue esto a los formularios que quiere guardar y restaurar:
private void IssuesForm_FormClosing(object sender, FormClosingEventArgs e)
{
new WindowSettings(this).save();
}
private void IssuesForm_Load(object sender, EventArgs e)
{
new WindowSettings(this).load();
}
Obviamente, siéntase libre de personalizar para sus propios fines. No hay garantía expresa o implícita. Utilice bajo su propio riesgo: rechazo cualquier derecho de autor.
Niall
private void Form1_Load( object sender, EventArgs e )
{
// restore location and size of the form on the desktop
this.DesktopBounds =
new Rectangle(Properties.Settings.Default.Location,
Properties.Settings.Default.Size);
// restore form''s window state
this.WindowState = ( FormWindowState )Enum.Parse(
typeof(FormWindowState),
Properties.Settings.Default.WindowState);
}
private void Form1_FormClosing( object sender, FormClosingEventArgs e )
{
System.Drawing.Rectangle bounds = this.WindowState != FormWindowState.Normal ? this.RestoreBounds : this.DesktopBounds;
Properties.Settings.Default.Location = bounds.Location;
Properties.Settings.Default.Size = bounds.Size;
Properties.Settings.Default.WindowState =
Enum.GetName(typeof(FormWindowState), this.WindowState);
// persist location ,size and window state of the form on the desktop
Properties.Settings.Default.Save();
}
Aquí está el código que utilicé.
private void SaveWindowPosition()
{
Rectangle rect = (WindowState == FormWindowState.Normal) ?
new Rectangle(DesktopBounds.Left, DesktopBounds.Top, DesktopBounds.Width, DesktopBounds.Height) :
new Rectangle(RestoreBounds.Left, RestoreBounds.Top, RestoreBounds.Width, RestoreBounds.Height);
RegistrySettings.SetSetting("WindowPosition", String.Format("{0},{1},{2},{3},{4}",
(int)this.WindowState,
rect.Left, rect.Top, rect.Width, rect.Height));
}
private void RestoreWindowPosition()
{
try
{
string s = RegistrySettings.GetSetting("WindowPosition", String.Empty) as string;
if (s != null)
{
List<int> settings = s.Split(new char[] { '','' }, StringSplitOptions.RemoveEmptyEntries)
.Select(v => int.Parse(v)).ToList();
if (settings.Count == 5)
{
this.SetBounds(
settings[1],
settings[2],
settings[3],
settings[4]);
this.WindowState = (FormWindowState)settings[0];
}
}
}
catch { /* Just leave current position if error */ }
}
También presenté este código en mi artículo Guardar y restaurar la posición de ventana de un formulario .