Examining the Calculator in Windows 7 (Part 2)

A while back, over two years ago in fact, I uploaded a post entitled, “Examining the Calculator in Windows 7.” Since that time, a number of people have asked about the other features that the new calculator includes. Yes, there are these rather significant problems that Microsoft has introduced, but there are some good things about the new calculator as well.

The good thing appears on the View menu. When you click this menu, you see options at the bottom of the list that provide access to the special features as shown here.

The View menu includes options for unit conversion, date conversion, and worksheets.
The Windows 7 Calculator View Menu

The Unit Conversion and Date Conversion options are the most useful. However, the worksheets can prove helpful when you need them. Of the new features, I personally use Unit Conversion the most and many people likely will. After all, it’s not often you need to figure out a new mortgage, vehicle lease amount, or the fuel economy of your vehicle (and if you do such work for a living, you’ll have something better than the Windows Calculator to use). To see what this option provides, click Unit Conversion. You see a new interface like the one shown here:

The Unit Conversion display makes it possible to convert from one unit of measure to another.
Calculator Unit Conversion Display

You start using this feature by selecting the type of unit you want to convert. As you can see from this list, the kinds of conversions you can perform are extensive:

Select a conversion type to determine what options are offered in the From and To fields.
The Calculator Supports a Healthy List of Conversion Types

The option you select determines the content of the From and To fields. For example, if you want to convert from kilometers to miles, you select the Length option. After you select the type of unit, type a value in the From field and select the From field unit of measure. Select the To field unit of measure last. Here is what happens when you convert 15 kilometers to miles:

The output shows that converting 15 kilometers to miles equals 9.32056788356001 miles.
Converting Kilometers to Miles

I’ve found use for most of the entries in the types list at one time or another. Every one of them works quite well and you’ll be happy they’re available when you need them. The Data Calculation option can be similarly useful if you work with dates relatively often, as I do. However, I can’t see many people needing to figure out the number of days between two dates on a regular basic. Even so, this feature is probably used more often than any of the worksheets.

The ability to perform conversions of various kinds and to access the worksheets that Windows 7 Calculator provides isn’t enough to change my opinion. The implementation of the Calculator is extremely flawed and I stick by my review in the first posting. However, you do have the right to know there are some positives, which is the point of this post. Let me know your thoughts about Calculator now that you have a better view of it at John@JohnMuellerBooks.com.

 

Some Interesting Windows 8 Information

I constantly track information for my books because I like to keep readers informed about changes when I can. Even though Windows 8 for Dummies Quick Reference appeared in print not long ago, there have been some interesting developments about the operating system it supports. Of course, the least newsworthy development has been the relatively slow adoption of the new operating system. A number of industry pundits are saying that Windows 8 is another Vista, or possibly worse. Statistics have never impressed me very much. Windows 8 will either succeed or it won’t, but it really is too early to tell.

The most interesting piece of information is that people aren’t actually using the much touted Windows 8 touch interface. People are actually buying the least expensive laptops possible to run Windows 8—devices that lack any sort of touch capability. This bit of information has taken me by surprise because Windows 8 really does appear to need a touch interface to work correctly. That said, Windows 8 for Dummies Quick Reference does include a considerable array of keyboard and mouse techniques because I had expected desktop users who upgraded to become completely lost without this information. It may turn out that the additional information helps a lot more than current desktop users based on what the press is saying.

It also appears that you may have an interesting time downgrading your Windows 8 installation to Windows 7, even though Microsoft tells you that you’re legally able to do so. The problem seems to be one of finding the copy of Windows 7 to use for the downgrade. The vendor who supplies the copy of Windows 8 with a system is supposed to provide the copy of Windows 7 to you, but the real world reality is that the vendor often doesn’t do so. The other problem is one of licensing. Microsoft constantly changes its licensing and uses terminology that even a lawyer can’t understand (much less us mere mortals). Trying to figure out whether you’re actually able to downgrade your copy of Windows 8 to Windows 7 can prove daunting. Microsoft has recently provided a clearer set of rules as part of a downloadable whitepaper that you can use to determine your rights.

I’d love to hear about your experiences using Windows 8. In addition, it would be useful to hear from people who have downgraded their copy to Windows 7 and why they made the change. Tell me about the Windows 8 coverage in my book and whether you need additional help with Windows 8 to make the book useful at John@JohnMuellerBooks.com. Windows 8 has truly turned into a surprising update; one that may require some additional posts to my blogs to provide good book support.

 

Retiring Windows XP

A number of readers have written me recently to ask about Windows XP and its impending retirement. The same questions occurred when Microsoft decided to retire Windows 98 and many of the same conditions remain true. Whether you have a good personal reason to switch or not depends on what you’re doing with your computers. I imagine a lot of people are still running Windows XP because it continues to meet their needs. After all, one of the older versions of Office probably works fine for most home users (truth be told, I don’t use the vast majority of the new features in Office myself). Your games will continue to run, just as they always have. If the system is meeting your personal needs, there probably isn’t a good reason to upgrade it from a personal perspective.

That said, mainstream support for Windows XP ended April 14, 2009 and extended support will end on April 8, 2014. From a management perspective, Windows XP is becoming a liability in some situations. You’re already not getting any sort of bug updates for Windows XP.  When extended (paid) support ends, you won’t get any security fixes either. That could be a problem if your systems are attached to the Internet and someone finds a way to exploit the security problems in Windows XP (and believe me, they will). Let’s just say you want to have a newer OS in place before the support situation gets too bad if you’re planning to remain connected to the Internet.

Nothing says that you ever have to upgrade if you don’t want to. I still run a copy of Windows 98 for some older applications I have and love. That system has no connections to anything else—it’s a standalone system and there is no chance whatsoever of contamination from it. I don’t care about upgrades because I’m not running any new software on it. Basically, it’s a working museum piece. So, if you’re willing to use these older operating systems in a safe environment—go for it, but I wouldn’t recommend continuing to use Windows XP for much longer on a system connected to the Internet—time for an upgrade.

