Draw a histogram with tooltips in C#

[histogram]

The example Draw a simple histogram in C# explains how to draw a simple histogram. When you click on a bar, that program displays a message box showing the bar’s value. This example takes a different approach. When you move the mouse over a bar, the program displays its value in a tooltip.

This version generates random data and displays it as before. The only feature of that piece of code is that the program now saves the transformation it uses to draw the histogram’s bars so it can use the transformation later.

// Draw a histogram.
private Matrix Transformation;
private void DrawHistogram(Graphics gr, Color back_color,
    float[] values, int width, int height)
{
    ...
    Transformation = new Matrix(data_bounds, points);
    gr.Transform = Transformation;
    ...
}

The following code shows the only really new piece of code, the PictureBox‘s MouseMove event handler.

// Record the mouse position.
private string TipText;
private void picHisto_MouseMove(object sender, MouseEventArgs e)
{
    // Determine which data value is under the mouse.
    float bar_wid =
        picHisto.ClientSize.Width / (int)DataValues.Length;
    int bar_number = (int)(e.X / bar_wid);
    if (bar_number >= DataValues.Length) return;

    // Get the coordinates of the top of the bar.
    PointF[] points =
        { new PointF(0, DataValues[bar_number]) };
    Transformation.TransformPoints(points);

    // See if the mouse is over the bar and not the space above it.
    string tip = "";
    if (e.Y >= points[0].Y) tip =
        "Item " + (bar_number + 1) + " has value " +
        DataValues[bar_number];

    // Update the tooltip if it has changed.
    if (TipText != tip)
    {
        TipText = tip;
        tipBar.SetToolTip(picHisto, tip);
    }
}

This code divides the PictureBox‘s width by the number of bars to determine the width of a bar. It then divides the mouse’s X coordinate by that width to see which bar contains the mouse’s position.

There’s a chance that rounding errors will give the bar a greater number than the number of bars (basically if the mouse is right at the edge of the PictureBox, so the code compares bar_number to the number of bars and returns if this is the case.

Otherwise the code creates an array holding a point with Y coordinate equal to the bar’s value. It then uses the transformation to transform the point. The resulting Y coordinate gives the top of the bar as it is drawn on the PictureBox.

If the mouse’s Y coordinate is greater than or equal to the transformed coordinate, then the mouse is actually on top of the bar and not sitting above it with a smaller Y coordinate. In that case, the code composes the tooltip text. If the mouse’s Y position is above the bar, the code sets the text to an empty string.

Finally, if the tooltip text is different from the previously displayed value, the program uses the tipBar ToolTip control’s SetToolTip method to set the PictureBox‘s tooltip. (As an experiment, see what happens if you call SetToolTip without checking to see if the text has changed. It’s pretty annoying.)


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in drawing, graphics, mathematics and tagged , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *