P3.NET

Using T4 to Create an AppSettings Wrapper, Part 3

In the previous article we expanded the template to dynamically set the type and namespace names based upon the project the template is used in.Now we are going to turn our focus to generating properties for each of the settings in the configuration file. For this we’ll be adding more code to the class block to open and read the settings from the project’s configuration file (which we’ll have to write code to retrieve). We’ll also have to decide how to convert string values to typed equivalents.

Read More

Using T4 to Create an AppSettings Wrapper, Part 2

In the first article in this series we created a basic, static T4 template.The template allowed us to replace standard boilerplate code for reading an app setting

string setting = ConfigurationManager.AppSettings["someSetting"];

with strongly typed property references like this

var myIntSetting = AppSettings.Default.IntValue;
var myDoubleSetting = AppSettings.Default.DoubleValue;

Here’s a summary of the requirements from the first article (slightly reordered).

  1. All settings defined in the project’s config file should be exposed, by default, as a public property that can be read. I’m not interested in writing to them.
  2. Based upon the default value (in the config file) each setting should be strongly typed (int, double, bool, string).
  3. The configuration file cannot be cluttered with setting-generation stuff. This was the whole issue with the Settings designer in .NET.
  4. Sometimes the project containing the config file is different than the project where the settings are needed (ex. WCF service hosts) so it should be possible to reference a config file in another project.
  5. Some settings are used by the infrastructure (such as ASP.NET) so they should be excluded.
  6. Some settings may need to be of a specific type that would be difficult to specify in the value (ex. a long instead of an int).

In this article we’re going to convert the static template to a dynamic template and begin working on requirements 1-3. From last time here are the areas of the template that need to be made more dynamic.

  1. The namespace of the type
  2. The name of the type, including pretty formatting
  3. Each public property name and type
Read More

Using T4 to Create an AppSettings Wrapper, Part 1

AppSettings are settings stored in your configuration file under the <appSettings> element. Almost every application has them. Each setting consists of a name and value. To access such a setting in code you need only do this.

string setting = ConfigurationManager.AppSettings["someSetting"];

There are a couple of problems with this approach.

  • Quite a bit of boilerplate code to access a setting given what it is actually doing
  • The setting name is hard coded and must match the config file
  • The returned value is a string so if you need a different type then you’ll need to convert it

In .NET v2.0 Microsoft added the Settings class to work around these issues. It allows you to create a setting with a type and value and the designer will generate a type to back it where each property matches the setting. This seems great but never really took off. Not even Microsoft uses it in their own framework. Part of the problem is that the config entries it generates are overly complex storing things like type information, default values and other things. Needless to say appSettings continue to be popular anyway. Fortunately we can get the simplicity of appSettings with the power of the newer Settings class all via T4.

In this series of posts I’m going to walk through the process of generating such a template including the ability to add some more advanced functionality. A full discussion of T4 is beyond the scope of a blog so refer to the following links for more information.

Read More

Strongly Typed Application Settings Using T4

We all know that the Settings infrastructure added to .NET a while back is the “correct” way to create strongly typed application settings in configuration files. The problem with this approach though is that the entries generated in the config file aren’t pretty. You have only limited control over the naming, there are lots of extra information to wade through and non-devs can easily get confused. The Appsettings that has existed since v1 is a simpler approach that most people are comfortable with. But you lose a lot of functionality by using AppSettings. The Settings infrastructure brings into play a Settings class with strongly typed properties for the settings and default values for settings that are missing. But sometimes that is overkill or simplicity is just too important.

Read More

Reading and Writing to Streams

Streams in .NET are prevalent. Most everything that requires input or output accepts a stream. The issue with streams is that they are too generic. They only support reading and writing bytes (or byte arrays). Since streams can be read only or write only this makes some sense. The reality though is that most times you know whether a stream is readable or writable. If worse comes to worse you can query the stream for read and write access. But you’re still stuck with reading and writing bytes. To make working with streams easier Microsoft introduced the BinaryReader/BinaryWriter types. These stream read/writers allow you to read and write CLR types to an underlying stream. The theory being that the code is more readable if you explicitly create a reader or writer. Here is an example of writing some data to a stream.

Read More