The other problem you’ll eventually encounter is hardware-related. I currently have three machine’s worth of spare parts for my Windows 98 museum piece. As long as I have spare parts, I can continue running that system and enjoying my old software on it, but there is going to come a time when the spares run out. At that point, using a new part in the old system doesn’t make sense. For one thing, the new part may not run at all because I won’t have drivers for it. In fact, the old motherboard may not even provide connectors for it. So, you may eventually have a need to upgrade your system simply because you no longer have working parts for the old one.

After I share my views on Windows XP, the next question that readers are asking is which operating system I recommend as an upgrade. My personal preference now is Windows 7 because it seems to be stable and offers improved security over Windows XP, without some of the issues presented by Windows Vista. I haven’t worked enough yet with Windows 8 to recommend it, but I feel that the new Metro Interface is likely to cause problems for people who have worked with Windows XP for a long time. The Windows 7 interface changes will be enough of a shock.

For me, the bottom line is that you’ll have to retire Windows XP eventually. Whether you retire it now or wait until later is up to you, but eventually you won’t have the hardware required to make the operating system perform well anymore. I ran into this problem at one point with Windows 3.1 and had to stop supporting any books that relied on that operating system. (As an interesting side note, I do maintain a DOS system and haven’t encountered any hardware so far that won’t run the ancient operating system.) I imagine that my Windows 98 museum piece will eventually fail too, never to rise again. If you truly enjoy using Windows XP, you shouldn’t let Microsoft dictate an upgrade to you. Then again, you have to consider the risks and eventual loss of ability to run the operating system. Let me know your thoughts about running museum piece systems at John@JohnMuellerBooks.com.

 

Examining Paint in Windows 7

By now you’ve had time to examine my post, “Examining the Calculator in Windows 7,” which shows some of the bad design decisions Microsoft has made in updating a simple application. It seems that Calculator isn’t the only victim of poor design in Windows 7. My colleague, Rod Stephens, examines how the same fate has affected Windows Paint in his post, “The ribbon interface: sacrificing usability for discoverability.” His take on things is a bit different from mine and it makes for exceptionally good reading. The bottom line in both cases is that Microsoft has taken relatively well-designed applications and made them harder to use for reasons only Microsoft can fathom.

As mentioned in my post, this isn’t about Microsoft bashing. In fact, Rod and I have both been staunch Microsoft supporters over the years. What these posts are about is pointing out that any company, even Microsoft, can make some bad design decisions and that the costs of these decisions are high. It’s incredibly important that you design applications with user needs in mind—not merely to meet some marketing need or follow the latest fashion trends. Both of us strive to provide good design information in our respective books. Of course, it’s always possible to provide better information. Always feel free to let me know your feelings about the application design information in my books by writing me at John@JohnMuellerBooks.com.

 

Examining the Calculator in Windows 7

Almost every book I write on programming has some element of application design in it. If you don’t create applications with a great design, users are less likely to use them. I examine general design issues in C# Design and Development. However, books like C++ All-In-One Desk Reference For Dummies, LINQ for Dummies, Professional IronPython, Start Here! Learn Microsoft Visual C# 2010 Programming, and Web Matrix Developer’s Guide all have design elements in them because I feel application design is extremely important. Even RibbonX for Dummies and VBA for Dummies have design discussions in them because they both talk about user interfaces. The most specialized book I’ve created about application design is Accessibility for Everybody: Understanding the Section 508 Accessibility Requirements, which discusses user interface requirements for those with special needs. All of these books have one thing in common, they all try to quantify what makes for good user design. They all ask the question, “How can you as a developer write an application that users will enjoy using and use efficiently?” Unfortunately, examples of poor design abound and seem to be more common as time goes on, which is the point of this post.

The Calculator application in Windows 7 is a perfect example of an application that has gone the wrong direction when it comes to the user interface. Sure, the Standard view is the same in both cases as shown here.

Calculator02 Calculator01

The Windows 95 version of Calculator is on the left and the Windows 7 version is on the right. As you can see, the buttons are the same, but someone at Microsoft felt obliged to rearrange them, just to make things difficult for anyone used to using the old version of Calculator. There isn’t a good reason for the change except to change for change’s sake. The Windows 7 version does have larger numbers, but at the expense of providing room for larger calculations. Personally, I’d prefer the Windows 95 version because sometimes I do need to perform really large calculations. Both versions of Calculator offer features such as digit grouping, so there isn’t any change here either. In short, Windows 7 offers less capability in a rearranged format that makes it hard for people who are used to the old version of Calculator to use it—breaking the rules of good design.

The problems get worse, unfortunately. I never used the Standard view of Calculator because I need to perform programmer math and scientific calculations relatively often. Switching to Scientific view in the Windows 95 version of Calculator, you see the perfect interface as shown here.

Calculator03

During the time I worked with Windows 95, I never switched out of this view. All I did was start Calculator whenever I needed it and did the math that I needed to do. Never once did the view I was in enter my mind. That’s great design! Users shouldn’t have to think about how your application works—the user’s only thought should be how to get work done.

The Windows 7 version of Calculator now has four modes: Standard, Scientific, Programmer, and Statistics. Every time I use Calculator now, I must first figure out what I want to do and change the view appropriately—wasting time and effort in the process. The views unnecessarily limit my options. For example, look at the Programmer view.

Calculator04

I do gain access to the RoL (rotate left) and RoR (rotate right) buttons, but I can’t think of when I’ll need them. The modern languages that most developers use don’t actually require these buttons. If I were using assembler, they could see some use, but I don’t remember ever using rotate left or rotate right with C#, Visual Basic (any version), Python, or even C++. So, these buttons are extraneous and only serve to complicate the interface. In addition, I do gain a bit display, which could prove helpful at some point, but I found that the Bin view on the old version of Calculator worked just fine and served my needs well. However, notice that the decimal point button is disabled. The loss of this button means that every time I have to perform any sort of math with a decimal point, I have to switch to another view. Programmers do use floating point numbers! So, a capable programmer calculator has been replaced with something less useful—something that makes me irritable and work harder.

