Drawing a Chart for non-numerical variables in C# [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a issue with chart drawing in my Windows form application project.
I want to draw a chart like this:
http://upload7.ir/imgs/2014-12/84930837744513480976.jpg
the words in axis X and axis Y is related and that letters in colorful rectangles are each relation's value. I want a chart exactly like this.
anyone can help me to draw something like that?
I''l be thankful.
Regards.

Here is a class AreaChart which draws a chart like the one you showed.
Here is what it looks like, with the built-in values:
Add the class to your project and compile. It'll show up in the toolbox and you can place it on your form. (Do a Backup of your project before you do that!)
You can set many values in the designer or in code, including the dimensions, BackColor, Font, and Labels.. Set the Colors and Texts in code using the methods provided!
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
class AreaChart : Panel
{
[Category("Appearance"), Description("Padding around the ChartArea")]
public Padding ChartPadding { get; set; }
[Category("Appearance"),
Description("Axixs Origin offsets from Bottom Left of the Chart")]
public Point AxisOriginOffset { get; set; }
[Category("Appearance"),Description("Number of Rows")]
public int RowNum { get; set; }
[Category("Appearance"), Description("Number of Columns")]
public int ColNum { get; set; }
[Category("Appearance"), Description("Labeltexts for Y-Axis")]
public string[] labelsY { get; set; }
[Category("Appearance"), Description("Labeltexts for X-Axis")]
public string[] labelsX { get; set; }
Color[][] colors { get; set; }
string[][] texts { get; set; }
Rectangle chartArea = Rectangle.Empty;
Point axisOrigin = Point.Empty
public void Init()
{
chartArea = new Rectangle(ChartPadding.Left, ChartPadding.Top,
this.Width - ChartPadding.Left - ChartPadding.Right,
this.Height - ChartPadding.Top - ChartPadding.Bottom);
axisOrigin = new Point(AxisOriginOffset.X, this.Height - AxisOriginOffset.Y);
colors = new Color[RowNum][];
for (int r = 0; r < RowNum; r++) colors[r] = new Color[ColNum];
texts = new string[RowNum][];
for (int r = 0; r < RowNum; r++) texts[r] = new string[ColNum];
labelsX = new string[ColNum]; //*
labelsY = new string[RowNum]; //*
}
public AreaChart()
{
ChartPadding = new Padding(80, 40, 40, 40);
AxisOriginOffset = new Point(60, 20);
RowNum = 3;
ColNum = 2;
BackColor = Color.AntiqueWhite;
Init();
}
protected override void OnPaint(PaintEventArgs e)
{
if (this.DesignMode) Init(); // make the designer show the current
if (this.DesignMode) InitDemo(); // ...sizes, colors and texts
int x = chartArea.X;
int y = chartArea.Y;
SizeF tSize = e.Graphics.MeasureString("XX", this.Font, 9999);
int th = (int)tSize.Height / 2;
int tw = (int)tSize.Width / 2;
int h = chartArea.Height / RowNum;
int w = chartArea.Width / ColNum; e.Graphics.Clear(BackColor);
e.Graphics.DrawLine(Pens.Black, axisOrigin,
new Point(axisOrigin.X, chartArea.Top));
e.Graphics.DrawLine(Pens.Black, axisOrigin,
new Point( chartArea.Right, axisOrigin.Y));
for (int r = 0; r < RowNum; r++)
for (int c = 0; c < ColNum; c++)
{
e.Graphics.FillRectangle(new SolidBrush(colors[r][c]),
x + c * w, y + r * h, w, h);
e.Graphics.DrawRectangle(Pens.Black, x + c * w, y + r * h, w, h);
e.Graphics.DrawString(texts[r][c], this.Font, Brushes.Black,
x + c * w + w / 2 - tw, y + r * h + h / 2 - th);
}
for (int r = 0; r < RowNum; r++)
e.Graphics.DrawString(labelsY[r], this.Font, Brushes.Black,
AxisOriginOffset.X - tw * 2, y + r * h + h / 2 - th); //*
for (int c = 0; c < ColNum; c++)
e.Graphics.DrawString(labelsX[c], this.Font, Brushes.Black,
x + c * w + w / 2 - tw, axisOrigin.Y ); //*
base.OnPaint(e);;
}
public void setColor (int row, int col, Color color)
{
try
{
colors[row][col] = color;
} catch { throw new Exception("setColor : array index out of bounds!"); }
}
public void setText(int row, int col, string text)
{
try
{
texts[row][col] = text;
} catch { throw new Exception("setText: array index out of bounds!"); }
}
public void setLabelX(int col, string text) //*
{
try
{
labelsX[col] = text;
} catch { throw new Exception("array index out of bounds!"); }
}
public void setLabelY(int row, string text) //*
{
try
{
labelsY[row] = text;
} catch { throw new Exception("array index out of bounds!"); }
}
public void InitDemo()
{
setColor(0, 0, Color.Plum);
setColor(1, 0, Color.GreenYellow);
setColor(2, 0, Color.Gold);
setColor(0, 1, Color.LightSkyBlue);
setColor(1, 1, Color.NavajoWhite);
setColor(2, 1, Color.Pink);
setText(0, 0, "AA");
setText(1, 0, "BA");
setText(2, 0, "CA");
setText(0, 1, "AB");
setText(1, 1, "BB");
setText(2, 1, "BC");
setLabelY(0, "A"); //*
setLabelY(1, "B"); //*
setLabelY(2, "C"); //*
setLabelX(0, "A"); //*
setLabelX(1, "B"); //*
}
}
After your Form's Initializecomponent() you should call
areaChart1.Init();
areaChart1.InitDemo();
to display the demo chart I show. To change it use calls like these:
areaChart1.ColNum = 3;
areaChart1.Init();
areaChart1.InitDemo();
areaChart1.setColor(0, 2, Color.Yellow);
areaChart1.setLabelY(2, "ZZ");
//..

