I'm using the following code to draw a selection rectangle over a picturebox and allow the user to select and drag it to the desired position.
What I intend to achieve is to allow the user to adjust the rectangle size by implementing option to adjust the rectangle size. Currently I have managed to achieve the following.
How to solve this issue?
public class DraggablePictureBox : PictureBox
{
Boolean hit1 = false, hit2 = false;
public Boolean notagimg = true;
public Boolean editedflag = false;
public Boolean notext = false;
public Boolean tdrawflag = false, tdrawflag2 = false;
Bitmap l;
public Form1 LaunchOrigin2 { get; set; }
public Point point = new Point(0, 0);
public Point point2 = new Point(0, 0);
public int sizemode = 1;
public DraggablePictureBox()
{
this.Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e)
{
this.Cursor = Cursors.Arrow;
if (e.Button == MouseButtons.Left)
{
point = e.Location;
base.OnMouseDown(e);
this.Invalidate();
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
PointF x = new PointF(e.X, e.Y);
Pen p = new Pen(Brushes.Red, 2f);
RectangleF rect2 = new RectangleF(1, 1, 1, 1);
RectangleF rect = new RectangleF(1, 1, 1, 1);
if (e.Button == MouseButtons.Left)
{
this.Cursor = Cursors.Hand;
//Creating Rectangles to check to find the selected object
if (notext == false)
{
rect = new RectangleF(point, new Size(400,400));
}
if (rect.Contains(x) && notext == false)
{
hit1 = true;
}
if (hit1 == true )
{
this.Invalidate();
}
this.Invalidate();
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
tdrawflag = false;
}
if (e.Button == MouseButtons.Left)
{
point = e.Location;
base.OnMouseDown(e);
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
Pen p = new Pen(Brushes.Red, 5);
p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
Pen p2 = new Pen(Brushes.LightYellow, 5);
p2.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
if (!hit1)
{
pe.Graphics.DrawRectangle(p, new Rectangle(point, new Size(400, 400)));
}
else
{
pe.Graphics.DrawRectangle(p2, new Rectangle(point, new Size(400, 400)));
hit1 = false;
}
}
}
You have different options:
You can draw a resizable frame on the picture box
You can create a resizable control and add it to picture box
In this answer, I've taken the second option to be able to use built-in sizing features of the controls. Here is a screen capture which shows how it looks like in action:
Example - Creating a Frame Control
As an example, I'll create a resizable control and will add it to the picture box.
using System;
using System.Drawing;
using System.Windows.Forms;
public class FrameControl : Control
{
public FrameControl()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
DoubleBuffered = true;
ResizeRedraw = true;
BackColor = Color.Transparent;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (var p = new Pen(Color.Black, 4))
{
p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
e.Graphics.DrawRectangle(p, 0, 0, Width - 1, Height - 1);
}
}
const int WM_NCHITTEST = 0x84;
const int WM_SETCURSOR = 0x20;
const int WM_NCLBUTTONDBLCLK = 0xA3;
protected override void WndProc(ref Message m)
{
int borderWidth = 10;
if (m.Msg == WM_SETCURSOR) /*Setting cursor to SizeAll*/
{
if ((m.LParam.ToInt32() & 0xffff) == 0x2 /*Move*/)
{
Cursor.Current = Cursors.SizeAll;
m.Result = (IntPtr)1;
return;
}
}
if ((m.Msg == WM_NCLBUTTONDBLCLK)) /*Disable Mazimiz on Double click*/
{
m.Result = (IntPtr)1;
return;
}
base.WndProc(ref m);
if (m.Msg == WM_NCHITTEST)
{
var pos = PointToClient(new Point(m.LParam.ToInt32() & 0xffff,
m.LParam.ToInt32() >> 16));
if (pos.X <= ClientRectangle.Left + borderWidth &&
pos.Y <= ClientRectangle.Top + borderWidth)
m.Result = new IntPtr(13); //TOPLEFT
else if (pos.X >= ClientRectangle.Right - borderWidth &&
pos.Y <= ClientRectangle.Top + borderWidth)
m.Result = new IntPtr(14); //TOPRIGHT
else if (pos.X <= ClientRectangle.Left + borderWidth &&
pos.Y >= ClientRectangle.Bottom - borderWidth)
m.Result = new IntPtr(16); //BOTTOMLEFT
else if (pos.X >= ClientRectangle.Right - borderWidth &&
pos.Y >= ClientRectangle.Bottom - borderWidth)
m.Result = new IntPtr(17); //BOTTOMRIGHT
else if (pos.X <= ClientRectangle.Left + borderWidth)
m.Result = new IntPtr(10); //LEFT
else if (pos.Y <= ClientRectangle.Top + borderWidth)
m.Result = new IntPtr(12); //TOP
else if (pos.X >= ClientRectangle.Right - borderWidth)
m.Result = new IntPtr(11); //RIGHT
else if (pos.Y >= ClientRectangle.Bottom - borderWidth)
m.Result = new IntPtr(15); //Bottom
else
m.Result = new IntPtr(2); //Move
}
}
}
Then add the control to the picture box:
var s = 100;
var c = new FrameControl();
c.Size = new Size(s, s);
c.Location = new Point((pictureBox1.Width - s) / 2, (pictureBox1.Height - s) / 2);
pictureBox1.Controls.Add(c);
To add a fancy effect of filling outside of the frame with semi-transparent color:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.ExcludeClip(pictureBox1.Controls[0].Bounds);
using (var b = new SolidBrush(Color.FromArgb(100, Color.Black)))
e.Graphics.FillRectangle(b, pictureBox1.ClientRectangle);
}
As you can see in the paint event, you can find the FrameControl using pictureBox1.Controls[0]. So you can find its location and size.
You can encapsulate all the logic of the picture box in a derived picture box.
Note: Flicker-free rendering
If you experience flickering when moving the frame, use the following code in your form:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // WS_EX_COMPOSITED
return cp;
}
}
Related
So I have a resizable control which I'm using WM_NCHITTEST to resize. I have double buffered the control and I'm drawing a border. However, when resizing, I get medium flickering issues.
Here's the code for drawing:
if (_cachedPen == null)
{
_cachedPen = new Pen(BorderColor, VisibleBorderWidth);
}
Rectangle clientRectangle = ClientRectangle;
if ((BorderSides & BorderSides.Left) == BorderSides.Left)
{
e.Graphics.DrawLine(_cachedPen, clientRectangle.X, clientRectangle.Y, clientRectangle.X, clientRectangle.Height);
}
if ((BorderSides & BorderSides.Right) == BorderSides.Right)
{
e.Graphics.DrawLine(_cachedPen, clientRectangle.Width - VisibleBorderWidth, clientRectangle.Y, clientRectangle.Width - VisibleBorderWidth, clientRectangle.Height);
}
if ((BorderSides & BorderSides.Bottom) == BorderSides.Bottom)
{
e.Graphics.DrawLine(_cachedPen, clientRectangle.X, clientRectangle.Height - VisibleBorderWidth, clientRectangle.Width, clientRectangle.Height - VisibleBorderWidth);
}
if ((BorderSides & BorderSides.Top) == BorderSides.Top)
{
e.Graphics.DrawLine(_cachedPen, clientRectangle.X, clientRectangle.Y, clientRectangle.Width, clientRectangle.Y);
}
And for resizing:
case WM_NCHITTEST:
{
Point pos = PointToClient(new Point(m.LParam.ToInt32()));
if ((BorderSides & BorderSides.Left) == BorderSides.Left && pos.X < PhysicalBorderWidth)
{
m.Result = new IntPtr(HTLEFT);
}
if ((BorderSides & BorderSides.Bottom) == BorderSides.Bottom && pos.Y > Height - PhysicalBorderWidth)
{
m.Result = new IntPtr(HTBOTTOM);
}
if ((BorderSides & BorderSides.Right) == BorderSides.Right && pos.X > Width - PhysicalBorderWidth)
{
m.Result = new IntPtr(HTRIGHT);
}
if ((BorderSides & BorderSides.Top) == BorderSides.Top && pos.Y < PhysicalBorderWidth)
{
m.Result = new IntPtr(HTTOP);
}
return;
}
case 0x0014:
return;
default:
base.WndProc(ref m);
break;
Note that SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.ResizeRedraw, true); is on. However, when resizing, I get light-medium flickering. Is there any way to solve this?
Just to note, it happens even when I don't cache the Pen objects.
The painting is just called from OnPaint. The custom control just inherits from Control.
The definition of BorderSides is as follows:
[Flags]
internal enum BorderSides
{
None = 0,
Left = 1,
Right = 2,
Top = 4,
Bottom = 8
}
And here are the constants:
private const int WM_NCHITTEST = 0x0084;
private const int HTBOTTOM = 15;
private const int HTLEFT = 10;
private const int HTRIGHT = 11;
private const int HTTOP = 12;
This is for a docking control. It doesn't have a graphic background, and I intend to inherit from it. It will host controls. I'm testing all 4 border sides, and all have slight flickering issues.
Thanks
I have a winforms app where I draw on an image in a picturebox. The drawing part works really well, except for lag when PictureBox.SizeMode = PictureBoxSizeMode.Zoom. The reason I set the SizeMode to Zoom is so I could zoom in and out of the image while preserving memory. Is there any way to speed up the drawing process?
The code for the PictureBox's Paint method looks like so:
pen = new Pen(color, 5);
solidBrush = new SolidBrush(solid);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.ScaleTransform(PictureScale, PictureScale);
foreach (List<Point> polygon in Polygons)
{
e.Graphics.DrawLines(pen, polygon.ToArray());
}
if (NewPolygon != null)
{
Pen pp = new Pen(color, 5);
if (NewPolygon.Count > 1)
{
e.Graphics.DrawLines(pp, NewPolygon.ToArray());
}
if (NewPolygon.Count > 0)
{
using (Pen dashed_pen = pp)
{
dashed_pen.DashPattern = new float[] { 3, 3 };
e.Graphics.DrawLine(dashed_pen, NewPolygon[NewPolygon.Count - 1], NewPoint);
}
}
}
The code allows the user to draw a series of points connected by some solid lines. After adding the first point, there is a dotted line going from the previous point to the mouse's current position. The program 'fills' in the line when the user adds a new Point NewPolygon is a List<Point> object, and the program adds a point every time the user clicks. Pol is a List<List<Point>> object which holds NewPolygon. I attached a GIF of the drawing process because an image is worth 1000 words. The lag in the gif is not noticeable at all in different size modes.
The if (NewPolygon.Count > 1) loop draws solid lines between at least 2 points. The if (NewPolygon.Count > 0) draws a dotted line between spot and NewPoint when there is at least one point.
EDIT : full drawing code
int x = 0;
int y = 0;
bool drag = false;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
Point spot = new Point((int)((float)(e.Location.X) / PictureScale), (int)((float)(e.Location.Y) / PictureScale));
if (e.Button == MouseButtons.Middle)
{
x = e.X;
y = e.Y;
drag = true;
}
else
{
if (NewPolygon != null)
{
if (e.Button == MouseButtons.Right)
{
if (NewPolygon.Count > 1)
{
int counter = NewPolygon.Count;
Polygons.Add(NewPolygon);
}
NewPolygon = null;
}
else if (e.Button == MouseButtons.Left)
{
if (NewPolygon[NewPolygon.Count - 1] != spot)
{
NewPolygon.Add(spot);
scaffolds.Add(new Rectangle(spot.X - 3, spot.Y - 3, 6, 6));
}
}
}
else
{
NewPolygon = new List<Point>();
NewPoint = spot;
NewPolygon.Add(spot);
scaffolds.Add(new Rectangle(spot.X - 3, spot.Y - 3, 6, 6));
}
}
//this.Capture = true;
pictureBox1.Refresh();
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (drag)
{
pictureBox1.Top += e.Y - y;
pictureBox1.Left += e.X - x;
this.Cursor = Cursors.SizeAll;
}
else
{
if (NewPolygon == null)
return;
NewPoint = new Point((int)((float)(e.Location.X) / PictureScale), (int)((float)(e.Location.Y) / PictureScale));
pictureBox1.Refresh();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.ScaleTransform(PictureScale, PictureScale);
foreach (Rectangle rect in scaffolds)
{
e.Graphics.DrawEllipse(pen, rect);
}
foreach (List<Point> polygon in Polygons)
{
e.Graphics.DrawLines(pen, polygon.ToArray());
}
if (NewPolygon != null)
{
Pen pp = new Pen(color, 5);
if (NewPolygon.Count > 0)
{
if (NewPolygon.Count > 1)
{
e.Graphics.DrawLines(pp, NewPolygon.ToArray());
}
using (Pen dashed_pen = pp)
{
dashed_pen.DashPattern = new float[] { 3, 3 };
e.Graphics.DrawLine(dashed_pen, NewPolygon[NewPolygon.Count - 1], NewPoint);
}
}
}
}
listbox selected index event:
private void listBoxSnap_SelectedIndexChanged(object sender, EventArgs e)
{
WindowSnap snap = this.listBoxSnap.SelectedItem as WindowSnap;
selectedIndex = this.listBoxSnap.SelectedIndex.ToString();
this.pictureBoxSnap.Image = snap.Image;
for (int i = 0; i < rectangles.Length; i++)
{
if (rectangles[i] != RectClone)
{
ClearGraphics = false;
}
else
{
ClearGraphics = true;
}
}
if (rectangles[listBoxSnap.SelectedIndex].Width == 0 && rectangles[listBoxSnap.SelectedIndex].Height == 0)
{
Reset.Enabled = false;
ConfirmRectangle.Enabled = false;
cm.MenuItems[0].Enabled = false;
cm.MenuItems[1].Enabled = false;
cm.MenuItems[2].Enabled = false;
}
if (rectangles[listBoxSnap.SelectedIndex].Width > 5 && rectangles[listBoxSnap.SelectedIndex].Height > 5)
{
Reset.Enabled = true;
if (IsRectangleConfirmed == true)
{
ConfirmRectangle.Enabled = false;
ClearGraphics = true;
cropRect = true;
}
else
{
ConfirmRectangle.Enabled = true;
}
cm.MenuItems[0].Enabled = true;
cm.MenuItems[1].Enabled = true;
cm.MenuItems[2].Enabled = true;
}
}
And the paint event of the pictureBox:
private void pictureBoxSnap_Paint(object sender, PaintEventArgs e)
{
if (pictureBoxSnap.Image != null)
{
{
if (ClearGraphics == false)
{
if (rectangles[listBoxSnap.SelectedIndex] != Rectangle.Empty)
{
e.Graphics.DrawRectangle(Pens.Firebrick, rectangles[listBoxSnap.SelectedIndex]);
}
}
if (cropRect == true)
{
if (recttest.Width > 5 && recttest.Height > 5)
{
pnt = PointToScreen(pictureBoxSnap.Location);
e.Graphics.Clear(Color.White);
e.Graphics.CopyFromScreen(pnt.X + rect.X, pnt.Y + rect.Y, rect.X, rect.Y, new Size(rect.Width, rect.Height));
}
}
}
}
}
The problem is with this part:
pnt = PointToScreen(pictureBoxSnap.Location);
e.Graphics.Clear(Color.White);
e.Graphics.CopyFromScreen(pnt.X + rect.X, pnt.Y + rect.Y, rect.X, rect.Y, new Size(rect.Width, rect.Height));
This part draw the cropped rectangle but then when i select another item in the listBox and then back to this item with the cropped rectangle again it's drawing it again and i want it just to remember it and show it again according to the selected item.
This part:
if (IsRectangleConfirmed == true)
{
ConfirmRectangle.Enabled = false;
ClearGraphics = true;
cropRect = true;
}
The IF: if (IsRectangleConfirmed == true) means that i clicked a button and a cropped rectangle created for this item im in now.
The problem is that when i get back each time to this item the cropped rectangle is drawing over again and i want it to just be shown like it will remember the cropped rectangle for this selected item(index).
What i want to do is a few things:
When i draw rectangle on the pictureBox and move between items in the listBox it will remember those items with already drawed rectangle. This part is working.
When i click on the button ConfirmRectangle_Click it will make a cropped rectangle from the rectangle i drawed i want that when i move between items in the listBox it will remember those items with cropped image.
This line get minimized windows screenshots:
this.listBoxSnap.Items.AddRange(WindowSnap.GetAllWindows(true, true).ToArray());
I add them to the listBox and when moving between items i see the screenshots of each one in the pictureBox.
I want to do now on items that have cropped image take screenshot of the part of the cropped image only.
If there is no cropped image take screenshot regular from the whole image.
This method GetAllWindows show in the listBox the text of the window but what i want to show in the listBox as item is only the name of it.
This is my project in zip file the name is CaptureZip
CaptureZip
And this is my project in winrar name Capture:
Capture
Set pictureBoxSnap SizeMode to normal.
private bool[] isCropped;
private Image img;
private Image imgClone;
public Form1()
{
InitializeComponent();
img = new Bitmap(pictureBoxSnap.Width, pictureBoxSnap.Height);
imgClone = new Bitmap(pictureBoxSnap.Width, pictureBoxSnap.Height);
Graphics g;
using (g = Graphics.FromImage(img))
{
g.Clear(Color.White);
}
pictureBoxSnap.Image = img;
...
...
rectangles = new Rectangle[listBoxSnap.Items.Count];
isCropped = new bool[listBoxSnap.Items.Count];
...
}
private void listBoxSnap_SelectedIndexChanged(object sender, EventArgs e)
{
drawpicbox(this.listBoxSnap.SelectedIndex);
}
private void drawpicbox(int index)
{
Graphics g, g1;
Size sz;
WindowSnap snap = this.listBoxSnap.SelectedItem as WindowSnap;
Bitmap testBmp;
using (g = Graphics.FromImage(img))
{
g.Clear(Color.White);
sz = calculateSizeAndPosition(snap.Image.Size);
if (isCropped[index] == true)
{
ConfirmRectangle.Enabled = false;
using (testBmp = new Bitmap (img.Width , img.Height )){
using (g1 = Graphics.FromImage(testBmp))
{
g1.Clear(Color.White);
g1.DrawImage(snap.Image, (int)((pictureBoxSnap.Width - sz.Width) / 2.0), (int)((pictureBoxSnap.Height - sz.Height) / 2.0), sz.Width, sz.Height);
}
g.DrawImage(testBmp, rectangles[index], rectangles[index], GraphicsUnit.Pixel);
g.DrawRectangle(Pens.Firebrick, rectangles[index]);
}
}
else if (rectangles[index].Width != 0)
{
ConfirmRectangle.Enabled = true;
g.DrawImage(snap.Image, (int)((pictureBoxSnap.Width - sz.Width) / 2.0), (int)((pictureBoxSnap.Height - sz.Height) / 2.0), sz.Width, sz.Height);
g.DrawRectangle(Pens.Firebrick, rectangles[index]);
}
else
{
ConfirmRectangle.Enabled = false;
g.DrawImage(snap.Image, (int)((pictureBoxSnap.Width - sz.Width) / 2.0), (int)((pictureBoxSnap.Height - sz.Height) / 2.0), sz.Width, sz.Height);
}
}
pictureBoxSnap.Invalidate();
}
private Size calculateSizeAndPosition(Size snapSize)
{
int wdth, hgt;
Single flt;
wdth = snapSize.Width;
hgt = snapSize.Height;
flt = (Single)wdth / (Single)hgt;
if (wdth <= pictureBoxSnap.Width && hgt <= pictureBoxSnap.Height)
{
//return new Size(wdth, hgt);
}
else{
if(wdth >= hgt){
while (true)
{
wdth--;
hgt = (int)(wdth / flt);
if (wdth <= pictureBoxSnap.Width && hgt <= pictureBoxSnap.Height)
{
break;
}
}
}
else{
while (true)
{
hgt--;
wdth = (int)((Single)hgt * flt);
if (wdth <= pictureBoxSnap.Width && hgt <= pictureBoxSnap.Height)
{
break;
}
}
}
}
return new Size(wdth, hgt);
}
private void pictureBoxSnap_MouseMove(object sender, MouseEventArgs e)
{
if (isCropped[listBoxSnap.SelectedIndex] == false && e.Button == MouseButtons.Left && e.Location != RectStartPoint)
{
DrawRectangle(e.Location);
}
}
private void DrawRectangle(Point pnt)
{
Graphics g = Graphics.FromImage(img);
//g.DrawRectangle(Pens.Firebrick, 50, 50, 300, 200);
g.DrawImage(imgClone, 0, 0);
if (pnt.X == RectStartPoint.X || pnt.Y == RectStartPoint.Y)
{
g.DrawLine(Pens.Firebrick, RectStartPoint.X, RectStartPoint.Y, pnt.X, pnt.Y);
}
else if (pnt.X > RectStartPoint.X && pnt.Y > RectStartPoint.Y) //Right-Down
{
rect.X = RectStartPoint.X; rect.Y = RectStartPoint.Y; rect.Width = pnt.X - RectStartPoint.X; rect.Height = pnt.Y - RectStartPoint.Y;
g.DrawRectangle(Pens.Firebrick, rect);
}
else if (pnt.X > RectStartPoint.X && pnt.Y < RectStartPoint.Y) //Right-Up
{
rect.X = RectStartPoint.X; rect.Y = pnt.Y; rect.Width = pnt.X - RectStartPoint.X; rect.Height = RectStartPoint.Y - pnt.Y;
g.DrawRectangle(Pens.Firebrick, rect);
}
else if (pnt.X < RectStartPoint.X && pnt.Y > RectStartPoint.Y) //Left-Down
{
rect.X = pnt.X; rect.Y = RectStartPoint.Y; rect.Width = RectStartPoint.X - pnt.X; rect.Height = pnt.Y - RectStartPoint.Y;
g.DrawRectangle(Pens.Firebrick, rect);
}
else //Left-Up
{
rect.X = pnt.X; rect.Y = pnt.Y; rect.Width = RectStartPoint.X - pnt.X; rect.Height = RectStartPoint.Y - pnt.Y;
g.DrawRectangle(Pens.Firebrick, rect);
}
g.Dispose();
pictureBoxSnap.Invalidate();
}
private void pictureBoxSnap_MouseDown(object sender, MouseEventArgs e)
{
Graphics g;
Size sz;
if (isCropped[listBoxSnap.SelectedIndex] == false && e.Button == MouseButtons.Left)
{
WindowSnap snap = this.listBoxSnap.SelectedItem as WindowSnap;
RectStartPoint = e.Location;
sz = calculateSizeAndPosition(snap.Image.Size);
using (g = Graphics.FromImage(imgClone))
{
g.Clear(Color.White);
g.DrawImage(snap.Image, (int)((pictureBoxSnap.Width - sz.Width) / 2.0), (int)((pictureBoxSnap.Height - sz.Height) / 2.0), sz.Width, sz.Height);
}
}
}
private void pictureBoxSnap_MouseUp(object sender, MouseEventArgs e)
{
if (isCropped[listBoxSnap.SelectedIndex] == false && e.Button == MouseButtons.Left && e.Location.X != RectStartPoint.X && e.Location.Y != RectStartPoint.Y)
{
ConfirmRectangle.Enabled = true;
rectangles[listBoxSnap.SelectedIndex] = rect;
//drawpicbox(this.listBoxSnap.SelectedIndex);
}
}
private void ConfirmRectangle_Click(object sender, EventArgs e)
{
isCropped[this.listBoxSnap.SelectedIndex] = true;
drawpicbox(this.listBoxSnap.SelectedIndex);
}
private void Reset_Click(object sender, EventArgs e)
{
isCropped[this.listBoxSnap.SelectedIndex] = false;
rectangles[this.listBoxSnap.SelectedIndex] = new Rectangle(0, 0, 0, 0);
drawpicbox(this.listBoxSnap.SelectedIndex);
}
private void pictureBoxSnap_Paint(object sender, PaintEventArgs e)
{
//Nothing
}
private void RefreshWindowsList()
{
Graphics g;
g = GraphicsfromImage(img);
g.Clear(Color.White);
ClearGraphics = true;
this.listBoxSnap.Items.Clear();
buttonSnap.Enabled = false;
this.listBoxSnap.Items.AddRange(WindowSnap.GetAllWindows(true, true).ToArray());
buttonSnap.Enabled = true;
for (int i = listBoxSnap.Items.Count - 1; i >= 0; i--)
{
string tt = listBoxSnap.Items[i].ToString();
if (tt.Contains(" ,"))
{
listBoxSnap.Items.RemoveAt(i);
}
}
rectangles = new Rectangle[listBoxSnap.Items.Count];
isCropped = new bool[listBoxSnap.Items.Count];
ConfirmRectangle.Enabled = false;
textBoxIndex.Text = listBoxSnap.Items.Count.ToString();
if (this.listBoxSnap.Items.Count > 0)
this.listBoxSnap.SetSelected(0, true);
listBoxSnap.Select();
pictureBoxSnap.Invalidate();
}
EDIT
Some minor corrections:
private void RefreshWindowsList()
{
//Graphics g; <- You dont need this
//g = GraphicsfromImage(img); <- You dont need this
//g.Clear(Color.White); <- You dont need this
//ClearGraphics = true; <- You dont need this
this.listBoxSnap.Items.Clear();
buttonSnap.Enabled = false;
this.listBoxSnap.Items.AddRange(WindowSnap.GetAllWindows(true, true).ToArray());
buttonSnap.Enabled = true;
for (int i = listBoxSnap.Items.Count - 1; i >= 0; i--)
{
string tt = listBoxSnap.Items[i].ToString();
if (tt.Contains(" ,"))
{
listBoxSnap.Items.RemoveAt(i);
}
}
rectangles = new Rectangle[listBoxSnap.Items.Count];
isCropped = new bool[listBoxSnap.Items.Count];
//ConfirmRectangle.Enabled = false; <- You dont need this
textBoxIndex.Text = listBoxSnap.Items.Count.ToString();
if (this.listBoxSnap.Items.Count > 0)
this.listBoxSnap.SetSelected(0, true);
listBoxSnap.Select();
//pictureBoxSnap.Invalidate(); <- You dont need this
}
Replace private void DrawRectangle(Point pnt) with:
private void DrawRectangle(Point pnt)
{
Graphics g = Graphics.FromImage(img);
g.DrawImage(imgClone, 0, 0);
if (pnt.X == RectStartPoint.X || pnt.Y == RectStartPoint.Y)
{
g.DrawLine(Pens.Firebrick, RectStartPoint.X, RectStartPoint.Y, pnt.X, pnt.Y);
}
else
{
g.DrawRectangle(Pens.Firebrick, Math.Min(RectStartPoint.X, pnt.X), Math.Min(RectStartPoint.Y, pnt.Y),
Math.Abs(RectStartPoint.X - pnt.X), Math.Abs(RectStartPoint.Y - pnt.Y));
}
g.Dispose();
pictureBoxSnap.Invalidate();
}
Replace private void pictureBoxSnap_MouseUp(object sender, MouseEventArgs e) with:
private void pictureBoxSnap_MouseUp(object sender, MouseEventArgs e)
{
if (isCropped[listBoxSnap.SelectedIndex] == false && e.Button == MouseButtons.Left)
{
if (Math.Abs(e.Location.X - RectStartPoint.X) < 10 || Math.Abs(e.Location.Y - RectStartPoint.Y) < 10)
{
rectangles[listBoxSnap.SelectedIndex] = new Rectangle(0, 0, 0, 0);
drawpicbox(listBoxSnap.SelectedIndex);
}
else
{
ConfirmRectangle.Enabled = true;
rectangles[listBoxSnap.SelectedIndex] = new Rectangle(Math.Min(RectStartPoint.X, e.X), Math.Min(RectStartPoint.Y, e.Y),
Math.Abs(RectStartPoint.X - e.X), Math.Abs(RectStartPoint.Y - e.Y));
}
}
}
Some explanation:
Function calculateSizeAndPosition() (should probably be calculateSize()), calculates the new size of snap image in order to fit to picturebox. It calculates it in a way similar to picturebox zoom mode.
img is what picturebox always draws after pictureBoxSnap.Invalidate();. So, if you want to make any changes to picturebox, draw on img and then invalidate.
Valter
As per your previous post you are trying to crop the image by Mouse drag. Now, you want to get that cropped image back when you select that item again after selecting another. In this case after cropping the image you are not setting that cropped image back to the SelectedItem so when you select that item again it will show cropped image not its original.
Image img = CropImage();
((WindowSnap)listBox.SelectedItem).Image = img;
or you can create another property in WindowSnap class.
ie. public image CroppedImage {get; set;}
So, when you select the item it should check that is item cropped or not. if it is then you can display cropped image instead of original.
WindowSnap snap = this.listBoxSnap.SelectedItem as WindowSnap;
selectedIndex = this.listBoxSnap.SelectedIndex.ToString();
///Here you can draw image at your desire position as you have done using e.DrawImage
///in pictureBoxSnap_Paint event instead of assigning pictureBoxSnap.Image property
this.pictureBoxSnap.Image = snap.CroppedImage
;
As part of my application I'd like to be able to grap a screenshot of a chosen area on my desktop. I came across example code of how to do this a while ago (if I could remember where I would cite) and the example works nicely, however it has a problem with multiple displays.
It works by creating a transparent full screen form and then you draw a rubberband in it to designate the area. The issue is it spawns on the main display, and only allows you to grab content on that display or one to the right of it. If you have 3 displays and your master is the center there is no way to grab the left.
My question is how I can allow capture across all 3 displays.
Example code:
RubberBand.cs
public partial class RubberBand : Form
{
public Point lastLoc;
public Size lastSize;
bool mouseDown = false;
Point mouseDownPoint = Point.Empty;
Point mousePoint = Point.Empty;
Main mainform;
Pen pen;
Rectangle bounds = new Rectangle();
public RubberBand(Main mainform)
{
this.mainform = mainform;
InitializeComponent();
this.TopMost = true;
this.Opacity = .30;
this.TransparencyKey = System.Drawing.Color.White;
this.Location = new Point(0, 0);
DoubleBuffered = true;
pen = new Pen(System.Drawing.Color.DarkRed, 3);
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
int maxX = 0;
int maxY = 0;
foreach (Screen screen in System.Windows.Forms.Screen.AllScreens)
{
int x = screen.Bounds.X + screen.Bounds.Width;
if (x > maxX)
maxX = x;
int y = screen.Bounds.Y + screen.Bounds.Height;
if (y > maxY)
maxY = y;
}
bounds.X = 0;
bounds.Y = 0;
bounds.Width = maxX;
bounds.Height = maxY;
this.Size = new Size(bounds.Width, bounds.Height);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
mouseDown = true;
mousePoint = mouseDownPoint = e.Location;
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
mouseDown = false;
// corey
this.lastLoc = new Point(Math.Min(mouseDownPoint.X, mousePoint.X), Math.Min(mouseDownPoint.Y, mousePoint.Y));
this.lastSize = new Size(Math.Abs(mouseDownPoint.X - mousePoint.X), Math.Abs(mouseDownPoint.Y - mousePoint.Y));
this.Close();
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
mousePoint = e.Location;
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
//base.OnPaint(e);
Region region = new Region(bounds);
if (mouseDown)
{
Rectangle selectionWindow = new Rectangle(
Math.Min(mouseDownPoint.X, mousePoint.X),
Math.Min(mouseDownPoint.Y, mousePoint.Y),
Math.Abs(mouseDownPoint.X - mousePoint.X),
Math.Abs(mouseDownPoint.Y - mousePoint.Y));
// make a hole, where we can see thru this form
region.Xor(selectionWindow);
e.Graphics.FillRegion(Brushes.Black, region);
}
else
{
e.Graphics.FillRegion(Brushes.LightGray, region);
e.Graphics.DrawLine(pen,
mousePoint.X, 0,
mousePoint.X, this.Size.Height);
e.Graphics.DrawLine(pen,
0, mousePoint.Y,
this.Size.Width, mousePoint.Y);
}
}
}
RubberBand.Designer.cs
partial class RubberBand
{
/// <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();
//
// RubberBand
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.White;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Cursor = System.Windows.Forms.Cursors.Cross;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Name = "RubberBand";
this.ShowInTaskbar = false;
this.Text = "RubberBand";
this.TransparencyKey = System.Drawing.Color.White;
this.ResumeLayout(false);
}
#endregion
}
And this is the code that calls it:
private void ShowRubberBand()
{
using (RubberBand rbf = new RubberBand(this))
{
rbf.ShowDialog();
Size sLastSize = rbf.lastSize;
if (sLastSize.Width > 0 && sLastSize.Height > 0)
{
Rectangle r = new Rectangle();
r.Location = rbf.lastLoc;
r.Size = sLastSize;
CaptureBitmap(r);
}
}
this.Show();
}
private void CaptureBitmap(Rectangle r)
{
bitmap = new Bitmap(r.Width, r.Height);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(r.Location, new Point(0, 0), r.Size);
}
PasteImage(bitmap);
}
this.Location = new Point(0, 0); is related to the main screen top left corner. Screens on the left or above the main(primary) screen have negative location coordinates. You have to take it into account when position your window and set its size.
In RubberBand constructor:
int maxX = 0;
int maxY = 0;
int minX = 0;
int minY = 0;
foreach (Screen screen in System.Windows.Forms.Screen.AllScreens)
{
int x = screen.Bounds.X + screen.Bounds.Width;
if (x > maxX)
maxX = x;
int y = screen.Bounds.Y + screen.Bounds.Height;
if (y > maxY)
maxY = y;
if(screen.Bound.X < minX) minX = screen.Bound.X;
if(screen.Bound.Y < minY) minY = screen.Bound.Y;
}
bounds.X = minX;
bounds.Y = minY;
bounds.Width = maxX - minX;
bounds.Height = maxY - minY;
this.Location = new Point(bounds.X, bounds.Y);
this.Size = new Size(bounds.Width, bounds.Height);
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!