Now let’s switch to Scientific view. Remember, I used to be able to do everything in one view. If I want to raise a value to a power now as part of checking application output, I have to switch to the Scientific view shown here.

Calculator05

As usual, someone felt that it was absolutely required to move the buttons around so that it takes a while to relearn how to use this view. For the most part, I don’t use any of the new features provided by this view. The few times I needed to use this feature with the old Calculator required a switch to Standard view, but the switches were seldom indeed. The Scientific view does include a number of additional features, all of which are likely helpful to someone, but the cost is one of having to switch views when you need to do something else.

Before someone writes to tell me that the new calculator has square root, cubed root, and root to any power buttons, the Windows 95 Calculator has these features as well. You just had to know how to use a calculator to understand them. Let’s say you want to find the cubed root of 27 using the Windows 95 Calculator. Simply type 27, check Inv, and click the x^3 button. You’ll see the cubed root answer of 3. Not convinced? OK, let’s try a quad root. Type 16, check Inv, and click the x^y button. Now, type 4 (the quad root) and press the = button. You’ll see the quad root of 16 is 2, which is the correct answer. The Windows 7 calculator adds nothing new in this regard—just more buttons to hunt and peck!

In short, the new Calculator is an example of a failed interface update. Most people will find that they have to constantly switch between views to get anything done. When you force people to think too much about the interface, they tend to get grumpy, less productive, and end up tossing out the application at some point. Personally, every since  I found the Windows 95 version of Calculator runs just fine on my Windows 7 system, I’ve been using it instead of the broken product Microsoft has offered. The Windows 95 version truly is the superior application. Let me know your thoughts on Calculator and on application design in general at John@JohnMuellerBooks.com.

 

Improving the GrabAPicture Application (Part 4)

Last week’s post, Improving the GrabAPicture Application (Part 3), began the process of modifying the forms to accept the special wallpaper settings supported by Windows 7 and newer versions of the Windows operating system. That post also stressed the need to make the forms flexible enough to support older versions of the operating system. The forms actually detect which operating system is in use and modify their appearance to match the capability of the operating system. This week you’ll see the code used to make the new settings work properly. Of course, these two posts together support the second objective outlined in the Improving the GrabAPicture Application (Part 1) post.

Modifying WinWallpaper.vb

The underlying code is less critical when it comes to detecting the operating system because the form already performs this task. The user can’t select an option that doesn’t work with the selected operating system if the forms don’t make that option available. Consequently, a lot of the changes in this example are straightforward. The first change is to extend the Styles enumeration initially discussed in the Exploring the GrabAPicture Application (Part 5) post as shown in the following code.

' A list of wallpaper display styles.
Public Enum Styles As Integer
   Tiled
   Centered
   Stretched
   Unknown
   Fit
   Fill
End Enum

Notice that I add the new options after Unknown to ensure that they don’t inadvertently affect any of the application code. Some developers might be tempted to add the options before Unknown, but this would be a mistake because you can’t be absolutely certain about potential side effects of doing so.

Now that you have the right enumerations available, it’s time to modify the code that relies on the enumerations. Before you can do anything though, you need to determine what values to provide for the  two new enumerations. Remember that in the Exploring the GrabAPicture Application (Part 7) post that the HKEY_CURRENT_USER\Control Panel\Desktop registry key WallpaperStyle value contains the information you need. When you set the desktop to use the Fit style, this value becomes 6 as shown here.

GrabAPictureUpdate0401

Setting the desktop wallpaper to Fill changes this value to 10. Consequently, the first change you need to make is to the Style() property (discussed in the Exploring the GrabAPicture Application (Part 7) post) as shown here.

Public Property Style() As Styles
   Get
      ' Contains the registry key that holds the
      ' desktop values.
      Dim StyleKey As RegistryKey
 
      ' Get the desktop key.
      StyleKey = _
         Registry.CurrentUser.OpenSubKey( _
            "Control Panel\Desktop", False)
 
      ' Obtain the current value.
      If StyleKey.GetValue("WallpaperStyle") = 2 And _
         StyleKey.GetValue("TileWallpaper") = 0 Then
         Return Styles.Stretched
      End If
      If StyleKey.GetValue("WallpaperStyle") = 1 And _
         StyleKey.GetValue("TileWallpaper") = 0 Then
         Return Styles.Centered
      End If
      If StyleKey.GetValue("WallpaperStyle") = 1 And _
         StyleKey.GetValue("TileWallpaper") = 1 Then
         Return Styles.Tiled
      End If
 
      ' Windows 7 and above-specific values.
      If StyleKey.GetValue("WallpaperStyle") = 6 And _
         StyleKey.GetValue("TileWallpaper") = 0 Then
         Return Styles.Fit
      End If
      If StyleKey.GetValue("WallpaperStyle") = 10 And _
         StyleKey.GetValue("TileWallpaper") = 0 Then
         Return Styles.Fill
      End If
 
      ' This value should only show up if someone has
      ' tampered with the registry and set the values
      ' incorrectly.
      Return Styles.Unknown
   End Get
   Set(ByVal Value As Styles)
      ' Because Styles.Unknown signifies an error
      ' condition, the developer can't provide it as an
      ' input value.
      If Value = Styles.Unknown Then
         Throw New ArgumentException( _
            "Cannot use Styles.Unknown as an input argument")
      End If
 
      ' Contains the registry key that holds the
      ' desktop values.
      Dim StyleKey As RegistryKey
 
      ' Get the desktop key.
      StyleKey = _
         Registry.CurrentUser.OpenSubKey( _
            "Control Panel\Desktop", True)
 
      ' Select one of the other input values and set the
      ' registry keys as needed.
      Select Case Value
         Case Styles.Stretched
            StyleKey.SetValue("WallpaperStyle", "2")
            StyleKey.SetValue("TileWallpaper", "0")
         Case Styles.Centered
            StyleKey.SetValue("WallpaperStyle", "1")
            StyleKey.SetValue("TileWallpaper", "0")
         Case Styles.Tiled
            StyleKey.SetValue("WallpaperStyle", "1")
            StyleKey.SetValue("TileWallpaper", "1")
 
            ' Provide Windows 7 and above-specific values.
         Case Styles.Fit
            StyleKey.SetValue("WallpaperStyle", "6")
            StyleKey.SetValue("TileWallpaper", "0")
         Case Styles.Fill
            StyleKey.SetValue("WallpaperStyle", "10")
            StyleKey.SetValue("TileWallpaper", "0")
      End Select
   End Set
