Use reflection to list a class’s fields in C#


[reflection]

Even though fields and properties are very similar when you interact with an item in code, to C# they are different. One side effect of that is that the GetProperties method provided by reflection lists only properties, not fields. Fortunately, the GetFields method works in a similar manner, although many of the details are different.

This example uses the following code to add some fields to the Form1 class.

// Add some fields.
private int MyPrivateField = 1;
public int MyPublicField = 2;
public static int MyPublicStaticField = 3;
public static int MyProtectedField = 4;
public const int MyConstField = 5;
public int[] MyArray = { 1, 2, 3, 4, 5 };
public int[] MyEmptyArray = { };
public int[] MyNullArray;

When the program’s form loads, the following code displays information about the class’s fields.

// List the fields.
// Use the class you want to study instead of Form1.
object property_value;
FieldInfo[] field_infos = typeof(Form1).GetFields(
    BindingFlags.FlattenHierarchy |
    BindingFlags.Instance |
    BindingFlags.NonPublic |
    BindingFlags.Public |
    BindingFlags.Static);
foreach (FieldInfo info in field_infos)
{
    string name = info.Name;
    string attributes = info.FieldType.Attributes.ToString();

    string visibility = "";
    if (info.IsAssembly) visibility += " assembly";
    if (info.IsFamily) visibility += " family";
    if (info.IsFamilyAndAssembly)
        visibility += " family AND assembly";
    if (info.IsFamilyOrAssembly)
        visibility += " family OR assembly";
    if (info.IsInitOnly) visibility += " init";
    if (info.IsLiteral) visibility += " literal";
    if (info.IsPrivate) visibility += " private";
    if (info.IsPublic) visibility += " public";
    if (info.IsStatic) visibility += " static";
    if (visibility.Length > 0)
        visibility = visibility.Substring(1);

    string value = "";

    // See if it's an array.
    if (!info.FieldType.IsArray)
    {
        // It's not an array.
        property_value = info.GetValue(this);
        if (property_value == null)
            value = "<null>";
        else
            value = property_value.ToString();
    }
    else
    {
        // It is an array.
        name += "[]";
        // If it's an array of integers, get the values.
        if (info.FieldType.Name == "Int32[]")
        {
            Int32[] values = (Int32[])info.GetValue(this);
            if (values == null)
            {
                value = "<null>";
            }
            else
            {
                foreach (Int32 val in values)
                    value += ", " + val.ToString();
                if (value.Length > 0) value = value.Substring(2);
                value = "[" + value + "]";
            }
        }
        else
        {
            value = "<array>";
        }
    }

    ListViewMakeRow(lvwProperties, name,
        info.FieldType.ToString(),
        attributes, visibility, value);
}

The code gets the Form1 type and calls its GetFields method to get information about the class’s fields. See the example Use reflection to list a class’s properties in C# for information about the BindingFlags parameters.

The code then loops through the FieldInfo objects that GetFields returns. The code uses the FieldInfo object’s Name property to get the field’s name. It uses the object’s FieldType.Attributes property to get information about the field’s attributes.

Next, the code checks a series of FieldInfo properties to get information about the field’s accessibility and build a string describing the values.

The code then uses methods similar to those used by the earlier example to display the field’s value. This example also shows how to show the values in an integer array. If the field’s type name is Int32[] and the code can get its value, then the program loops through the field’s value (which is an array) and adds its entries to a string.

The code finishes by calling the ListViewMakeRow method to display the information in the form’s ListView control. Download the example program to see how that works.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in reflection | Tagged , , , , , , , , , , , , | Leave a comment

Use reflection to list SystemInformation properties in C#


[reflection]

This example shows how you can use reflection to get the properties defined by the SystemInformation class.

The SystemInformation class is chock-full of useful properties that give information about system parameters. These include such values as the thickness of a text caret, the size of menu buttons, the default font, and the name of the computer. The example Use reflection to list a class’s properties in C# explains how to list a class’s properties. This example uses the reflection techniques explained in that post to explore the SystemInformation class and list its properties and their values.

When the program’s form loads, the following code displays information about the class’s properties.

// List the SystemInformation class's properties.
object property_value;
PropertyInfo[] property_infos =
    typeof(SystemInformation).GetProperties(
        BindingFlags.FlattenHierarchy |
        BindingFlags.Instance |
        BindingFlags.NonPublic |
        BindingFlags.Public |
        BindingFlags.Static);
