Add links and code examples to Help topics you create

In my last post, I explained how to add a simple, text-only topic to your local Help Library. I also described how metadata connects content into the help system. Now let’s look at what we can do to make our topic a little more interesting. (Skip ahead to the hands-on tutorial if you’re not interested in the details.)

Links

There are three common link types in Help Library content: internal, external and image.

Internal links reference other topics within the local Help Library. They specify link targets by their topic ID alone—an approach we call “identity linking.” Since help topics are referenced without knowledge of their absolute or relative pathnames, topic linking does not depend on the structure of Library content. Why use this approach? The help system separates content, structure, presentation and behavior to enable extensibility and portability to future content formats.

It is the help runtime that maps topic IDs to their corresponding XHTML pages. The help runtime is called via the ms-xhelp API and we reference a specific help system topic by passing its ID into that API. The format of an ms-xhelp URL is:

ms-xhelp:///?Id=Microsoft.Help.ID

Here is an example of how the API is used inside a topic (the class=”mtps-internal-link” markup supports CSS formatting):

<a class="mtps-internal-link" href="ms-xhelp:///?Id=b3382805-aa6b-4e6f-a346-73d20f74d0cd">Links, Code Examples and Language-specific Text</a>

External links reference web pages outside of the Help Library and use standard HTTP URLs. Here’s an example of how external links are used inside a topic (the class=”mtps-external-link” markup supports link formatting):

<a class="mtps-external-link" href="http://msdn.microsoft.com/en-us/library/default.aspx">MSDN Library</a>

Image links are used to embed images in topics. Embedded images generally reside in the same package (MSHC file) that contains the topic. An example image link:

<img class="mtps-img-src" src="image.png" />

Branding Package Controls

The appearance and behavior of Help content is defined by a branding package, basically a collection of CSS files, JavaScript, images and other resource files. The help system allows each catalog to specify its own branding package. For this post, we’ll limit ourselves to controls that are provided by the default branding package that ships with the Help Viewer. Using this branding package enables us to easily create topics that look and behave like Visual Studio help content.

The default Help Viewer branding package supports three commonly used controls we’ll look at today: CollapsibleArea, CodeSnippet and LanguageSpecificText.

Collapsible Areas

In Visual Studio Help content, collapsible areas group sections within a topic. They serve two functions: 1) provide formatting for the title of the section, and 2) enable the user to collapse entire sections when reading a topic. This is useful for extremely long topics or for FAQ pages.

Collapsible areas were only partially implemented in Help Viewer 1.x. They provide proper title formatting but they don’t provide a collapse feature. However, marking up your content with the CollapsibleArea tag ensures it can take advantage of this capability in future releases.

The CollapsibleArea control contains the area to be collapsed and specifies the title of the section. For example:

<CollapsibleArea Expanded="1" Title="Content Linking" xmlns="http://msdn2.microsoft.com/mtps">

… section content …

</CollapsibleArea>

Note that, if Expanded="0", the area starts collapsed. Expanded="1" is the default.

Code Examples (CodeSnippets)

Many Visual Studio help topics contain code examples and syntax documentation. The help system CodeSnippet control displays formatted code examples in the user’s preferred development language. (Note that Help system “CodeSnippets” are not the same as Visual Studio “Code Snippets.”)

The help system automatically groups adjacent code snippets into a “snippet group” that enables readers to easily switch between examples in different development languages. A single CodeSnippet is expressed as follows:

<!-- Snippet for the C# language -->
<CodeSnippet EnableCopyCode="true" Language="CSharp" ContainsMarkup="false" DisplayLanguage="C#" xmlns="http://msdn2.microsoft.com/mtps">
using System;

// A "hello, world" program in C#
namespace HelloWorld {
  class Hello {
    static void Main() {
      System.Console.WriteLine("hello, world");
    }
  }
}
</CodeSnippet>

The CodeSnippet control uses two separate tags to support source code formatting. The Language tag specifies the development language used for code colorization. The DisplayLanguage tag specifies the text to be displayed on the snippet tab. Supported tag values include:

Language DisplayLanguage
CSharp C#
VisualBasic Visual Basic
ManagedCPlusPlus Visual C++
FSharp F#
JScript JScript
xaml XAML

Language-specific Text

It is common to use language-specific syntax in help documentation. Because syntax varies from language to language, the help system provides the ability to display text as a function of the reader’s chosen development language. This feature eliminates the need to author separate, redundant topics for each language.