End Property

All of the required changes are marked with comments so you can find them easily. In all cases, it’s simply a matter of making the right registry changes. The behavior of the code remains unchanged.

During testing, I found that if the value of the WallpaperStyle registry setting is set to either 6 or 10 on a Windows XP system, Windows assumes you mean stretched (the option normally associated with a value of 2). Testing on a Vista system shows the same thing happens. I’ll be interested to hear from readers whether this is the case on their systems. If not, the example may very well need to include additional operating system-specific code for the Style() property.

Modifying the Command Line Interface

There is one place where things can get incredibly messy, and that’s with the command line interface. The Exploring the GrabAPicture Application (Part 9) post describes the command line interface in detail. In addition, you’ve already seen on update to this interface in the Improving the GrabAPicture Application (Part 2) post. In order to add the new Windows 7 functionality to the command line, you’ll need to perform another update of it that includes operating system version checking similar to the checking provided for the forms. For now, we’ll leave the command line interface alone and save this update for another time.

However, in order to keep the command line interface from working improperly, you do need to implement a few changes to the /Random command line switch code. This code ensures that the Windows 7 and above-specific settings are handled when working with random wallpaper selections as shown here:

If CmdArg.ToUpper() = "/RANDOM" Then
   ' Current application settings.
   Dim CurrentSettings As GrabAPictureSettings
 
   ' Number of settings to randomize.
   Dim Settings As Int32 = 0
 
   ' The selected image number.
   Dim Selection As Int32 = 0
 
   ' Contains the wallpaper location.
   Dim NewUri As Uri
 
   ' Wallpaper manipulation class.
   Dim Wallpaper As New WinWallpaper
 
   ' Initialize the stored settings.
   CurrentSettings = GrabAPictureSettings.LoadSettings()
 
   ' Verify that there are settings to use.
   If CurrentSettings Is Nothing Then
      MessageBox.Show( _
         "This application isn't configured to use random sources.")
      Return -1
   End If
 
   ' Obtain the number of settings to randomize.
   If CurrentSettings.LocalChecked And CurrentSettings.RemoteChecked Then
 
      ' Detect configuration errors.
      If CurrentSettings.LocalUris Is Nothing Or _
         CurrentSettings.RemoteUris Is Nothing Then
 
         MessageBox.Show("Application not set up to use " + _
                         "both local and remote locations.")
         Return -2
      End If
 
      ' Determine the number of settings.
      Settings = CurrentSettings.LocalUris.Length + _
         CurrentSettings.RemoteUris.Length - 1
 
      ' Randomize the settings.
      Randomize(DateTime.Now.Millisecond)
      Selection = Convert.ToInt32(Settings * Rnd())
 
      ' Obtain the style and location.
      If Selection < CurrentSettings.LocalUris.Length Then
 
         ' Choose the wallpaper style.
         Select Case CurrentSettings.LocalUris(Selection).Style
            Case WinWallpaper.Styles.Stretched
               Wallpaper.Style = WinWallpaper.Styles.Stretched
            Case WinWallpaper.Styles.Centered
               Wallpaper.Style = WinWallpaper.Styles.Centered
            Case WinWallpaper.Styles.Tiled
               Wallpaper.Style = WinWallpaper.Styles.Tiled
 
               ' Add the Windows 7 and above-specific options.
            Case WinWallpaper.Styles.Fit
               Wallpaper.Style = WinWallpaper.Styles.Fit
            Case WinWallpaper.Styles.Fill
               Wallpaper.Style = WinWallpaper.Styles.Fill
         End Select
 
         ' Create a wallpaper URI.
         NewUri = New Uri(CurrentSettings.LocalUris(Selection).Location)
      Else
         ' Subtract the local resources.
         Selection -= CurrentSettings.LocalUris.Length
 
         ' Choose the wallpaper style.
         Select Case CurrentSettings.RemoteUris(Selection).Style
            Case WinWallpaper.Styles.Stretched
               Wallpaper.Style = WinWallpaper.Styles.Stretched
            Case WinWallpaper.Styles.Centered
               Wallpaper.Style = WinWallpaper.Styles.Centered
            Case WinWallpaper.Styles.Tiled
               Wallpaper.Style = WinWallpaper.Styles.Tiled
 
               ' Add the Windows 7 and above-specific options.
            Case WinWallpaper.Styles.Fit
               Wallpaper.Style = WinWallpaper.Styles.Fit
            Case WinWallpaper.Styles.Fill
               Wallpaper.Style = WinWallpaper.Styles.Fill
         End Select
 
         ' Create a wallpaper URI.
         NewUri = New Uri(CurrentSettings.RemoteUris(Selection).Location)
      End If
 
      ' Set the wallpaper location.
      Wallpaper.WallpaperURI = NewUri
 
   ElseIf CurrentSettings.LocalChecked Then
 
      ' Detect configuration errors.
      If CurrentSettings.LocalUris Is Nothing Then
         MessageBox.Show("Application not set up " + _
                         "to use local locations.")
         Return -2
      End If
 
      ' Determine the number of settings.
      Settings = CurrentSettings.LocalUris.Length - 1
 
      ' Randomize the settings.
      Randomize(DateTime.Now.Millisecond)
      Selection = Convert.ToInt32(Settings * Rnd())
 
      ' Obtain the style and location.
      ' Choose the wallpaper style.
      Select Case CurrentSettings.LocalUris(Selection).Style
         Case WinWallpaper.Styles.Stretched
            Wallpaper.Style = WinWallpaper.Styles.Stretched
         Case WinWallpaper.Styles.Centered
            Wallpaper.Style = WinWallpaper.Styles.Centered
         Case WinWallpaper.Styles.Tiled
            Wallpaper.Style = WinWallpaper.Styles.Tiled
 
            ' Add the Windows 7 and above-specific options.
         Case WinWallpaper.Styles.Fit
            Wallpaper.Style = WinWallpaper.Styles.Fit
         Case WinWallpaper.Styles.Fill
            Wallpaper.Style = WinWallpaper.Styles.Fill
      End Select
 
      ' Create a wallpaper URI.
      NewUri = New Uri(CurrentSettings.LocalUris(Selection).Location)
 
      ' Set the wallpaper location.
      Wallpaper.WallpaperURI = NewUri
 
   ElseIf CurrentSettings.RemoteChecked Then
 
      ' Detect configuration errors.
      If CurrentSettings.RemoteUris Is Nothing Then
         MessageBox.Show("Application not set up " + _
                         "to use remote locations.")
         Return -2
      End If
 
      ' Determine the number of settings.
      Settings = CurrentSettings.RemoteUris.Length - 1
 
      ' Randomize the settings.
      Randomize(DateTime.Now.Millisecond)
      Selection = Convert.ToInt32(Settings * Rnd())
 
      ' Obtain the style and location.
      ' Choose the wallpaper style.
      Select Case CurrentSettings.RemoteUris(Selection).Style
         Case WinWallpaper.Styles.Stretched
            Wallpaper.Style = WinWallpaper.Styles.Stretched
         Case WinWallpaper.Styles.Centered
            Wallpaper.Style = WinWallpaper.Styles.Centered
         Case WinWallpaper.Styles.Tiled
            Wallpaper.Style = WinWallpaper.Styles.Tiled
 
            ' Add the Windows 7 and above-specific options.
         Case WinWallpaper.Styles.Fit
            Wallpaper.Style = WinWallpaper.Styles.Fit
         Case WinWallpaper.Styles.Fill
            Wallpaper.Style = WinWallpaper.Styles.Fill
      End Select
 
      ' Create a wallpaper URI.
      NewUri = New Uri(CurrentSettings.RemoteUris(Selection).Location)
 
      ' Set the wallpaper location.
      Wallpaper.WallpaperURI = NewUri
 
   Else
      MessageBox.Show("None of the random settings are selected.")
   End If
   Return 0