foreach (PropertyInfo info in property_infos)
{
    string name = info.Name;
    string value = "";

    // See if it's an array.
    if (!info.PropertyType.IsArray)
    {
        // It's not an array.
        if (info.CanRead) property_value =
            info.GetValue(this, null);
        else property_value = "---";

        if (property_value == null)
            value = "<null>";
        else
            value = property_value.ToString();
    }
    else
    {
        // It is an array.
        name += "[]";
        value = "lt;array>";
    }

    ListViewMakeRow(lvwProperties, name, value);
}

The code gets the SystemInformation class’s type and calls its GetProperties method to get information about the class’s properties. See the example Use reflection to list a class’s properties in C# for information about the BindingFlags parameters.

The code then loops through the PropertyInfo objects that GetProperties returns. The code gets the properties’ names and values, and calls the ListViewMakeRow method to display the information in the form’s ListView control. Download the example program to see how the ListViewMakeRow method works and for other details.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in reflection | Tagged , , , , , , , , , , , | 2 Comments

Use reflection to list a class’s properties in C#


[reflection]

This post begins a short series on using reflection. The tools that make C# work (such as the .NET Framework and the compiler that turns C# into IL code) use techniques that require them to learn a lot about the classes (and other things such as struct and enum) that go into a program. To make that possible, the whole system instruments classes so they know a lot about themselves. You can use those same reflection tools to query a class’s type to learn about it.

Reflection lets you discover such things as the properties, fields, methods, and events that a class provides. It also lets you learn other information about those items such as their data types, accessibility (public, private), and attributes. It lets you learn about your own classes and even classes that are pre-defined in the .NET Framework or in other libraries. It even lets you examine base classes. For example, a Windows Forms program usually has a Form1 class that inherits from the System.Windows.Form class. Reflection lets you see any properties, methods, and events that you added to the Form1 class, in addition to properties, methods, and events inherited from the Form class.

Often you don’t need to use reflection. If you’re writing the code, you know what you put into it. Even when you’re using a class that you didn’t write, such as a .NET Framework class, you can often use the documentation and IntelliSense to figure out how to use it. Sometimes, however, reflection can be useful for learning about undocumented features. I have used it occasionally to see what’s inside libraries that I’ve been working with that didn’t come with good documentation.

This example shows how to list a class’s properties. The example includes a lot of code dealing with displaying values in a ListView control. The following discussion omits that code and only shows the code that deals with reflection. Download the example program to see all the rest of the details.

To make using reflection easier, the form’s code starts with the following using directive.

using System.Reflection;

This example uses reflection to examine the Form1 class. To make it a bit easier to see the effects of different kinds of property declarations, the program uses the following code to add several properties to the class.

// Add some properties.
private int _MyPrivateProperty;
private int MyPrivateProperty
{
    get { return _MyPrivateProperty; }
    set { _MyPrivateProperty = value; }
}
public int MyPublicProperty
{
    get { return 2; }
    set { }
}
public static int MyPublicStaticProperty
{
    get { return 3; }
}
protected int MyProtectedProperty
{
    get { return 4; }
}
public virtual int MyPublicVirtualProperty
{
    set { }
}

All of the properties’ names begin with My so they all appear together in the program’s display.

This code defines:

  • A private property with a typical backing variable.
  • A public property that always returns the value 2.
  • A public read-only static property.
  • A protected read-only property.
  • A public virtual property.

When the form loads, the following code executes to display information about the Form1 class’s properties including those defined by the previous code. (The ListViewMakeRow method just displays values in the program’s ListView control. It doesn’t really have anything to do with reflection so you can ignore it for now.)

// List the properties.
// Use the class you want to study instead of Form1.
object property_value;
PropertyInfo[] property_infos = typeof(Form1).GetProperties(
    BindingFlags.FlattenHierarchy |
    BindingFlags.Instance |
    BindingFlags.NonPublic |
    BindingFlags.Public |
    BindingFlags.Static);