Your question is pretty vague, but if you want EXACTLY that chart, does that mean you don't need the values to be dynamic? If so, wouldn't the simplest solution be to save it as an image and display the image in your application where you need it. Obviously this won't work if you need the values or colors to be dynamic.

Related

Drawing and Saving an Image

I am in the process of developing an app that will be later integrated with another app I developed some time ago.
Basically, this app will generate an image file of X and Y dimensions with a grid printed on it, of which the user also specifies it's interval.
I've done this form so far, but I am having difficulty deciding what the best way to generate an actual image with the proper dimensions and grid spacing should be.
I don't want to save the image that is displayed on the form because it is only a representation and could very well be extremely dissimilar from the final product.
So I guess my question is, what do you think the best way is to generate a black and white image when I click "save"?
Also, I have no need to see the image being saved, I just want to generate and save it behind the scenes.
Here is the "draw" button click event
private void btnDraw_Click(object sender, EventArgs e)
{
this.Width = 560;
using (g = pb.CreateGraphics())
{
g.Clear(Color.White);
PaintCanvass canvass = new PaintCanvass();
canvass.Width = Convert.ToDouble(tbWidth.Text);
canvass.Height = Convert.ToDouble(tbHeight.Text);
canvass.Resolution = Convert.ToInt32(cbResolution.Text.Substring(0,3));
canvass.UOM = cbUOM.Text;
canvass.Interval = Convert.ToInt32(tbInterval.Text);
Pen pencil = new Pen(Color.Black, 2);
int hpfact = Convert.ToInt32((double)pb.Height / (double)canvass.horizontalLinesQuantity);
int hp = hpfact;
for (int i = 0; i < canvass.horizontalLinesQuantity-1; i++)
{
g.DrawLine(pencil, new Point(0, hp), new Point(pb.Width, hp));
hp = hp + hpfact;
}
int vpfact = Convert.ToInt32((double)pb.Width / (double)canvass.verticalLinesQuantity);
int vp = vpfact;
for (int i = 0; i < canvass.verticalLinesQuantity-1; i++)
{
g.DrawLine(pencil, new Point(vp, 0), new Point(vp, pb.Height));
vp = vp + vpfact;
}
canvass = null;
And here is my PaintCanvass class which seems to just be ending up as a container for properties for now
class PaintCanvass
{
public double Width { get; set; }
public double Height { get; set; }
public string UOM { get; set; }
public int Resolution { get; set; }
public int Interval { get; set; } = 50;
public int hdots
{
get
{
if (this.UOM == "mm")
{
return Convert.ToInt32(Width * 0.03937008F * Resolution);
}
else
{
return Convert.ToInt32(Width * Resolution);
};
}
}
public int vdots
{
get
{
// Set the quantity of lines
if (this.UOM == "mm")
{
return Convert.ToInt32(Height * 0.03937008F * Resolution);
}
else
{
return Convert.ToInt32(Height * Resolution);
};
}
}
public int horizontalLinesQuantity
{
get
{
return vdots / this.Interval;
}
}
public int verticalLinesQuantity
{
get
{
return hdots / this.Interval;
}
}
}
Edit: as suggested I went with the bitmap method.
private void btnSave_Click(object sender, EventArgs e)
{
SetupCanvass();
using (Bitmap bmp = new Bitmap(canvass.hdots, canvass.vdots))
{
using (Graphics g = Graphics.FromImage(bmp))
{
using (SolidBrush brush = new SolidBrush(Color.FromArgb(255, 255, 255)))
{
g.FillRectangle(brush, 0, 0, canvass.hdots, canvass.vdots);
}
int hp = canvass.Interval;
for (int i = 0; i < canvass.horizontalLinesQuantity - 1; i++)
{
g.DrawLine(pencil, new Point(0, hp), new Point(canvass.hdots, hp));
hp = hp + canvass.Interval;
}
int vp = canvass.Interval;
for (int i = 0; i < canvass.verticalLinesQuantity - 1; i++)
{
g.DrawLine(pencil, new Point(vp, 0), new Point(vp, canvass.vdots));
vp = vp + canvass.Interval;
}
}
bmp.Save(Path.Combine(Path.GetTempPath(), "labelGrid.png")); //Save image somwhere on disk
}
}
If you want to save an image without displaying a preview, just do something like this:
using (Bitmap bmp = new Bitmap(500, 500))
{
using (Graphics g = Graphics.FromImage(bmp))
{
//Draw your stuff directly onto the bitmap here
}
bmp.Save("C:\\image.bmp"); //Save image somwhere on disk
}

Winforms FlowLayoutPanel remove unneeded spaces with autosize controls

I have FlowLayoutPanel with
AutoScroll = True
FlowDirection = LeftToRight
WrapContents = True
Added controls dynamically have same Width but AutoSize in Height. So the panel will be like this, which has vertical spaces between items. As the height of row managed by the greatest height of controls. So I want to remove these unneeded spaces, and the final result will be like this.
If there's no way to do it with FlowLayoutPanel, What's the proper idea to done it perfectly ?
Its a matrix and should be treated like a matrix.
my opinion is that Panel is more appropriate than a FlowLayoutpanel here.
please see my suggestion and output to achieve such a behavior.
clarification: this code needs improvements to be adapted to all possible cases but you can learn from it the basic idea how to deal with such problem.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Example();
}
// space beetween controls (top and right)
public int MarginSpace = 8;
// first element location
public Point StartPoint = new Point(10, 10);
private void Example()
{
var fixesWidth = 70;
List<Label> randomLables = new List<Label>();
Random rand = new Random();
// generate lables with random heights
for (int i = 1; i < 10; i++)
{
Label lr = new Label();
var randheight = rand.Next(60, 120);
lr.Size = new Size(fixesWidth, randheight);
lr.Text = i.ToString();
lr.BackColor = Color.Black;
lr.ForeColor = Color.White;
randomLables.Add(lr);
}
// check how many elements in one "column" (possible also to add right+left margin)
var cols = panel1.Width / fixesWidth;
// create matrix object to get locations of each label
MyMatrix m = new MyMatrix(cols, randomLables.Count, 15, 70, StartPoint);
m.SetMatrix(randomLables);
int counter = 0;
// pupulate all lables with the points from MyMatrix object
foreach (Point p in m.pointsMatrix)
{
randomLables[counter].Location = p;
panel1.Controls.Add(randomLables[counter]);
counter++;
}
}
}
class MyMatrix
{
private int Rows;
private int TotalElements;
private int Cols;
private int Margin;
private int ElementWidth;
private Point StartPoint;
public MyMatrix(int cols, int totalelements, int margin, int elementwidth, Point startingpoint)
{
this.Cols = cols;
this.TotalElements = totalelements;
this.Margin = margin;
this.ElementWidth = elementwidth;
this.StartPoint = startingpoint;
// calculate number of rows
Rows = totalelements / cols;
}
public List<Point> pointsMatrix = new List<Point>();
int cellCounter = 0;
public void SetMatrix(List<Label> Labels)
{
for (int i = 0; i < Rows; i++)
{
for (int j = 0; j < Cols; j++)
{
var x = StartPoint.X + j * (Margin + ElementWidth);
var y = StartPoint.Y;
if (cellCounter >= Cols)
{
// find the parallel cell in the row above
y = pointsMatrix[cellCounter - Cols].Y + Labels[cellCounter - Cols].Height + Margin;
}
else
{
// do nothing it is first row
}
Point p = new Point(x, y);
pointsMatrix.Add(p);
cellCounter += 1;
}
}
}
}
Output:

Creating same size cells with TableLayoutPanel

I'm trying to use the TableLayoutPanel in C# to fill out a Form. The TableLayoutPanel should hold 10x10 panels that all have the same size (by percentage).
Though I don't seem to get it to work for either the last row or the last column.
allPanel.RowCount = 10;
allPanel.ColumnCount = 10;
allPanel.Padding = 10;
allPanel.BackColor = Color.Green;
allPanel.AutoSize = true;
allPanel.Dock = DockStyle.Fill;
allPanel.RowStyles.Clear();
allPanel.ColumnStyles.Clear();
windowsForm.Controls.Add(allPanel);
for (int i = 0; i < 10; i++) {
allPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 10));
}
for (int i = 0; i < 10; i++) {
allPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 10));
}
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
boardTiles[i, j] = new Panel();
boardTiles[i, j].BackColor = Color.White;
allPanel.Controls.Add(boardTiles[i, j], i, j);
}
}
The result looks as follows:
The Cells' dimensions are integers; so for the layout to work you need to make sure that the net area of the TLP in in fact divisible by the number of cells you want it to contain.
The net area is the ClientSize minus the Padding.
So with a Padding of 10 around all sides you need a size of (n * w + 20, m * h + 20) for n x m cells of Width w and Height h.
Since you want to fill a container you need to either:
control the container size to match the formula
or compute the Padding so that it corrects for the integer divison errors
Here is a function to compute the correct Padding:
Padding GetCorrectionPadding(TableLayoutPanel TLP, int minimumPadding)
{
int minPad = minimumPadding;
Rectangle netRect = TLP.ClientRectangle;
netRect.Inflate(-minPad, -minPad);
int w = netRect.Width / TLP.ColumnCount;
int h = netRect.Height / TLP.RowCount;
int deltaX = (netRect.Width - w * TLP.ColumnCount) / 2;
int deltaY = (netRect.Height - h * TLP.RowCount) / 2;
int OddX = (netRect.Width - w * TLP.ColumnCount) % 2;
int OddY = (netRect.Height - h * TLP.RowCount) % 2;
return new Padding(minPad + deltaX, minPad + deltaY,
minPad + deltaX + OddX, minPad + deltaY + OddY);
}
Note that the code..
assumes the the TLP is already filled
assumes some value for the minimum Padding you want. Since we need up to n-1 pixels to do the correction the horizontal and vertical paddings may differ by half of that, in your case by up to 4 or 5 pixels.
Here is how you could call it:
allPanel.Padding = GetCorrectionPadding(allPanel, 5);
If you want to avoid this you need to go for option one, i.e. make sure the container has a suitable size!
The correction Padding will need to be applied again after each resizing, of course..
I don't like TableLayoutPanel. I can achieve same with code below. The number of properties on a TableLayoutPanel are limited and I often find I need additional properties. You can inherit any class (I used buttons). I place buttons on a form but you can also place the buttons on a standard Panel so the panel can be moved on a form and all the buttons move together.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Buttons
{
public partial class Form1 : Form
{
const int ROWS = 5;
const int COLS = 10;
public Form1()
{
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
}
public void Form1_Load(object sender, EventArgs e)
{
new MyButton(ROWS, COLS, this);
}
}
public class MyButton : Button
{
const int WIDTH = 50;
const int HEIGHT = 50;
const int SPACE = 5;
const int BORDER = 20;
public static List<List<MyButton>> buttons { get; set; }
public static List<MyButton> buttonList { get; set; }
public Form1 form1;
public int row { get; set; }
public int col { get; set; }
public MyButton()
{
}
public MyButton(int rows, int cols, Form1 form1)
{
buttons = new List<List<MyButton>>();
buttonList = new List<MyButton>();
this.form1 = form1;
for(int row = 0; row < rows; row++)
{
List<MyButton> newRow = new List<MyButton>();
buttons.Add(newRow);
for (int col = 0; col < cols; col++)
{
MyButton newButton = new MyButton();
newButton.Height = HEIGHT;
newButton.Width = WIDTH;
newButton.Top = row * (HEIGHT + SPACE) + BORDER;
newButton.Left = col * (WIDTH + SPACE) + BORDER;
newButton.row = row;
newButton.col = col;
newRow.Add(newButton);
buttonList.Add(newButton);
newButton.Click += new System.EventHandler(Button_Click);
form1.Controls.Add(newButton);
}
}
}
public void Button_Click(object sender, EventArgs e)
{
MyButton button = sender as MyButton;
MessageBox.Show(string.Format("Pressed Button Row {0} Column {1}", button.row, button.col));
}
}
}

