Windows 7 Taskbar Dynamic Overlay Icons and Progress Bars

We covered the basics of the Windows 7 Taskbar in Developing for the Windows 7 Taskbar – Application ID, and how you can create a Jump List for your application in Developing for the Windows 7 Taskbar – Jump into Jump Lists – Part 1, Part 2, and Part 3). In this post, we will explore how you can leverage the cool Taskbar functionality of dynamic overlay icons and multi-state progress bars.

A central Windows 7 tenet is that the "User Is in Control"; that is, we empower users to take ownership of their desktop looks and functionality. From little things, like allowing users to arrange their Taskbar icons as they see fit, to enabling users to control the number of icons on the Taskbar. Windows 7 “removed” the System Tray Icon area. By default, almost all the tray icons are concealed. Consequently, it is safe to assume that large number of the notification balloons will also not be visible and most users will not see them. You can read more about the updates to the Notification Area here. To compensate for this lack of notification, Windows 7 Taskbar offers Overlay Icons and Progress Bars. By using overlay icons and progress bars, your application can provide contextual status information to the user in spite of the lack of a System Tray Icon area and even if the application’s window does not display. The user doesn’t even have to look at the thumbnail or the live preview of your app – the Taskbar button itself can reveal whether you have any interesting status updates. This functionality is part of our commitment to provide users with easily accessible information about an application's status without any extra clicking.

Overlay Icons

The ITaskbarList4 interface, specifically its SetOverlayIcon function, exposes the native overlay functionality. The function takes a window handle, an icon handle, and optional description text, as you can see in the following code snippet.

HICON hIcon = NULL; // for IDM_OVERLAY_CLEAR
hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_OVERLAY1));
// Set the window's overlay icon, possibly NULL value
g_pTaskbarList->SetOverlayIcon(hWnd, hIcon, NULL);
if (hIcon) {
// need to clean up the icon as we no longer need it
DestroyIcon(hIcon);
}

Make sure you obtain ITaskbarList3 *g_pTaskbarList = NULL;as we did before, and CoCreate it:

CoCreateInstance(
CLSID_TaskbarList,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&g_pTaskbarList));
When running the above code in the proper context (you can download the application) the result looks like the following pictures. On the left, you see the application without any overlay icons, and on the right you can see the application with a red icon overlay.

image The managed wrapper for this feature resides in the Taskbar class that is part of the Windows API Code Pack for the .NET Framework. All that you need to do is use the OverlayImage property (Taskbar.OverlayImage). Simply call:

Taskbar.OverlayImage = 
new OverlayImage(TaskbarDemo.Properties.Resources.Red, "Red");

Doing so allows you to provide an OverlayImage for the taskbar button. The TaskbarDemo project is a WinForms demo, and you can find the above code in the TaskbarDemoMainForm.cs.

It’s equally easy to provide an extension method that does this to a WPF Window. Note that the only thing that you need to do is get the right icon, which is easy using .NET resources.

Progress Bars

If you already use a standard progress bar in your application’s top level window, the DMW will pick it up and, by default, display its progress as an overlay on top of your application. However, you can programmatically control the progress bar behavior on your application’s icon.

The native functionality is again found in the ITaskbarList3 interface, this time in the SetProgressState and SetProgressValue functions. The functions are quite self-explanatory. You can set the progress bar’s state (SetProgressState) to, for example, indeterminate or error, and use SetProgressValue to set the progress value. The following code snippet illustrates how to use these functions:

case WM_TIMER:
g_nProgress++;
if (g_nProgress == 1)
{
// First time through, so we'll set our progress state
// to be indeterminate - this simulates a background
// computation to figure out how much progress we'll need.
g_pTaskbarList->SetProgressState(hWnd, TBPF_INDETERMINATE);
}
else if (g_nProgress == MAX_PROGRESS_IND)
{
// Now set the progress state to indicate we have some
// normal progress to show.
g_pTaskbarList->SetProgressValue(hWnd, 0, MAX_PROGRESS_NORMAL);
g_pTaskbarList->SetProgressState(hWnd, TBPF_NORMAL);
}
else if (g_nProgress > MAX_PROGRESS_IND)
{
if (g_nProgress - MAX_PROGRESS_IND <= MAX_PROGRESS_NORMAL)
{
// Now show normal progress to simulate a background
// operation
g_pTaskbarList->SetProgressValue(
hWnd,
g_nProgress - MAX_PROGRESS_IND,
MAX_PROGRESS_NORMAL);
}
else
{
// Progress is done, stop the timer and reset progress
// state
KillTimer(hWnd, g_nTimerId);
g_nTimerId = 0;
g_pTaskbarList->SetProgressState(hWnd, TBPF_NOPROGRESS);
MessageBox(hWnd, L"Done!", L"Progress Complete", MB_OK);
}
}
break;