foreach (PropertyInfo info in property_infos)
{
    string name = info.Name;
    string attributes = info.PropertyType.Attributes.ToString();
    if (info.CanRead) attributes += " get";
    if (info.CanWrite) attributes += " set";

    string value = "";

    // See if it's an array.
    if (!info.PropertyType.IsArray)
    {
        // It's not an array.
        if (info.CanRead) property_value = info.GetValue(this, null);
        else property_value = "---";

        if (property_value == null)
            value = "<null>";
        else
            value = property_value.ToString();
    }
    else
    {
        // It is an array.
        name += "[]";
        value = "<array>";
    }

    ListViewMakeRow(lvwProperties, name,
        info.PropertyType.ToString(),
        attributes, value);
}

The code starts by using typeof(Form1) to get a System.Type object representing the Form1 class. It calls that object’s GetProperties method to get information about the properties defiend by the class. It passes GetProperties values to indicate what information it should return. The BindingFlag values that this code uses are:

  • FlattenHierarchy – Return information about properties that are inherited from parent classes
  • Instance – Return information about instance (non-static) properties
  • NonPublic – Return information about non-public properties
  • Public – Return information about public properties
  • Static – Return information about static properties

The code loops through the PropertyInfo objects returned by GetProperties. It uses the following PropertyInfo properties:

  • Name – Gives the property’s name
  • PropertyType.Attributes – Gives information about the property’s attributes
  • CanRead – True if the property is readable
  • CanWrite – True if the property is writable

Next, the code tries to get the property’s value. This can be somewhat tricky depending on the property’s data type and whether it is an array.

If the PropertyType.IsArray property indicates the property is not an array, the code uses CanRead to see if it can read the value. If the program can read the value, it uses the PropertyInfo object’s GetValue method to get the value for the current form object (this). If the program cannot read the value, it displays the value ---.

If the program got a property value object and that object is not null, the code calls its ToString method to convert it into a string and displays the result.

If the IsArray method indicates that the property is an array, the code adds brackets around the property’s name and displays its value as <array>.

Finally, the call to ListViewMakeRow displays the property’s information in the program’s ListView control. Download the example program to see how that works.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in reflection | Tagged , , , , , , , , , , | 2 Comments

Copy files to the clipboard in C#

[copy files]

The example Paste files from the clipboard in C# shows how a program can paste files from the clipboard. You can copy the files to the clipboard by selecting them in Windows Explorer and pressing Ctrl+C.

This example shows how a C# program can use code to copy files to the clipboard.

As you saw in the previous example, a list of files copied to the clipboard is actually an array of file names added to the clipboard with the data type FileDrop. This example simply builds an array of string names and places it in the clipboard, setting its data type to FileDrop.

The following code shows how the program does this.

private void Form1_Load(object sender, EventArgs e)
{
    // Copy some files to the clipboard.
    List<string> file_list = new List<string>();
    foreach (string file_name in
            Directory.GetFiles(Application.StartupPath))
        file_list.Add(file_name);
    Clipboard.Clear();
    Clipboard.SetData(DataFormats.FileDrop, file_list.ToArray());

    // Paste the file list back out of the clipboard.
    string[] file_names = (string[])
        Clipboard.GetData(DataFormats.FileDrop);

    // Display the pasted file names.
    lstFiles.DataSource = file_names;
}

First, the program makes an array of file names. This example makes a List<string> containing the files in the application’s startup directory, but your program can build the array in any way you like.

The code then clears the clipboard’s data and uses the Clipboard object’s SetData method to set the object’s data to the file names (converted into an array). It passes the SetData method the parameter FileDrop so the Clipboard knows this is a list of file names.

Next, to show that the clipboard contains the list of files, the program uses the Clipboard object’s GetData method to retrieve the file names. It sets the ListBox control’s DataSource to the array of file names so you can see them.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in clipboard, interoperability | Tagged , , , , , , , , , , , | Leave a comment

Paste files from the clipboard in C#

[paste files]

It’s a bit harder to paste files from the clipboard than it is to paste text. Copying and pasting text is relatively straightforward. See Copy and paste text to and from the clipboard C#.

When you copy files to the clipboard, the data copied is actually an array of strings holding the names of the files. This example shows how you can paste those files from the clipboard.

At design time, I set the form’s KeyPreview property to true so the form receives keyboard events before its controls do. The following KeyDown event handler looks for Ctrl+V events and pastes files.