End If

All of the Windows 7 additions are marked with comments. The code simply ensures that the stored settings are handled appropriately. There isn’t any change in command line syntax or behavior with these changes.

Modifying frmMain

The majority of the changes for this update appear in frmMain. The only way to accomplish the task is to go through the code one step at a time. The first change appears in frmMain_Load(), which was originally discussed in Exploring the GrabAPicture Application (Part 10). The Select statement needs to be updated to ensure that the form loads with the controls configured correctly as shown here.

' Get the current wallpaper style.
Select Case Wallpaper.Style
   Case WinWallpaper.Styles.Stretched
      rbStretched.Checked = True
      rbCentered.Checked = False
      rbTiled.Checked = False
      rbFit.Checked = False
      rbFill.Checked = False
   Case WinWallpaper.Styles.Centered
      rbStretched.Checked = False
      rbCentered.Checked = True
      rbTiled.Checked = False
      rbFit.Checked = False
      rbFill.Checked = False
   Case WinWallpaper.Styles.Tiled
      rbStretched.Checked = False
      rbCentered.Checked = False
      rbTiled.Checked = True
      rbFit.Checked = False
      rbFill.Checked = False
   Case WinWallpaper.Styles.Fit
      rbStretched.Checked = False
      rbCentered.Checked = False
      rbTiled.Checked = False
      rbFit.Checked = True
      rbFill.Checked = False
   Case WinWallpaper.Styles.Fill
      rbStretched.Checked = False
      rbCentered.Checked = False
      rbTiled.Checked = False
      rbFit.Checked = False
      rbFill.Checked = True
End Select

You must also add event handlers for the Fit and Fill radio buttons on frmMain. These event handlers as similar to those discussed for the other radio buttons as shown here.

Private Sub rbFit_CheckedChanged(sender As System.Object, _
                                 e As System.EventArgs) _
                              Handles rbFit.CheckedChanged
   Dim Wallpaper As New WinWallpaper
 
   ' Set the new style.
   Wallpaper.Style = WinWallpaper.Styles.Fit
End Sub
 
Private Sub rbFill_CheckedChanged(sender As System.Object, _
                                  e As System.EventArgs) _
                               Handles rbFill.CheckedChanged
   Dim Wallpaper As New WinWallpaper
 
   ' Set the new style.
   Wallpaper.Style = WinWallpaper.Styles.Fill
End Sub

Modifying frmConfigure

The two Select buttons on frmConfigure (discussed in the Exploring the GrabAPicture Application (Part 11) post) require modification to work with the new options. When a user clicks Select, the code configures the Desktop with the newly selected wallpaper. The updates merely make it possible for the configured sources to contain the new fit and fill options. The code for the local resources version of the Select button appears here.

