I am trying to design a piano for an assignment in C#. I have created a MusicKey class which stores music keys (as well as a BlackMusicKey class). I am populating the panel, 'panel1' with music keys like this:
this.panel1.Controls.Add(bmk);
In the music key constructor, I am setting a location and size for each music key, as well as ensuring that Visibility is set to true. However, when I run the form, it is completely blank.
Is there something that I am missing? I am quite sure that there is nothing wrong with the visibility of the music keys, so surely there is something that I am missing with regards to making the panel visible.
Any help will be appreciated, thanks!
Note: I have also tried using panel1.Show() which still did not work.
All relevant code can be found down below:
MusicKeyClass:
class MusKey : System.Windows.Forms.Button
{
private int musicNote; //determines the pitch mapped to number
public MusKey(int iNote, int x, int y) : base()
{
musicNote = iNote;
this.Location = new System.Drawing.Point(x, y);
this.Size = new System.Drawing.Size(20, 80);
this.Visible = true;
}
public int getMusicNote()
{
return musicNote;
}
}
Form1 Class:
public partial class Form1 : Form
{
int count = 0;
int xLoc = 50;
int yLoc = 30;
int[] whitePitch = { 1, 3, 5, 6, 8, 10, 12, 13, 15, 17, 18, 20, 22, 24 };
Panel panel1 = new Panel();
System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
Button button1 = new Button();
private void Form1_Load(object sender, EventArgs e)
{
this.Paint += new PaintEventHandler(function);
MusKey mk;
BlackMusKey bmk;
for (int k = 0; k < 14; k++)
{
int pitch = whitePitch[k];
int ixPos = k * 20;
mk = new MusKey(pitch, ixPos, yLoc);
mk.MouseDown += new MouseEventHandler(this.button1_MouseDown);
mk.MouseUp += new MouseEventHandler(this.button1_MouseUp);
this.panel1.Controls.Add(mk);
}
int xOffs = 20;
int[] blackPitch = { 2, 4, 7, 9, 11, 14, 16, 19, 21, 23 };
int[] xPos = { 10, 30, 70, 110, 150, 170, 210, 230, 250 };
const int yPosBlack = 50;
for (int k = 0; k < 10; k++)
{
int pitch = blackPitch[k];
int ixPos = xPos[k];
bmk = new BlackMusKey(pitch, ixPos, yPosBlack);
bmk.MouseDown += new System.Windows.Forms.MouseEventHandler(this.button1_MouseDown); //create event MouseDown
bmk.MouseUp += new System.Windows.Forms.MouseEventHandler(this.button1_MouseUp); //create event MouseUp
this.panel1.Controls.Add(bmk);
this.panel1.Controls[this.panel1.Controls.Count - 1].BringToFront();
}
}
SoundPlayer sp = new SoundPlayer();
int count1;
private void button1_MouseDown(object sender, MouseEventArgs e)
{
foreach (MusKey mk in this.panel1.Controls)
{
if (sender == mk)
{ //true for the specific key pressed on the Music Keyboard
if (e.Button == MouseButtons.Left)
{
timer1.Enabled = true; //variable of the Timer component
count = 0; //incremented by the timer1_Tick event handler
timer1.Start();
sp.SoundLocation = (mk.getMusicNote() + ".wav"); //might need to convert ToString() ??
sp.Play();
}
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
count = count++;
}
private void button1_MouseUp(object sender, MouseEventArgs e)
{
foreach (MusKey mk in this.panel1.Controls)
{
if (sender == mk) //true for the specific key pressed on the Music Keyboard
{
if (e.Button == MouseButtons.Left)
{
timer1.Enabled = false;
sp.Stop();
string bNoteShape = null;
int duration = 0;
if (count >= 16)
{
bNoteShape = "SemiBreve";
duration = 16;
}
if (count >= 8 && count <= 15)
{
bNoteShape = "DotMinim";
duration = (8 + 15) / 2;
}
if (count >= 4 && count <= 7)
{
bNoteShape = "Crotchet";
duration = (4 + 7) / 2;
}
if (count >= 2 && count <= 3)
{
bNoteShape = "Quaver";
duration = (2 + 3) / 2;
}
if (count >= 1)
{
bNoteShape = "Semi-Quaver";
duration = 1;
}
MusicNote mn = new MusicNote(mk.getMusicNote(), duration, bNoteShape); //music note construction
// mn.Location = new Point(xLoc, yLoc);
//this.panel2.Controls.Add(this.mn); //adding MusicNote component to MusicStaff (panel2) collection
xLoc = xLoc + 15;
}
}
}
}
private void function(object sender, PaintEventArgs e)
{
panel1.Show();
panel1.Visible = true;
panel1.BackColor = Color.Blue;
panel1.Size = new Size(5, 5);
panel1.Location = new Point(3, 3);
this.Controls.Add(panel1);
this.Controls.Add(button1);
}
private void Form1_Load_1(object sender, EventArgs e)
{
}
}
Form 1 [designer] Class:
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.SuspendLayout();
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load_1);
this.ResumeLayout(false);
}
#endregion
}
Music Note Class
class MusicNote
{
public int notepitch;
public String noteshape;
public int noteduration;
enum accid { sharp, flat, sole };
bool dragging = false;
System.Timers.Timer timer1 = new System.Timers.Timer();
public MusicNote(int iNotepitch, int iDuration, String iBnoteShape)
{
notepitch = iNotepitch;
noteduration = iDuration;
noteshape = iBnoteShape;
}
bool timeron = false;
bool changenote = false;
public static int start = 0;
//public void click(object sender, MouseEventArgs e) { }
//public void RightPress(object sender, MouseEventArgs e) { }
}
}
Black Music Key Class
class BlackMusKey : MusKey
{
public BlackMusKey(int iNote, int x, int y) : base(iNote, x, y)
{
this.BackColor = Color.Black;
this.Size = new System.Drawing.Size(20, 60);
}
}
Program Class
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());
}
}
According to Form1 class code, there is constructor missing. Please add proper constructor with InitializeComponent() method call. It can be added anywhere in class body.
Code snippet:
public partial class Form1 : Form
{
[...] //your objects declarations
public Form1()
{
InitializeComponent();
}
[...] //rest of your code
}
Related
Hey I have two classes
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BMIcalculator
{
class BmrCalculator
{
BMIcalculator BMICalc = new BMIcalculator();
private int age;
private double BMR;
private Gender Gender;
private double weight;
private double height;
public void setWeight(double weight)
{
this.weight = weight;
}
public void setHeight(double height)
{
this.height = height;
}
public double GetWeight()
{
return weight;
}
public double GetHeight()
{
return height;
}
public void SetGender(Gender Gender)
{
this.Gender = Gender;
}
public Gender GetGender()
{
return this.Gender;
}
public double CalculateBMR()
{
if (Gender == Gender.Female)
{
BMR = (10 * weight) + (6.25 * height) - (5 * age) - 161;
}
else
{
BMR = (10 * BMICalc.getWeight()) + (6.25 * BMICalc.getHeight()) - (5 * age) + 5;
}
return BMR;
}
public void SetAge(int age)
{
this.age = age;
}
}
}
2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BMIcalculator
{
class BMIcalculator
{
private double height;
private double weight;
private UnitTypes unit;
public BMIcalculator()
{
unit = UnitTypes.Metric;
}
#region Setters and getters
public double getHeight()
{
return height;
}
public void setHeight(double height)
{
if(height >= 0.0)
this.height = height;
}
public double getWeight()
{
return weight;
}
public void setWeight(double weight)
{
if (weight >= 0.0)
this.weight = weight;
}
public UnitTypes getUnit()
{
return unit;
}
public void setUnit(UnitTypes unit)
{
this.unit = unit;
}
#endregion
}
}
Main form:
namespace BMIcalculator
{
public partial class MainForm : Form
{
private string name = string.Empty; // instance variable
BMIcalculator bmiCalc = new BMIcalculator();
BmrCalculator bmrCalc = new BmrCalculator();
public MainForm()
{
InitializeComponent();
InitializeGUI();
}
private void InitializeGUI()
{
rbtnMetric.Checked = true;
lblBmr.Text = String.Empty;
}
private void MainForm_Load(object sender, EventArgs e)
{
CenterToScreen();
}
#region BMICalculator
private void UpdateHeightText()
{
if(rbtnMetric.Checked == true)
{
lblHeight.Text = "Height (Cm)";
lblWeight.Text = "Weight (Kg)";
}
else
{
lblHeight.Text = "Height (Ft)";
lblWeight.Text = "Weight (lbs)";
}
}
private void rbtnMetric_CheckedChanged(object sender, EventArgs e)
{
UpdateHeightText();
}
private void rbtnImperial_CheckedChanged(object sender, EventArgs e)
{
UpdateHeightText();
}
private bool ReadInputBMI()
{
ReadUnit();
bool weightOK = ReadWeight();
bool heightOK = ReadHeight();
return weightOK && heightOK;
}
private void ReadUnit() // this void looks which one is checked
{
if(rbtnMetric.Checked)
{
bmiCalc.setUnit(UnitTypes.Metric);
}
else
{
bmiCalc.setUnit(UnitTypes.Imperial);
}
}
private bool ReadWeight()
{
double weight = 0.0;
bool ok = double.TryParse(txtWeight.Text, out weight);
if (!ok)
{
MessageBox.Show("Invalid weight value , error");
}
bmiCalc.setWeight(weight);
return ok;
}
private bool ReadHeight()
{
double height = 0.0;
bool ok = double.TryParse(txtCmFt.Text, out height);
if (!ok)
{
MessageBox.Show("Invalid height value , error");
}
double inch = 0.0;
// cm -> m ft -> inches
if(bmiCalc.getUnit() == UnitTypes.Metric)
{
height = height / 100; // cm -> m
}
else
{
height = height * 12.0 + inch; // ft -> inch
}
bmiCalc.setHeight(height);
return ok;
}
#endregion
#region BMRCalculator
private void UpdateGenderStatus()
{
if(rbtnFemale.Checked)
{
bmrCalc.SetGender(Gender.Female);
}
else
{
bmrCalc.SetGender(Gender.Male);
}
}
private void rbtnFemale_CheckedChanged(object sender, EventArgs e)
{
UpdateGenderStatus();
}
private void rbtnMale_CheckedChanged(object sender, EventArgs e)
{
UpdateGenderStatus();
}
private void ReadAge()
{
int age;
bool ok = int.TryParse(txtAge.Text , out age);
if(!ok)
{
MessageBox.Show("Error Wrong Age");
}
else
{
bmrCalc.SetAge(age);
}
}
#endregion
private void btnCalculateBMR_Click(object sender, EventArgs e)
{
double weight = double.Parse(txtWeight.Text);
double height = double.Parse(txtCmFt.Text);
bmrCalc.setWeight(weight);
bmrCalc.setHeight(height);
ReadAge();
//bmrCalc.CalculateBMR();
lblBmr.Text = bmrCalc.CalculateBMR().ToString();
}
}
}
designer:
namespace BMIcalculator
{
partial class MainForm
{
/// <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.lblHeight = new System.Windows.Forms.Label();
this.txtCmFt = new System.Windows.Forms.TextBox();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.rbtnMetric = new System.Windows.Forms.RadioButton();
this.lblWeight = new System.Windows.Forms.Label();
this.txtWeight = new System.Windows.Forms.TextBox();
this.groupBox4 = new System.Windows.Forms.GroupBox();
this.btnCalculateBMR = new System.Windows.Forms.Button();
this.groupBox6 = new System.Windows.Forms.GroupBox();
this.lblBmr = new System.Windows.Forms.Label();
this.txtAge = new System.Windows.Forms.TextBox();
this.lblAge = new System.Windows.Forms.Label();
this.groupBox5 = new System.Windows.Forms.GroupBox();
this.rbtnMale = new System.Windows.Forms.RadioButton();
this.rbtnFemale = new System.Windows.Forms.RadioButton();
this.groupBox1.SuspendLayout();
this.groupBox4.SuspendLayout();
this.groupBox6.SuspendLayout();
this.groupBox5.SuspendLayout();
this.SuspendLayout();
//
// lblHeight
//
this.lblHeight.AutoSize = true;
this.lblHeight.Location = new System.Drawing.Point(27, 39);
this.lblHeight.Name = "lblHeight";
this.lblHeight.Size = new System.Drawing.Size(54, 20);
this.lblHeight.TabIndex = 1;
this.lblHeight.Text = "Height";
//
// txtCmFt
//
this.txtCmFt.Location = new System.Drawing.Point(165, 32);
this.txtCmFt.Name = "txtCmFt";
this.txtCmFt.Size = new System.Drawing.Size(51, 27);
this.txtCmFt.TabIndex = 3;
//
// groupBox1
//
this.groupBox1.Controls.Add(this.rbtnMetric);
this.groupBox1.Location = new System.Drawing.Point(319, 23);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(163, 88);
this.groupBox1.TabIndex = 6;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Unit";
//
// rbtnMetric
//
this.rbtnMetric.AutoSize = true;
this.rbtnMetric.Location = new System.Drawing.Point(26, 35);
this.rbtnMetric.Name = "rbtnMetric";
this.rbtnMetric.Size = new System.Drawing.Size(121, 24);
this.rbtnMetric.TabIndex = 0;
this.rbtnMetric.TabStop = true;
this.rbtnMetric.Text = "Metric(kg,cm)";
this.rbtnMetric.UseVisualStyleBackColor = true;
this.rbtnMetric.CheckedChanged += new System.EventHandler(this.rbtnMetric_CheckedChanged);
//
// lblWeight
//
this.lblWeight.AutoSize = true;
this.lblWeight.Location = new System.Drawing.Point(27, 77);
this.lblWeight.Name = "lblWeight";
this.lblWeight.Size = new System.Drawing.Size(56, 20);
this.lblWeight.TabIndex = 9;
this.lblWeight.Text = "Weight";
//
// txtWeight
//
this.txtWeight.Location = new System.Drawing.Point(165, 70);
this.txtWeight.Name = "txtWeight";
this.txtWeight.Size = new System.Drawing.Size(125, 27);
this.txtWeight.TabIndex = 10;
//
// groupBox4
//
this.groupBox4.Controls.Add(this.btnCalculateBMR);
this.groupBox4.Controls.Add(this.groupBox6);
this.groupBox4.Controls.Add(this.txtAge);
this.groupBox4.Controls.Add(this.lblAge);
this.groupBox4.Controls.Add(this.groupBox5);
this.groupBox4.Location = new System.Drawing.Point(27, 130);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(392, 314);
this.groupBox4.TabIndex = 15;
this.groupBox4.TabStop = false;
this.groupBox4.Text = "BMR calculator";
//
// btnCalculateBMR
//
this.btnCalculateBMR.Location = new System.Drawing.Point(68, 274);
this.btnCalculateBMR.Name = "btnCalculateBMR";
this.btnCalculateBMR.Size = new System.Drawing.Size(212, 29);
this.btnCalculateBMR.TabIndex = 4;
this.btnCalculateBMR.Text = "Calculate BMR";
this.btnCalculateBMR.UseVisualStyleBackColor = true;
this.btnCalculateBMR.Click += new System.EventHandler(this.btnCalculateBMR_Click);
//
// groupBox6
//
this.groupBox6.Controls.Add(this.lblBmr);
this.groupBox6.Location = new System.Drawing.Point(177, 55);
this.groupBox6.Name = "groupBox6";
this.groupBox6.Size = new System.Drawing.Size(185, 213);
this.groupBox6.TabIndex = 3;
this.groupBox6.TabStop = false;
this.groupBox6.Text = "how many calories you need";
//
// lblBmr
//
this.lblBmr.AutoSize = true;
this.lblBmr.Location = new System.Drawing.Point(45, 67);
this.lblBmr.Name = "lblBmr";
this.lblBmr.Size = new System.Drawing.Size(58, 20);
this.lblBmr.TabIndex = 5;
this.lblBmr.Text = "label10";
//
// txtAge
//
this.txtAge.Location = new System.Drawing.Point(98, 182);
this.txtAge.Name = "txtAge";
this.txtAge.Size = new System.Drawing.Size(50, 27);
this.txtAge.TabIndex = 2;
//
// lblAge
//
this.lblAge.AutoSize = true;
this.lblAge.Location = new System.Drawing.Point(31, 185);
this.lblAge.Name = "lblAge";
this.lblAge.Size = new System.Drawing.Size(36, 20);
this.lblAge.TabIndex = 1;
this.lblAge.Text = "Age";
//
// groupBox5
//
this.groupBox5.Controls.Add(this.rbtnMale);
this.groupBox5.Controls.Add(this.rbtnFemale);
this.groupBox5.Location = new System.Drawing.Point(17, 42);
this.groupBox5.Name = "groupBox5";
this.groupBox5.Size = new System.Drawing.Size(131, 125);
this.groupBox5.TabIndex = 0;
this.groupBox5.TabStop = false;
this.groupBox5.Text = "Gender";
//
// rbtnMale
//
this.rbtnMale.AutoSize = true;
this.rbtnMale.Location = new System.Drawing.Point(14, 63);
this.rbtnMale.Name = "rbtnMale";
this.rbtnMale.Size = new System.Drawing.Size(63, 24);
this.rbtnMale.TabIndex = 1;
this.rbtnMale.TabStop = true;
this.rbtnMale.Text = "Male";
this.rbtnMale.UseVisualStyleBackColor = true;
this.rbtnMale.CheckedChanged += new System.EventHandler(this.rbtnMale_CheckedChanged);
//
// rbtnFemale
//
this.rbtnFemale.AutoSize = true;
this.rbtnFemale.Location = new System.Drawing.Point(14, 33);
this.rbtnFemale.Name = "rbtnFemale";
this.rbtnFemale.Size = new System.Drawing.Size(78, 24);
this.rbtnFemale.TabIndex = 0;
this.rbtnFemale.TabStop = true;
this.rbtnFemale.Text = "Female";
this.rbtnFemale.UseVisualStyleBackColor = true;
this.rbtnFemale.CheckedChanged += new System.EventHandler(this.rbtnFemale_CheckedChanged);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(512, 484);
this.Controls.Add(this.groupBox4);
this.Controls.Add(this.txtWeight);
this.Controls.Add(this.lblWeight);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.txtCmFt);
this.Controls.Add(this.lblHeight);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
this.MaximizeBox = false;
this.Name = "MainForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Form1";
this.Load += new System.EventHandler(this.MainForm_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.groupBox4.ResumeLayout(false);
this.groupBox4.PerformLayout();
this.groupBox6.ResumeLayout(false);
this.groupBox6.PerformLayout();
this.groupBox5.ResumeLayout(false);
this.groupBox5.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Label lblHeight;
private TextBox txtCmFt;
private GroupBox groupBox1;
private RadioButton rbtnMetric;
private Label lblWeight;
private TextBox txtWeight;
private GroupBox groupBox4;
private Button btnCalculateBMR;
private GroupBox groupBox6;
private TextBox txtAge;
private Label lblAge;
private GroupBox groupBox5;
private RadioButton rbtnMale;
private RadioButton rbtnFemale;
private Label lblBmr;
}
}
The problem is i cant acess another class by creating new BMIcalculator(); because then its empty or 0.
So my question is how can i access the getter from the BMIcalculator without creating new object. I want to get access to instance variables height and weigh and then use it in Bmrcalculator.
I have very similar problem to this one: Call Methods from another class c#
but i still cant solve it. I began programming 2 weeks ago, sorry if its an obvious question.
I've 4 panels, having same Y and different X, that are created at the program start on a picturebox. When I click on a panel, it sets the focus and is ready to get a keysDown event so i.e. if I click on up arrow key the panel moves up.
This is the code:
public partial class FormView : Form
{
List<CircleButton> myPanels = new List<CircleButton>(); // array of panels CircleButton
Point[] arrayPoints_milestones; // array of X,Y
int index;
public FormView()
{
InitializeComponent();
arrayPoints_milestones = new Point[4];
for (int i = 0; i < 4; i++ )
{
arrayPoints_milestones[i] = new Point { X = 20, Y = 20 };
}
test();
}
protected void panel_Click(object sender, EventArgs e)
{
myPanels[index].PreviewKeyDown -= new PreviewKeyDownEventHandler(panel_KeyDown);
CircleButton panel = sender as CircleButton;
index = (int)panel.Tag;
myPanels[index].Focus(); //panel.Focus();
myPanels[index].PreviewKeyDown += new PreviewKeyDownEventHandler(panel_KeyDown);
}
private void panel_KeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Up)
{
myPanels[index].Centre = new Point(myPanels[index].Centre.X, myPanels[index].Centre.Y - 10);
MessageBox.Show("" + myPanels[index].Centre.Y);
Invalidate();
}
if (e.KeyCode == Keys.Down)
{
myPanels[index].Centre = new Point(myPanels[index].Centre.X, myPanels[index].Centre.Y + 10);
MessageBox.Show("" + myPanels[index].Centre.Y);
Invalidate();
}
}
private void test()
{
//for (int i = 0; i < 4; i++)
int i=0;
foreach(var value in arrayPoints_milestones)
{
CircleButton panel = new CircleButton();
panel.Tag = i;
panel.Centre = new Point(arrayPoints_milestones[i].X + i * 10, arrayPoints_milestones[i].Y);
panel.Radius = 10;
panel.BackColor = Color.Red;
panel.Message = "Index: " + panel.Tag.ToString();
myPanels.Add(panel); // qui aggiungo il pannello alla lista di pannelli myPanels
pictureBox1.Controls.Add(myPanels[i]);
myPanels[i].Click += new EventHandler(panel_Click);
i++;
}
}
}
and this is the custom panel class:
public class CircleButton : Panel
{
//Properties to draw circle
float radius;
public float Radius
{
get { return radius; }
set
{
radius = value;
this.Size = new Size((int)Radius, (int)Radius);
}
}
public string Name
{
get;
set;
}
Point centre;
public Point Centre
{
get { return centre; }
set
{
centre = value;
this.Location = Centre;
}
}
public string Message { get; set; }
public CircleButton()
{
//Default Values
Name = "panel_base";
this.BackColor = Color.Black;
Radius = 1;
Centre = new Point(0, 0);
this.DoubleBuffered = true;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//Defines a graphic path and set it as the panel's region
//For custom region use different path's
if (centre != null)
{
GraphicsPath path = new GraphicsPath();
path.AddEllipse(0, 0, radius, radius);
this.Region = new Region(path);
path.Dispose();
}
}
}
Each time you click a panel, a PreviewKeyDownEventHandler is added - so 3 clicks will trigger 3 (different) eventhandlers with the same invocation target, and each will move your panel for 10 pixels up/down:
protected void panel_Click(object sender, EventArgs e) {
CircleButton panel = sender as CircleButton;
index = (int)panel.Tag;
myPanels[index].Focus(); //panel.Focus();
myPanels[index].PreviewKeyDown += new PreviewKeyDownEventHandler(panel_KeyDown);
}
Updated code for FormView:
public partial class FormView : Form {
List<CircleButton> myPanels = new List<CircleButton>(); // local use only in my example
Point[] arrayPoints_milestones; //not needed anymore
int index; //not needed anymore
public FormView() {
InitializeComponent();
this.Load += FormView_Load;
}
void FormView_Load(object sender, EventArgs args) {
Point panelOffset = new Point(20, 20);
for (int i = 0; i < 4; i++) {
var panel = new CircleButton() {
Name = "panel" + i, //Attention! You have hidden the property "Name" in "Control" with a re-declaration in "CircleButton"
Tag = i, //not needed anymore, right?
Centre = new Point(panelOffset.X + i * 10, panelOffset.Y),
Radius = 10,
BackColor = Color.Red,
Message = "Index: " + i.ToString(),
};
panel.Click += (s, e) => {
panel.Focus();
};
panel.PreviewKeyDown += (s, e) => {
if(e.KeyCode == Keys.Up) {
Point centre = panel.Centre; //copy value
centre.Y -= 10;
panel.Centre = centre; //assign modified copy
Invalidate();
}
if(e.KeyCode == Keys.Down) {
Point centre = panel.Centre; //copy value
centre.Y += 10;
panel.Centre = centre; //assign modified copy
Invalidate();
}
};
myPanels.Add(panel);
pictureBox1.Controls.Add(panel);
}
}
}
I have an array which is populated by MusicNotes. Each MusicNote is an object with it's properties, e.g. pitch and duration. Duration is created using a timer in the MusicNote class.
The problem is that when I iterate through the array and play all the sounds the duration of each MusicNote is lost and it will play the whole wav file (for each note).
I know that the problem is related to the timer and I know that it maybe related to the Play() method in the MusicNote but I don't have any ideas on how to fix it. I have posted my the code related to this problem.
public class MusicNote : PictureBox
{
Timer tmr1 = new Timer();
int tmr1duration;
public SoundPlayer sp = new SoundPlayer();
public Timer tmr = new Timer();
public int pitch; //The no. of the music key (e.g. the sound freuency).
public int noteDuration; //Shape of note.
public string noteShape;
static int xLoc = 0;
int yLoc = 100;
public MusicNote(int iPitch, int iNoteDuration)
: base()
{
pitch = iPitch;
noteDuration = iNoteDuration;
Size = new Size(40, 40);
this.BackColor = Color.Transparent;
this.MouseClick += new MouseEventHandler(MusicNote_MouseClick);
this.MouseDown += new MouseEventHandler(MusicNote_MouseDown);
this.MouseUp += new MouseEventHandler(MusicNote_MouseUp);
tmr1.Tick += new EventHandler(tmr1_Tick);
tmr.Tick += new EventHandler(ClockTick);
}
public void ShowNote()
{
if (this.noteDuration == 1) noteShape = "Quaver.png";
if (this.noteDuration == 4) noteShape = "Crotchet.png";
if (this.noteDuration == 7) noteShape = "minim.png";
if (this.noteDuration == 10) noteShape = "DotMin.png";
if (this.noteDuration == 12) noteShape = "SemiBreve.png";
this.BackgroundImage = Image.FromFile(noteShape);
this.BackColor = Color.Transparent;
Location = new Point(xLoc, yLoc);
xLoc = xLoc + 40;
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
public void Play()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Play();
//Timer to play the duration
this.tmr.Interval = 100 * this.noteDuration;
this.tmr.Start();
}
void ClockTick(object sender, EventArgs e)
{
sp.Stop();
tmr.Stop();
}
private void MusicNote_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Play();
}
}
}
}
And this is the class were I have the array...
public class MusicStaff: Panel
{
public ArrayList musicNotes = new ArrayList(); //Array to store the Music Notes.
SoundPlayer sp = new SoundPlayer();
public void AddNote(MusicNote newNote) //Method to add the notes.
{
musicNotes.Add(newNote);
}
public int ListSize()
{
return musicNotes.Count; //Returns the size of the list.
}
public void PlayAll()
{
foreach (MusicNote m in musicNotes)
{
m.Play();
}
I have removed some code from the classes which is not replated to the problem so that question is not too long. Any help how can I solve this would be greatly appreciated. Tks.
Try something like this:
public void PlayAll()
{
foreach (MusicNote m in musicNotes)
{
m.sp.Stop();
m.sp.PlaySync();
Thread.Sleep(m.noteDuration); //duration should be in milliseconds
}
}
Should this work you can remove your timer completely.
I suggest you look into the use of Properties in C# to not let fields be public.
By the way I did this assignment two years ago :)
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,
I'm looking for a free winforms component for an application I'm writing. I basicly need a textbox that contains line numbers in a side column. Being able to tabulate data within it would be a major plus too.
Does anyone know of a premade component that could do this?
Referencing Wayne's post, here is the relevant code. It is using GDI to draw line numbers next to the text box.
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
SetStyle(ControlStyles.UserPaint, True)
SetStyle(ControlStyles.AllPaintingInWmPaint, True)
SetStyle(ControlStyles.DoubleBuffer, True)
SetStyle(ControlStyles.ResizeRedraw, True)
End Sub
Private Sub RichTextBox1_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles RichTextBox1.SelectionChanged
FindLine()
Invalidate()
End Sub
Private Sub FindLine()
Dim intChar As Integer
intChar = RichTextBox1.GetCharIndexFromPosition(New Point(0, 0))
intLine = RichTextBox1.GetLineFromCharIndex(intChar)
End Sub
Private Sub DrawLines(ByVal g As Graphics, ByVal intLine As Integer)
Dim intCounter As Integer, intY As Integer
g.Clear(Color.Black)
intCounter = intLine + 1
intY = 2
Do
g.DrawString(intCounter.ToString(), Font, Brushes.White, 3, intY)
intCounter += 1
intY += Font.Height + 1
If intY > ClientRectangle.Height - 15 Then Exit Do
Loop
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
DrawLines(e.Graphics, intLine)
End Sub
Private Sub RichTextBox1_VScroll(ByVal sender As Object, ByVal e As System.EventArgs) Handles RichTextBox1.VScroll
FindLine()
Invalidate()
End Sub
Private Sub RichTextBox1_UserScroll() Handles RichTextBox1.UserScroll
FindLine()
Invalidate()
End Sub
The RichTextBox is overridden like this:
Public Class UserControl1
Inherits System.Windows.Forms.RichTextBox
Public Event UserScroll()
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = &H115 Then
RaiseEvent UserScroll()
End If
MyBase.WndProc(m)
End Sub
End Class
(Code by divil on the xtremedotnettalk.com forum.)
Take a look at the SharpDevelop C# compiler/IDE source code. They have a sophisticated text box with line numbers. You could look at the source, figure out what they're doing, and then implement it yourself.
Here's a sample of what I'm referencing:
(source: sharpdevelop.net)
There is a project with code available at http://www.xtremedotnettalk.com/showthread.php?s=&threadid=49661&highlight=RichTextBox.
You can log into the site to download the zip file with the user/pass: bugmenot/bugmenot
There is a source code editing component in CodePlex for .net,
http://www.codeplex.com/ScintillaNET
Here's some C# code to do this. It's based on the code from xtremedotnettalk.com referenced by Wayne. I've made some changes to make it actually display the editor text, which the original didn't do. But, to be fair, the original code author did mention it needed work.
Here's the code (NumberedTextBox.cs)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace NumberedTextBoxLib {
public partial class NumberedTextBox : UserControl {
private int lineIndex = 0;
new public String Text {
get {
return editBox.Text;
}
set {
editBox.Text = value;
}
}
public NumberedTextBox() {
InitializeComponent();
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
editBox.SelectionChanged += new EventHandler(selectionChanged);
editBox.VScroll += new EventHandler(OnVScroll);
}
private void selectionChanged(object sender, EventArgs args) {
FindLine();
Invalidate();
}
private void FindLine() {
int charIndex = editBox.GetCharIndexFromPosition(new Point(0, 0));
lineIndex = editBox.GetLineFromCharIndex(charIndex);
}
private void DrawLines(Graphics g) {
int counter, y;
g.Clear(BackColor);
counter = lineIndex + 1;
y = 2;
int max = 0;
while (y < ClientRectangle.Height - 15) {
SizeF size = g.MeasureString(counter.ToString(), Font);
g.DrawString(counter.ToString(), Font, new SolidBrush(ForeColor), new Point(3, y));
counter++;
y += (int)size.Height;
if (max < size.Width) {
max = (int) size.Width;
}
}
max += 6;
editBox.Location = new Point(max, 0);
editBox.Size = new Size(ClientRectangle.Width - max, ClientRectangle.Height);
}
protected override void OnPaint(PaintEventArgs e) {
DrawLines(e.Graphics);
e.Graphics.TranslateTransform(50, 0);
editBox.Invalidate();
base.OnPaint(e);
}
///Redraw the numbers when the editor is scrolled vertically
private void OnVScroll(object sender, EventArgs e) {
FindLine();
Invalidate();
}
}
}
And here is the Visual Studio designer code (NumberedTextBox.Designer.cs)
namespace NumberedTextBoxLib {
partial class NumberedTextBox {
/// Required designer variable.
private System.ComponentModel.IContainer components = null;
/// Clean up any resources being used.
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
private void InitializeComponent() {
this.editBox = new System.Windows.Forms.RichTextBox();
this.SuspendLayout();
//
// editBox
//
this.editBox.AcceptsTab = true;
this.editBox.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.editBox.Location = new System.Drawing.Point(27, 3);
this.editBox.Name = "editBox";
this.editBox.Size = new System.Drawing.Size(122, 117);
this.editBox.TabIndex = 0;
this.editBox.Text = "";
this.editBox.WordWrap = false;
//
// NumberedTextBox
//
this.Controls.Add(this.editBox);
this.Name = "NumberedTextBox";
this.Size = new System.Drawing.Size(152, 123);
this.ResumeLayout(false);
}
private System.Windows.Forms.RichTextBox editBox;
}
}
I guess it depends on the Font size, I used "Courier New, 9pt, style=bold"
Added fix for smooth scrolling, (not line by line)
Added fix for big files, when scroll value is over 16bit.
NumberedTextBox.cs
public partial class NumberedTextBox : UserControl
{
private int _lines = 0;
[Browsable(true),
EditorAttribute("System.ComponentModel.Design.MultilineStringEditor, System.Design","System.Drawing.Design.UITypeEditor")]
new public String Text
{
get
{
return editBox.Text;
}
set
{
editBox.Text = value;
Invalidate();
}
}
private Color _lineNumberColor = Color.LightSeaGreen;
[Browsable(true), DefaultValue(typeof(Color), "LightSeaGreen")]
public Color LineNumberColor {
get{
return _lineNumberColor;
}
set
{
_lineNumberColor = value;
Invalidate();
}
}
public NumberedTextBox()
{
InitializeComponent();
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
editBox.SelectionChanged += new EventHandler(selectionChanged);
editBox.VScroll += new EventHandler(OnVScroll);
}
private void selectionChanged(object sender, EventArgs args)
{
Invalidate();
}
private void DrawLines(Graphics g)
{
g.Clear(BackColor);
int y = - editBox.ScrollPos.Y;
for (var i = 1; i < _lines + 1; i++)
{
var size = g.MeasureString(i.ToString(), Font);
g.DrawString(i.ToString(), Font, new SolidBrush(LineNumberColor), new Point(3, y));
y += Font.Height + 2;
}
var max = (int)g.MeasureString((_lines + 1).ToString(), Font).Width + 6;
editBox.Location = new Point(max, 0);
editBox.Size = new Size(ClientRectangle.Width - max, ClientRectangle.Height);
}
protected override void OnPaint(PaintEventArgs e)
{
_lines = editBox.Lines.Count();
DrawLines(e.Graphics);
e.Graphics.TranslateTransform(50, 0);
editBox.Invalidate();
base.OnPaint(e);
}
private void OnVScroll(object sender, EventArgs e)
{
Invalidate();
}
public void Select(int start, int length)
{
editBox.Select(start, length);
}
public void ScrollToCaret()
{
editBox.ScrollToCaret();
}
private void editBox_TextChanged(object sender, EventArgs e)
{
Invalidate();
}
}
public class RichTextBoxEx : System.Windows.Forms.RichTextBox
{
private double _Yfactor = 1.0d;
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, ref Point lParam);
private enum WindowsMessages
{
WM_USER = 0x400,
EM_GETSCROLLPOS = WM_USER + 221,
EM_SETSCROLLPOS = WM_USER + 222
}
public Point ScrollPos
{
get
{
var scrollPoint = new Point();
SendMessage(this.Handle, (int)WindowsMessages.EM_GETSCROLLPOS, 0, ref scrollPoint);
return scrollPoint;
}
set
{
var original = value;
if (original.Y < 0)
original.Y = 0;
if (original.X < 0)
original.X = 0;
var factored = value;
factored.Y = (int)((double)original.Y * _Yfactor);
var result = value;
SendMessage(this.Handle, (int)WindowsMessages.EM_SETSCROLLPOS, 0, ref factored);
SendMessage(this.Handle, (int)WindowsMessages.EM_GETSCROLLPOS, 0, ref result);
var loopcount = 0;
var maxloop = 100;
while (result.Y != original.Y)
{
// Adjust the input.
if (result.Y > original.Y)
factored.Y -= (result.Y - original.Y) / 2 - 1;
else if (result.Y < original.Y)
factored.Y += (original.Y - result.Y) / 2 + 1;
// test the new input.
SendMessage(this.Handle, (int)WindowsMessages.EM_SETSCROLLPOS, 0, ref factored);
SendMessage(this.Handle, (int)WindowsMessages.EM_GETSCROLLPOS, 0, ref result);
// save new factor, test for exit.
loopcount++;
if (loopcount >= maxloop || result.Y == original.Y)
{
_Yfactor = (double)factored.Y / (double)original.Y;
break;
}
}
}
}
}
NumberedTextBox.Designer.cs
partial class NumberedTextBox
{
/// <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 Component 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.editBox = new WebTools.Controls.RichTextBoxEx();
this.SuspendLayout();
//
// editBox
//
this.editBox.AcceptsTab = true;
this.editBox.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.editBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.editBox.Location = new System.Drawing.Point(27, 3);
this.editBox.Name = "editBox";
this.editBox.ScrollPos = new System.Drawing.Point(0, 0);
this.editBox.Size = new System.Drawing.Size(120, 115);
this.editBox.TabIndex = 0;
this.editBox.Text = "";
this.editBox.WordWrap = false;
this.editBox.TextChanged += new System.EventHandler(this.editBox_TextChanged);
//
// NumberedTextBox
//
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.Controls.Add(this.editBox);
this.Name = "NumberedTextBox";
this.Size = new System.Drawing.Size(150, 121);
this.ResumeLayout(false);
}
private RichTextBoxEx editBox;
#endregion
}