Show tooltip in LineSeries WinForms Chart? - c#

I am working on a Dashboard System where i am using Line Chart in WinForms. I need to show the tooptip on each line. I have tried this
var series = new Series
{
Name = chartPoint.SetName,
Color = chartPoint.ChartColor,
ChartType = SeriesChartType.Line,
BorderDashStyle = chartPoint.ChartDashStyle,
BorderWidth = chartPoint.BorderWidth,
IsVisibleInLegend = !chartPoint.HideLegend,
ToolTip = "Hello World"
};
but its not working for me

You have two options either use Keywords accepted by the Chart control.
myChart.Series[0].ToolTip = "Name #SERIESNAME : X - #VALX{F2} , Y - #VALY{F2}";
In the Chart control, a Keyword is a character sequence that is replaced with an automatically calculated value at run time. For a comprehensive list of keywords accepted by the Chart control look up Keyword reference
or
if you want something more fanciful, you have to handle the event GetToolTipText
this.myChart.GetToolTipText += new System.Windows.Forms.DataVisualization.Charting.Chart.ToolTipEventHandler(this.myChart_GetToolTipText);
Now I am not sure what you want to show on the ToolTip but you could add the logic accordingly. Assuming you want to show the values of the DataPoints in the series
private void myChart_GetToolTipText(object sender, System.Windows.Forms.DataVisualization.Charting.ToolTipEventArgs e)
{
switch(e.HitTestResult.ChartElementType)
{
case ChartElementType.DataPoint:
e.Text = myChart.Series[0].Points[e.HitTestResult.PointIndex]).ToString()
+ /* something for which no keyword exists */;
break;
case ChartElementType.Axis:
// add logic here
case ....
.
.
default:
// do nothing
}

After some RnD i got tooltips on Line Series, but still confused why its not working with this solution.
Here is the solution
series.ToolTip = string.Format("Name '{0}' : X - {1} , Y - {2}", chartPoint.SetName, "#VALX{F2}",
"#VALY{F2}");
mainChartControl.GetToolTipText += ChartControlGetToolTipText;
private void ChartControlGetToolTipText(object sender, ToolTipEventArgs e)
{
}

Related

How to highlight HTML syntax in C# windows form RichTextBox?