Note that on the first timer tick, we set the progress bar to TBPF_INDETERMINATE, and only after that did we set it to TBPF_NORMAL, which set the progress indicator to grow in size from left to right in proportion to the estimated amount of the operation completed.

For managed code, we use the Windows Code Pack API. Much like the native progress bar, the managed code Taskbar class includes a progress bar property (it is in its own a class), which allows you to set current value, max value, and statethe progress bar state. The progress bar states (found in the TaskbarButtonProgressState class) are:

  • NoProgress –equal to the TBPF_NOPROGRESS native state
  • Indeterminate –equal to the TBPF_INDETERMINATE native state
  • Normal –equal to the TBPF_NORMAL native state
  • Error –equal to the TBPF_ERROR native state
  • Paused –equal to the TBPF_PAUSED native state

You can find a WinForms demo in the TaskbarDemo project and in the TaskbarDemoMainForm.cs, you can find the UpdateProgressBar function that is called by a timer to update the progress bar.

Taskbar.ProgressBar.State = 
(TaskbarButtonProgressState)Enum.Parse(
typeof(TaskbarButtonProgressState),
(string)comboBoxProgressBarStates.SelectedItem);

if (Taskbar.ProgressBar.State != TaskbarButtonProgressState.Indeterminate)
Taskbar.ProgressBar.CurrentValue = progressBar1.Value;

As you can see, the code enables you to choose the state of the progress bar. Changing it to the error state turns the color of the progress bar on the Taskbar Icon to red.

The icing on the Taskbar progress bar "cake" is that you get this functionality FOR FREE if you use the standard progress dialog for file operations. (As we advance in this series, you’ll see that you get lots of functionality for free if you follow the standard guidelines of Windows programming.) For example, if you invoke a file operation using the SHFileOperation API or IFileOperation interface, the Taskbar button progress bar automatically displays the progress information (including errors) of that operation. This is what Windows Explorer does with great success.

Original post from Sasha Goldstein



Is Your Application Ready for Windows 7 RTM?

Yesterday Windows 7 completed a major milestone--release to manufacturing (RTM)! And in three months time – on October 22nd – Windows 7 will be available for everyone to enjoy. Excitement about the upcoming public release of Windows 7 has been growing for months and expectations are for a much quicker adoption rate than what we saw with the previous Windows version.

As we approach October 22nd you need to ask yourself: Is your application ready for Windows 7? What will happen when end users install your application on Windows 7? Will your application run? Will your application behave like a Windows 7 first class citizen? Will users see any difference when running applications on Windows 7 versus Windows Vista or XP? October 22nd is just around the corner and we are here to help you answer, “YES!” to these questions and be able to state with confidence that, “Absolutely, my application rocks on Windows 7.” We want to help your users get the best possible Windows 7 experience from your application starting on Day 1.

All this sounds great, but what steps do you need to take in order to be able to say: “Yes my application is a first-class Windows citizen”? Is there a check list? You bet!