Comparing Characters

.NET provides great support for comparing strings.  Using StringComparer we can compare strings using the current culture settings or with case insensitivity.  This makes it easy to use strings with dictionaries or just compare them directly.  As an example we can determine if a user is a member of a particular group by using the following code.

bool IsInSpecialGroup ( string user )
{
   var groups = GetUserGroups(user);

   var comparer = StringComparer.CurrentCultureIgnoreCase;
            
   foreach (var group inn groups)
   {
      if (comparer.Compare(group, “group1”;) == 0 ||
          comparer.Compare(group, “group2”;) == 0 ||
          comparer.Compare(group, “group3”;) == 0)
         returnn true;
   };

   return false;
}

Characters have most of the same problems as strings do (culture, case, etc) but .NET provides almost no support for comparing them.  If we want to compare characters without regard to case or in a culture sensitive manner we have to write the code ourselves.  Fortunately it is easy to emulate this using the existing infrastructure.  CharComparer is a parallel type to StringComparer.  It provides identical functionality except it works against characters instead of strings.  As an example the following code determines if a character is a vowel or not.

bool IsAVowel ( char ch )
{
   var vowels = new char[] { ‘a’‘e’‘i’‘o’‘u’ };

   var comparer = CharComparer.CurrentCultureIgnoreCase;

   foreach(var vowel in vowels)
   {
      if (comparer.Compare(vowel, ch) == 0)
         return true;
   };

   return false;

Just like StringComparer, CharComparer has static properties exposing the standard comparison types available in .NET.  Furthermore since StringComparison is commonly used in string comparisons CharComparer provides the static method GetComparer that accepts a StringComparison and returns the corresponding CharComparer instance. 

bool ContainsACharacter ( this IEnumerable<char> source, char value, StringComparison comparison )
{
   var comparer = CharComparer.GetComparer(comparison);

   return source.Contains(value, comparer);            
}

CharComparer doesn’t actually do comparisons directly.  This process can be difficult to get right so it just defers to StringComparer internally.  Naturally this means that CharComparer doesn’t actually do anything different than you would normally do nor does it perform any better.  What it does do is provide an abstraction over the actual process and simplify it down to a couple of lines of code.  If, one day, .NET exposes a better way of comparing characters then CharComparer can be updated without breaking existing code.  Even better is that your code can use CharComparer and StringComparer almost interchangeably without worrying about the details under the hood.

CharComparer implements the standard comparison interfaces: IComparer<char>, IComparer, IEqualityComparer<char> and IEqualityComparer.  The non-generic versions are privately implemented to enforce type safety.  The generic methods are abstract as is CharComparer.  Comparison is specific to the culture being used.  CharComparer defines a couple of nested, private types to implement the culture-specific details.  The nested types are responsible for providing the actual implementation of the comparison methods.  Refer to the source code for the gory details.  Note that this pattern is derived from how StringComparer works.

Feel free to use this code in any of your projects and provide feedback on any issues found.  Unfortunately I’m not posting the unit tests for this class at this time.  However I’ve used this type in several projects and haven’t run into any problems with it.  But, as always, test your code before using it in production.

ServiceBase.OnStart Peculiarity

When implementing a service you really have to have a good understanding of how Windows services work.  If you do it wrong then your service won’t work properly, or worse, can cause problems in Windows.  Services must be responsive and be a good citizen when working with the Service Control Manager (SCM).  The .NET implementation hides a lot of these details but there is a hidden complexity under the hood that you must be aware of.  But first a brief review of how Windows services work.

Windows Services Internals (Brief)

All services run under the context of the SCM.  The SCM is responsible for managing the lifetime of a service.  All interaction with a service must go through the SCM.  The SCM must be thread safe since any number of processes may be interacting with a service at once.  In order to ensure that a single service does not cause the entire system to grind to a halt the SCM manages each service on a separate thread.  The exact internal details are not formally documented but we know that the SCM uses threads to work with each service. 

Each service is in one of several different states such as started, paused or stopped.  The SCM relies on the state of a service to determine what the service will and will not support.  Since state changes can take a while most states have a corresponding pending state such as start pending or stop pending.  The SCM expects a service to update its state as it runs.  For example when the SCM tells a service to start the service is expected to move to the start pending state and, eventually, the started state.  The SCM won’t wait forever for a service to respond.  If a service does not transition fast enough then the SCM considers the service hung.  To allow for longer state changes a service must periodically notify the SCM that it needs more time.

One particularly important state change is the stop request.  When Windows shuts down the SCM sends a stop request to all services.  Every service is expected to stop quickly.  The SCM gives a (configurable) time for each service to stop before it is forcifully terminated.  If it wasn’t for this behavior a hung or errant service could cause Windows shutdown to freeze.

A Day In the Life Of a Service

A service is normally a standard Windows process and hence has a WinMain.  However a single process can host multiple services (many of the Windows services are this way) so WinMain itself is not the service entry point.  Instead a service process must register the list of supported services and their entry points to the SCM via a call to StartServiceCtrlDispatcher.  This method, which is a blocking call, hooks up the process to the SCM and doesn’t return until all listed services are stopped.  The method takes the service name and its entry point (normally called ServiceMain).  When the SCM needs to start a service it calls the entry point on a separate thread (hence each service gets its own in addition to the process).  The entry point is required to call RegisterServiceCtrlHandlerEx to register a function that handles service requests (the control handler).  It also must set the service state to start pending.  Finally it should initialize the service and then exit.  The thread will go away but the service will continue to run. 

One caveat to the startup process is the fact that it must be quick.  The SCM uses an internal lock to serialize startup.  Therefore services cannot start at the same time and a long running service can stall the startup process.  For this reason the general algorithm is to set the state to start pending, spawn a worker thread to do the real work and then set the service to running.  Any other variant can slow the entire system down.

All future communication with the service will go through the control handler function.  Each time the function is called (which can be on different threads) the service will generally change state.  This will normally involve changing to the pending state, doing the necessary work and then setting the service to the new state.  Note that in all cases the SCM expects the service to respond quickly.

.NET Implementation

In .NET the ServiceBase class hides most of the state details from a developer.  To ensure that the service is a good citizen the .NET implementation hides all this behind a few virtual methods that handle start, stop, pause, etc.  All a developer need do is implement each one.  The base class handles setting the state to pending and to the final state while the virtual call is sandwiched in between.  However the developer is still responsible for requesting additional time if needed.  Even the registration process is handled by the framework.  All a developer needs to do is call ServiceBase.Run and pass in the service(s) to host.

 All is wonderful and easy in .NET land, or is it.  If you read the documentation carefully you’ll see a statement that says the base implementation hides all the details of threading so you can just implement the state methods as needed but this is not entirely true.  All the implementations except OnStart behave the same way.  When the control handler is called it sets the service to the pending state, executes the corresponding virtual method asynchronously and returns.  Hence the thread used to send the request is not the same thread that handles the request and ultimately sets the service state.  This makes sense and meets the requirements of the SCM.  More importantly it means the service can take as long as it needs to perform the request without negatively impacting the SCM.

The start request is markedly different.  When the start request is received the base class moves the service to the start pending state, executes the OnStart virtual method asynchronously and then…waits for it to complete before moving the service to the start state.  See the difference?  The start request thread won’t actually return until OnStart completes.  Why does the implementation bother to call the method asynchronously just to block waiting for it to complete?  Perhaps the goal was to make all the methods behave symmetrically in terms of thread use.  Perhaps the developers didn’t want the service to see the real SCM thread.  Nevertheless it could have used a synchronous call and behaved the same way. 

What does this mean for service developer?  It means your OnStart method still needs to run very fast (create a thread and get out) even in the .NET implementation even though all the other control methods can be implemented without regard for the SCM.  If OnStart takes too long then it’ll block the SCM.  More importantly the OnStart method needs to periodically request additional time using RequestAdditionalTime to avoid the SCM thinking it is hung.

Summary

When implementing a service in .NET it is still important to understand how native services and the SCM work together.  The OnStart method must be fast and well behaved to avoid causing problems with Windows.  The other control methods are less restrictive but still require awareness of how the base implementation works.  Writing a service is trivial as far as coding goes but services require a great deal of care in order to ensure they behave properly.  This doesn’t even get into the more complex issues of security, installation, event logging and error handling which are broad topics unto themselves.

String Extension Methods

Haven’t posted in a while and don’t have a lot of time today so I’ll just throw up a copy of the string extension methods I’ve been using over the years.  Summary of the provided functions (note that not all of them have been fully tested).

  • Combine – Basically acts like String.Join but handles cases where the delimiters are already part of the string.
  • Is… – Equivalent to Char.Is… but applies to an entire string.
  • Left/Right – Gets the leftmost/rightmost N characters in a string.
  • LeftOf/RightOf – Gets the portion of a string to the left/right of a character or string.
  • Mid – Gets a portion of a string.
  • IndexOfNone/LastIndexOfNone – Finds the index of the first character NOT IN a list of tokens.
  • ReplaceAll – Replaces all occurrences of a token with another token.
  • ToCamel/ToPascal – Camel or Pascal cases a string.
  • ToMultipleWords – Pretty prints a string such as taking SomeValue and converting it to “Some Value”.

Download the Library Code

Extension Method Guidelines Rebuffed

With the additional of extension methods developers have a powerful new way of extending existing types.  As extension methods become more and more common guidelines will be needed to ensure that extension methods “fit in” with the general design of the library.  If you are not aware of what an extension method is then the quick summary would be that it is a method that appears as an instance method of a type but is, in fact, defined in a separate static class.  This allows us to extend existing types without modifying the type itself.  It really becomes a powerful feature when applied to interfaces.  We can enhance an interface to expose a lot of new functionality while not requiring the interface implementer to do any extra work.  LINQ is a good example of this extensibility.  I personally tend to view extension methods more as static methods on a type  that be called using the instance-method syntax.  This, to me, gives a more accurate picture of what is happening and, as you will see, what is allowed.

Currently there are a lot of “guidelines” floating around that people like to mention.  Unfortunately it is still too early to determine which of these are truly best practices and which are opinions.  One guideline in particular bothers me the wrong way: extension methods should throw a NullReferenceException if the source is null.

Let’s start with a regular method as an example.  This method will return everything to the left of a particular string in another string.

static string Leftof ( string source, string value )
{
   if (String.IsNullOrEmpty(source))
      return “”;

   if (String.IsNullOrEmpty(value))
      return “”;
   …
}

This is a pretty handy function so it makes sense to make it an extension method so we might do this.

static class StringExtension
{
   public static string Leftof ( this string source, string value )
   {
      if (String.IsNullOrEmpty(source))
         return “”;

      if (String.IsNullOrEmpty(value))
         return “”;
      …
   }
}

So far so good but it violates the aforementioned rule about throwing an exception if a null is passed in.  The rationale is that an extension method appears to the developer as an instance method and should therefore behave like one.  While that is a reasonable argument I don’t think it applies in all cases.  Why do we have static methods on types, such as String.IsNullOrEmpty?  The general reason is because the method does not need an instance to perform its work.  But if the method itself considers null to be valid then the method would also need to be static.  So syntactically we cannot allow an instance method to accept null but static methods (and by definition extension methods) we can.

One of the big arguments against this approach is that “extension methods should look and act like instance methods”.  Why?  The only real reason I can see is because they look like instance methods when used but we, as developers, are use to the actual code being quite different than what we expect.  The assignment operator, for example, we would never expect to throw an exception yet it can if the type implements the assignment operator and does something inappropriate.  Addition, subtraction and other operators are the same way.    How about the relational operators? 

Data value1 = null;
Data value2 = null;
            
bool result = value1 < value2;

We would never expect the above code to throw an exception and yet a method call is occurring under the hood.  If that method throws an exception then so does the above code.  As developers we have to be aware that we don’t know everything that is going on under the hood so we should expect errors anywhere.

Another problem I have with this guideline is the solution.  The guideline is that extension methods should behave like instance methods but that simply isn’t possible.  If you call an instance method with a null reference then you will get a NullReferenceException.  This particular exception is one of a handful of system exceptions.  A system exception is an exception that is raised by the runtime proper.  Normal code, aka ours, should not throw system exceptions.  If you explicitly throw a system exception then code analysis tools like FxCop will generate CA warnings about it.  That is what you want.

Instead we have “application” exceptions.  Hence when we receive an argument that is null and we do not allow them then we throw ArgumentNullException.  So to make our extension method behave like an instance method we would need to either throw a system exception explicitly (which we aren’t suppose to do) or reference the source variable.  Here’s what we’d have to do to our earlier example to get it to throw the appropriate exception while still making code analysis happy.

public static string Leftof ( this string source, string value )
{
   //Force a NullReferenceException
   int len = source.Length;

   if (String.IsNullOrEmpty(value))
      return “”;

   …
}

I have a really big problem writing code just to force something to happen like throw a specific exception.  If I really wanted the exception I’d just throw ArgumentNullException.  But if I do that then I’m no longer making my extension method act like an instance method.  This becomes even more of an issue if you can short-circuit the method return based upon other argument values. 

A final argument for the guideline is that if an extension method eventually becomes an instance method then your application should behave the same but the reality is that you should have unit tests to verify your application’s behavior so a major change like going from extension to instance should be thoroughly tested anyway.  Here are my guidelines for extension methods.  Take them with a grain of salt.

  • Extension methods should be placed in a static class called TypeExtension.  For interfaces the “I” can be left off.
  • Extension classes should be only for extension methods and should not contain non-extension code.
  • Each extension method’s first parameter should be this Type source.
  • Use an extension method only if the source parameter makes sense and is used in the method.  Use a normal static method otherwise.
  • An extension method should not throw ArgumentNullException for source.    Other arguments are fine.  If source cannot be null then referencing the value will be sufficient to generate the correct exception.
  • If null is not necessarily an invalid value then do not throw any exceptions.  An extension method does not need to follow instance method semantics.
  • Document the behavior if source is null if it is not going to throw an exception.

Persisting Form Settings

(Originally published: 15 September 2007)

This article was originally written when .NET v2 was released.  Some of the information in here may be outdated with newer .NET versions but there is still some good information on persisting form settings and avoiding some pitfalls in the process.  Therefore this article is being posed unchanged from its initial form.

When working with Windows applications users expect that the application will remember its state when it is closed and restore that state when it is opened.  This allows the user to customize the layout of the application to fit their needs.  If Bill only works with a single application at a time he might like to have the application take up the whole screen so he can maximize his view.  Julie, on the other hand, runs several applications at once.  She wants to keep windows laid out in a certain order so she can efficiently copy and paste data between applications.  It doesn’t make sense to require Julie and Bill to share the same window layouts when their individual settings can be stored easily.

In the early betas of .NET v2 this functionality was available.  It seems to have been removed before the final release.  This article will discuss how to add in form state persistence to your WinForms applications.  This article will only deal with a single form and the basic form attributes but it can be extended to multiple forms with many different properties including tool windows and docking state.

Where to Store the Data

For persisting data on a per-user basis you basically have three common choices: registry, isolated storage and settings file.  The registry is commonly used for old-school programming.  The HKEY_CURRENT_USER key is designed for storing per-user settings.  It works a lot like a file system.  The registry is generally not recommended anymore.  It is designed for small pieces of data and has limited support for data formats.  It is, however, secure and requires more than a passing knowledge of Windows to use properly.  Therefore it is a good choice for settings that should generally be protected but not to big in size.  A big limitation of the registry is that it can’t be used in applications that don’t have registry access (like network applications or smart clients).

Isolated storage is a step up the file system hierarchy.  It looks like a file system (and actually resides in the system somewhere) but its actual location is hidden from applications.  Isolated storage allows any application to store data per-user.  The downside to isolated storage is that it can be a little confusing to use.  Additionally, since the actual path and file information is hidden, it can be hard to clean up corrupt data if something were to go wrong. 

Finally there is the settings file.  We are talking about the user settings file here, not the application settings file.  Each user can have their own settings file.  This file works similar to the application property settings file that you can use for application-wise settings.  The difference is that each user has their own copy and it is store in the user’s profile directory.

Before moving on it is important to consider versioning of the settings.  If you want a user running v1 of your application to be able to upgrade to v2 and not lose any of their settings then you must be sure to chose a persistence location that is independent of the version of the application.  The registry is a good choice here as isolated storage and user settings are generally done by application version.  Still it doesn’t make sense in all cases to be backward compatible with the settings file.  You will have to decide on a case by case basis.

FormSettings

Let’s start with the basic class we’ll use.  Ultimately, since we might have quite a few forms to persist we want to create a base class (FormSettings) that will take care of the details.  We can derive from this class for custom form settings as needed.  In this article we will use the user’s setting file so we derive from ApplicationSettingsBase.  If you want to use a different storage mechanism then you’ll need to make the appropriate changes. 

Since we want our class to work with multiple forms we need to make each form unique.  We will use the SettingsKey to make each form unique.  Each form must specify the key it will use.  Here is the start of our class.

public class FormSettings : ApplicationSettingsBase 

   public FormSettings ( string prefix ) 
   { 
      SettingsKey = prefix; 
   } 

   public void Load ( Form target )  />   {
      //Load
   }

   public void Save ( Form target ) />   {
      //Save
   }
}