I am writing a c# Html editor application, in which you type the code in a RichTextBox control. I want the RichTextBox to behave like notepad++ and other code editors in which the Html syntax gets highlighted in colors, like this for example:
How can I establish this in C# windows form RichTextBox? I have searched almost everywhere and didn't find anything that helped me. This is what I tried so far but I doesn't give the result I want:
private void SyntaxHighlight()
{
string[] tags = { "html","head","body","a","b","img","strong","p","h1","h2","h3","h4","h5","h6","embed","iframe","span","form",
"button","input","textarea","br","div","style","script","table","tr","td","th","i","u","link","meta","title"};
foreach (string s in tags)
{
richTextBox1.Find("<" + s);
richTextBox1.SelectionColor = Color.Blue;
richTextBox1.Find(">");
richTextBox1.SelectionColor = Color.Blue;
}
string[] attributes = { "href","src","height","width","rowspan","colspan","target","style","onclick","id","name","class"};
foreach (string s in attributes)
{
richTextBox1.Find(s + "=");
richTextBox1.SelectionColor = Color.Red;
}
}
Can someone help me? What should I write inside the SyntaxHighlight() method? can someone give me the appropriate code?
Thank you
Within your code you are only finding the 1st occurrence of the HTML tag and highlighting it. But instead, you should loop through the entire rich text content to finding proceeding occurrences of the same text. I just did a quick mock based on your exact code, please check it out.
private void highlightHTMLText()
{
string[] tags = { "html","head","body","a","b","img","strong","p","h1","h2","h3","h4","h5","h6","embed","iframe","span","form",
"button","input","textarea","br","div","style","script","table","tr","td","th","i","u","link","meta","title"};
foreach (string s in tags)
{
findAndHighlight("<" + s, Color.Blue);
findAndHighlight("</" + s, Color.Blue);
findAndHighlight(">", Color.Blue);
}
string[] attributes = { "href", "src", "height", "width", "rowspan", "colspan", "target", "style", "onclick", "id", "name", "class" };
foreach (string s in attributes)
{
findAndHighlight(s + "=", Color.Red);
}
}
private void findAndHighlight(string sSearchStr, Color oColor)
{
int index = richTextBox1.Text.IndexOf(sSearchStr);
while (index != -1)
{
richTextBox1.Select(index, sSearchStr.Length);
richTextBox1.SelectionColor = oColor;
index = richTextBox1.Text.IndexOf(sSearchStr, index + sSearchStr.Length);
}
}
Further as per this answer you should be able to make use of the same utility library Scintilla used by Notepad++ itself. As pointed out you do not need to re-invent the wheel, but as a developer I obviously prefer my own util (it is just me ;) ). Hope this helps.
Find doesn't move a cursor, it returns the location of the first match. Try this instead:
How to select text from the RichTextBox and then color it?
A little late to the party but, after wanting to create my own offline version of CodePen, I implemented my own version of html syntax highlighting following CodePen's theme.
This does syntax highlighting and markup formatting, though the formatting depends on whether or not your html is well-formed.
Just add this as a class for your RichTextBox, instantiate it accordingly and call it within whichever event works for you (I'm using it with the RTB's double_click event but that does eliminate double-click text selection). What I'm planning to do is add a timer, some boolean variables and work this within the key_up and key_down events to set the highlight update to be a bit more automatic and less intrusive on shortcuts. (which is hereby included below the class)
public void HighlightHTM(RichTextBox Htm_Input)
{
Htm_Input.Visible = false;
#region store the original caret position + forecolor
int originalIndex = Htm_Input.SelectionStart;
int originalLength = Htm_Input.SelectionLength;
Color originalColor = Color.FromArgb(200, 200, 200); // Grey
#endregion
#region try to format the markup
try { Htm_Input.Text = XElement.Parse(Htm_Input.Text).ToString(); } catch { }
#endregion
#region match everything but puncutation and equals
Regex e = new Regex(#"(.*?|=)[^\w\s]");
MatchCollection eMatches = e.Matches(Htm_Input.Text);
foreach (Match m in eMatches)
{
Htm_Input.SelectionStart = m.Groups[1].Index;
Htm_Input.SelectionLength = m.Groups[1].Length;
Htm_Input.SelectionColor = Color.FromArgb(221, 202, 126); // Yellow
}
#endregion
#region match tags
Regex t = new Regex(#"(<\w+|</\w+|/>|>)[^=]");
MatchCollection tMatches = t.Matches(Htm_Input.Text, 0);
foreach (Match m in tMatches)
{
Htm_Input.SelectionStart = m.Groups[1].Index;
Htm_Input.SelectionLength = m.Groups[1].Length;
Htm_Input.SelectionColor = Color.FromArgb(167, 146, 90); // Brown
}
#endregion
#region match quotes
Regex q = new Regex("\".*?\"");
MatchCollection qMatches = q.Matches(Htm_Input.Text);
foreach (Match m in qMatches)
{
Htm_Input.SelectionStart = m.Index;
Htm_Input.SelectionLength = m.Length;
Htm_Input.SelectionColor = Color.FromArgb(150, 179, 138); // Green
}
#endregion
#region match inner html
Regex h = new Regex(">(.+?)<");
MatchCollection hMatches = h.Matches(Htm_Input.Text);
foreach (Match m in hMatches)
{
Htm_Input.SelectionStart = m.Groups[1].Index;
Htm_Input.SelectionLength = m.Groups[1].Length;
Htm_Input.SelectionColor = Color.FromArgb(200, 200, 200); // Grey
}
#endregion
#region restoring the original colors, for further writing
Htm_Input.SelectionStart = originalIndex;
Htm_Input.SelectionLength = originalLength;
Htm_Input.SelectionColor = originalColor; // Light Grey
#endregion
Htm_Input.Focus();
Htm_Input.Visible = true;
}
Happy coding!
Edit: I should also mention that !doctype breaks formatting as it's not exactly xml-friendly in the context of "well-formed". For my purposes, all tags including body and relevant closings, css and js links are added programmatically at page save so only markup within the body tags are worked with inside the html RTB. This eliminates that problem.
You'll notice that this relies exclusively on Regex rather than on hard-coded tags and properties. I did this because tags and properties have a tendency to pop on and off the w3 scene quite often. That would force a dev to continually have to go back and edit those strings to remove deprecated tags / properties or to add new. Not optimal.
I also thought it prudent to go ahead and include the instantiation / usage examples to make this a bit more plug&play.
Above public Main(), instantiate like so:
#region Class Instantiation
SyntaxHighlight syntax = new SyntaxHighlight();
#endregion
... and, within your chosen event handler, call it like so:
private void htm_input_DoubleClick(object sender, EventArgs e)
{
syntax.HighlightHTM(Htm_Input);
}
Naturally, adding a SaveFileDialog and an OpenFileDialog pretty much provides this the functionality of your very own, albeit very basic, html editor. Toss in a WebBrowser control and apply the RTB's text as the WebBrowser's source and you've upgraded to live-view.
In the very least, this should serve as a viable reference for syntax highlighting in general. It really just boils down to identifying patterns and manipulating their colors so, for example, this will work effectively with css, javascript and even C# with some light adjusting of the pattern identification parameters.
The following is how I setup the automatic refresh with key_up / key_down and a timer set to 1000 ms:
#region Globals
int r = 0;
bool refresh = false;
#endregion
private void Htm_Input_KeyUp(object sender, KeyEventArgs e)
{
refresh = true; // enter refresh cycle
}
private void Htm_Input_KeyDown(object sender, KeyEventArgs e)
{
refresh = false; // abort refresh cycle
}
private void Timer_Refresh_Tick(object sender, EventArgs e)
{
// check if refresh cycle is entered, refresh at 3 seconds or reset the counter if aborted
if (refresh) { if (r == 3) { syntax.HighlightHTM(Htm_Input); refresh = false; r = 0; } r++; } else { r = 0; }
}

C# .NET Chart - Adding a legend scrollbar and checkboxes

I am using the Chart class in Visual Studio 2013 to visualize some of my data. However, my data quickly spawns many series and it's very important to have them all in one chart. I limited the legend area to 20% of the complete chart area, and so I pretty much cannot display more than 7-8 legend items when I stretch my chart to its maximum size. The control just puts ... after it runs out of space for legend items.
Instead of it just writing ..., is it somehow possible to add a scrollbar to the legend and be able to see all of the items? I am aware that I can implement my own legend in some way, but I would like to squeeze the most out of what the Chart class has to offer. I would also like to add checkboxes next to each legend item which would indicate whether the series should be hidden on the chart or not. Is this possible to do without my own legend implementation?
Additionally, I would also like to have a menu expand on right click on a legend item with a few options, but that's completely optional. Scrollbar and checkboxes are my main problem now.
Thanks.
General idea: You have to create two charts. One is main and second for legend only. You will have same series style if series order will be the same.
For showing pop up on right click on legend item:
Connect ContextMenu (ContextMenuStrip class in toolbox) to your legend's chart.
For showing hiding series from legend:
You have to implement MouseClick event handler and check what object is under mouse cursor using math (GetChildAtPoint() method doesn't work for legend items). Equation: is series_index = control_relative_mouse_y / c_legendItemHeight where c_legendItemHeight is value you provide to compute controls height (height of single legend item).
You have to configure your legend chart to contain LegendStyle to Row, MaximumAutoSize to 100, Docking to Left, IsTextAutoFit to false and IsEquallySpacedItems to true.
You have define 3 columns in your legend (one for series style, second for checkbox and third for series name). Use series CustomProperties to keep visibility state. In check column use this custom property (Text = "#CUSTOMPROPERTY(...)") to show check state. Chart does not support auto sizing. You can do it manually. During series load set your chart height to calculated value. This value equals to _stock.Shares.Count * c_legendItemHeight + 9. Where: _stock.Shares.Count is number of items in legend, c_legendItemHeight constant height of item (integer value, numbers grater then 18 seems to work for me), 9 (seems to be constant). I know it is not nice but I cannot find any better solution. I've added 502 series in my example and it worked fine. Make sure that you don't have any margin in your chart because otherwise you will be not able to calculate series number correctly.
For "many series in legend" problem:
Put your legend chart into a panel with AutoScroll property turned on. Set panels and legends height using expression from above description.
Source code:
public partial class Form1 : Form
{
private const int c_legendItemHeight = 20;
private const string c_checkCustomPropertyName = "CHECK";
private const string c_checkedString = "✔"; // see http://www.edlazorvfx.com/ysu/html/ascii.html for more
private const string c_uncheckedString = "✘";
private Stock _stock;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
_stock = Stock.Load();
// mainChart
mainChart.Legends.Clear();
foreach (Share share in _stock.Shares)
{
Series series = mainChart.Series.Add(share.Name);
series.ChartType = SeriesChartType.Line;
foreach (ShareQuotation shareQuotation in share.Quotations)
{
series.Points.AddXY(shareQuotation.Date.ToString(), shareQuotation.Close);
}
}
// LegendChart
Legend legend = legendChart.Legends[0];
legendChart.Series.Clear();
legend.IsTextAutoFit = false;
legend.IsEquallySpacedItems = true;
legend.MaximumAutoSize = 100;
legend.Docking = Docking.Left;
legend.LegendStyle = LegendStyle.Column;
legend.Position.Auto = true;
legend.Position.Width = 100;
legend.Position.Height = 100;
legend.CellColumns[1].Text = "#CUSTOMPROPERTY(" +c_checkCustomPropertyName+ ")";
foreach (Share share in _stock.Shares)
{
Series series = legendChart.Series.Add(share.Name);
series.SetCustomProperty(c_checkCustomPropertyName,c_checkedString);
}
legendChart.Height = _stock.Shares.Count * c_legendItemHeight + 9; // 9 - seems to be constant value
legendPanel.Height = legendChart.Height;
}
private void legendChart_MouseClick(object sender, MouseEventArgs e)
{
Point mousePosition = legendChart.PointToClient(Control.MousePosition);
int seriesNo = mousePosition.Y / c_legendItemHeight;
Series series = legendChart.Series[seriesNo]; // TODO - check if not out of range
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
// check uncheck series
if (series.GetCustomProperty(c_checkCustomPropertyName) == c_checkedString)
{
// if checked
// uncheck
series.SetCustomProperty(c_checkCustomPropertyName, c_uncheckedString);
series.CustomProperties = series.CustomProperties; // workaround - trigger change - is this a bug?
// hide in mainChart
mainChart.Series[seriesNo].Enabled = false;
}
else
{
// if unchecked
legendChart.Series[seriesNo].SetCustomProperty(c_checkCustomPropertyName, c_checkedString);
series.CustomProperties = series.CustomProperties; // workaround - trigger change - is this a bug?
// show in mainChart
mainChart.Series[seriesNo].Enabled = true;
}
}
}
private void contextMenu_Opening(object sender, CancelEventArgs e)
{
Point mousePosition = legendChart.PointToClient(Control.MousePosition);
int seriesNo = mousePosition.Y / c_legendItemHeight;
Series series = legendChart.Series[seriesNo]; // TODO - check if not out of range
contextMenu.Items.Clear();
string state = series.GetCustomProperty(c_checkCustomPropertyName) == c_checkedString ? "visible" : "hidden";
contextMenu.Items.Add("&Some strange action for " + state + " item named " + series.Name);
contextMenu.Items.Add("&Another action ...");
}
}
Result should look like this:

Links inside rich textbox?

I know that richtextboxes can detect links (like http://www.yahoo.com) but is there a way for me to add links to it that looks like text but its a link? Like where you can choose the label of the link? For example instead of it appearing as http://www.yahoo.com it appears as Click here to go to yahoo
edit: forgot, im using windows forms
edit: is there something thats better to use (as in easier to format)?
Of course it is possible by invoking some WIN32 functionality into your control, but if you are looking for some standard ways, check this post out:
Create hyperlink in TextBox control
There are some discussions about different ways of integration.
greetings
Update 1:
The best thing is to follow this method:
http://msdn.microsoft.com/en-us/library/f591a55w.aspx
because the RichText box controls provides some functionality to "DetectUrls". Then you can handle the clicked links very easy:
this.richTextBox1.LinkClicked += new System.Windows.Forms.LinkClickedEventHandler(this.richTextBox1_LinkClicked);
and you can simple create your own RichTextBox contorl by extending the base class - there you can override the methods you need, for example the DetectUrls.
Here you can find an example of adding a link in rich Textbox by linkLabel:
LinkLabel link = new LinkLabel();
link.Text = "something";
link.LinkClicked += new LinkLabelLinkClickedEventHandler(this.link_LinkClicked);
LinkLabel.Link data = new LinkLabel.Link();
data.LinkData = #"C:\";
link.Links.Add(data);
link.AutoSize = true;
link.Location =
this.richTextBox1.GetPositionFromCharIndex(this.richTextBox1.TextLength);
this.richTextBox1.Controls.Add(link);
this.richTextBox1.AppendText(link.Text + " ");
this.richTextBox1.SelectionStart = this.richTextBox1.TextLength;
And here is the handler:
private void link_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start(e.Link.LinkData.ToString());
}
I found a way which may not be the most elegant, but it's just a few lines of code and does the job. Namely, the idea is to simulate hyperlink appearance by means of font changes, and simulate hyperlink behavior by detecting what the mouse pointer is on.
The code:
public partial class Form1 : Form
{
private Cursor defaultRichTextBoxCursor = Cursors.Default;
private const string HOT_TEXT = "click here";
private bool mouseOnHotText = false;
// ... Lines skipped (constructor, etc.)
private void Form1_Load(object sender, EventArgs e)
{
// save the right cursor for later
this.defaultRichTextBoxCursor = richTextBox1.Cursor;
// Output some sample text, some of which contains
// the trigger string (HOT_TEXT)
richTextBox1.SelectionFont = new Font("Calibri", 11, FontStyle.Underline);
richTextBox1.SelectionColor = Color.Blue;
// output "click here" with blue underlined font
richTextBox1.SelectedText = HOT_TEXT + "\n";
richTextBox1.SelectionFont = new Font("Calibri", 11, FontStyle.Regular);
richTextBox1.SelectionColor = Color.Black;
richTextBox1.SelectedText = "Some regular text";
}
private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
{
int mousePointerCharIndex = richTextBox1.GetCharIndexFromPosition(e.Location);
int mousePointerLine = richTextBox1.GetLineFromCharIndex(mousePointerCharIndex);
int firstCharIndexInMousePointerLine = richTextBox1.GetFirstCharIndexFromLine(mousePointerLine);
int firstCharIndexInNextLine = richTextBox1.GetFirstCharIndexFromLine(mousePointerLine + 1);
if (firstCharIndexInNextLine < 0)
{
firstCharIndexInNextLine = richTextBox1.Text.Length;
}
// See where the hyperlink starts, as long as it's on the same line
// over which the mouse is
int hotTextStartIndex = richTextBox1.Find(
HOT_TEXT, firstCharIndexInMousePointerLine, firstCharIndexInNextLine, RichTextBoxFinds.NoHighlight);
if (hotTextStartIndex >= 0 &&
mousePointerCharIndex >= hotTextStartIndex && mousePointerCharIndex < hotTextStartIndex + HOT_TEXT.Length)
{
// Simulate hyperlink behavior
richTextBox1.Cursor = Cursors.Hand;
mouseOnHotText = true;
}
else
{
richTextBox1.Cursor = defaultRichTextBoxCursor;
mouseOnHotText = false;
}
toolStripStatusLabel1.Text = mousePointerCharIndex.ToString();
}
private void richTextBox1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && mouseOnHotText)
{
// Insert your own URL here, to navigate to when "hot text" is clicked
Process.Start("http://www.google.com");
}
}
}
To improve on the code, one could create an elegant way to map multiple "hot text" strings to their own linked URLs (a Dictionary<K, V> maybe). An additional improvement would be to subclass RichTextBox to encapsulate the functionality that's in the code above.
Many moons later there is a solution for .NET (Core), as of at least .NET 6.0 (possibly earlier) - for .NET Framework (whose latest and last version is 4.8) you'll still need one of the other solutions here:
The .Rtf property now recognizes RTF-format hyperlinks; e.g., the following renders as:
This is a true RTF hyperlink: Example Link
this.richTextBox1.Rtf = #"{\rtf1 This is a true RTF hyperlink:\line {\field{\*\fldinst HYPERLINK ""https://example.org""}{\fldrslt Example Link}}} }";
The standard RichTextBox control (assuming you are using Windows Forms) exposes a rather limited set of features, so unfortunately you will need to do some Win32 interop to achieve that (along the lines of SendMessage(), CFM_LINK, EM_SETCHARFORMAT etc.).
You can find more information on how to do that in this answer here on SO.