You need to do three things to ensure a smooth transition:

  1. Make sure your application is Windows 7 compatible
  2. Optimize your application experience and performance for Windows 7
  3. Provide new and exciting user experiences with Windows 7 

    Make sure your application is Windows 7 compatible

    Before considering using any new Windows 7 features, make sure your application is compatible with Windows 7. There is no escape from this; it is essential that you make sure that your application runs well on Windows 7. There is nothing worse for an end user than to be excited about the new Windows 7 operating system just to discover that a favorite application doesn’t perform properly. A bad user experience hurts everyone--which is why you have to make sure your application installs and runs on all Windows 7 versions (including E - Windows 7 E Best Practices for ISVs) and supports both 32- and 64-bit versions.

    If your application is compatible with Windows Vista you are in a good shape! We expect most applications that run on Windows Vista to run on Windows 7. Obviously, you can’t take this for granted and must check (and double check) that your application truly is compatible with Windows 7. There are a few differences between Windows Vista and Windows 7 that can affect specific application functions, so if you haven’t checked the Windows 7 Quality Cookbook lately, we highly recommend that you do so.

    If your application was designed for Windows XP (or earlier Windows versions), and you haven't confirmed its compatibility with Windows Vista, there are a few areas (for example, UAC), that you should especially note. It is important to keep in mind that there is no one silver bullet for application compatibility issues. Each application comes with its own set of issues that are dependent on specific implementation details. The Windows Vista Application Compatibility Cookbook is still very relevant for Windows 7, as 99% of its topics apply to Windows 7. With that said, a few topics rise above the others. The following seven areas represent about a large number of the reported application compatibility problems.

    • Version Checking – by far the top application compatibility problem. Ever get a message from an application saying, “Requires Windows XP or higher” when you are running on Windows 7? If so, you hit a version checking issue. You can read more about this topic - Application Compatibility: Operating System Versioning
    • Data Redirection – beginning with Windows Vista, standard users have restricted access to certain files, folders, and registry keys. When an application is trying to write to these locations, it gets redirected to somewhere else. Most of the time this is transparent to both users and application developers, but sometimes it is not and that lead to some very interesting results. You can read about this topic - Common file and registry virtualization issues in Windows Vista
    • IE Protected Mode – starting with Windows Vista, by default IE runs with lower privileges. This usually means that some ActiveX controls that work on Windows XP don’t work on Windows Vista and Windows 7. Need more information, you can read Protected Mode in Vista IE7 (and yes this is still applicable for IE8.)
    • Session 0 Isolation - in Windows Vista, services run in their own session (session 0) and not in the user session(s) (session 1 and above). This security boundary protects the system from many vicious attack vectors and is absolutely necessary. However, it also introduces communication problems between services and application like blocking your messages! You can read more about this topic -  Modifying the Mandatory Integrity Level for a Securable Object in Windows Vista
    • Installer Detection – starting with Windows Vista, the OS automatically tries to detect if a given application is an installer application, which usually means that the application requires elevation to administrator privileges. However, sometimes these heuristics can cause problems. Interested in additional information, read about The Windows Vista and Windows Server® 2008 Developer Story
    • User Interface Privilege Isolation – this prevents an application (process) from sending messages to another process with higher privileges even if running under the same user's account. While this protects from shatter attacks, it can also break some applications.
    • High DPI –during install, Windows 7 automatically detects whether your screen supports High DPI. If it does, Windows 7 automatically sets the screen resolution to High DPI. If your application is not High DPI aware, this may cause some display issues (like text clipping). Read more about Ensuring your application displays properly on High-DPI Displays

    In the following weeks, we will address in detail each of the above topics to help you get ready for Windows 7.

    Optimize your application experience and performance for Windows 7

    After verifying that your application can install and run on Windows 7 without any problems, it is time to step up and optimize your application’s user experiences and performance while running on Windows 7. Do this by taking advantage of the great new features offered with Windows 7. These include new user interface innovations like the Taskbar and Libraries, to more fundamental features like Trigger Start Services or the new Troubleshooting platform. By optimizing your application for Windows 7, you can make sure that your end user's experiences when running your application on Windows 7 surpasses their expectations. Users will expect applications to work properly with the Taskbar (just one example); but if your application is not optimized for the new Windows 7 Taskbar experience, end users might just notice that.

    When you're ready to optimize your application for Windows 7, you might consider using one or more of the following features:

    • Taskbar – The new Taskbar in Windows 7 provides more information to the user in more intuitive ways, with features like Jump Lists that helps users quickly “jump” into where they want to go. You can read more Developing for the Windows 7 Taskbar – Application ID.
    • Libraries Libraries are the primary entry points to user data in Windows 7. A Windows 7 Library is a user-defined collection of content that represents the user’s data independently from the folder hierarchy. Users can unify and flatten the folder hierarchy by aggregating any number of physical locations (on their local machine or on remote machines) into a single view – which is the library. You can read more - Windows 7 Programming Guide – Libraries.

    image 
    • Trigger Start Services – The Windows 7 Service Control Manager has been extended so that a service can be automatically started and stopped when a specific system event, or trigger, occurs on the system. Trigger-start capabilities remove the need for services to start up automatically at computer startup and then poll or wait for an event to occur, such as a device arrival. More about this topic – Service Trigger Events.
    • Power Optimization – Windows 7 provides the infrastructure and tools that make it easy for developers to determine the energy impact of their applications. A set of event callbacks enable applications to reduce their activity when the system is on battery power and automatically scale up when the system is on AC power.
    • Troubleshooting Platform – Windows 7 delivers a comprehensive and extensible Troubleshooting Platform that uses a PowerShell-based mechanism to troubleshoot and resolve problems. The Troubleshooting Platform seamlessly integrates with the Windows 7 PC Solution Center, enabling other applications to execute diagnostics in a similar manner as part of their PC management regimen. Read more about Windows Troubleshooting Platform.

    image

    • Windows Error Reporting - Windows Error Reporting (WER) is a set of Windows technologies that capture software crash data and support end-user reporting of crash information. Through Winqual services, software and hardware vendors can access reports in order to analyze and respond to these problems. This set of tools provides amazing real-time information about the quality of your software and can help facilitate software updates and patches. Get Started with Windows Error Reporting.
    • I/O Optimization – I/O prioritization improves the responsiveness of the system without significantly decreasing the throughput of the system. If you have any I/O-bound long services that you can run in the background, the user will be thankful. Non-I/O optimized applications tend to hug the I/O and put an extra burden on the system. If your application optimizes the I/O for non critical application services, it can dramatically improve the overall system behavior.
    • Restart Manager – This technology allows automatic post-crash restarts as well as application and operating system updates without rebooting the entire machine. When you implement this functionality, you get a second chance to save critical information if your application crashes. Windows will automatically restart your application and try to reload the information the user just used. This same technology facilitates updating most applications and the operating system without the need to reboot. If a reboot is needed, then Windows will make sure your application restarts and returns to its latest state

    Provide new and exciting user experiences with Windows 7

    Once your application has passed the first two steps, you can really differentiate your it by creating new and exciting user experiences. Windows 7 enables developers to create distinctive and intuitive applications that significantly enhance discoverability, usability, and sheer enjoyment. New methods of desktop integration put application functionality right at the user’s fingertips. New Touch APIs enable natural interactions through multitouch and finger-panning gestures. Rapid advances in hardware and software technology are also driving higher-fidelity user experiences. Windows 7 brings these advances under developer control with new and flexible APIs that take full advantage of the technology, while making it even easier to develop compelling applications.

    Windows 7 includes many new features that can make your application shine, raising it above the competition. When you think about creating new and exciting user experiences, consider using one or more of the following features:

    • Ribbon – Windows 7 features the Ribbon interface from Office 2007 throughout the operating system, enabling improved user interface development on the platform. This means that developers can eliminate much of the drudgery of Win32 UI development and deliver a rich, graphical, animated, and highly familiar user interface by using the markup-based UI and a small, high-performance, native code runtime.

    image 

    • Multitouch & Ink – Windows 7 features improved touch and gesture support, empowering developers to quickly and easily create unique application experiences that go beyond simple mouse pointing, clicking, and dragging. The new multi-touch APIs support rich gestures, such as pan, zoom, and rotate. All gestures provide direct visual feedback, and interact with underlying content in a natural and intuitive manner.
    • Sensor and Location Platform - Windows 7 has changed how developers use sensors. It includes native support for sensors, expanded by a new development platform for working with sensors, including location sensors (such as GPS devices) and sensors (such as an ambient light sensor or a temperature gauge), to create environmental awareness in Windows applications. Location sensors can unlock new opportunities for location-based services.
    • New Graphics Stack – Windows 7 puts new graphics capability into the hands of application developers through a new set of DirectX APIs. Win32 developers can take advantage of the latest innovations in GPUs to add fast, scalable, high-quality, 2D and 3D graphics, text, and images to their applications.

    image

    • Media Platform – Media Foundation and DirectShow® provide the basis for media support in Windows. Media Foundation was introduced in Windows Vista as the replacement for DirectShow. In Windows 7, Media Foundation has been enhanced to provide better format support, including:
      • MPEG-4,
      • Support for video capture devices and hardware codecs, including H.264 video, MJPEG, and MP3
      • New sources for MP4, 3GP, MPEG2-TS, and AVI
      • New file sinks for MP4, 3GP, and MP3

    And for developers Windows 7 adds new high-level APIs that make it much simpler to write media applications.

  1. Federated Search – Windows 7 supports searching for documents beyond the user’s own PC. Developers and IT professionals can enable their search engines, document repositories, Web applications, and proprietary data stores to be searched from Windows 7 without needing to write and deploy client code. This enables end users to search their corporate intranet or the Web as easily as they can search their local files—all from within the same familiar Windows interface.
  2. Device Stage Integration – Windows 7 combines software and services to create exciting new experiences for mobile phones, portable media players, cameras, and printers. Windows 7 makes it easier to use these devices directly from the Windows desktop. It also provides device makers with prominent placement on the Windows desktop, with branding opportunities and a simple interface for presenting the functionality and services that the device supports.

    I hope this post give you enough to start work with, making sure your application rocks on Windows 7!


  3. 7 Ways to Get Free Tickets to PDC 2009 Plus up to $17,777

    Do you want to win a free trip to Los Angeles and a free ticket to PDC 2009? Do you think you have what it takes to win $17,777? Do you think you can write an amazing Windows 7 application?

    Well, if your answer to any of the above question is "Yes!" then say hello to the Code7 Contest. The Code7 contest is where your application design ingenuity gives you the opportunity to get millions of eyes on your work, plus a trip to LA for PDC09, and up to $17,777 in cash!

    clip_image002

    Code7 is a special coding contest for developers. It is a great opportunity to show the world your creativity and coding powers. It is a way for you to cash in on your knowledge and skills.

    This is not just another standard code contest; this contest gives the finalists the opportunity to present their application at PDC 2009 in LA. The first prize is a real gem: $17,777 in cash, the opportunity to present the application to Microsoft executives at PDC 2009, plus worldwide interest in your application including a massive “marketing bump” for your application.

    To enter, you must:

    Build an original, consumer-oriented client application prototype that runs natively on Windows 7 (for example Win32, WPF, MFC or WinForms – not an Air application or just a gadget) and addresses one or more of the following topic categories:

    • Simplify My Life
    • More Media, More Places
    • Gaming
    • Work From Anywhere
    • Safeguard Your Work
    • Applications for a Better Tomorrow

    The application must use at least one of the following Windows 7 technology features; however, judging will give more weight to entries that take advantage of more than one of these features:

    • Libraries
    • Windows Touch
    • Shell Integration
    • DX11 (DirectX 11)
    • Sensor and Location Platform

    So if you have being following my blog you have some advantage.

    The contest has several stages and few rules you need to be aware of:

    • To enter this contest you must create and submit a video in which you describe and demonstrate your application.
    • The first qualifying round starts at 12:00 a.m. Pacific Time (PT) on July 13, 2009, and ends at 11:59 p.m. PT on October 10, 2009 (“Entry Period”). You will be able to able to submit your video until midnight October 10, 2009. Your entry will be included in a pool with all eligible entries based on your geographical region.
    • Entries received by 11:59 p.m. PT on August 15, 2009, will be eligible to win an “Early Bird” prize described in the Winner Determination section below.
    • Following the close of the first qualifications, a panel of judges will select two runner-up winners and one Finalist from each Region.
    • Following judging, Microsoft will notify all winners and finalists and provide instructions for submitting their applications for evaluation.
    • Finalists will be invited to present their applications to a panel of judges at the Microsoft Partner Developer Conference 2009 (PDC09) in Los Angeles, CA, USA.

    For the complete contest rules and legal notice, please refer to the “RULES” section on the Code7 Contest Web site - https://www.code7contest.com/.

    So, what are you waiting for? Get going and start working on your Windows 7 application!


    Windows 7 E Best Practices for ISVs

    We are intent on providing people with the best possible experience using their PCs with Windows. Building on that important principle, we will ship the same version of Windows 7 in Europe as in rest of the world on the  worldwide launch date of 22 October, 2009. This version of Windows 7 includes Windows Internet Explorer 8 to help people get the most from their PCs and the Internet.

    We will not ship E editions of Windows 7, which would not have included Internet Explorer.  Customers who pre-order Windows 7 will receive versions of the product that include Internet Explorer. Customers participating in the Windows Upgrade Option available with select new PCs running Windows Vista will also receive versions of Windows 7 that include Internet Explorer.  Customers in Europe will also be able to choose between upgrade and full versions of Windows 7.

    I asked Giorgio Sardo, to write about the E editions for Windows 7 and the changes developers need to be aware of. Since the E edition for Windows 7 will ship without  Internet Explorer 8. Giorgio is the Technical Evangelist working on IE and other web technologies.

    Yochay

    In a previous post, we explained how Microsoft is working to fulfill our legal obligations in Europe for Windows 7. In the meantime, we received some questions about what the E editions of Windows 7 will mean for ISVs and developers.

    I took the most common questions and posed them to Arik Cohen, a Program Manager who is working on the E editions of Windows 7. If you have other questions about how this could affect your applications, please add your comments to the post to let us know and we’ll work to get your questions answered.

    Q: What are the differences between standard editions of Windows 7 and E editions of Windows 7?

    A: The only functional difference is that the Internet Explorer 8 component is not available. This is the same component that your users can turn off in the “Turn Windows features on and off” control panel in the Windows 7 RC build. The Internet Web Platform components (for example, WebOC) are still installed and available on all editions of Windows 7, since they are part of the Windows core.

    image

    Q: How should I test my application to ensure that it will work without IE?

    A: To get the same functional behavior as a clean install of the E editions of Windows 7, go to “Turn Windows features on and off” dialog and uncheck Internet Explorer 8. We recommend testing your application both without a browser installed and with a browser installed (remember to set the installed browser as the default).

    Q: What happens if I try to open a link without a browser installed?

    A: You will get an “Application not found” exception.

    image

    Q: What general impacts of Windows 7 E editions have you seen on applications – especially ones that rely on the WebOC?

    A: During our application compatibility testing, we’ve found that the vast majority of applications work on Windows 7 E editions without any changes. This includes applications that use many of the Internet Web Platform embedding methods (including WebBrowser control, hosting Trident, and HTML Help).

    For instance, the following screenshot shows a .NET application that embeds the WebBrowser control running correctly on the E edition of Windows 7.

    image

    Q: My Windows application (WPF, Win Forms, Java, etc.) uses the Web Browser control. Is there any compatibility issue?

    A: Everything should work as expected. However, we’ve seen some issues when applications depend directly on a specific browser. In particular, if while using the Web Browser control, you allow the application to open new windows that do not respect the user’s default browser choice, you may see some issues.

    Q: What are the most common issues that you have found in your testing of applications? And what do you recommend ISVs do about them?

    A: I have seen applications encounter three classes of issues on E editions of Windows 7:

    1. The application has hard coded dependencies to launch Internet Explorer when starting a browser to access the net. This is normally done by explicitly launching “iexplore.exe http://contoso.com” rather than running a ShellExecute on http://contoso.com. This generates an exception on a Windows 7 system without IE installed and enabled. There are times when this is intentional (for example, the Web site you are opening is only supported on IE), in which case you probably want to check for IE availability and provide a good error message to the user if it’s not available.

      We’ve seen this many times, especially in instances where the desired behavior is to open the application in the user’s default browser. You will need to switch to using the more generic case for these scenarios.

    2. The application allows launching a new window from within the WebBrowser control (for example, user accesses “Open in New Window” via the content menu, the page does a window.open() call, etc.).

      These links would always have opened in IE (regardless of the default browser on the system). If you designed your application to open in the default browser, you will need to provide a function that allows that.

      The recommended way to implement custom behavior when opening a new window is to use the NewWindow3 event. Sample code to hook this up in a C# .NET application would look like the following examples.

      In the form initialization code:

      webBrowser1.Navigate("about:blank");
      SHDocVw.WebBrowser web1 =
      (SHDocVw.WebBrowser)webBrowser1.ActiveXInstance;

      web1.NewWindow3 +=
      new SHDocVw.DWebBrowserEvents2_NewWindow3EventHandler(web1_NewWindow3);
      
      

      And the handler:

      void web1_NewWindow3(
      ref object ppDisp,
      ref bool Cancel,
      uint dwFlags,
      string bstrUrlContext,
      string bstrUrl )
      {
      Process.Start(bstrUrl);
      Cancel = true;
      }
      
      
       
    3. Applications don’t handle cases where no browser is installed on the system. We have seen applications that don’t handle this failure case when executing a URL.

      These tend to occur when users don’t have a default browser on their systems and then try to click a “go online for more information” link. We think this is going to be an extremely narrow case – even so, applications should handle these failures gracefully.

    Q: How do I identify the user’s default browser?

    A: Use the IApplicationAssociationRegistration::QueryCurrentDefault API to determine the registered browser by checking QueryCurrentDefault(“http”, AT_URLPROTOCOL,  AL_EFFECTIVE, out progID).

    Q: My app needs to open the browser. What are the best practices?

    A: Run shellexecute() without hard-coding the name of the browser. Respect the user’s choice of default browser and gracefully handle cases where no browser is installed on the system.

    Q: How can I check if I’m running in one of the E edition for Windows 7?

    A: The GetProductInfo() API (introduced in Windows Vista) is how to tell exactly what edition of Windows you are running. The new constant values for the E editions of Windows 7 will be available in the Windows 7 SDK.

    Example of code to determine if you are running on Home Premium vs. Ultimate:

    [DllImport("Kernel32.dll")]
    internal static extern bool GetProductInfo(
    int osMajorVersion,
    int osMinorVersion,
    int spMajorVersion,
    int spMinorVersion,
    out uint edition);


    private void CheckEdition()
    {
    uint edition;
    GetProductInfo(6, 1, 0, 0, out edition);

    switch ((ProductEditions)(edition))
    {

    case ProductEditions.HOMEPREMIUM :
    case ProductEditions.HOMEPREMIUME:
    case ProductEditions.HOMEPREMIUMN:

    MessageBox.Show("Running on a Home Premium edition");
    break;

    case ProductEditions.ULTIMATE :
    case ProductEditions.ULTIMATEE:
    case ProductEditions.ULTIMATEN:
    MessageBox.Show("Running on an Ultimate edition");
    break;

    }
    }
    
    

     

    Q: Are the E editions of Windows 7 going to be available on MSDN? If so, when?

    A: Yes, both the E editions of Windows 7 and the standard editions will be available on MSDN at the same time.

    Q: What about the Internet Explorer 8 Feature Pack for Windows 7 E? If and when will Microsoft release it to the public?

    A: Yes, the Internet Explorer 8 Feature Pack for Windows 7 E will be available on the Microsoft Download Center soon after Windows 7 becomes generally available.

    Giorgio Sardo

    IE Technical Evangelist – Microsoft Corp


    Developing for the Windows 7 Taskbar – Jump into Jump Lists – Part 3

    So far, you have seen how you can opt into the Windows 7 Taskbar Jump List experience by creating a Jump List for your application (in the Developing for the Windows 7 Taskbar – Jump into Jump Lists – Part 2 post.) You have also seen the Windows 7 default support for listing “Recent” or “Frequent” destinations as well as how to create your own custom categories. In this post, we will explore more of the Jump List features and discover how easy it is to add Tasks to your application's Jump List.

    User tasks are customized tasks that get their own Tasks category. As a developer, you can set the title of the displayed task, the icon on the left and, more important, and the “application” that is launched once you activate this task. You can view user’s tasks as shortcuts to the functionality our applications can provide. As you might remember, user tasks are the verbs in our vocabulary; for example, Windows Media Player provides a “Resume last playlist” task and Sticky Notes provides a “New note” task.

    A user task is usually an IShellLink object that launches any given application (your application or any other one you choose) with specific command line parameters. While you cannot categorize tasks, you can separate them using a special separator object. Here’s an example of a Jump List that uses a separator to split three tasks into a group of two plus an additional task:

    image

    So what does it take to add tasks to a Jump List? Well, not that much. Basically it is a single call to the AddUserTasks function in an interface that we are already familiar with, the ICustomDestinationList (ICustomDestinationList::AddUserTasks(IObjectArray) Method). Looking at the code, you will see a single line of code, hr = pcdl->AddUserTasks(poa);. However, as always, someone needs to create and build that poa, IObjectArray, and parameter and fill it with relevant information. Let’s review that process now.

    We are going to create a collection of IShellLinks. This collection will be later cast to the required IObjectArray parameter. The following code is the beginning of that process.

    IObjectCollection *poc;
    HRESULT hr = CoCreateInstance(
    D_EnumerableObjectCollection, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&poc));
    if (SUCCEEDED(hr))
    {
    IShellLink * psl;
    hr = _CreateShellLink(L"/Task1", L"Task 1", &psl);
    if (SUCCEEDED(hr))
    {
    hr = poc->AddObject(psl);
    psl->Release();
    }
    }

    Here you can see that we used COM (again) and CoCreate and IObjectCollection, poc. Next, we call to a helper function called CreateShellLink that receives three parameters:

    • The first parameter is the command line argument to the task
    • The second parameter is the title that will be displayed
    • The last parameter is a pointer to IShellLink

    The object is then filed according to the relevant information.

    Last, we add the recently created IShellLink to the object collection. You may ask yourself where the parameter that provides the path to the executable that we plan to launch is. Well that is a good question. For simplicity, we have hard-coded that information as shown in the following code snippet:

    if (SUCCEEDED(hr))
    {
    hr = _CreateShellLink2(
    L"C:\\Users\\<my user>\\Documents\\new text file.txt",
    L"NotePad",
    &psl);

    if (SUCCEEDED(hr))
    {
    hr = poc->AddObject(psl);
    psl->Release();
    }
    }

    Here you can see we call to a hard-coded _CreateShellLink2 function. This receives a path to a text file as one of its parameters and, as you can see, we are launching Notepad.

    Here is the code for the CreateShellLink2 function:

    HRESULT _CreateShellLink2(
    PCWSTR pszArguments, PCWSTR pszTitle,
    IShellLink **ppsl)
    {
    IShellLink *psl;
    HRESULT hr = CoCreateInstance(
    CLSID_ShellLink,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_PPV_ARGS(&psl));
    if (SUCCEEDED(hr))
    {
    hr = psl->SetPath(c_szNotePadExecPath);
    if (SUCCEEDED(hr))
    {
    hr = psl->SetArguments(pszArguments);
    if (SUCCEEDED(hr))
    {
    // The title property is required on Jump List items
    // provided as an IShellLink instance. This value is used
    // as the display name in the Jump List.
    IPropertyStore *pps;
    hr = psl->QueryInterface(IID_PPV_ARGS(&pps));
    if (SUCCEEDED(hr))
    {
    PROPVARIANT propvar;
    hr = InitPropVariantFromString(pszTitle, &propvar);
    if (SUCCEEDED(hr))
    {
    hr = pps->SetValue(PKEY_Title, propvar);
    if (SUCCEEDED(hr))
    {
    hr = pps->Commit();
    if (SUCCEEDED(hr))
    {
    hr = psl->QueryInterface
    (IID_PPV_ARGS(ppsl));
    }
    }
    PropVariantClear(&propvar);
    }
    pps->Release();
    }
    }
    }
    else
    {
    hr = HRESULT_FROM_WIN32(GetLastError());
    }
    psl->Release();
    }
    return hr;
    }

    To start with, again we need to use COM and CoCreate to create an IShellLink COM object. A quick look at the SDK reveals that the IShellLink object has many functions. Here are few that we will use:

    • GetPath Gets the path and file name of a Shell link object, that is the path to the executable
    • GetShowCmd Gets the show command for a Shell link object, the executable name
    • SetArguments Sets the command-line arguments for a Shell link object
    • SetDescription Sets the description for a Shell link object; the description can be any application-defined string
    • SetIconLocation Sets the location (path and index) of the icon for a Shell link object SetPath Sets the path and file name of a Shell link object
    • SetWorkingDirectory Sets the name of the working directory for a Shell link object

    As you can see, for each parameter we must get and set appropriate methods. There are additional parameters; take a look at the SDK - IShellLink if you want to learn more.

    In the above example, we set the path to Notepad (by default in the Windows 7 installation, c:\windows\notepad.exe). We also passed a hard-coded (not a good practice) command line argument pointing to a text file in my private document folder (C:\Users\<my user>\Documents\new text file.txt.) The rest of the code sets the title property that is required on Jump List items.

    We call the CreateShellLink2 and CreateShellLink a few more times to add all three shortcuts as shown in the above screen capture.

    Now let’s add a separator.

    To add a separator to our Task List, we need to create an IShellLink, and set the PKEY_AppUserModel_IsDestListSeparator property using the COM property variant as shown in the following code snippet:

    // The Tasks category of Jump Lists supports separator items. 
    // These are simply IShellLink instances that have the
    // PKEY_AppUserModel_IsDestListSeparator property set to TRUE.
    // All other values are ignored when this property is set.
    HRESULT _CreateSeparatorLink(IShellLink **ppsl)
    {
    IPropertyStore *pps;
    HRESULT hr = CoCreateInstance(
    CLSID_ShellLink,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_PPV_ARGS(&pps));
    if (SUCCEEDED(hr))
    {
    PROPVARIANT propvar;
    hr = InitPropVariantFromBoolean(TRUE, &propvar);
    if (SUCCEEDED(hr))
    {
    hr = pps->SetValue(PKEY_AppUserModel_IsDestListSeparator, propvar);
    if (SUCCEEDED(hr))
    {
    hr = pps->Commit();
    if (SUCCEEDED(hr))
    {
    hr = pps->QueryInterface(IID_PPV_ARGS(ppsl));
    }
    }
    PropVariantClear(&propvar);
    }
    pps->Release();
    }
    return hr;
    }

    Here you can see that we used CoCreate to create an IShellLink object. Next, we set a PROPVARIANT, propvar, to true and set the IShellLink object PKEY_AppUserModel_IsDestListSeparator property to true. This will instruct the OS to render this IShellLink as a separator and not just as regular IShellLink.

    OK, that was long. Now let’s look at the short version, using .NET. For that we are going to use the Windows API Code pack for the .NET Framework.

    As we can expect from .NET, we get abstraction from most of the “COM code behind” that is required. The Microsoft.WindowsAPICodePack.Shell.Taskbar namespace includes a JumpListLink object that extends the ShellLink object and implements IJumpListTasks.

    The JumpList class contains the UserTasks collection of IJumpListTasks to which you can simple add new JumpListLink objects as shown in the following code snippet:

    // Path to Windows system folder
    string systemFolder =
    Environment.GetFolderPath(Environment.SpecialFolder.System);

    jumpList.UserTasks.Add(new JumpListLink
    {
    Title = "Open Notepad",
    Path = Path.Combine(systemFolder, "notepad.exe"),
    IconReference = new IconReference(
    (systemFolder, "notepad.exe"), 0)
    });

    Using the C# 3.0 syntax, we initialize a new JumpListLink object and add it to the UserTasks collection. As you can see, the managed code JumpListLink has very similar properties to the native one (which makes perfect sense). We also added an icon to the Notepad shortcut to the above code, but didn't provide any command line parameters.

    You want to add a separator? Well, that is also very easy: just add a JumpListSeperator object to the UserTasks collection.

    jumpList.UserTasks.Add(new JumpListSeparator());
    Please note that, as always, when working with the Windows Code pack API Taskbar, you have to call the “refresh” function in order to commit the changes, as we explained in the previous post.
    Taskbar.JumpList.RefreshTaskbarList();

    After the refresh, the Jump List looks as follows:

    image

    I’ve compiled a version of a native example from the Windows 7 SDK. You can get a copy of that code from here

    You can download the Windows API Code Pack that includes the manage code example we used in this post.

    This concludes our Jump List discussion. Our next Taskbar topic is Icon Overlay.