a few days back i started reading Head first C#, i use visual c# 2015 for building code and learning C# but however the book is based on visual studio 2010, i never ran into any problem so far while learning until i ran into this exercise when i have to build a typing game, i followed all the procedure as mentioned by the book and built it with no errors. but in the end when i run the code a key press from the keyboard should initialize the game but nothing seems t o start the game not even a mouse click or even from virtual keyboard.
Here is the code
namespace WindowsFormsApplication15{
public partial class Form1 : Form
{
Random random = new Random();
Stats stats = new Stats();
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
listBox1.Items.Add((Keys)random.Next(65, 70));
if (listBox1.Items.Count > 7)
{
listBox1.Items.Clear();
listBox1.Items.Add("Game over");
timer1.Stop();
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (listBox1.Items.Contains(e.KeyCode))
{
listBox1.Items.Remove(e.KeyCode);
listBox1.Refresh();
if (timer1.Interval > 400)
timer1.Interval -= 10;
if (timer1.Interval > 250)
timer1.Interval -= 7;
if (timer1.Interval > 100)
timer1.Interval -= 2;
difficultyProgressBar.Value = 800 - timer1.Interval;
stats.Update(true);
}
else
{
stats.Update(false);
}
correctLabel.Text = "Correct:" + stats.Correct;
missedLabel.Text = "Missed:" + stats.Missed;
totalLabel.Text = "Total:" + stats.Total;
accuracyLabel.Text = "Accuracy:" + stats.Accuracy + "%";
}
}
}
class for the code
namespace WindowsFormsApplication15{
class Stats
{
public int Total = 0;
public int Missed = 0;
public int Correct = 0;
public int Accuracy = 0;
public void Update(bool correctKey)
{
Total++;
if (!correctKey)
{
Missed++;
}
else
{
Correct++;
}
Accuracy = 100 * Correct / (Missed + Correct);
}
}
}
Form designer code
namespace WindowsFormsApplication15{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.listBox1 = new System.Windows.Forms.ListBox();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.correctLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.missedLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.totalLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.accuracyLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
this.difficultyProgressBar = new System.Windows.Forms.ToolStripProgressBar();
this.statusStrip1.SuspendLayout();
this.SuspendLayout();
//
// listBox1
//
this.listBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.listBox1.Font = new System.Drawing.Font("Microsoft Sans Serif", 80.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.listBox1.FormattingEnabled = true;
this.listBox1.ItemHeight = 120;
this.listBox1.Location = new System.Drawing.Point(0, 0);
this.listBox1.MultiColumn = true;
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(887, 261);
this.listBox1.TabIndex = 0;
//
// timer1
//
this.timer1.Interval = 800;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.correctLabel,
this.missedLabel,
this.totalLabel,
this.accuracyLabel,
this.toolStripStatusLabel1,
this.difficultyProgressBar});
this.statusStrip1.Location = new System.Drawing.Point(0, 239);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(887, 22);
this.statusStrip1.SizingGrip = false;
this.statusStrip1.TabIndex = 1;
this.statusStrip1.Text = "statusStrip1";
//
// correctLabel
//
this.correctLabel.Name = "correctLabel";
this.correctLabel.Size = new System.Drawing.Size(58, 17);
this.correctLabel.Text = "Correct: 0";
//
// missedLabel
//
this.missedLabel.Name = "missedLabel";
this.missedLabel.Size = new System.Drawing.Size(56, 17);
this.missedLabel.Text = "Missed: 0";
//
// totalLabel
//
this.totalLabel.Name = "totalLabel";
this.totalLabel.Size = new System.Drawing.Size(45, 17);
this.totalLabel.Text = "Total: 0";
//
// accuracyLabel
//
this.accuracyLabel.Name = "accuracyLabel";
this.accuracyLabel.Size = new System.Drawing.Size(78, 17);
this.accuracyLabel.Text = "Accuracy: 0%";
//
// toolStripStatusLabel1
//
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
this.toolStripStatusLabel1.Size = new System.Drawing.Size(533, 17);
this.toolStripStatusLabel1.Spring = true;
this.toolStripStatusLabel1.Text = "Difficulty";
this.toolStripStatusLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// difficultyProgressBar
//
this.difficultyProgressBar.Name = "difficultyProgressBar";
this.difficultyProgressBar.Size = new System.Drawing.Size(100, 16);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(887, 261);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.listBox1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.Text = "Form1";
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ListBox listBox1;
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripStatusLabel correctLabel;
private System.Windows.Forms.ToolStripStatusLabel missedLabel;
private System.Windows.Forms.ToolStripStatusLabel totalLabel;
private System.Windows.Forms.ToolStripStatusLabel accuracyLabel;
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
private System.Windows.Forms.ToolStripProgressBar difficultyProgressBar;
}
}
I just started learning C# and working with visual studio this month, i don't know much about programming
My guess is the problem lies some where with the KeyDown event
In all of that code I cannot see where timer1 is started - try adding
timer1.Start();
after InitializeComponent();
The problem is simple - your input focus is on the listbox. The guy who wrote the sample probably didn't test it all that much, or you didn't follow the procedure precisely enough :)
To make sure the form receives key press on a child control, you need to set the form's KeyPreview property to true.
Also, as PaulF noted, you never start the timer. The simplest solution is to set Enabled to true.
I'm late to this, but here's what I've got. I'm working through the same book and ran into the same problem, which is that the instructions tell you to set the listbox font at 72pt size. This makes the letters too large to display properly in the listbox on the form, and the Dock Fill property (or some other property, I'm new at C#) causes the ListBox (and its contents) to not display on the form during runtime.
The fix was to reduce ListBox1's font size down to the next size down, at 48pt.
I had the same problem and I had to set the timer to start or enabled and also set the font size to 48pt.
Add one of these lines in Form1.cs underneath InitializeComponent().
this.timer1.Enabled = true;
this.timer1.Start();
Related
I know how to scroll vertically/horizontally with buttons but I am not able to figure out how to scroll towards Left/Right.
What I want is that when I click the button LeftScrlBtn I should scroll to left and when I click the RightScrlBtn I should scroll to right.
My FlowLayoutPanel's AutoScroll property is set to false because I don't want the scroll bar, only the buttons.
Edit
To make this post more understandable, here is the code:
using System;
using [...];
//rest of the code
private void LeftScrlBtn_Click(object sender, EventArgs e) {
//Code to scroll to Left
}
private void RightScrlBtn_Click(object sender, EventArgs e) {
//Code to scroll to Right
}
//I want to know the code to scroll left and the code to scroll right
Note
I wanted to tell that this question didn't help me.
You can try the following code to scroll the FlowLayoutPanel by using the button.
public Form1()
{
InitializeComponent();
// need to disable AutoScroll, otherwise disabling the horizontal scrollbar doesn't work
flowLayoutPanel.AutoScroll = false;
// disable horizontal scrollbar
flowLayoutPanel.HorizontalScroll.Enabled = false;
}
public int scrollValue = 0;
public int ScrollValue
{
get
{
return scrollValue;
}
set
{
scrollValue = value;
if (scrollValue < flowLayoutPanel1.HorizontalScroll.Minimum)
{
scrollValue = flowLayoutPanel1.HorizontalScroll.Minimum;
}
if (scrollValue > flowLayoutPanel1.HorizontalScroll.Maximum)
{
scrollValue = flowLayoutPanel1.HorizontalScroll.Maximum;
}
flowLayoutPanel1.HorizontalScroll.Value = scrollValue;
flowLayoutPanel1.PerformLayout();
}
}
private void btnleft_Click(object sender, EventArgs e)
{
ScrollValue -= flowLayoutPanel1.HorizontalScroll.LargeChange;
}
private void btnright_Click(object sender, EventArgs e)
{
ScrollValue += flowLayoutPanel1.HorizontalScroll.LargeChange;
}
private void button1_Click(object sender, EventArgs e)
{
flowLayoutPanel1.Controls.Add(new Button() { Width = 67, Height = flowLayoutPanel1.Height});
}
Result:
You could place all your controls in a panel that is transparent and is overflowing over the form's bounds (eg. if form is 500px in width and 600px in height you can make the panel be wider than the form and place controls in there). Leave some space under the panel and add your buttons there.
To the LeftScrlBtn_Click block of code add the following: this.panel1.Left--;
Add this to the RightScrlBtn_Click: this.panel1.Left++;
Of course, you can change the incremention value of the panels so it would scroll faster. Just replace ++ with +=5 or -- with -=5 to scroll 5 pixels on click, per example.
Here is a code sample I did (goes into Form1.cs) :
using System.Collections.Generic;
using System.Windows.Forms;
namespace StackOfAnswer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//Scrolling left
this.panel1.Left--;
}
private void button2_Click(object sender, EventArgs e)
{
//Scrolling right
this.panel1.Left++;
}
}
}
Here is the code that goes into Form1.Designer.cs :
namespace StackOfAnswer
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.panel1 = new System.Windows.Forms.Panel();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.BackColor = System.Drawing.Color.Black;
this.panel1.Controls.Add(this.label1);
this.panel1.Location = new System.Drawing.Point(-3, -1);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(904, 422);
this.panel1.TabIndex = 0;
//
// button1
//
this.button1.Location = new System.Drawing.Point(24, 427);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 1;
this.button1.Text = "scroll left";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(713, 427);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 1;
this.button2.Text = "scroll right";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.ForeColor = System.Drawing.Color.White;
this.label1.Location = new System.Drawing.Point(24, 136);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(1561, 13);
this.label1.TabIndex = 0;
this.label1.Text = " example example example example example example example example example example example example example example example example example example example example example example example ";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.panel1);
this.Name = "Form1";
this.Text = "Form1";
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
}
}
This should do it.
Ah.. I'm a beginner. I cant come up with a method that would generate an array of random numbers on button click. Another click should make a new array an so on.
like..
first click
TheNumbers = new int [3] {1, 2, 3};
second click
TheNumbers2 = new int [3] {4, 5, 7};
etc..
This code should work for you. I assume you're working with WinForms
Read Random Constructors
Form1.cs
using System;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
//https://learn.microsoft.com/en-us/dotnet/api/system.random.-ctor?view=netframework-4.8
// The default seed value is derived from the system clock, which has finite resolution.
// As a result, on the .NET Framework only, different Random objects that are created in
// close succession by a call to the parameterless constructor will have identical default
// seed values and, therefore, will produce identical sets of random numbers. This problem
// can be avoided by using a single Random object to generate all random numbers.
private readonly Random objRandom = new Random();
//Everytime the button is clicked, this array is loaded with 3 random numbers
private int[] theNumbers;
public Form1()
{
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
theNumbers = GenerateThreeRandomsEachLessThanTen();
//just to demo the creation of the numbers
textBox1.Text = String.Join(Environment.NewLine, theNumbers);
}
private int[] GenerateThreeRandomsEachLessThanTen()
{
return new int[] { objRandom.Next(10), objRandom.Next(10), objRandom.Next(10) };
}
}
}
Form1.Designer.cs
namespace WindowsFormsApp1
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(86, 24);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "Go";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.Button1_Click);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(19, 63);
this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(203, 91);
this.textBox1.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(234, 179);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.button1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Name = "Form1";
this.Text = "Randoms";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
}
}
Output from clicking on "Go" button 3 times
I'm trying to create a pop up to notify users of a successful action. It is supposed to be visible for a couple seconds and fade away on its own. To do this, I've created a form that inherits from Form and sets the ShowWithoutActivation property to true, as well as a static class to control its construction and manipulate its opacity.
The problem is that when the new form is created, it has the correct size and initial opacity, but is completely blank. The only child control, a docked (Fill) label does not show. The Background/Foreground Color properties I set in the designer seem to be ignored in favor of default values as well. The Form fades and closes as intended.
The form itself:
public partial class TempForm : Form
{
protected override bool ShowWithoutActivation
{
get { return true; }
}
public TempForm(string message)
{
InitializeComponent();
messageLabel.Text = message;
}
private TempForm() { }
}
The static class that creates it:
public static class FadeAwayNotifier
{
public static void DisplayFadeNotification(Point parentLocation, string message)
{
Task t = Task.Factory.StartNew(() =>
{
int fadeDelay = 2000;
int animationLength = 1000;
int threadRestLength = 20;
Form popUp = buildForm(parentLocation, message);
popUp.Show();
int opacityIncrements = (animationLength / threadRestLength);
double opacityDecrementAmount = popUp.Opacity / opacityIncrements;
Thread.Sleep(fadeDelay);
for (int i = 0; i < opacityIncrements; i++)
{
Thread.Sleep(threadRestLength);
popUp.Opacity -= opacityDecrementAmount;
}
popUp.Close();
});
}
private static Form buildForm(Point startLocation, string text)
{
TempForm returnForm = new TempForm(text);
returnForm.Location = startLocation;
returnForm.messageLabel.Text = text;
returnForm.BackColor = Color.Black;
returnForm.ForeColor = Color.White;
return returnForm;
}
}
And, if it's helpful, here is the designer code for TempForm:
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.messageLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// messageLabel
//
this.messageLabel.BackColor = System.Drawing.Color.Black;
this.messageLabel.Dock = System.Windows.Forms.DockStyle.Fill;
this.messageLabel.Font = new System.Drawing.Font("Cambria", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.messageLabel.ForeColor = System.Drawing.Color.White;
this.messageLabel.Location = new System.Drawing.Point(0, 0);
this.messageLabel.Name = "messageLabel";
this.messageLabel.Size = new System.Drawing.Size(254, 81);
this.messageLabel.TabIndex = 0;
this.messageLabel.Text = "Message";
this.messageLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// TempForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 19F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Black;
this.ClientSize = new System.Drawing.Size(254, 81);
this.Controls.Add(this.messageLabel);
this.Font = new System.Drawing.Font("Cambria", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.ForeColor = System.Drawing.Color.White;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.Name = "TempForm";
this.Opacity = 0.8D;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "tempForm";
this.TopMost = true;
this.ResumeLayout(false);
}
#endregion
public System.Windows.Forms.Label messageLabel;
For those asking how the method is being called:
private void btnUpdate_Click(object sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
/* Input validation here */
if (cmbBox.SelectedValue != null)
{
updateMethod(a, b....out errorMessage);
if (String.IsNullOrEmpty(errorMessage))
FadeAwayNotifier.DisplayFadeNotification(this.Location, "Rule successfully updated");
}
else
MessageBox.Show("A selection must be made in order to update");
Cursor.Current = Cursors.Default;
}
I've searched around but haven't seen anything that seemed to relate to the situation. I'm happy to be corrected if I missed something, though.
Why is the form that's created completely blank?
Your form is blank because you are trying to show it inside Task.Factory.StartNew().
Task.Factory.StartNew() runs code inside it asynchronous which is for some reason problem for form.Show() method.
Solution for this is to instead of Task t = Task.Factory.StartNew(... use Task t = new Tast(.... and then after you created task you run it with t.RunSynchronously(). This way it will work.
How i am displaying temp forms is:
Create temporary form create new blank winform (through vs solution explorer)
Add code like this:
public partial class TempForm : Form
{
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
double seconds = 3;
public TempForm(int secs, string text)
{
InitializeComponent();
//Custom property to dock it to down right to the screen
Rectangle workingArea = Screen.GetWorkingArea(this);
this.Location = new Point(workingArea.Right - Size.Width, workingArea.Bottom - Size.Height);
t = new System.Windows.Forms.Timer();
this.seconds = (secs != 0) ? secs : this.seconds;
richTextBox1.Text = text;
}
private void TempForm_Load(object sender, EventArgs e)
{
t.Interval = (int)(seconds * 1000);
t.Tick += new EventHandler(CloseForm);
t.Start();
}
private void CloseForm(object sender, EventArgs e)
{
this.Close();
this.Dispose();
}
public static void Show(int seconds, string text)
{
TempForm tf = new TempForm(seconds, text);
tf.Show();
}
}
To call it just use TempForm.Show(10, "SomeText");
Also make it look better (not like standard form) so it looks like this:
I have a TChart Component, with a Fastline Series and a ColorBand Tool. On the form I also have a buttom which starts a timer. On every timer elapse event I generate 2048 samples of random data and update the Fasline Series. When I start the timer, there is no animation on the TChart! It seems to work randomly, though... And, when I hide and show the form (by minimizing/maximizing, or by tChart1.Hide()/tChart1.Show()) then the animation starts to work again, OR when I drag one of the ColorBand lines BEFORE starting the timer, then the animation works. But the animation does not work when I start the timer first. And, additionaly, when it does not work, the TChart seems to be frozen, i.e, ot does not respond to any mouse commands such as panning or zooming. Here is some code:
In my form.designer.cs:
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.tChart1 = new Steema.TeeChart.TChart();
this.checkBox1 = new System.Windows.Forms.CheckBox();
this.SuspendLayout();
//
// button1
//
this.button1.BackColor = System.Drawing.SystemColors.Control;
this.button1.Location = new System.Drawing.Point(12, 12);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(60, 23);
this.button1.TabIndex = 1;
this.button1.Text = "Start";
this.button1.UseVisualStyleBackColor = false;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// tChart1
//
//
//
//
//
//
//
this.tChart1.Axes.Depth.LabelsAsSeriesTitles = true;
//
//
//
this.tChart1.Axes.DepthTop.LabelsAsSeriesTitles = true;
this.tChart1.Location = new System.Drawing.Point(12, 41);
this.tChart1.Name = "tChart1";
this.tChart1.Size = new System.Drawing.Size(789, 318);
this.tChart1.TabIndex = 2;
//
// checkBox1
//
this.checkBox1.AutoSize = true;
this.checkBox1.Location = new System.Drawing.Point(78, 16);
this.checkBox1.Name = "checkBox1";
this.checkBox1.Size = new System.Drawing.Size(49, 17);
this.checkBox1.TabIndex = 3;
this.checkBox1.Text = "Drag";
this.checkBox1.UseVisualStyleBackColor = true;
this.checkBox1.Click += new System.EventHandler(this.checkBox1_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(823, 371);
this.Controls.Add(this.checkBox1);
this.Controls.Add(this.tChart1);
this.Controls.Add(this.button1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
this.Name = "Form1";
this.Text = "Form1";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
this.SizeChanged += new System.EventHandler(this.Form1_SizeChanged);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button button1;
private Steema.TeeChart.TChart tChart1;
private System.Windows.Forms.CheckBox checkBox1;
}
And then in my form.cs:
public partial class Form1 : Form
{
System.Timers.Timer timer;
private Steema.TeeChart.Tools.ColorBand tool;
Steema.TeeChart.Styles.FastLine primaryLine;
double w = 0;
bool enabled = false;
public Form1()
{
InitializeComponent();
initPrimaryGraph();
initTool();
timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Interval = 50;
timer.Stop();
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
Random rnd = new Random();
for (int i = 0; i < 2048; i++)
{
primaryLine.XValues[i] = i;
primaryLine.YValues[i] = 20 + rnd.Next(50);
}
primaryLine.BeginUpdate();
primaryLine.EndUpdate();
}
private void initTool()
{
tool = new Steema.TeeChart.Tools.ColorBand();
tChart1.Tools.Add(tool);
tool.Axis = tChart1.Axes.Bottom;
tool.Start = 300;
tool.End = 400;
tool.Brush.Color = Color.Yellow;
tool.Pen.Color = Color.Blue;
tool.Pen.Width = 2;
tool.Transparency = 60;
tool.StartLine.AllowDrag = true;
tool.StartLine.DragRepaint = true;
tool.ResizeStart = true;
tool.StartLine.DragLine += new EventHandler(StartLine_DragLine);
tool.EndLine.AllowDrag = true;
tool.EndLine.DragRepaint = true;
tool.ResizeEnd = true;
tool.EndLine.DragLine += new EventHandler(EndLine_DragLine);
}
void StartLine_DragLine(object sender, EventArgs e)
{
if (enabled)
{
tool.End = tool.Start + w;
}
}
void EndLine_DragLine(object sender, EventArgs e)
{
if (enabled)
{
tool.Start = tool.End - w;
}
}
private void initPrimaryGraph()
{
tChart1.Header.Visible = true;
tChart1.Axes.Bottom.Automatic = false;
tChart1.Axes.Bottom.Minimum = 0;
tChart1.Axes.Bottom.Maximum = 2048;
tChart1.Axes.Bottom.Labels.Font.Color = Color.White;
tChart1.Axes.Bottom.Grid.Visible = false;
tChart1.Axes.Left.Automatic = false;
tChart1.Axes.Left.Minimum = 0;
tChart1.Axes.Left.Maximum = 300;
tChart1.Axes.Left.Labels.Font.Color = Color.White;
tChart1.Aspect.View3D = false;
tChart1.Walls.Back.Visible = false;
tChart1.Walls.Bottom.Visible = false;
tChart1.Walls.Left.Visible = false;
tChart1.Walls.Right.Visible = false;
tChart1.Legend.Visible = false;
tChart1.BackColor = Color.Black;
tChart1.Panel.Visible = false;
//PRIMARY GRAPH.....
primaryLine = new Steema.TeeChart.Styles.FastLine();
tChart1.Series.Add(primaryLine);
Random rnd = new Random();
for (int i = 0; i < 2048; i++)
{
double x = i;
double y = 20 + rnd.Next(50);
primaryLine.Add(x, y);
}
primaryLine.LinePen.Style = System.Drawing.Drawing2D.DashStyle.Solid;
primaryLine.LinePen.Color = Color.White;
primaryLine.LinePen.Width = 1;
primaryLine.VertAxis = Steema.TeeChart.Styles.VerticalAxis.Left;
}
private void tool_DragLine(object sender, EventArgs e)
{
Steema.TeeChart.Tools.ColorLine t = sender as Steema.TeeChart.Tools.ColorLine;
this.Text = t.Value.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
if (timer.Enabled)
{
timer.Stop();
button1.Text = "Start";
}
else
{
timer.Start();
button1.Text = "Stop";
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
timer.Stop();
}
private void checkBox1_Click(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
w = tool.End - tool.Start;
}
enabled = checkBox1.Checked;
}
}
I have another question. I want to create a black-box implementation of a TeeChart Component by writing a custom API (a Custom User Control) to expose specific functionality so that I can use it in other projects, and so that one or more of my colleagues at work can use it in their projects. What version/license of TeeChart should I purchase which would allow me to wrap TeeChart functionality in a custom component/dll which may be used over various projects/computers?
Thanks in advance :-)
I have a TChart Component, with a Fastline Series and a ColorBand
Tool. On the form I also have a buttom which starts a timer. On every
timer elapse event I generate 2048 samples of random data and update
the Fasline Series. When I start the timer, there is no animation on
the TChart! It seems to work randomly, though... And, when I hide and
show the form (by minimizing/maximizing, or by
tChart1.Hide()/tChart1.Show()) then the animation starts to work
again, OR when I drag one of the ColorBand lines BEFORE starting the
timer, then the animation works. But the animation does not work when
I start the timer first. And, additionaly, when it does not work, the
TChart seems to be frozen, i.e, ot does not respond to any mouse
commands such as panning or zooming. Here is some code:
I have modified a little your code and now it works in my end. See next:
Timer timer;
private Steema.TeeChart.Tools.ColorBand tool;
Steema.TeeChart.Styles.FastLine primaryLine;
double w = 0;
bool enabled = false;
public Form1()
{
InitializeComponent();
initPrimaryGraph();
initTool();
timer = new Timer();
//Enable Timer
timer.Enabled = true;
timer.Interval = 50;
timer.Tick += timer_Tick;
}
void timer_Tick(object sender, EventArgs e)
{
AnimateSeries(tChart1);
}
private void AnimateSeries(TChart tChart)
{
Random rnd = new Random();
tChart.AutoRepaint = false;
primaryLine.BeginUpdate();
foreach (Steema.TeeChart.Styles.Series s in tChart.Series)
{
for (int i = 0; i < 2048; i++)
{
primaryLine.XValues[i] = i;
primaryLine.YValues[i] = 20 + rnd.Next(50);
}
}
tChart.AutoRepaint = true;
primaryLine.EndUpdate();
}
private void initTool()
{
tool = new Steema.TeeChart.Tools.ColorBand();
tChart1.Tools.Add(tool);
tool.Axis = tChart1.Axes.Bottom;
tool.Start = 300;
tool.End = 400;
tool.Brush.Color = Color.Yellow;
tool.Pen.Color = Color.Blue;
tool.Pen.Width = 2;
tool.Transparency = 60;
tool.StartLine.AllowDrag = true;
tool.StartLine.DragRepaint = true;
tool.ResizeStart = true;
tool.StartLine.DragLine += new EventHandler(StartLine_DragLine);
tool.EndLine.AllowDrag = true;
tool.EndLine.DragRepaint = true;
tool.ResizeEnd = true;
tool.EndLine.DragLine += new EventHandler(EndLine_DragLine);
}
void StartLine_DragLine(object sender, EventArgs e)
{
if (enabled)
{
tool.End = tool.Start + w;
}
}
void EndLine_DragLine(object sender, EventArgs e)
{
if (enabled)
{
tool.Start = tool.End - w;
}
}
private void initPrimaryGraph()
{
tChart1.Header.Visible = true;
tChart1.Aspect.View3D = false;
tChart1.Walls.Back.Visible = false;
tChart1.Walls.Bottom.Visible = false;
tChart1.Walls.Left.Visible = false;
tChart1.Walls.Right.Visible = false;
tChart1.Legend.Visible = false;
tChart1.BackColor = Color.Black;
tChart1.Panel.Visible = false;
//PRIMARY GRAPH.....
primaryLine = new Steema.TeeChart.Styles.FastLine();
tChart1.Series.Add(primaryLine);
Random rnd = new Random();
for (int i = 0; i < 2048; i++)
{
double x = i;
double y = 20 + rnd.Next(50);
primaryLine.Add(x, y);
}
primaryLine.LinePen.Style = System.Drawing.Drawing2D.DashStyle.Solid;
primaryLine.LinePen.Color = Color.White;
primaryLine.LinePen.Width = 1;
//AXES
tChart1.Axes.Bottom.Automatic = false;
tChart1.Axes.Bottom.Minimum = primaryLine.XValues.Minimum;
tChart1.Axes.Bottom.Maximum = primaryLine.XValues.Maximum;
tChart1.Axes.Bottom.Increment = 200;
tChart1.Axes.Bottom.Labels.Font.Color = Color.White;
tChart1.Axes.Bottom.Grid.Visible = false;
tChart1.Axes.Left.Automatic = false;
tChart1.Axes.Left.Minimum = 0;
tChart1.Axes.Left.Maximum = 300;
tChart1.Axes.Left.Labels.Font.Color = Color.White;
primaryLine.VertAxis = Steema.TeeChart.Styles.VerticalAxis.Left;
tChart1.Draw();
}
private void tool_DragLine(object sender, EventArgs e)
{
Steema.TeeChart.Tools.ColorLine t = sender as Steema.TeeChart.Tools.ColorLine;
this.Text = t.Value.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
if (timer.Enabled)
{
timer.Stop();
button1.Text = "Start";
}
else
{
timer.Start();
button1.Text = "Stop";
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
timer.Stop();
}
As you see in the code I have changed the type of Timer for other I consider more appropriate. Could you tell us if previous code works as you expected?
I have another question. I want to create a black-box implementation
of a TeeChart Component by writing a custom API (a Custom User
Control) to expose specific functionality so that I can use it in
other projects, and so that one or more of my colleagues at work can
use it in their projects. What version/license of TeeChart should I
purchase which would allow me to wrap TeeChart functionality in a
custom component/dll which may be used over various
projects/computers?
TeeChart may be reused by another designtime assembly (dll) that publishes certain characteristics of teeChart. Please not though that machines that reuse tee component in designtime should also install a TeeChart Developer license.
I hope will helps.
Thanks,
In Windows Forms (C#) is there a way to set the tooltip's height and width dynamically (meaning in code). I am working with a DataViewGrid control, so I am having to use the method Show. However, I have noticed (when left to it's own devices) that the tooltip control does not always adjust to the content provided....
An example:
Having a ToolTip control added to a form (called ttText) and then having it first show the text:
ttText.Show("I'm hungry\nand waiting!");
will truncate the next call:
ttText.Show("Well, too bad -- so much for your stamina, you should not be here!\nSo the little bear responds!");
Any thoughts on this?
Keep in mind that a DataGridView requires a mechanism to display ToolTip help hence the use of the Show methods and I've seen this behavior elsewhere in non-DataViewGrids...
Here is an Example of code:
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace TestForm
{
class Form1 : Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.ttText = new System.Windows.Forms.ToolTip(this.components);
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// dataGridView1
//
this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Location = new System.Drawing.Point(13, 19);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(453, 321);
this.dataGridView1.TabIndex = 0;
this.dataGridView1.CellMouseEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_MouseCellEnter);
//
// ttText
//
this.ttText.AutomaticDelay = 60;
this.ttText.AutoPopDelay = 600000;
this.ttText.InitialDelay = 60;
this.ttText.IsBalloon = true;
this.ttText.ReshowDelay = 60;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(478, 352);
this.Controls.Add(this.dataGridView1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
}
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.ToolTip ttText;
public Form1()
{
InitializeComponent();
var ds = Sayings().ToList();
dataGridView1.DataSource = ds;
}
public List<dynamic> Sayings()
{
return new List<dynamic>
{
new
{
Human = "I'm hungry\nand waiting!",
BabyBear = "Well, too bad -- so much for your stamina, you should not be here!\nSo the little bear responds!"
}
};
}
private void dataGridView1_MouseCellEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != -1 && e.RowIndex != -1)
{
var rect = dataGridView1.GetColumnDisplayRectangle(e.ColumnIndex, true);
var left = rect.Left + (int)(rect.Width * .5f);
var top = rect.Top;
Point displayPoint = new Point(left + this.ClientRectangle.Left, top + this.ClientRectangle.Top + 40);
ttText.Show(dataGridView1[e.ColumnIndex, e.RowIndex].Value.ToString(), this, displayPoint);
}
}
}
}
If you hover over the 1st column, then the second, the the tool tip text gets truncated.
OK, it has been several months now since I posted this question. I haven’t really given this problem any thought since then – just accepted the behavior... until tonight.
Since no-one else thought of an answer (or cared to provide an alternative Window Forms idea), it occurred to me to re-look at the general problem. The balloon tool tip seems to be a free-form kind of thing... It takes the previous shape it encounters. It's probably Microsoft's laziness at work. Or better – it's Microsoft's way of pointing developers in a different direction. After all, the only new direction provided was towards wpf...
However, as I stated in the original question, I needed a solution that was ONLY windows forms, not mixing WPF or Silverlight or other technologies into the pot. After all, if you are a WPF programmer, you may want to add Windows Forms controls in to the mix, but for the purest, this won't do.
So here is a bit more to the solution to the puzzle – how to make a balloon resize to the dimensions desired...
I re-looked at the problem and noticed that the balloon would resize each time the mouse pointer entered into the cell, so to that end, the following was derived:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace TestForm
{
class Form1 : Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.ttText = new System.Windows.Forms.ToolTip(this.components);
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// dataGridView1
//
this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Location = new System.Drawing.Point(17, 23);
this.dataGridView1.Margin = new System.Windows.Forms.Padding(4);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(604, 395);
this.dataGridView1.TabIndex = 0;
this.dataGridView1.CellMouseEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_MouseCellEnter);
this.dataGridView1.MouseLeave += new System.EventHandler(this.dataGridView1_MouseLeave);
this.dataGridView1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.event_MouseMove);
//
// ttText
//
this.ttText.AutomaticDelay = 0;
this.ttText.AutoPopDelay = 0;
this.ttText.InitialDelay = 10;
this.ttText.IsBalloon = true;
this.ttText.OwnerDraw = true;
this.ttText.ReshowDelay = 0;
this.ttText.ShowAlways = true;
this.ttText.UseAnimation = false;
this.ttText.UseFading = false;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(637, 433);
this.Controls.Add(this.dataGridView1);
this.Margin = new System.Windows.Forms.Padding(4);
this.Name = "Form1";
this.Text = "Form1";
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.event_MouseMove);
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
}
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.ToolTip ttText;
public Form1()
{
InitializeComponent();
dataGridView1.ShowCellToolTips = false;
var ds = Sayings().ToList();
dataGridView1.DataSource = ds;
}
public List<dynamic> Sayings()
{
return new List<dynamic>
{
new
{
Human = "I'm hungry\nand waiting!",
BabyBear = "Well, too bad -- so much for your stamina, you should not be here!\nSo the little bear responds!"
},
new
{
Human = "What a selfish bear!\n\n\nAt least you could do is wait for\nothers to join you!",
BabyBear = "Boo Hoo!"
},
new
{
Human = "Oh, I'm sorry!",
BabyBear = "Now, I'm going to eat you!"
},
new
{
Human = "\n\n\n!!!\n\nWhat?????\n\n\n\nI don't think so!\n\n(Human pulls out Honey Jar)",
BabyBear = "Yum!"
},
};
}
private void dataGridView1_MouseCellEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != -1 && e.RowIndex != -1)
{
this.SuspendLayout();
var rectC = dataGridView1.GetColumnDisplayRectangle(e.ColumnIndex, true);
var left = rectC.Left + (int)(rectC.Width * .5f);
var rectR = dataGridView1.GetRowDisplayRectangle(e.RowIndex, true);
var top = (rectR.Top + (int)(rectR.Height * .5f));
Point displayPoint = new Point(left + this.ClientRectangle.Left, top + this.ClientRectangle.Top + 40);
var column = e.ColumnIndex;
var row = e.RowIndex;
for (int i = 0; i < 5; ++i)
{
ttText.Show(dataGridView1[column, row].Value.ToString(), this, displayPoint);
ttText.Hide(this);
}
ttText.Show(dataGridView1[column, row].Value.ToString(), this, displayPoint);
this.ResumeLayout();
}
}
private void dataGridView1_MouseLeave(object sender, EventArgs e)
{
Rectangle mouseRect = new Rectangle(MousePosition, new Size(1, 1));
var rectC = dataGridView1.GetColumnDisplayRectangle(dataGridView1.Columns.Count - 1, true);
var right = rectC.Right;
var rectR = dataGridView1.GetRowDisplayRectangle(dataGridView1.Rows.Count - 1, true);
var bottom = rectR.Bottom;
var rect = new Rectangle(
dataGridView1.PointToScreen(dataGridView1.Location),
new Size(right, bottom));
if (!rect.IntersectsWith(mouseRect))
ttText.Hide(this);
}
void event_MouseMove(object sender, MouseEventArgs e)
{
dataGridView1_MouseLeave(sender, EventArgs.Empty);
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
I have expanded the narrative in the grid to help demonstrate the general problem.
I know that this is not a completely elegant solution – but that's what encapsulation is all about.
The new problem... Is it possible to have the point of the balloon tool tip be displayed at the mouse point – or am I just living a pipe dream?
Now, as far as a possible solution... I have read a bit about inheriting the Tool Tip object to perform drawing with a custom class. Is it not feasible to use that to determine the size of the text, and then determine which direction the balloon would display and the offset of the text?
On MSDN it mentions using the RenderSize property for this sort of thing but with some caveats.
What worked for me to avoid truncating the tool tip is to set the ToolTip text explicitly. What I think is subtle is that the default ToolTip text uses the same cell content, only the default handler does truncate it as noted in the original question. By overriding the event and setting the ToolTip text (even though it's exactly the same cell text!) now the default length restriction seems to go away.
protected override void OnCellToolTipTextNeeded(DataGridViewCellToolTipTextNeededEventArgs e)
{
if((e.RowIndex >= 0) && (e.ColumnIndex >= 0))
{
// By setting this explicitly we can make the ToolTip show the
// entire length even though the content itself has not changed.
e.ToolTipText = this[e.ColumnIndex, e.RowIndex].Value.ToString();
}
base.OnCellToolTipTextNeeded(e);
}