When the form is loaded it will call Load to load its settings.  When the form is closed it will call Save.  Here is sample code for our form.

protected override void OnLoad(EventArgs e) 

    base.OnLoad(e); 

    m_Settings.Load(this); 

protected override void OnFormClosing ( FormClosingEventArgs e ) 

    base.OnFormClosing(e); 

    if (!e.Cancel) 
        m_Settings.Save(this);
}

private FormSettings m_Settings = new FormSettings(“MainForm”);

 

Persisting Properties

At a minimum a user would expect to be able to move the window around and resize it to fit their needs.  Therefore we need to load and save the following properties: DesktopLocation, Size and WindowStateDesktopLocation specifies the position, relative to the top-left corner of the desktop, of the top-left corner of the form.  The Size property indicates the width and height of the form.  Finally the WindowState is used to track when a window is minimized or maximized.  We will discuss this property shortly.

To load and save properties using the settings file we need to define a property for each item we want to save.  We need to mark the property as user-scoped and we need to get the value from and set the value to the settings file.  This is pretty straightforward so we will not dwell on the details.  Here is the code for getting and setting the property values.  One point of interest is that we use special values when we can not find the property values.  This will come back later when we talk about loading the settings.

public class FormSettings : ApplicationSettingsBase  
{
   … 

   [UserScopedSetting] 
   public Point Position  BR />   { 
      get 
      { 
         object value = this[“Position”]; 
         return (value != null) ? (Point)value : Point.Empty; 
      } 
      set { this[“Position”] = value; } 
   } 