WinForms Dynamic Label

I am creating dynamic labels and letting users change attributes of the labes like backcolor and so by sending unicode. However I don't know how to check if the label exists therefore I can't manipulate the dynamicly created label. below is my code:
if ((InputBox.Text.StartsWith("π")) && (InputBox.Text.EndsWith("}")))// only process if the message starts with π and ends with }
{
string Message = InputBox.Text;
InputBox.Text = "";// Clear the box when done.
// Butt1 message line
if (Message.StartsWith("πlabelt1"))
{
if (Message.StartsWith("πlabelt1_BackColor"))
{
Message = Message.Substring(19);
//labelt1.BackColor = System.Drawing.Color.FromName(Message.Replace("}", ""));
}
}
private void ImageBox_DragDrop(object sender, DragEventArgs e)
{
//Graphics g = ImageBox.CreateGraphics();
//g.DrawImage((Image)e.Data.GetData(DataFormats.Bitmap),
//new Point(e.X - this.Left, e.Y - this.Top - 150));
Point p2 = PointToClient(Cursor.Position);
Label buttlbl_ = new Label();
labelCount++;
buttlbl_.Name = "labelt" + labelCount.ToString();
buttlbl_.Location = new Point(p2.X, p2.Y);
buttlbl_.Size = new System.Drawing.Size(37, 37);
buttlbl_.BackColor = System.Drawing.Color.DarkGray;
this.Controls.Add(buttlbl_);
buttlbl_.BringToFront();
ImageBox.Invalidate();
}
}
Any suggestions?
you may set buttlbl_ as a class member so you can check if it is created
before creation you can find it in this.Controls collection (by id)
I think you've approached this problem incorrectly. You are apparently trying to offer the user an opportunity to edit these textboxes using a language-based interface. You either need to build a full parser to help you here or to look at an alternative paradigm, perhaps following the same approach that VS uses to allow you to create and edit labels via a GUI-type interface. That way you can maintain a tighter control over the actions that can be completed without the complexity of 'natural' language parsing.