// Handle paste events.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    // Look for Ctrl+V.
    if (e.Control && (e.KeyCode == Keys.V))
    {
        // Paste.
        // Clear the ListBox.
        lstFiles.Items.Clear();

        // Get the DataObject.
        IDataObject data_object = Clipboard.GetDataObject();

        // Look for a file drop.
        if (data_object.GetDataPresent(DataFormats.FileDrop))
        {
            string[] files = (string[])
                data_object.GetData(DataFormats.FileDrop);
            foreach (string file_name in files)
            {
                string name = file_name;
                if (System.IO.Directory.Exists(file_name))
                    name = "[" + name + "]";
                lstFiles.Items.Add(name);
            }
        }
    }
}

The code looks for a control key together with the V key. If it finds that, then it clears the form’s ListBox. It then gets the Clipboard object’s data object and uses that object’s GetDataPresent method to see if a file drop is present.

If there is a FileDrop present, the program uses the GetData method to get the data. The result is a generic object, so the code casts it into an array of strings.

Finally, the method loops through the array of file names, displaying them in the form’s ListBox.

If you look closely at the picture, you’ll see that the project’s bin, obj, and Properties subdirectories are included in the list. There’s no indication in the clipboard’s data that some of the “files” in the file drop are actually directories. You just get a list of names.

The program uses the System.IO.Directory.Exists method to test each file to see if it is actually a directory. If a file is a directory, the program adds [ brackets ] around its name before adding it to the ListBox.

In an actual program, you’ll need to decide what to do with the files that are pasted into your application. For example, you might copy them into a backup directory, display their text in a TextBox, or update their last modification times.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in clipboard, interoperability | Tagged , , , , , , , , , , , , | 1 Comment

Display a horizontal scrollbar in a ListBox in C#

[horizontal scrollbar]

Displaying a horizontal scrollbar is easy but useful. If you need to display some long values in a ListBox, you may want to be able to scroll to the right to see the ends of the values. For example, this program displays the names of the files in its application directory. On my system, the files are in a deep directory hierarchy so all of the values begin with the same long path. It’s much more useful to see the file names rather than the shared path.

To display the horizontal scroll bar, simply set the ListBox control’s HorizontalScrollbar property to true. You can do this at design time or at run time as shown in the following code.

private void Form1_Load(object sender, EventArgs e)
{
    lstFiles.HorizontalScrollbar = true;
    lstFiles.DataSource =
        Directory.GetFiles(Application.StartupPath);
}

This code sets the HorizontalScrollbar property and then makes the ListBox display the names of the files in the application’s startup directory.

Note that the ListBox only displays the scroll bar when it is necessary. If the values in the ListBox are short enough to fit, the scroll bar doesn’t appear. (Actually the control allows a bit of extra space so it may appear when it strictly doesn’t need to. The control seems to be trying to allow enough room for a vertical scroll bar in case that is needed. You get the idea, though.)


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in controls, user interface | Tagged , , , , , , , , , , , | Leave a comment

How to use the examples at C# Helper

[examples]

First, read over the text and the code shown on the web page. If you only need a small piece of code, that may be all you need. For example, if you don’t remember how to draw lines with custom dash patterns, then the post Draw lines with custom dash patterns in C# may be enough to refresh your memory and get the job done.

[examples]
Second, if the text of the post isn’t enough by itself, download the example! The text and code on the web page only describes the most interesting or confusing pieces of the example program and often that’s not enough to get a program to actually run. Often the downloadable example includes setup code, code that supports the main features, and properties and controls that are defined on the main form.

To see the whole example program, click the Download button at the bottom of the post.

Third, if you do download the example program, unzip it! Windows Explorer is smart enough to pretend a zip file is a normal directory, but Visual Studio isn’t that smart. If you use Windows Explorer to dig into the zip file, you can double-click on the .sln file and Visual Studio will start. Unfortunately Visual Studio gets confused and displays an uninformative error message such as the following.


[examples]

A similar problem may occur if you manage to open a project but then get permission errors or errors writing files. Either you don’t have permission for Visual Studio to write temporary files in the directory where you opened the project, or you managed to open the project inside the zip file and Visual Studio cannot figure out how to write the files inside it. In this case, make sure you have unzipped the file and make sure you have permission to write in your current directory.