   [UserScopedSetting] 
   public Size Size  R />   { 
      get 
      { 
         object value = this[“Size”]; 
         return (value != null) ? (Size)value : Size.Empty; 
      } 
      set { this[“Size”] = value; } 
   } 

   [UserScopedSetting] 
   public FormWindowState State  R />   { 
      get 
      { 
         object value = this[“State”]; 
         return (value != null) ? (FormWindowState)value : FormWindowState.Normal; 
      } 
      set { this[“State”] = value; } 
   } 
}

 

Saving the Settings

Saving the settings is really easy.  All we have to do is set each of the user-scoped property values and then call Save on the base settings class.  This will flush the property values to the user’s settings file.

public void Save ( Form target ) 

   //Save the values 
   Position = target.DesktopLocation; 
   Size = target.Size; 
   State = target.WindowState; 

   //Save the settings
   Save(); 
}

 

Loading the Settings

Loading the settings requires a little more work.  On the surface it is similar to the save process: get each property value and assign it to the form.  The only issue that comes up is what to do when no settings have been persisted (or they are corrupt).  In this case I believe the best option is to not modify the form’s properties at all and, therefore, let it use whatever settings were defined in the designer.  Let’s do that now and see what happens.

public void Load ( Form target ) 

   //If the saved position isn’t empty we will use it 
   if (!Position.IsEmpty) 
        target.DesktopLocation = Position; 
   //If the saved size isn’t empty we will use it 
   if (!Size.IsEmpty) 
     target.Size = Size; 

   target.WindowState = State; 
}

