Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Write your own UserControl with C++/CLI: an RSS reader

0.00/5 (No votes)
21 Mar 2006 2  
Thsi article explains how to create an RSS reader user control.

Introduction

This article is about the construction of an RSS reader UserControl, and is my first contribution to CodeProject. I will show you through the development of this reader, explaining how to create a User Control with the C++/CLI using the .NET 2.0 framework.

Project Creation

First, you have to create a new CLR / Windows Forms Control Library project. I'll name it rssFeeder. Visual Studio 2005 will generates a class, that derives from System::Windows::Forms::UserControl.

public ref class rssFeederControl : 
       public System::Windows::Forms::UserControl

The form rssFeederControl.h will represent our control. It's empty for now. Before filling it, we'll first talk about RSS quickly, and then about the properties of a UserControl.

Some words about RSS

RSS is used for syndicating a structured page, like a blog. We use an XML that describes the page. A sample page will look like this:

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" [...]>
    <channel>
        <title>Title of the blog</title> 
        <link>http://url.of.blog.com</link> 
          <description>This is the description of the blog.</description> 
        <item>
              <author>Me</author> 
            <title>The last news</title> 
              <link>http://url.of.blog.com/?news=2</link> 
              <description>Description of the news</description> 
          </item>
        <item>
              <author>Me</author> 
            <title>The first news</title> 
              <link>http://url.of.blog.com/?news=1</link> 
              <description>Description of the news</description> 
         </item>
      </channel>
</rss>

We can have an XML feed, for the comments too, the format is quite the same.

I will create a class (in fact, two classes) to load the content of the XML.

ref class CRssObject
{
public:
    CRssObject(void);
    String ^ title;
    String ^ link;
    String ^ description;
    String ^ language;
    System::Collections::ArrayList ^ listItem;
    bool LoadFromUrl(String ^, int, String ^);
    bool LoadFromFile(String ^, int, String ^);
private:
    bool isRssVersion2(Xml::XmlNode ^);
    String ^ GetText(Xml::XmlNode ^, String ^);
    bool LoadObject(Xml::XmlDocument ^, int, Xml::XmlDocument ^);
};

ref class CItemRss
{
public:
    CItemRss(void);
    String ^ author;
    String ^ title;
    String ^ link;
    int nbComments;
};

I will construct an RssObject from an XML URL (or file). I will load only elements that I want to use, for example the title and the link. This object can be loaded only if the RSS version is 2.0.

You can look in the sources files to know how I'm loading the object from XML; as an example of code, I'm using the HttpWebRequest object to read XML from a URL.

HttpWebRequest ^ HttpWReq = 
   dynamic_cast<HttpWebRequest^>(WebRequest::Create(url));
HttpWReq->CachePolicy = 
   gcnew Cache::HttpRequestCachePolicy(Cache::HttpRequestCacheLevel::Reload);
HttpWResp = dynamic_cast<HttpWebResponse^>(HttpWReq->GetResponse());
sr = gcnew StreamReader(HttpWResp->GetResponseStream());
Xml::XmlDocument ^ xml = gcnew Xml::XmlDocument();
xml->LoadXml(sr->ReadToEnd());

In the CPP file, you will see my own method that finds out how many comments there are on the news. As I didn't see any specifications for this, I looked for the URL of the news in the URL of the comments. If I find it, I get a comment.

Attributes

Existing common controls (button, checkbox, etc.) already have some properties, like visible, size, location, .... This control has those default properties too. We are now going to add some extra properties to our control. We will add as properties, the URL of the XML file, the number of news to display, and the delay for refreshing the control. We will add the URL of the comments as an optional property.

To create a property, add this code:

[Category("Configuration")]
[Description("Type here the Url or the xml")]
property String ^ url
{
    String ^ get() { return url_; }
    void set(String ^ value) 
    {
        url_ = value; 
        refreshControl();
    }
}

We use the Category attribute to name the field where the property will be put (if this attribute is not specified, it would be put in the Misc. category). We use the Description attribute to display a description when clicking on the field. Now, by adding our control to the toolbox and by drawing the user control on a form, we will see this in the property windows:

A property can only be a string! Here, the types of my properties are simple (string, int etc.). For complex types, use a TypeConverter.

Creation of the control

As we will not know before the configuration, how many news to display, we will construct the form dynamically. We will use a control box and a cli:array of LinkLabels. See this in the source code.

Add a personal image to the control

By default, the image for the user control is a wheel. We may want to add our own image. It's very simple in C#, but with C++/CLI, you have to follow these instructions:

  • add [ToolboxBitmap(rssFeeder::rssFeederControl::typeid)] before your class.
  • Create a 16x16 bitmap.
  • Name it as follows: Namespace.ClasseName.bmp.
  • Add it as a resource: Right click on project --> Add --> Resource --> Import (bitmap).
  • Link it with the DLL. Right click on the project --> Properties --> Linker --> Input --> Embed Managed Resource File, and add the name of the bitmap.

Events on the control

We may want to do a particular action when we click on a link (for example, when browsing the URL). The user then should intercept the Click event on a LinkLabel item. To do this, we have to create a delegate:

delegate void ItemClickHandler(Object ^ sender, 
           LinkLabelLinkClickedEventArgs ^ e);

Then we have to add this event to the configuration category:

[Category("Configuration"), Browsable(true), 
   Description("Event raised when clicking on an item")] 
   event ItemClickHandler ^ itemClick;

And raise the event when clicking on a LinkLabel. For this, during the user control creation, we add a Click event handler on each LinkLabel, as follows:

linkLabel->LinkClicked += gcnew 
  System::Windows::Forms::LinkLabelLinkClickedEventHandler(
  this, &rssFeeder::rssFeederControl::linkLabel_LinkClicked);

Then, we just have to do this to raise the event:

void linkLabel_LinkClicked(Object ^ sender, 
   System::Windows::Forms::LinkLabelLinkClickedEventArgs ^ e)
{
    if (&rssFeederControl::itemClick != nullptr)
        itemClick(this, e);
}

Finalizing the control

This is the main part. Don't hesitate to finalize the control, for example, I've overridden the Paint method to measure the string, to avoid the LinkLabel being larger than the control. I've added the output of the number of comments (if I can load it), and a tooltip on the LinkLabel with the author.

You can use the attribute DefaultValue("Default value") for setting a default value. I've done this in the constructor.

Conclusion

With this article, you should now be able to create a user control. In the Zip files, you will find the complete source code and the binaries of the user control and the project demo. Don't hesitate to send me feedback about this control or this article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here