Finally, make sure you have a new enough version of Visual Studio. I normally post examples in an older version of Visual Studio so you can open them in any newer version. Most of the examples were built in Visual Studio 2008 and any of the newer versions should be able to open them. If you’re using an even older version such as Visual Studio 2005, you might want to upgrade. You can download Visual Studio 2017 Community Edition for free here.

Good luck!


Follow me on Twitter   RSS feed   Donate




Posted in example program, miscellany | Tagged , , , , , , , | Leave a comment

Draw text on a circle in C#

[text on a circle]

This example uses some of the techniques described in the post Measure character positions when drawing long strings in C# to draw text on a circle. The previous post explains how to determine where the characters in a string will be drawn. In particular, it shows how to determine the width and height of each of the characters in a string.

The DrawTextOnCircle method shown in the following code uses that information to draw text along the top and bottom of a circle.


// Draw text centered on the top and bottom of the circle.
private void DrawTextOnCircle(Graphics gr, Font font,
    Brush brush, float radius, float cx, float cy,
    string top_text, string bottom_text)
{
    // Use a StringFormat to draw the middle
    // top of each character at (0, 0).
    using (StringFormat string_format = new StringFormat())
    {
        string_format.Alignment = StringAlignment.Center;
        string_format.LineAlignment = StringAlignment.Far;

        // Used to scale from radians to degrees.
        double radians_to_degrees = 180.0 / Math.PI;

        // **********************
        // * Draw the top text. *
        // **********************
        // Measure the characters.
        List<RectangleF> rects =
            MeasureCharacters(gr, font, top_text);

        // Use LINQ to add up the character widths.
        var width_query = from RectangleF rect in rects
            select rect.Width;
        float text_width = width_query.Sum();

        // Find the starting angle.
        double width_to_angle = 1 / radius;
        double start_angle = -Math.PI / 2 -
            text_width / 2 * width_to_angle;
        double theta = start_angle;

        // Draw the characters.
        for (int i = 0; i < top_text.Length; i++)
        {
            // See where this character goes.
            theta += rects[i].Width / 2 * width_to_angle;
            double x = cx + radius * Math.Cos(theta);
            double y = cy + radius * Math.Sin(theta);

            // Transform to position the character.
            gr.RotateTransform((float)(radians_to_degrees *
                (theta + Math.PI / 2)));
            gr.TranslateTransform((float)x, (float)y,
                MatrixOrder.Append);

            // Draw the character.
            gr.DrawString(top_text[i].ToString(), font, brush,
                0, 0, string_format);
            gr.ResetTransform();

            // Increment theta.
            theta += rects[i].Width / 2 * width_to_angle;
        }

        // *************************
        // * Draw the bottom text. *
        // *************************
        // Measure the characters.
        rects = MeasureCharacters(gr, font, bottom_text);

        // Use LINQ to add up the character widths.
        width_query = from RectangleF rect in rects
            select rect.Width;
        text_width = width_query.Sum();

        // Find the starting angle.
        width_to_angle = 1 / radius;
        start_angle = Math.PI / 2 +
            text_width / 2 * width_to_angle;
        theta = start_angle;

        // Reset the StringFormat to draw above the drawing origin.
        string_format.LineAlignment = StringAlignment.Near;

        // Draw the characters.
        for (int i = 0; i < bottom_text.Length; i++)
        {
            // See where this character goes.
            theta -= rects[i].Width / 2 * width_to_angle;
            double x = cx + radius * Math.Cos(theta);
            double y = cy + radius * Math.Sin(theta);

            // Transform to position the character.
            gr.RotateTransform((float)(radians_to_degrees *
                (theta - Math.PI / 2)));
            gr.TranslateTransform((float)x, (float)y,
                MatrixOrder.Append);

            // Draw the character.
            gr.DrawString(bottom_text[i].ToString(), font, brush,
                0, 0, string_format);
            gr.ResetTransform();

            // Increment theta.
            theta -= rects[i].Width / 2 * width_to_angle;
        }
    }
}

The method does some preliminary work and then draws the text on the top of the circle.

The code calls the MeasureCharacters method described in the earlier post to get the characters’ widths. It uses LINQ to add up the widths so it knows how long the entire string would be if drawn normally.

Next the code divides the string’s total width by 2 (to get half of the width) and divides the result by the circle’s radius (to get the angular size of half of the string). It subtracts that angular width from -π/2 to get the angle where the text should start. It then sets the variable theta equal to this starting angle.