Drawing Multiple Rectangles c#

What would be the best way to draw 25 rectangles (5*5) in c#?
I later need to be able to reach a specific rectangle and change its color, for instance change the color to red if the user inputs the incorrect word.
Would it be more suitable to create an array of rectangles in this case?
This is what i have so far
Graphics g = pictureBox1.CreateGraphics();
int x =0;
int y= 0;
int width = 20;
int height = 20;
for (int i = 0; i < 25; i++)
{
if (i <= 4)
{
g.FillRectangle(Brushes.Blue, x, y, width, height);
x += 50;
}
else if (i > 4)
{
y = 50;
g.FillRectangle(Brushes.Blue, x, y, width, height);
x += 50;
}
}
This should get you started, not the complete code. You will need to add a PictureBox control and use the default name (picurebox1). EDIT: Need to add a button too :)
public partial class Form1 : Form
{
public List<Rectangle> listRec = new List<Rectangle>();
Graphics g;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Rectangle rect = new Rectangle();
rect.Size = new Size(100,20);
for (int x = 0; x < 5; x++)
{
rect.X = x * rect.Width;
for (int y = 0; y < 5; y++)
{
rect.Y = y * rect.Height;
listRec.Add(rect);
}
}
foreach (Rectangle rec in listRec)
{
g = pictureBox1.CreateGraphics();
Pen p = new Pen(Color.Blue);
g.DrawRectangle(p, rec);
}
}
public void ChangeColor(Rectangle target, Color targetColor)
{
Pen p = new Pen(targetColor);
g.DrawRectangle(p, target.X, target.Y, target.Width, target.Height);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.D0: ChangeColor(listRec[0], Color.Red);
break;
case Keys.D1: ChangeColor(listRec[1], Color.Red);
break;
//..more code to handle all keys..
}
}
}
If you're not concerned with performance or the looks, then the easiest approach would be to create a List of Lists of Panels in your Form_Load event as one of the comments mentions.
List<List<Panel>> panelGrid = new List<List<Panel>>();
for (var i = 0; i < 5; i++)
{
var panelRow = new List<Panel>();
for (var j = 0; j < 5; j++)
{
panelRow.Add(new Panel());
// add positioning logic here
}
panelGrid.Add(panelRow);
}
Then you will be able to reference each individual one at a later stage...
If you have to use Graphics class (which is the better approach), then you should setup something similar however replacing Panel with a class of your own. Then in Form_Paint event you would iterate through the list of objects and render them.
class MyPanel
{
public Size size;
public Color color;
}
...
foreach (var myPanelRow in myPanelGrid)
foreach (var myPanel in myPanelRow)
g.FillRectangle(myPanel.color, myPanel.size); // this obviously won't work as is, but you get the idea
Then when you need to change a color, you do something like:
myPanelsGrid[0][0].color = Color.Blue;
myForm.Invalidate();
The second line will result in Paint in event being called again.