It seems to work.  This is too easy, right?  Now try minimizing the form and then closing it.  Open the form again.  Can’t restore it can you? 

Minimizing and Maximizing Forms

The problem is that for a minimized/maximized form the DesktopLocation and Size properties are not reliable.  Instead we need to use the RestoreBounds property which tracks the position and size of the form in its normal state.  If we persist this property when saving then when we load we can restore the normal position and size and then set the state to cause the form to minimize or maximize properly.  But there is another problem.  RestoreBounds isn’t valid unless the form is minimized or maximized.  Therefore our save code has to look at the state of the form and use DesktopLocation when normal and RestoreBounds when minimized/maximized.  Note that RestoreBounds.Size is valid in both cases although whether this is by design or not is unknown.  The load code remains unchanged as we will set the values based upon the form’s normal state and then tell the form to minimize or maximize.  Here is the updated code.

public void Save ( Form target ) 

   //Save the values 
   if (target.WindowState == FormWindowState.Normal) 
      Position = target.DesktopLocation; 
   else 
      Position = target.RestoreBounds.Location; 

   Size = target.RestoreBounds.Size; 
   State = target.WindowState; 

   //Save the settings 
   Save(); 
}

 

Disappearing Windows

The final problem with our code is the problem of disappearing windows.  We’ve all seen it happen.  You start an application and the window shows up in the Task Bar but not on the screen.  Windows doesn’t realize that the application’s window is off the screen.  This often occurs when using multiple monitors and we switch the monitors around or when changing the screen resolution.  Fortunately we can work around it.