[draw text]

The code then loops through the string’s characters. For each character, the code adds half of the character’s angular width to theta to find the angular position of the horizontal middle of the character. It then uses the circle’s radius, together with the sine and cosine functions, to calculate the position of this point on the circle. This point is where the bottom center of the character should be. (See the red point in the picture on the right.)

The next step is to apply a transformation to the Graphics object to rotate and translate the character to the desired position. The code first creates a rotation transformation to rotate the character appropriately. The angle theta + π/2 is at right angles to the character’s position angle theta. The result of that calculation is in radians, but the Graphics object’s RotateTransform method works in degrees, so the code translates from radians to degrees and then creates the rotation transformation.

Next, the code adds a translation transformation so the origin (0, 0) is translated to the red point on the circle shown in the previous picture.

If you look back at the beginning of the method, you’ll see these two lines:

string_format.Alignment = StringAlignment.Center;
string_format.LineAlignment = StringAlignment.Far;

These lines align text that is printed at a point so it is centered horizontally and drawn above the point. That’s exactly the situation we need for the red point in the previous picture. The code simply draws the character at the origin (0, 0) and the transformations rotate and translate it into position.

The loop finishes by resetting the Graphics object’s transformation (to remove the current transformations) and adding half of the character’s angular width to theta to move to the beginning of the next character’s position on the circle.

[draw text]

Next, the code draws the text below the circle. The steps are very similar to those used to draw the text above the circle. The biggest change is that this time the code must draw the characters below the circle. (See the blue point in the picture on the right.) To do that, the code simply uses the following statement.

// Reset the StringFormat to draw below
// the drawing origin.
string_format.LineAlignment = StringAlignment.Near;

The code also decreases theta with each character (to move left-to-right across the bottom of the circle), and it rotates the characters differently so they don’t appear upside down. See the code for additional details.

Note that this kind of text that follows a path looks best if the path doesn’t curve too abruptly. In this example, that means the circle has a large radius.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, fonts, geometry, graphics, strings | Tagged , , , , , , , , , , , , , , , , , , , | Leave a comment

List Dictionary keys and values in C#

[dictionary]

A Dictionary object’s Keys property is a KeyCollection containing the dictionary’s keys. Similarly, its Values property is a ValueCollection containing the dictionary’s values. These collections are slightly different from the List objects that you probably use in your code. In particular, you cannot use index these collections the way you can an array or List.

However, you can use a foreach loop to iterate through the collections and you can use ToArray to copy their values into normal arrays.

This example uses the following code to initialize a Dictionary.

// The dictionary of digit names.
private Dictionary<int, string> Numbers =
    new Dictionary<int, string>()
{
    {0, "Zero"},
    {1, "One"},
    {2, "Two"},
    {3, "Three"},
    {4, "Four"},
    {5, "Five"},
    {6, "Six"},
    {7, "Seven"},
    {8, "Either"},
    {9, "Nine"}
};

The form’s Load event handler then uses the following code to display the Dictionary object’s keys, values, and key/value pairs.

private void Form1_Load(object sender, EventArgs e)
{
    // Display the keys.
    foreach (int number in Numbers.Keys)
        lstKeys.Items.Add(number);

    // Convert the Dictionary's ValueCollection
    // into an array and display the values.
    string[] values = Numbers.Values.ToArray();
    for (int i = 0; i < values.Length; i++)
        lstValues.Items.Add(values[i]);

    // Display the keys and values.
    foreach (int number in Numbers.Keys)
        lstKeysAndValues.Items.Add(number.ToString() +
            ": " + Numbers[number]);
}

First, the code uses a foreach loop to iterate through the Dictionary object’s Keys collection, adding each key value to the ListBox named lstKeys.

Next, the program uses ToArray to convert the Dictionary object’s Values collection into an array. It then uses a for loop to loop through the array, adding each value to the lstValues ListBox. This kind of for loop will not work with the Values collection itself.

Finally, the code uses a foreach loop to iterate over the keys in the Dictionary object’s Keys collection. It uses the key values as indices into the Dictionary and displays each key and its corresponding value in the lstKeysAndValues ListBox.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, controls, lists | Tagged , , , , , , , , , , , , | Leave a comment

Animate a point on a polar coordinate curve in C#