The LanguageSpecificText control displays dynamic text based on the development language selected by the reader using the CodeSnippet control.

For example, the following language-specific text example is used frequently in Visual Studio content to modify namespace delimiters:

<LanguageSpecificText devLangcs="." devLangvb="." devLangcpp="::" devLangnu="." xmlns="http://msdn2.microsoft.com/mtps">.</LanguageSpecificText>

And here is the list of supported language tags:

Language Tag
C# devLangcs
VB devLangvb
C++ devLangcpp
Other devLangnu

Linking and Code Example Tutorial

Now it’s time to apply what you’ve learned. In this section, you’ll add links and use controls from the Help Viewer branding package to add code examples to your custom topic. This tutorial takes about 5 minutes and makes the following assumptions:

  • Visual Studio 2010 (RTM or SP1) is installed on your machine.
  • You have administrator privileges on your machine.
  • You have successfully used the local Help Viewer to read EN-US help content.

When you’ve completed the exercise, you can remove the tutorial content without side effects to your help system.

Step 1: Create a Topic

To begin, create a folder for your help content and then create a topic in that folder. For the purposes of this tutorial, you’ll create a folder named “HelpTutorial2” in your main Documents folder.

  1. Use Windows Explorer to create the folder or from a command prompt:
    mkdir %userprofile%\Documents\HelpTutorial2
  2. Launch Notepad.
  3. Copy the following XHTML and paste it into Notepad:
    (Tip: If you lose carriage returns when pasting into Notepad, consider copying this XHTML from within Chrome or Firefox. The code examples in this topic will not display correctly if lines don’t break in the correct locations.)

    <?xml version="1.0" encoding="UTF-8"?>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <title>Links, Code Examples and Language-specific Text</title>
      <!-- Specify the topic content key: ID, locale and version -->
      <meta name="Microsoft.Help.Id" content="ecab3be4-257f-4649-864b-761cfd9510c2" />
      <meta name="Microsoft.Help.Locale" content="en-us" />
      <meta name="Microsoft.Help.TopicLocale" content="en-us" />
      <meta name="Microsoft.Help.TopicVersion" content="100" />
      <!-- Use the default branding package to render the topic -->
      <meta name="Microsoft.Help.SelfBranded" content="false" />
      <!-- Place the topic in the TOC under the root node -->
      <meta name="Microsoft.Help.TocParent" content="-1" />
      <meta name="Microsoft.Help.TocOrder" content="0" />
      <!-- Enable topic access from the keyword index -->
      <meta name="Microsoft.Help.Keywords" content="help content links" />
      <meta name="Microsoft.Help.Keywords" content="Code Example (CodeSnippet)" />
      <meta name="Microsoft.Help.Keywords" content="LanguageSpecificText" />
      <!-- Enable topic access via F1 help -->
      <meta name="Microsoft.Help.F1" content="CodeSnippet" />
      <meta name="Microsoft.Help.F1" content="LanguageSpecificText" />
      <!-- Provide a description for use in the search results list -->
      <meta name="Description" content="This text provides an overview of this topic and is displayed in the search results list." />
    </head>
    <body>
      <h1 class="title">Links, Code Examples and Language-specific Text</h1>
      <div id="mainSection">
        <CollapsibleArea Expanded="1" Title="Content Linking" xmlns="http://msdn2.microsoft.com/mtps">
          <p>There are three common types of links: internal, external and image.</p>
          <table class="members" xmlns="http://www.w3.org/1999/xhtml">
            <tr>
              <th>Type</th>
              <th>Example</th>
              <th>Description</th>
            </tr>
            <tr>
              <td>Internal Link</td>
              <td><a class="mtps-internal-link" href="ms-xhelp:///?Id=1838dc17-b428-4db2-938e-10fa07f63e81">Help System Feature Overview</a></td>
              <td>Internal link to a topic in local Help system documentation</td>
            </tr>
            <tr>
              <td>External Link</td>
              <td><a class="mtps-external-link" href="http://msdn.microsoft.com/en-us/library/default.aspx">MSDN Library</a></td>
              <td>External link to the online MSDN Library</td>
            </tr>
            <tr>
              <td>Image Link</td>
              <td><img class="mtps-img-src" src="image.png" /></td>
              <td>Example of an embedded image</td>
            </tr>
          </table>
        </CollapsibleArea>
    
        <CollapsibleArea Expanded="1" Title="Language-specific Text" xmlns="http://msdn2.microsoft.com/mtps">
          <p>This text adjusts to match the coding language selected in the SnippetGroup (below).</p>
          <ul>
            <li>Current code language: <strong>
              <LanguageSpecificText devLangcs="C#" devLangvb="VB" devLangcpp="C++" devLangnu="other" xmlns="http://msdn2.microsoft.com/mtps">other</LanguageSpecificText></strong></li>
            <li>Namespace delimiter (example): <strong>XmlReader
              <LanguageSpecificText devLangcs="." devLangvb="." devLangcpp="::" devLangnu="." xmlns="http://msdn2.microsoft.com/mtps">.</LanguageSpecificText>Read Method</strong></li>
          </ul>
        </CollapsibleArea>
    
        <CollapsibleArea Expanded="1" Title="Examples" xmlns="http://msdn2.microsoft.com/mtps"><a id="exampleToggle" xmlns="http://www.w3.org/1999/xhtml"><!----></a>
          <p>Note that all of the tabs in the SnippetGroup are populated with a code example.</p>
          <!-- Declare the SnippetGroup container -->
          <div id="snippetGroup" xmlns="http://www.w3.org/1999/xhtml">
            <!-- Snippet for the VB language -->
            <!-- Language is the code colorization language -->
            <!-- DisplayLanguage is the tab title language -->
            <CodeSnippet EnableCopyCode="true" Language="VisualBasic" ContainsMarkup="false" DisplayLanguage="Visual Basic" xmlns="http://msdn2.microsoft.com/mtps">
    Imports System
    
    ' A "hello, world" program in Visual Basic
    Module Hello
      Sub Main()
          MsgBox("hello, world")
      End Sub
    End Module
            </CodeSnippet>
            <!-- Snippet for the C# language -->
            <CodeSnippet EnableCopyCode="true" Language="CSharp" ContainsMarkup="false" DisplayLanguage="C#" xmlns="http://msdn2.microsoft.com/mtps">
    using System;
    
    // A "hello, world" program in C#
    namespace HelloWorld {
      class Hello {
        static void Main() {
          System.Console.WriteLine("hello, world");
        }
      }
    }
            </CodeSnippet>
            <CodeSnippet EnableCopyCode="true" Language="ManagedCPlusPlus" ContainsMarkup="false" DisplayLanguage="Visual C++" xmlns="http://msdn2.microsoft.com/mtps">
    // A "hello, world" program in C++
    main( ) {
      printf("hello, world");
    }
            </CodeSnippet>
            <CodeSnippet EnableCopyCode="true" Language="FSharp" ContainsMarkup="false" DisplayLanguage="F#" xmlns="http://msdn2.microsoft.com/mtps">
    // A "hello, world" program in F#
    #light  
    open System  
    printfn "hello, world"
            </CodeSnippet>
            <CodeSnippet EnableCopyCode="true" Language="JScript" ContainsMarkup="false" DisplayLanguage="JScript" xmlns="http://msdn2.microsoft.com/mtps">
    // A "hello, world" program in JScript
    print("hello world");
            </CodeSnippet>
          </div>
    
          <p>Singleton with tab and language colorization:</p>
          <CodeSnippet EnableCopyCode="true" Language="html" ContainsMarkup="false" DisplayLanguage="XHTML" xmlns="http://msdn2.microsoft.com/mtps">
    &lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
      &lt;head /&gt;
      &lt;body&gt;
        &lt;p&gt;hello, world&lt;/p&gt;
      &lt;/body&gt;
    &lt;/html&gt;
          </CodeSnippet>
    
          <p>Singleton with no tab, no colorization:</p>
          <CodeSnippet EnableCopyCode="true" Language="other" DisplayLanguage="" ContainsMarkup="false" xmlns="http://msdn2.microsoft.com/mtps">
    HRESULT SetDeviceEnumPreference(
      [in]  DWORD dwEnumPref
    );
          </CodeSnippet>
        </CollapsibleArea>
      </div>
    </body>
    </html>
    
  4. Save the file as: %userprofile%\Documents\HelpTutorial2\topic2.html
  5. Close Notepad.
  6. Right click on the MSDN image below and “Save picture as…” image.png in the HelpTutorial2 folder.