During loading we need to verify that the window is going to be in the workspace of the screen (which includes all monitors).  If it isn’t then we need to adjust the window to appear (at least slightly) on the screen.  We can do this by doing a quick check to make sure the restore position is valid and update it if not. 

What makes this quite a bit harder is the fact that screen coordinates are based off the primary monitor.  Therefore it is possible to have negative screen coordinates.  We also don’t want the Task Bar or other system windows to overlap so we will use the working area of the screen which is possibly smaller than the screen size itself.  .NET has a method to get the working area given a control or point but it returns the closest match.  In this case we don’t want a match.  .NET also has SystemInformation.VirtualScreen which gives us the upper and lower bounds of the entire screen but it doesn’t take the working area into account.

For this article we’ll take the approach of calculating the working area manually by enumerating the monitors on the system and finding the smallest and largest working areas.  Once we have the work area we need to determine if the caption of the form fits inside this area.  The caption height is fixed by Windows but the width will match whatever size the form is.  We do a little math and viola.  If the caption is visible then we will set the position otherwise, in this case, we simply let the form reset to its initial position.  Here is the load code.

public void Load ( Form target ) 

   //If the saved position isn’t empty we will use it 
   if (!Position.IsEmpty) 
   { 
       //Verify the position is visible (at least partially) 
       Rectangle rcArea = GetWorkingArea(); 

       //We want to confirm that any portion of the caption is visible 
       //The caption is the same width as the window but the height is fixed 
       //from the top-left of the window 
       Size sz = (Size.IsEmpty) ? target.Size : this.Size; 
       Rectangle rcForm = new Rectangle(Position, new Size(sz.Width, SystemInformation.CaptionHeight)); 
       if (rcArea.IntersectsWith(rcForm)) 
          target.DesktopLocation = Position; 
   }; 

   //If the saved size isn’t empty we will use it 
   if (!Size.IsEmpty) 
       target.Size = Size; 

   target.WindowState = State; 

private Rectangle GetWorkingArea () 

   int minX, maxX, minY, maxY; 
   minX = minY = Int32.MaxValue; 
   maxX = maxY = Int32.MinValue; 

   foreach (Screen scr in Screen.AllScreens) 
   { 
      Rectangle area = scr.WorkingArea; 

      if (area.Bottom < minY) minY = area.Bottom; 
      if (area.Bottom > maxY) maxY = area.Bottom; 

      if (area.Top < minY) minY = area.Top; 
      if (area.Top > maxY) maxY = area.Top; 

      if (area.Left < minX) minX = area.Left; 
      if (area.Left > maxX) maxX = area.Left; 

      if (area.Right < minX) minX = area.Right; 
      if (area.Right > maxX) maxX = area.Right; 
   }; 

   return new Rectangle(minX, minY, (maxX – minX), (maxY – minY)); 
}