[animate]

The example Graph a curve in polar coordinates in C# explained how to draw the flower-like curve on the right. Once you know how to draw such a curve, it’s not too hard to animate points moving along it.

The major changes this example makes to the previous one are the following.

  • This version saves the image of the curve so it can use it later to redraw the curve
  • This version saves the points on the curve so it can use them later to position the animated point
  • This version uses a Timer to periodically redraw the image with the moving point on it

The following code declares the program’s class-level variables.

// The background Bitmap.
private Bitmap Background;

// The points on the curve.
private List<PointF> Points;

// The transformation used to draw.
private Matrix Transform;

// The current point number where the atom is.
private int AtomPoint = 0;

This code declares the following variables.

  • Background – Holds an image of the curve.
  • Points – Holds the points that define the curve. The program uses them to draw the curve (as before) and to position the animated point as it moves along the curve.
  • Transform – Holds the drawing transformation matrix. The program uses it to draw the point in the correct position.
  • AtomPoint – The index in the Points list of the moving point.

The program’s Form_Load event handler is almost exactly as in the previous example. The only differences are that it enables double buffering (to make the animation smoother) and that it enables the tmrMoveAtom Timer. The following code shows the event handler with the unchanged code removed.

// Draw the graph.
private void Form1_Load(object sender, EventArgs e)
{
    // Enable double buffering.
    this.DoubleBuffered = true;

    // Make the Bitmap and associated Graphics object.
    ...

    // Enable the atom timer.
    tmrMoveAtom.Enabled = true;
}

The DrawGraph method also works almost exactly as before. The only real difference is that method uses the following code to save the drawing transformation in the class-level Transform variable.

// Set up a transformation to map the region
// -2.1 <= X <= 2.1, -2.1 <= Y <= 2.1 onto the  Bitmap.
RectangleF rect = new RectangleF(-2.1f, -2.1f, 4.2f, 4.2f);
PointF[] pts =
    {
        new PointF(0, Background.Height),
        new PointF(Background.Width, Background.Height),
        new PointF(0, 0),
    };
Transform = new Matrix(rect, pts);
gr.Transform = Transform;

The program uses this transformation later to draw the animated point so it is in the correct location on the drawing.

When the Form_Load event handler calls DrawGraph, it passes it the form-level Background Bitmap so the image is available later.

The only really new piece of code is the following event handler, which executes when the tmrMoveAtom Timer fires its Tick event (about 50 times per second).

// Draw the atom.
private void tmrMoveAtom_Tick(object sender, EventArgs e)
{
    // Refresh the image with the background.
    Bitmap bm = (Bitmap)Background.Clone();

    // Draw the atom.
    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.Transform = Transform;
        gr.SmoothingMode = SmoothingMode.AntiAlias;
        gr.FillEllipse(Brushes.Green,
            Points[AtomPoint].X - 0.075f,
            Points[AtomPoint].Y - 0.075f,
            0.15f, 0.15f);
    }

    // Display the result.
    picGraph.Image = bm;

    // Move the atom.
    AtomPoint = (AtomPoint + 1) % Points.Count;
}

This code makes a Bitmap that is a copy of the Background bitmap. This is a picture of the curve without the moving point on it. (Note that the Clone method returns an object, so the code must cast it into a Bitmap to save it in a Bitmap variable.)

The code makes a Graphics object associated with the copied Bitmap. It then sets that object’s Transform property to the class-level Transform variable. That makes this Graphics object use the same drawing transformation that was used to originally draw the curve.

The code also sets the Graphics object’s SmoothingMode property to AntiAlias so it draws smoothly.

The event handler then draws an ellipse at point number AtomPoint in the Points list and displays the result (the Background image plus the point).

The code finishes by incrementing AtomPoint so the next time the Tick event fires it draws the point in the next location. The modulus operator % makes AtomPoint start over at the first point after the program has used the last point.

Note that you can use the same technique to animate points moving along just about any curve. The basic steps are:

  • Save an image of the curve in a class-level variable
  • Save the list of points on the curve in a class-level variable
  • In a Timer component’s Tick event handler, redraw the curve’s image and draw the point on top of it
  • Increment the index of the point in the points list


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, animation, graphics, mathematics | Tagged , , , , , , , , , , , , , , , | Leave a comment