Private Sub btnLSelect_Click(ByVal sender As System.Object, _
                             ByVal e As System.EventArgs) _
                          Handles btnLSelect.Click
   ' Wallpaper manipulation class.
   Dim Wallpaper As New WinWallpaper
 
   ' Choose the wallpaper style.
   Select Case CurrentSettings.LocalUris(lstLocal.SelectedIndex).Style
      Case WinWallpaper.Styles.Stretched
         Wallpaper.Style = WinWallpaper.Styles.Stretched
      Case WinWallpaper.Styles.Centered
         Wallpaper.Style = WinWallpaper.Styles.Centered
      Case WinWallpaper.Styles.Tiled
         Wallpaper.Style = WinWallpaper.Styles.Tiled
 
         ' Add the Windows 7 and above-specific Styles.
      Case WinWallpaper.Styles.Fit
         Wallpaper.Style = WinWallpaper.Styles.Fit
      Case WinWallpaper.Styles.Fill
         Wallpaper.Style = WinWallpaper.Styles.Fill
   End Select
 
   ' Create a wallpaper URI.
   Dim NewUri As New Uri( _
      CurrentSettings.LocalUris(lstLocal.SelectedIndex).Location)
 
   ' Set the wallpaper location.
   Wallpaper.WallpaperURI = NewUri
End Sub

The remote version of the Select button code appears here.

Private Sub btnSelect_Click(ByVal sender As System.Object, _
                            ByVal e As System.EventArgs) _
                         Handles btnSelect.Click
   ' Wallpaper manipulation class.
   Dim Wallpaper As New WinWallpaper
 
   ' Choose the wallpaper style.
   Select Case CurrentSettings.RemoteUris(lstRemote.SelectedIndex).Style
      Case WinWallpaper.Styles.Stretched
         Wallpaper.Style = WinWallpaper.Styles.Stretched
      Case WinWallpaper.Styles.Centered
         Wallpaper.Style = WinWallpaper.Styles.Centered
      Case WinWallpaper.Styles.Tiled
         Wallpaper.Style = WinWallpaper.Styles.Tiled
 
         ' Add the Windows 7 and above-specific Styles.
      Case WinWallpaper.Styles.Fit
         Wallpaper.Style = WinWallpaper.Styles.Fit
      Case WinWallpaper.Styles.Fill
         Wallpaper.Style = WinWallpaper.Styles.Fill
   End Select
 
   ' Create a wallpaper URI.
   Dim NewUri As New Uri( _
      CurrentSettings.RemoteUris(lstRemote.SelectedIndex).Location)
 
   ' Set the wallpaper location.
   Wallpaper.WallpaperURI = NewUri
End Sub

Modifying frmAddEdit

The final set of changes for this update is to frmAddEdit, which is discussed in the Exploring the GrabAPicture Application (Part 12) post. It’s important to remember that unlike frmMain, the radio buttons on this form don’t have any event handlers. The settings are handled in a different way in the code. The first set of changes appear in frmAddEdit_Load() to ensure that the form is configured correctly when the user opens it as shown here.

' Set the form up for editing.
If _IsEdit Then
   ' Make sure you use the correct database.
   If _IsRemote Then
      txtName.Text = _RemoteSources(_RecordNumber).Name
      txtLocation.Text = _RemoteSources(_RecordNumber).Location
      Select Case _RemoteSources(_RecordNumber).Style
         Case Styles.Stretched
            rbStretched.Checked = True
            rbCentered.Checked = False
            rbTiled.Checked = False
            rbFit.Checked = False
            rbFill.Checked = False
         Case Styles.Centered
            rbStretched.Checked = False
            rbCentered.Checked = True
            rbTiled.Checked = False
            rbFit.Checked = False
            rbFill.Checked = False
         Case Styles.Tiled
            rbStretched.Checked = False
            rbCentered.Checked = False
            rbTiled.Checked = True
            rbFit.Checked = False
            rbFill.Checked = False
         Case Styles.Fit
            rbStretched.Checked = False
            rbCentered.Checked = False
            rbTiled.Checked = False
            rbFit.Checked = True
            rbFill.Checked = False
         Case Styles.Fill
            rbStretched.Checked = False
            rbCentered.Checked = False
            rbTiled.Checked = False
            rbFit.Checked = False
            rbFill.Checked = True
      End Select
   Else
      txtName.Text = _Resources(_RecordNumber).Name
      txtLocation.Text = _Resources(_RecordNumber).Location
      Select Case _Resources(_RecordNumber).Style
         Case Styles.Stretched
            rbStretched.Checked = True
            rbCentered.Checked = False
            rbTiled.Checked = False
            rbFit.Checked = False
            rbFill.Checked = False
         Case Styles.Centered
            rbStretched.Checked = False
            rbCentered.Checked = True
            rbTiled.Checked = False
            rbFit.Checked = False
            rbFill.Checked = False
         Case Styles.Tiled
            rbStretched.Checked = False
            rbCentered.Checked = False
            rbTiled.Checked = True
            rbFit.Checked = False
            rbFill.Checked = False
         Case Styles.Fit
            rbStretched.Checked = False
            rbCentered.Checked = False
            rbTiled.Checked = False
            rbFit.Checked = True
            rbFill.Checked = False
         Case Styles.Fill
            rbStretched.Checked = False
            rbCentered.Checked = False
            rbTiled.Checked = False
            rbFit.Checked = False
            rbFill.Checked = True
      End Select
   End If
End If

The second set of changes occurs in the btnAddEdit_Click() event handler, which determines what happens to the user selections when the user closes the form (no matter what the button caption might say at the time). Here are the changes for this event handler.

