Project 3 — Weather Tracker

Requirements (100 points)

Your task is to implement a simple weather tracker with two main features:

  1. Displaying the current temperature in the Windows system tray
  2. Displaying the 7-day forecast in the application window
You will consume public, externally developed web services in your application to retrieve this weather data, and you will display them using WinForms and basic drawing functionality from GDI+.

User Interface

There are two components to the application interface: the tray icon and the application window itself.

Tray icon

This should be showing at all times while the application is running. The icon should display the current temperature. To add a tray icon to your application you will need to use the NotifyIcon control. Check the Resources page for a link on how to get started with this.

Double-clicking the tray icon should restore the application window if it is currently hidden; otherwise it should have no effect. Right-clicking on the icon should bring up a ContextMenu, the same type of control used for regular file menus at the tops of your applications. To attach a context menu to the tray icon instead of the window, set the ContextMenuStrip property of the NotifyIcon object to your context menu object. This process is also described in the same tutorial mentioned above.

The context menu should contain the following items: Exit, Change Location, Update, and Restore. Change Location should allow the user to specify a new location. One possibility is to display a window that asks the user to specify a zip code, for example. Update should retrieve the current temperature and update the icon, and if the window is currently displayed, the forecast should be retrieved and displayed again. Restore should unhide the application window if it is hidden.

Application Window

The window should display the city, state, and zip code for the forecast it contains. You can choose to lay out the contents of the 7-day forecast however you'd like. The items that must be displayed for each day are the high and low temperatures.

Minimizing the window should result in the window becoming hidden. This will also remove the application from the task bar. The application will still be running, and the window can be restored using the menu from the tray icon.

Remember that unless you design your window's contents to adjust nicely upon resizing, disable resizing and the maximize box.

Functionality

When the user selects the location for which he wants weather information, he will expect that to remain the same in future uses of the app. Use a settings file to maintain this user option.

You will query web services to retrieve all weather information you need. You are free to search for and use any public web services that you can find that satisfy the requests you need to make. Or you can simply use the following web services for your different data needs:

You should provide exception handling to deal gracefully with any failures that occur while querying the web services. In particular, one thing you should check is that your program does not crash when there is no Internet connection. In this situation, you might want to display an error message to the user that the connection is down and to try again later.

Because there may be delays in waiting for the web services to respond, you should spawn each web service request in a new thread so the application doesn't become unresponsive. Because these child threads will not be able to access the window's controls directly, you will need to declare and use delegates that get invoked when the web service requests complete. These delegate calls will take care of updating the displays appropriately with the data returned from the server.

To invoke a delegate, you should use the BeginInvoke method of the form class. For example, if your form has an instance of a delegate called OnWebRequestCallback that takes a string parameter, to invoke this method from the child thread:

BeginInvoke(OnWebRequestCallback, new object[]{ currentTemp });

To draw the current temperature on the icon in the system tray, you will want to use the Graphics class. In class, we saw how to attach a Graphics object to a bitmap image. We can then use this bitmap as the icon in the system tray. Here is a skeleton of how this works:

Bitmap b = new Bitmap(16, 16);
Graphics g = Graphics.FromImage(b);
/* logic to draw shapes/text onto image */
trayIcon.Icon = Icon.FromHandle(b.GetHicon());

Extra Credit (10 points)

Display Forecast Using GDI+ (8 points)

Instead of using labels or text boxes or other form controls to display the forecast, use the Graphics class to make the presentation more interesting. You are free to be creative and display the forecast in a more appealing way than just plain text. For example, you may want to use different colors for each day depending on what the temperature is (for example, "red-er" colors for warmer temperatures and "blue-er" colors for colder temperatures).

Recall that the Graphics class has a method DrawString for drawing string data. Also explore the Graphics class for other ways to make the forecast display more interesting.

Option to Display Temperatures in Celsius (2 points)

Allow the user to choose the units to display, Fahrenheit or Celsius. This choice should also be saved in the settings file.

Sample

Here is a sample weather tracker. This sample is not feature-complete but does provide a general idea of how your application should behave. Yours must, of course, implement the specification as described, but you have the freedom to design the interface in a way that you think will be useful to the user.