views:

1905

answers:

7

In a WinForms 2.0 C# application, what is the typical method used for saving and restoring form position and size in an application?

Related, is it possible to add new User scoped application settings AT RUNTIME? I totally see how to add settings at design time, that's not a problem. But what if I want to create one at runtime?

More details:

My application is a conversion of an existing Visual FoxPro application. I've been trying to read as much as I can about application settings, user settings, etc. and get myself clear on the .Net way of doing things, but there are still several things I am confused on.

In the Fox app, saved settings are stored in the registry. My forms are subclassed, and I have base class code that automatically saves the form position and size in the registry keyed on the form name. Whenever I create a new form, I don't have to do anything special to get this behavior; it's built in to the base class. My .Net forms are also subclassed, that part is working well.

In .Net, I get the impression I'm supposed to use User scoped settings for things like user preferences. Size and location of a form definitely seem like a user preference. But, I can't see any way to automatically add these settings to the project. In other words, every time I add a new form to my project (and their are 100's of forms), I have to remember to ADD a User scoped application setting and be sure to give it the same name as the form, i.e., "FormMySpecialSizePosition" to hold the size and position. I'd rather not have to remember to do that. Is this just tough luck? Or am I totally barking up the wrong tree by trying to use User scoped settings? Do I need to create my own XML file to hold settings, so that I can do whatever I want (i.e, add a new setting at runtime)? Or something else?

Surely this is a very common and somebody can tell the "right" way to do it. Thanks in advance!

A: 

Architecturally speaking, if your app requires more, than 100 forms, you are either working on a very large-scale app, or, more likely, your design is broken. Try to zoom out a little bit, and ask what the application tries to solve, and how to properly design objects around that business logic.

Regarding your questions: you can store runtime user information by the (projectname).properties namespace, this will manipulate the app XML file directly. Though I'm not really sure, if you really want to apply this to 100++ forms -again, try to view it from an OOP point of view.

Silver Dragon
A: 

OK, you got me on the 100 forms thing, there aren't really 100 forms - I was just trying to be very clear that I don't want to have to "do something" every time I do add a new form to the application. I want everything to be handled in the form base class.

You said "try to view it from an OOP point of view". That's very much what I'm trying to do, I think I'm just not understanding how things work in .Net. I realize now that my problem is even worse than I thought. As I mentioned, all of my forms are derived from a common base class, which is in a separate library. Regardless of what solution I come up with for storing user settings, how can I access the user settings in a generic way from within my base class form? For example, I'm going to want code in the load event that reads the settings and sets the form position and size. How do I put code in my base class form to read user settings for the current application?

+1  A: 

You could create a base form class with common functionality such as remembering the position and size and inherit from that base class.

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 ;)
}

Well, something like that ;)

Stormenet
A: 

I think I'm not being clear in my request, based on the code sample given. See the commented line that says "// load the settings and apply them"? That's what I need to know how to do! I know how to do all the other stuff given in the code sample, in fact I've got that - a set of base form classes that are used throughout my application. But how, in the base class code, do I reference settings for the active application / user?

A: 

I'm in the same boat as you, in that I have a number of forms (MDI children, in my case) that I want to preserve the position and size of for each user. From my research, creating application settings at runtime is not supported. (see this blog entry) However, you don't have to stick everything in the main settings file. You can add a Settings file to your project (explained here in the MSDN) and use it via the Properties.Settings object. This won't ease the pain of having to remember to create new settigns for each form, but at least it will keep them together, and not clutter up your main application settings.

As far as using the base class to retrieve the settings... I don't know if you can do it there. What I would (and probably will) do is name each attribute , then use Me.GetType().ToString() (I'm working in VB) to composite the names of the attributes I want to retrieve in the Load() event of each form.

+3  A: 
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 )
{
    Properties.Settings.Default.Location = this.DesktopBounds.Location;
    Properties.Settings.Default.Size = this.DesktopBounds.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();
}
This solution has a problem if you close the window in a minized state.
Robert Schneider
A: 

i just stream it out to a separate xml file - quick and dirty and probably not what youre after:

        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

and

        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)
fusi