Private Sub btnAddEdit_Click(ByVal sender As System.Object, _
                             ByVal e As System.EventArgs) _
                          Handles btnAddEdit.Click
   If IsEdit Then
      If _IsRemote Then
         ' Change the array data.
         _RemoteSources(_RecordNumber).Name = txtName.Text
         _RemoteSources(_RecordNumber).Location = txtLocation.Text
         If rbStretched.Checked Then
            _RemoteSources(_RecordNumber).Style = Styles.Stretched
         End If
         If rbCentered.Checked Then
            _RemoteSources(_RecordNumber).Style = Styles.Centered
         End If
         If rbTiled.Checked Then
            _RemoteSources(_RecordNumber).Style = Styles.Tiled
         End If
 
         ' Add the Windows 7 and above-specific options.
         If rbFit.Checked Then
            _RemoteSources(_RecordNumber).Style = Styles.Fit
         End If
         If rbFill.Checked Then
            _RemoteSources(_RecordNumber).Style = Styles.Fill
         End If
      Else
         ' Change the array data.
         _Resources(_RecordNumber).Name = txtName.Text
         _Resources(_RecordNumber).Location = txtLocation.Text
         If rbStretched.Checked Then
            _Resources(_RecordNumber).Style = Styles.Stretched
         End If
         If rbCentered.Checked Then
            _Resources(_RecordNumber).Style = Styles.Centered
         End If
         If rbTiled.Checked Then
            _Resources(_RecordNumber).Style = Styles.Tiled
         End If
 
         ' Add the Windows 7 and above-specific options.
         If rbFit.Checked Then
            _Resources(_RecordNumber).Style = Styles.Fit
         End If
         If rbFill.Checked Then
            _Resources(_RecordNumber).Style = Styles.Fill
         End If
      End If
   Else
      If _IsRemote Then
         ' Add a new array element.
         If _RemoteSources Is Nothing Then
            ReDim _RemoteSources(0)
         Else
            ReDim Preserve _RemoteSources(_RemoteSources.Length)
         End If
 
         ' Instantiate a new array item.
         _RemoteSources(_RemoteSources.Length - 1) = New RemoteUri
 
         ' Add the data to the array.
         _RemoteSources(_RemoteSources.Length - 1).Name = txtName.Text
         _RemoteSources(_RemoteSources.Length - 1).Location = txtLocation.Text
         If rbStretched.Checked Then
            _RemoteSources(_RemoteSources.Length - 1).Style = Styles.Stretched
         End If
         If rbCentered.Checked Then
            _RemoteSources(_RemoteSources.Length - 1).Style = Styles.Centered
         End If
         If rbTiled.Checked Then
            _RemoteSources(_RemoteSources.Length - 1).Style = Styles.Tiled
         End If
 
         ' Add the Windows 7 and above-specific options.
         If rbFit.Checked Then
            _RemoteSources(_RemoteSources.Length - 1).Style = Styles.Fit
         End If
         If rbFill.Checked Then
            _RemoteSources(_RemoteSources.Length - 1).Style = Styles.Fill
         End If
      Else
         ' Add a new array element.
         If _Resources Is Nothing Then
            ReDim _Resources(0)
         Else
            ReDim Preserve _Resources(_Resources.Length)
         End If
 
         ' Instantiate a new array item.
         _Resources(_Resources.Length - 1) = New LocalUri
 
         ' Add the data to the array.
         _Resources(_Resources.Length - 1).Name = txtName.Text
         _Resources(_Resources.Length - 1).Location = txtLocation.Text
         If rbStretched.Checked Then
            _Resources(_Resources.Length - 1).Style = Styles.Stretched
         End If
         If rbCentered.Checked Then
            _Resources(_Resources.Length - 1).Style = Styles.Centered
         End If
         If rbTiled.Checked Then
            _Resources(_Resources.Length - 1).Style = Styles.Tiled
         End If
 
         ' Add the Windows 7 and above-specific options.
         If rbFit.Checked Then
            _Resources(_Resources.Length - 1).Style = Styles.Fit
         End If
         If rbFill.Checked Then
            _Resources(_Resources.Length - 1).Style = Styles.Fill
         End If
      End If
   End If
End Sub

As you can see, the new options work precisely the same as the existing ones. When the user adds or edits a local or remote wallpaper, the code makes the appropriate changes to the stored settings.

If you compile your application at this point, you’ll find that you can now work with the Fit and Fill wallpaper settings in Windows 7. These settings will also be available when you move your application to Windows 8. All of these code changes come down to one thing really. The new settings involve additions to the WallpaperStyle registry settings: 6 for Fit and 10 for Fill. Let me know if you have any questions about these changes at John@JohnMuellerBooks.com.

 

Improving the GrabAPicture Application (Part 3)

The second feature described in the in the Improving the GrabAPicture Application (Part 1) post is to make it possible to use the Windows 7 extended wallpaper settings. It might seem like a simple task at first, but remember that the GrabAPicture application must continue to work on older systems that don’t have the required settings. Consequently, this feature requires that you not only add the new functionality, but that you also make it possible to detect the operating system and act accordingly. When the user has Windows 7 installed, the GrabAPicture application needs to allow and react to two new settings (my book, Professional Windows 7 Development Guide, explains these and other Windows 7-specific features in greater detail):

 

  • Fit: The graphic is resized to fit within the confines of the display, without modifying its aspect ration (as stretch will do).
  • Fill: The graphic is resized to completely fill the confines of the display, even if this means chopping off part of the graphic, without modifying its aspect ratio.


Modifying frmMain

There are a number of techniques you can use to implement features that are operating system version specific. The best way is to customize the handling of the feature so that users who have older, less capable, versions of the operating system don’t even realize the feature exists, which is the approach taken with this example. The first step in accomplishing this goal is to modify the interface so that the extra options are added with Windows 7 and above, but not with older versions. The new frmMain interface looks like this:

GrabAPictureUpdate0301