namespace doesn't exist

I would like to try out a code in Microsoft Visual C# Express Edition and I'm getting this error:
The type or namespace name 'Properties' does not exist in the namespace 'EducationalSuite.Core' (are you missing an assembly reference?)
I right click the Reference but I didn't find the "Properties" either the "EducationalSuite.Core".
Here is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Media;
using System.Resources;
namespace EducationalSuite.Core.Plugins
{
public delegate void RectangleItemClickedDelegate(Rectangle rect, int index);
public partial class GeoSafariItem : Control
{
protected List<Rectangle> lastFlashingItems = new List<Rectangle>();
protected int lastHeight = 0;
private Image imageFile = null;
protected List<Rectangle> hotspots = new List<Rectangle>();
protected Dictionary<int, string> textItems = new Dictionary<int, string>();
protected Dictionary<int, FileInfo> audioItems = new Dictionary<int, FileInfo>();
protected Rectangle lastRectangle;
protected int selectedIndex = 0;
protected int countItemsLeft = 6;
protected int countItemsRight = 6;
protected int imageOffsetTop = 0;
protected int imageOffsetBottom = 0;
protected bool paintHotSpots = false, colorSwitch = false, paintItemLabels = false;
protected Timer timer = new Timer();
public event RectangleItemClickedDelegate HotspotClick;
public event RectangleItemClickedDelegate QuestionItemClick;
public event RectangleItemClickedDelegate QuestionItemRightClick;
protected void OnHotspotClick(Rectangle rect, int index)
{
if (HotspotClick != null)
{
HotspotClick(this.RectangleToScreen(rect), index);
}
}
protected void OnQuestionItemRightClick(Rectangle rect, int index)
{
if (QuestionItemRightClick != null)
{
QuestionItemRightClick(this.RectangleToScreen(rect), index);
}
}
protected void OnQuestionItemClick(Rectangle rect, int index)
{
if (QuestionItemClick != null)
{
QuestionItemClick(this.RectangleToScreen(rect), index);
}
}
public GeoSafariItem()
{
this.imageFile = EducationalSuite.Core.Properties.Resources.singlepixel;
timer.Interval = 100;
timer.Tick += new EventHandler(timer_Tick);
timer.Enabled = true;
this.MouseUp += new MouseEventHandler(GeoSafariItem_MouseUp);
// Activates double buffering
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
this.DoubleBuffered = true;
//InitializeComponent();
}
public void SetItemText(int index, string text)
{
if (string.IsNullOrEmpty(text))
{
if (this.textItems.ContainsKey(index)) textItems.Remove(index);
}
else
{
this.textItems[index] = text;
}
if (PaintItemLabels)
{
this.Invalidate();
}
}
public string GetItemText(int index)
{
if (this.textItems.ContainsKey(index))
{
return this.textItems[index];
}
else
{
return string.Empty;
}
}
public void SetItemAudio(int index, FileInfo file)
{
if ((file == null) && !file.Exists)
{
if (this.audioItems.ContainsKey(index)) audioItems.Remove(index);
}
else
{
this.audioItems[index] = file;
}
}
public FileInfo GetItemAudio(int index)
{
if (this.audioItems.ContainsKey(index))
{
return this.audioItems[index];
}
else
{
return null;
}
}
#region Recording Regions
bool isRecording = false;
int recordingIndex = 0;
Point recordTopLeft = Point.Empty;
Point recordBottomRight = Point.Empty;
List<Rectangle> recordedRectangles = new List<Rectangle>();
public void StartRecording()
{
isRecording = true;
recordingIndex = 0;
selectedIndex = 0;
recordedRectangles.Clear();
this.MouseUp += new MouseEventHandler(GeoSafariItemRecord_MouseUp);
this.Invalidate();
}
public List<Rectangle> FinishRecording()
{
isRecording = false;
this.MouseUp -= new MouseEventHandler(GeoSafariItemRecord_MouseUp);
this.Invalidate();
this.Hotspots.Clear();
foreach (Rectangle r in recordedRectangles)
{
this.Hotspots.Add(r);
}
return recordedRectangles;
}
private void GeoSafariItemRecord_MouseUp(object sender, MouseEventArgs e)
{
if (isRecording)
{
Rectangle size = SizeRect;
double ratio = (double)imageFile.Height / (double)size.Height;
if (recordTopLeft == Point.Empty)
{
recordTopLeft = new Point(
(int)(((double)e.Location.X - (double)size.Left) * ratio),
(int)(((double)e.Location.Y - (double)size.Top) * ratio)
);
}
else
{
recordBottomRight = new Point(
(int)(((double)e.Location.X - (double)size.Left) * ratio),
(int)(((double)e.Location.Y - (double)size.Top) * ratio)
);
Rectangle r = new Rectangle(recordTopLeft,
new Size(recordBottomRight.X - recordTopLeft.X, recordBottomRight.Y - recordTopLeft.Y));
this.recordedRectangles.Add(r);
recordingIndex++;
selectedIndex++;
recordTopLeft = Point.Empty;
recordBottomRight = Point.Empty;
}
}
this.Invalidate();
}
#endregion
void timer_Tick(object sender, EventArgs e)
{
colorSwitch = !colorSwitch;
if (lastRectangle.Width > 0)
{
this.Invalidate(lastRectangle);
}
else
{
this.Invalidate();
}
}
private Rectangle SizeRect
{
get
{
int rw, rh,
cw = (this.Width - 42),
ch = (this.Height - 2),
ox = 21,
oy = 1;
rw = cw;
rh = ch;
double imageRatio = (double)imageFile.Width / (double)imageFile.Height;
double controlRatio = (double)cw / (double)ch;
if (controlRatio > imageRatio)
{
rw = (int)Math.Round((double)rh * imageRatio);
ox += Math.Abs(rw - cw) / 2;
}
else if (controlRatio < imageRatio)
{
rh = (int)Math.Round((double)rw / imageRatio);
oy += Math.Abs(rh - ch) / 2;
}
return new Rectangle(ox, oy, rw, rh);
}
}
void GeoSafariItem_MouseUp(object sender, MouseEventArgs e)
{
Rectangle size = SizeRect;
for (int i = 0; i < hotspots.Count; i++)
{
Rectangle hotspot = hotspots[i];
double ratio = (double)size.Height / (double)imageFile.Height;
Rectangle adjustedRectange = new Rectangle(
size.Left + (int)(hotspot.X * ratio),
size.Top + (int)(hotspot.Y * ratio),
(int)(hotspot.Width * ratio),
(int)(hotspot.Height * ratio));
if (adjustedRectange.Contains(e.Location))
{
OnHotspotClick(hotspot, i);
return;
}
}
for (int i = 0; i < lastFlashingItems.Count; i++)
{
if (lastFlashingItems[i].Contains(e.Location))
{
if (e.Button == MouseButtons.Right)
OnQuestionItemRightClick(lastFlashingItems[i], i);
else
OnQuestionItemClick(lastFlashingItems[i], i);
return;
}
}
}
public List<Rectangle> Hotspots
{
get { return hotspots; }
}
public Image ImageFile
{
get { return imageFile; }
set
{
imageFile = value;
lastFlashingItems.Clear();
this.Invalidate();
}
}
public int SelectedIndex
{
get { return selectedIndex; }
set { selectedIndex = value; this.Invalidate(); }
}
public int CountItemsLeft
{
get { return countItemsLeft; }
set
{
countItemsLeft = value;
lastFlashingItems.Clear();
this.Invalidate();
}
}
public int CountItemsRight
{
get { return countItemsRight; }
set
{
countItemsRight = value;
lastFlashingItems.Clear();
this.Invalidate();
}
}
public int ImageOffsetTop
{
get { return imageOffsetTop; }
set
{
imageOffsetTop = value;
lastFlashingItems.Clear();
this.Invalidate();
}
}
public int ImageOffsetBottom
{
get { return imageOffsetBottom; }
set
{
imageOffsetBottom = value;
lastFlashingItems.Clear();
this.Invalidate();
}
}
public bool PaintHotSpots
{
get { return paintHotSpots; }
set { paintHotSpots = value; this.Invalidate(); }
}
public bool PaintItemLabels
{
get { return paintItemLabels; }
set { paintItemLabels = value; this.Invalidate(); }
}
protected override void OnPaint(PaintEventArgs pe)
{
Graphics g = pe.Graphics;
string itemText;
SizeF sizeItemText;
double topOffset = imageOffsetTop;
double bottomOffset = imageOffsetBottom;
double topOffsetPct = (double)topOffset / (double)imageFile.Height;
double bottomOffsetPct = (double)bottomOffset / (double)imageFile.Height;
Rectangle size = SizeRect;
SolidBrush brush = new SolidBrush(this.BackColor);
g.FillRectangle(brush, 0, 0, this.Width - 1, this.Height - 1);
g.FillRectangle(Brushes.Ivory, size.X - 25, size.Y, size.Width + 50, size.Height);
g.DrawRectangle(Pens.DarkKhaki, size.X - 25, size.Y - 1, size.Width + 50, size.Height + 1);
g.DrawImage(imageFile, size.X, size.Y, size.Width, size.Height);
Rectangle rect, rectItemText;
Brush selectedColor = (colorSwitch ? Brushes.Crimson : Brushes.Red);
topOffset = topOffsetPct * size.Height;
bottomOffset = bottomOffsetPct * size.Height;
int tmpHeight = (size.Height - (int)topOffset - (int)bottomOffset) / countItemsLeft;
if (size.Height != this.lastHeight || this.lastFlashingItems.Count == 0)
{
lastHeight = size.Height;
lastFlashingItems.Clear();
int actualIndex = 0;
for (int i = 0; i < countItemsLeft; i++)
{
int yy = size.Y + (tmpHeight * i) + (int)topOffset;
int xx = size.X - 18;
rect = new Rectangle(xx, yy, 16, 8);
this.lastFlashingItems.Add(rect);
g.FillRectangle((actualIndex == selectedIndex ? selectedColor : Brushes.Khaki), rect);
g.DrawRectangle(Pens.DarkKhaki, rect);
if (actualIndex == selectedIndex)
{
lastRectangle = rect;
}
itemText = this.GetItemText(actualIndex);
if (PaintItemLabels && !string.IsNullOrEmpty(itemText))
{
// Draw Text next to each notch
sizeItemText = g.MeasureString(itemText, this.Font);
int xxx = size.X + 10;
rectItemText = new Rectangle(xxx, yy, Convert.ToInt32(sizeItemText.Width), Convert.ToInt32(sizeItemText.Height));
PaintHotspot(g, Color.White, rectItemText, 200);
g.DrawString(itemText, this.Font, Brushes.Black, (float)xxx, (float)yy);
}
actualIndex++;
}
tmpHeight = (size.Height - (int)topOffset - (int)bottomOffset) / countItemsRight;
for (int i = 0; i < countItemsRight; i++)
{
int yy = size.Y + (tmpHeight * i) + (int)topOffset;
int xx = size.X + size.Width + 2;
rect = new Rectangle(xx, yy, 16, 8);
this.lastFlashingItems.Add(rect);
g.FillRectangle((actualIndex == selectedIndex ? selectedColor : Brushes.Khaki), rect);
g.DrawRectangle(Pens.DarkKhaki, rect);
if (actualIndex == selectedIndex)
{
lastRectangle = rect;
}
itemText = this.GetItemText(actualIndex);
if (PaintItemLabels && !string.IsNullOrEmpty(itemText))
{
// Draw Text next to each notch
sizeItemText = g.MeasureString(itemText, this.Font);
int xxx = size.X + size.Width - 10 - Convert.ToInt32(sizeItemText.Width);
rectItemText = new Rectangle(xxx, yy, Convert.ToInt32(sizeItemText.Width), Convert.ToInt32(sizeItemText.Height));
PaintHotspot(g, Color.White, rectItemText, 200);
g.DrawString(itemText, this.Font, Brushes.Black, (float)xxx, (float)yy);
}
actualIndex++;
}
}
else
{
lastHeight = size.Height;
for (int i = 0; i < lastFlashingItems.Count; i++)
{
g.FillRectangle((i == selectedIndex ? selectedColor : Brushes.Khaki), lastFlashingItems[i]);
g.DrawRectangle(Pens.DarkKhaki, lastFlashingItems[i]);
if (i == selectedIndex)
{
lastRectangle = lastFlashingItems[i];
}
}
if (PaintItemLabels)
{
int actualIndex = 0;
for (int i = 0; i < countItemsLeft; i++)
{
itemText = this.GetItemText(actualIndex);
if (!string.IsNullOrEmpty(itemText))
{
int yy = size.Y + (tmpHeight * i) + (int)topOffset;
// Draw Text next to each notch
sizeItemText = g.MeasureString(itemText, this.Font);
int xxx = size.X + 10;
rectItemText = new Rectangle(xxx, yy, Convert.ToInt32(sizeItemText.Width), Convert.ToInt32(sizeItemText.Height));
PaintHotspot(g, Color.White, rectItemText, 200);
g.DrawString(itemText, this.Font, Brushes.Black, (float)xxx, (float)yy);
}
actualIndex++;
}
tmpHeight = (size.Height - (int)topOffset - (int)bottomOffset) / countItemsRight;
for (int i = 0; i < countItemsRight; i++)
{
itemText = this.GetItemText(actualIndex);
if (!string.IsNullOrEmpty(itemText))
{
int yy = size.Y + (tmpHeight * i) + (int)topOffset;
// Draw Text next to each notch
sizeItemText = g.MeasureString(itemText, this.Font);
int xxx = size.X + size.Width - 10 - Convert.ToInt32(sizeItemText.Width);
rectItemText = new Rectangle(xxx, yy, Convert.ToInt32(sizeItemText.Width), Convert.ToInt32(sizeItemText.Height));
PaintHotspot(g, Color.White, rectItemText, 200);
g.DrawString(itemText, this.Font, Brushes.Black, (float)xxx, (float)yy);
}
actualIndex++;
}
}
}
// Calling the base class OnPaint
base.OnPaint(pe);
if (this.isRecording)
{
for (int i = 0; i < this.recordedRectangles.Count; i++)
{
rect = recordedRectangles[i];
double ratio = (double)size.Height / (double)imageFile.Height;
Rectangle adjustedRectange = new Rectangle(
size.Left + (int)(rect.X * ratio),
size.Top + (int)(rect.Y * ratio),
(int)(rect.Width * ratio),
(int)(rect.Height * ratio));
PaintHotspot(g, Color.LightBlue, adjustedRectange, (i + 1).ToString());
}
}
else if (this.paintHotSpots)
{
for (int i = 0; i < hotspots.Count; i++)
{
Rectangle hotspot = hotspots[i];
double ratio = (double)size.Height / (double)imageFile.Height;
Rectangle adjustedRectange = new Rectangle(
size.Left + (int)(hotspot.X * ratio),
size.Top + (int)(hotspot.Y * ratio),
(int)(hotspot.Width * ratio),
(int)(hotspot.Height * ratio));
PaintHotspot(g, Color.LightGreen, adjustedRectange, (i + 1).ToString());
}
}
}
protected virtual void PaintHotspot(Graphics g, Color c, Rectangle hotspot, int alpha)
{
PaintHotspot(g, c, hotspot, alpha, null);
}
protected virtual void PaintHotspot(Graphics g, Color c, Rectangle hotspot, string txt)
{
PaintHotspot(g, c, hotspot, 100, txt);
}
protected virtual void PaintHotspot(Graphics g, Color c, Rectangle hotspot, int alpha, string txt)
{
SolidBrush brush = new SolidBrush(Color.FromArgb(alpha, c));
g.FillRectangle(brush, hotspot);
if (!string.IsNullOrEmpty(txt))
g.DrawString(txt, this.Font, Brushes.DarkGreen, hotspot.Location);
}
}
}
Update
I imagine the following line is causing the error.
this.imageFile = EducationalSuite.Core.Properties.Resources.singlepixel;
The code is referring to a image resource "singlepixel". This image must be in the default resource file of the EducationalSuite.Core assembly. First confirm that you are currently editing the said assembly by opening Project Properties and checking the Default Namespace on the Application page. This should state "EducationalSuite.Core". If this isn't the case, you are most likely missing a reference to the said assembly.
If you have the EducationalSuite.Core project open the easiest way to add the singlepixel resource is to open project properties, Resources tab and creating a new default resource file. From the top open the Add Resource drop down and select existing file or new image depending on whether you have the file already or if you need to create it. Name the resource "singlepixel".
Visual Studio will generate Resources helper class under Properties namespace for you so you can access the resource through the Properties.Resources.singlepixel under EducationalSuite.Core in your code.
Old answer
In general Properties namespace is the namespace which contains application or user specific settings. You can add these settings (and the namespace) by navigating to the Settings tab in the Properties of the project.
Unfortunately it's kind of hard to say more based on this information. Could you provide the piece of code that causes this error?
If you double click the error message the IDE will take you to the line which is causing the error.
Most likely the piece of code is expecting a setting variable which is not added to the project.
Looks like you are missing the Reference. If it is not under References in solution explorer than I would do a file search in windows for "EducationalSuite.Core" to see where it is on the system and add it. You may also be missing the "using" statement? If you hover over the "Properties" text you should get a small drop down that will add the using's for you.
If this does not help, more information would be helpful?
Hope this helps!

Categories

Resources