Step 2: Create a Package

Next, place your topic in a package.

  1. In Windows Explorer, right click on the topic2.html file you created in Step 1 and send it to a Compressed (zipped) folder named mycontent2.zip.
  2. Drag image.png into the mycontent2.zip folder.
  3. Rename the mycontent2.zip folder to mycontent2.mshc. (Click ‘Yes’ on the Rename dialog that pops up.)

Step 3: Create a Book

The last step in preparing your content is placing your package in a “book”. As you’ll recall from my previous post, a book is a collection of packages and is defined in an asset manifest file named HelpContentSetup.msha.

  1. Launch Notepad.
  2. Copy the following XHTML content and paste it into Notepad:
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head />
      <body class="vendor-book">
        <div class="details">
          <span class="vendor">My Company</span>
          <span class="locale">en-us</span>
          <span class="product">My Custom Content</span>
          <span class="name">More Custom Topics</span>
        </div>    
        <div class="package-list">
          <div class="package">
            <span class="name">mycontent2</span>
            <span class="deployed">true</span>
            <a class="current-link" href="mycontent2.mshc">mycontent2.mshc</a>
          </div>
        </div>
      </body>
    </html>
    
  3. Save the file as:
    %userprofile%\Documents\HelpTutorial2\HelpContentSetup.msha
    (Tip: Set the “Save as type” dropdown list in Notepad to “All Files (*.*)” )
  4. Close Notepad.