In order to achieve this update, you perform these steps:

 

  1. Change the frmMain.Size property to 328, 317.
  2. Change the cbRemote.Location property to 8, 256.
  3. Change the cbLocal.Location property to 8, 224.
  4. Change the GroupBox1.Size property to 192, 148.
  5. Add a new RadioButton control with the following property values:
    • (Name) = rbFit
    • Location = 16, 96
    • Modifiers = Friend
    • Size = 104, 24
    • TabIndex = 9
    • Text = &Fit
  6. Add a new RadioButton control with the following property values:
    • (Name) = rbFill
    • Location = 16, 120
    • Modifiers = Friend
    • Size = 104, 24
    • TabIndex = 10
    • Text = Fi&ll
  7. Change the cbRemote.TabIndex property to 11.
  8. Change the cbLocal.TabIndex property to 12.


However, you still need to maintain the ability to use the old interface. This means making it possible to hide the two new controls and changing settings for four existing controls back to the old state when working with an older operation system. These four settings are:

 


  • frmMain.Size = 328, 269

  • GroupBox1.Size = 192,100

  • cbLocal.Location = 8, 176

  • cbRemote.Location = 8, 208

With this in mind, you must modify the frmMain_Load() method by adding some code to the beginning of the method. This code checks the operating system version and then makes changes as shown here to return the application appearance to its original condition (you originally saw this code in the Exploring the GrabAPicture Application (Part 10) post).

' Detect the operating system version.
Dim OS As OperatingSystem = Environment.OSVersion
 
' Check the operating system version and modify the interface
' as needed.
If OS.Version.Major < 6 Or OS.Version.Minor < 1 Then
 
   ' Disable the two wallpaper and make them invisible.
   rbFill.Enabled = False
   rbFill.Visible = False
   rbFit.Enabled = False
   rbFit.Visible = False
 
   ' Change the properites back to their old configuration.
   Me.Size = New Size(328, 269)
   GroupBox1.Size = New Size(192, 100)
   cbLocal.Location = New Point(8, 176)
   cbRemote.Location = New Point(8, 208)
End If

When GrabAPicture runs, it displays the appearance that best matches the host operating system. It’s important to disable the rbFill and rbFit controls so that the user can’t access them accidentally. In addition, you make them invisible so that the user can’t see them either. Notice that the If statement relies on an Or condition because either value could trigger the code. For example, Vista is version 6.0, so it would trigger the code because the Version.Minor value is 0.

Modifying frmAddEdit

The changes you make to frmMain also apply to frmAddEdit. However, this form is less complex, so the changes are less extensive. Follow this procedure to make the changes to the form.

  1. Change the frmAddEdit.Size property to 300, 316.
  2. Change the grpStyleSelect.Size property to 192, 148.
  3. Add a new RadioButton control with the following property values:
    • (Name) = rbFit
    • Location = 16, 96
    • Modifiers = Friend
    • Size = 104, 24
    • TabIndex = 3
    • Text = &Fit
  4. Add a new RadioButton control with the following property values:
    • (Name) = rbFill
    • Location = 16, 120
    • Modifiers = Friend
    • Size = 104, 24
    • TabIndex = 10
    • Text = Fi&ll

At this point, frmAddEdit should look like this:

GrabAPictureUpdate0302

You’ll need to add code to the frmAddEdit_Load() method to change the user interface back to it simpler form when the user has an older version of Windows. As before, add the following code to the beginning of the method (you originally saw this code in the Exploring the GrabAPicture Application (Part 12) post).

' Detect the operating system version.
Dim OS As OperatingSystem = Environment.OSVersion
 
' Check the operating system version and modify the interface
' as needed.
If OS.Version.Major < 6 Or OS.Version.Minor < 1 Then
 
   ' Disable the two wallpaper and make them invisible.
   rbFill.Enabled = False
   rbFill.Visible = False
   rbFit.Enabled = False
   rbFit.Visible = False
 
   ' Change the properites back to their old configuration.
   Me.Size = New Size(300, 266)
   grpStyleSelect.Size = New Size(192, 100)
End If

As before, the code checks the OS version and makes a decision about whether it can use the new features. If not, the form is configured to allow for the older wallpaper setup.

This is a good stopping point for this week. Next week you’ll see how to finish this particular update. You’ll need to modify the underlying code to allow use of the new settings. However, there are a few surprises in this area—things you have to discover by looking at the registry. In the meantime, let me know if you have any questions about this part of the change at John@JohnMuellerBooks.com. You can see the next post in this series at Improving the GrabAPicture Application (Part 4).

 

Supporting Sensors in Windows 7

Windows 7 includes an amazing set of new features and I describe how to develop applications to use them in my book Professional Windows 7 Development Guide. One of the most amazing new features is the ability to work with sensors of all kinds within your application. In fact, I found this particular technology so compelling that I used an entire chapter to discuss it. Chapter 18 tells you about various sensor types and how to use them in your application, including:

 

  • Biometric (such as fingerprint and retina readers)
  • Electrical (devices that output some sort of electrical current that don’t fit in another category)
  • Environmental (devices that measure environmental conditions such as temperature and humidity)
  • Light (a device used to measure either the amount of light or a specific kind of light)
  • Location (usually refers to GPS devices, but Windows 7 supports other types)
  • Mechanical (defines a mechanical measurement, such as how far a door is open)
  • Motion (detects any sort of motion)
  • Orientation (measures angular rotation around the center of a mass in one of three axis: yaw, pitch, and roll)
  • Scanner (any device that contains a CCD and is used to capture an image, such as a camera or scanner)


Sensors are created from either hardware (with a driver) or software. The software sensors include a special software sensor, Geosense for Windows. The builder of this software sensor, Rafael Rivera, was kind enough to spend several hours with me online explaining precisely how sensors work in general and this sensor in particular. Geosense for Windows is a great way to discover Windows 7 sensors because you don’t need to buy anything special to experiment with it.

Rafael was also nice enough to provide a review of my book recently. You can find it on his Within Windows blog. If you have an interest in sensors or simply want to find out more about my book, please be sure to read Rafael’s review. Of course, I’m always available to answer your book-related questions at John@JohnMuellerBooks.com.