Can I display links in a ListView's detail mode?

I'm displaying a set of search results in a ListView. The first column holds the search term, and the second shows the number of matches.
There are tens of thousands of rows, so the ListView is in virtual mode.
I'd like to change this so that the second column shows the matches as hyperlinks, in the same way as a LinkLabel shows links; when the user clicks on the link, I'd like to receive an event that will let me open up the match elsewhere in our application.
Is this possible, and if so, how?
EDIT: I don't think I've been sufficiently clear - I want multiple hyperlinks in a single column, just as it is possible to have multiple hyperlinks in a single LinkLabel.
You can easily fake it. Ensure that the list view items you add have UseItemStyleForSubItems = false so that you can set the sub-item's ForeColor to blue. Implement the MouseMove event so you can underline the "link" and change the cursor. For example:
ListViewItem.ListViewSubItem mSelected;
private void listView1_MouseMove(object sender, MouseEventArgs e) {
var info = listView1.HitTest(e.Location);
if (info.SubItem == mSelected) return;
if (mSelected != null) mSelected.Font = listView1.Font;
mSelected = null;
listView1.Cursor = Cursors.Default;
if (info.SubItem != null && info.Item.SubItems[1] == info.SubItem) {
info.SubItem.Font = new Font(info.SubItem.Font, FontStyle.Underline);
listView1.Cursor = Cursors.Hand;
mSelected = info.SubItem;
}
}
Note that this snippet checks if the 2nd column is hovered, tweak as needed.
Use ObjectListView -- an open source wrapper around a standard ListView. It supports links directly:
This recipe documents the (very simple) process and how you can customise it.
The other answers here are great, but if you don't want to have to hack some code together, look at the DataGridView control which has support for LinkLabel equivalent columns.
Using this control, you get all the functionality of the details view in a ListView, but with more customisation per row.
You can by inheriting the ListView control override the method OnDrawSubItem.
Here is a VERY simple example of how you might do:
public class MyListView : ListView
{
private Brush m_brush;
private Pen m_pen;
public MyListView()
{
this.OwnerDraw = true;
m_brush = new SolidBrush(Color.Blue);
m_pen = new Pen(m_brush)
}
protected override void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
{
e.DrawDefault = true;
}
protected override void OnDrawSubItem(DrawListViewSubItemEventArgs e)
{
if (e.ColumnIndex != 1) {
e.DrawDefault = true;
return;
}
// Draw the item's background.
e.DrawBackground();
var textSize = e.Graphics.MeasureString(e.SubItem.Text, e.SubItem.Font);
var textY = e.Bounds.Y + ((e.Bounds.Height - textSize.Height) / 2);
int textX = e.SubItem.Bounds.Location.X;
var lineY = textY + textSize.Height;
// Do the drawing of the underlined text.
e.Graphics.DrawString(e.SubItem.Text, e.SubItem.Font, m_brush, textX, textY);
e.Graphics.DrawLine(m_pen, textX, lineY, textX + textSize.Width, lineY);
}
}
You can set HotTracking to true so that when the user hovers mouse over the item it appears as link.

Categories