Step 4: Install the Book

Launch the Help Library Manager in administrative mode and install the book from disk. If you’re unsure how to do this, follow the install instructions from my previous post.

Step 5: Explore Your Content

Select “View Help” from the Visual Studio Help menu. Note that your topic appears in the Table of Contents as a child of the root node:

topic2toc

If you select this topic you’ll see the following page:

Help Topic with Code Examples

To Learn More

This tutorial covers the basics of the Visual Studio Help Viewer branding package. To learn more about designing content for the Microsoft Help Viewer, check out these resources:

This entry was posted in Microsoft Help Viewer, Visual Studio 2010 and tagged , . Bookmark the permalink. Both comments and trackbacks are currently closed.

4 Comments

  1. Posted July 29, 2011 at 6:45 pm | Permalink

    Thanks Jeff. A very thorough bootstrap into the world of VS 2010 local help.

  2. Tom Yates
    Posted July 30, 2011 at 1:25 am | Permalink

    Thanks for the article.

    I would like to resurrect an old inquiry made by a reader of your blog here:

    http://thirdblogfromthesun.com/2011/03/new-local-help-viewer-available-in-visual-studio-2010-sp1/#comment-595

    Could you tell us what is going on with topics on Win32 missing in the TOC? Similarly to BV, I – and many of my colleagues – develop client applications. The absolute majority of topics we are interested in are not currently in the TOC. Examples: CreateWindow, CB_ADDSTRING, TBBUTTON, SetClipboardData, IRichEditOle, all related overviews, etc.

    In the linked subthread, Paul O’Rear from Microsoft said that the problem is going to be fixed “within around the next week or so”. That was in May 25. We are two months past the supposed fix date now, the problem is still not fixed. Could you please check what’s going on?

  3. Tom Yates
    Posted August 2, 2011 at 7:24 am | Permalink

    It turns out the topics on .NET 3.5 also can not be found in the TOC. The same topics for .NET 4.0 are in the TOC. Examples: System.String class, TypeLib class, Assembly to Type Library Conversion Summary, Type Library Exporter (Tlbexp.exe), etc.

    This is very frustrating.

  4. Jeff Braaten
    Posted September 3, 2011 at 12:02 pm | Permalink

    To my readers: Tom has re-asked these questions on a subsequent post. Follow our discussion at
    http://thirdblogfromthesun.com/2011/08/export-then-print-multiple-library-topics-beta/#comment-675

One Trackback

  • By July 27, 2011 – Learn TFS Daily | Learn TFS on July 27, 2011 at 10:36 am

    […] Add Links and Code Examples to Help Topics You Create from Jeff Braaten I really like this post on how to add links and code examples to custom help topics. This might provide an alternative option to a Wiki for internal guidance for your own team or provide some insight in how to ship better help documentation for your solutions. This post authored by Trent Nix Read more from Blog Click here to cancel reply. […]

%d bloggers like this: