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 UTUResultWithCoordinates
{
public partial class GetCoordinates : Form
{
private string sem;
private string branch;
private int mouseisdown = 0;
private int recx = 0;
private int recy = 0;
private int mousemovingwhilepressed = 0;
public GetCoordinates()
{
InitializeComponent();
}
public GetCoordinates(string p, string p_2)
{
// TODO: Complete member initialization
InitializeComponent();
branch = p;
sem = p_2;
pictureBox1.Controls.Add(pictureBox2);
pictureBox2.Location = new Point(0, 0);
pictureBox2.BackColor = Color.Transparent;
pictureBox2.Width = 1191;
pictureBox2.Height = 842;
}
private void GetCoordinates_Load(object sender, EventArgs e)
{
pictureBox1.ImageLocation = #"D:\DotNet\UTUResultWithCoordinates\UTUResultWithCoordinates\bin\Debug\ComputerScience6.jpg";
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
if (mouseisdown == 1 && mousemovingwhilepressed==1)
{
System.Drawing.Graphics graphicsObj;
graphicsObj = this.CreateGraphics();
Pen myPen = new Pen(System.Drawing.Color.Blue, 100);
Rectangle myRectangle = new Rectangle(recx, recy, 20, 20);
e.Graphics.DrawRectangle(myPen, myRectangle);
}
}
private void pictureBox2_MouseDown(object sender, MouseEventArgs e)
{
mouseisdown = 1;
recx = e.X;
recy = e.Y;
pictureBox2.CreateGraphics();
}
private void pictureBox2_MouseMove(object sender, MouseEventArgs e)
{
label1.Text = e.X + "," + e.Y;
mousemovingwhilepressed = 1;
recx = e.X;
recy = e.Y;
pictureBox2.CreateGraphics();
}
private void pictureBox2_MouseUp(object sender, MouseEventArgs e)
{
mousemovingwhilepressed = 0;
mouseisdown = 0;
pictureBox2.CreateGraphics();
}
}
}
I have created a pictureBox1 in which an image is displayed. Then I have created a pictureBox2 inside it so that I can paint on that image a rectangle by dragging the mouse. But nothing is happening on clicking the mouse. What is the error?
Calling CreateGraphics does not trigger the painting of the PictureBox.
Use Invalidate to cause a redraw.
For a full example see: How to select an area on a PictureBox.Image with mouse in C#
Side notes:
Calling InitializeControl in a method other than the constructor is not a good idea.
when you need a boolean use a boolean, not an integer.
Objects that implement IDisposable (such as Pen) should be created as few times as possible and be disposed when no longer needed/used.
Related
i am trying to make signature panel in c# windowsform application where input is from drawing tablet
my code as below this code working for line drawing not dot created.
So please suggest how dot and line both are create.
{
Graphics graphics;
Boolean cusorMoving = false;
Pen cursorPen;
int cursorX = -1;
int cursorY = -1;
public SignPad()
{
InitializeComponent();
graphics = panel2.CreateGraphics();
cursorPen = new Pen(Color.Black, 2);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
cursorPen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
cursorPen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
Mouse Down event
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
cusorMoving = true;
cursorX = e.X;
cursorY = e.Y;
}
private void panel2_MouseUp(object sender, MouseEventArgs e)
{
cusorMoving = false;
cursorX = -1;
cursorY = -1;
}
Mouse Move event
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (cursorX != -1 && cursorY != -1 && cusorMoving == true)
{
graphics.DrawLine(cursorPen, new Point(cursorX, cursorY), e.Location);
cursorX = e.X;
cursorY = e.Y;
}
}
You need to store individual points in a collection and draw them separately in the Paint handler. Every time you add a point to the collection, you also need to tell the panel to draw the area where the new segment was added. Something like this:
using System.Collections.Generic;
using System.Drawing;
namespace Lines
{
public partial class SignPad : Form
{
Pen cursorPen = SystemPens.ControlText;
List<Point> points = new List<Point>();
bool cursorMoving = false;
public SignPad()
{
InitializeComponent();
cursorPen = new Pen(Color.Black, 2);
cursorPen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
cursorPen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
private void panel2_Paint(object? sender, PaintEventArgs e)
{
var g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
for (int i = 1; i < points.Count; ++i)
g.DrawLine(cursorPen, points[i - 1], points[i]);
}
private void panel2_MouseDown(object? sender, MouseEventArgs e)
{
if (!cursorMoving)
{
cursorMoving = true;
points.Clear();
points.Add(e.Location);
panel2.Invalidate();
}
}
private void panel2_MouseMove(object? sender, MouseEventArgs e)
{
if (cursorMoving && points.Count > 0)
{
var p = e.Location;
var q = points[points.Count - 1];
var r = Rectangle.FromLTRB(Math.Min(p.X, q.X), Math.Min(p.Y, q.Y), Math.Max(p.X, q.X), Math.Max(p.Y, q.Y));
r = Rectangle.Inflate(r, (int)cursorPen.Width, (int)cursorPen.Width);
points.Add(p);
panel2.Invalidate(r);
}
}
private void panel2_MouseUp(object? sender, MouseEventArgs e)
{
cursorMoving = false;
}
}
}
Don't forget to add the Paint handler the same way you added MouseMove, MouseDown and MouseUp handlers - in the Designer.
Before starting a project, I want to know beforehand whether the following would work.
The application creates a System.Drawing.Bitmap and paints on it.
The Bitmap is much larger than the PictureBox. The Height of the Bitmap and the PictureBox are the same. Now I would like to be able to move the Image from left to right within (along) the PictureBox by pressing the left mouse button and moving it.
See the drawing:
I just realized that I haven't answered yet, which I am trying to make up for.
As a solution, I use Jimi's solution. I've shortened the code here to meet my needs.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Windows.Forms;
namespace Zoom_an_image_from_the_mouse_location
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
string imagePath = "C:\\Users\\yourPath\\Pictures\\....jpeg";
drawingImage = (Bitmap)Image.FromStream(new MemoryStream(File.ReadAllBytes(imagePath)));
imageRect = new RectangleF(Point.Empty, drawingImage.Size);
canvas = new PictureBoxEx(new Size(525,700));
canvas.Location = new Point(10, 10);
canvas.MouseMove += this.canvas_MouseMove;
canvas.MouseDown += this.canvas_MouseDown;
canvas.MouseUp += this.canvas_MouseUp;
canvas.Paint += this.canvas_Paint;
this.Controls.Add(canvas);
}
private void FormMain_Load(object sender, EventArgs e)
{
this.BackColor = Color.FromArgb(174, 184, 177);
}
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
}
private float rotationAngle = 0.0f;
private float zoomFactor = 1.0f;
private RectangleF imageRect = RectangleF.Empty;
private PointF imageLocation = PointF.Empty;
private PointF mouseLocation = PointF.Empty;
private Bitmap drawingImage = null;
private PictureBoxEx canvas = null;
private void canvas_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
mouseLocation = e.Location;
imageLocation = imageRect.Location;
canvas.Cursor = Cursors.NoMove2D;
}
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
imageRect.Location =
new PointF(imageLocation.X + (e.Location.X - mouseLocation.X),
imageLocation.Y); //+ (e.Location.Y - mouseLocation.Y));
canvas.Invalidate();
}
private void canvas_MouseUp(object sender, MouseEventArgs e) =>
canvas.Cursor = Cursors.Default;
private void canvas_Paint(object sender, PaintEventArgs e)
{
var drawingRect = GetDrawingImageRect(imageRect);
using (var mxRotation = new Matrix())
using (var mxTransform = new Matrix())
{
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
mxRotation.RotateAt(rotationAngle, GetDrawingImageCenterPoint(drawingRect));
mxTransform.Multiply(mxRotation);
e.Graphics.Transform = mxTransform;
e.Graphics.DrawImage(drawingImage, drawingRect);
}
}
#region Drawing Methods
public RectangleF GetScaledRect(RectangleF rect, float scaleFactor) =>
new RectangleF(rect.Location,
new SizeF(rect.Width * scaleFactor, rect.Height * scaleFactor));
public RectangleF GetDrawingImageRect(RectangleF rect) =>
GetScaledRect(rect, zoomFactor);
public PointF GetDrawingImageCenterPoint(RectangleF rect) =>
new PointF(rect.X + rect.Width / 2f, rect.Y + rect.Height / 2f);
#endregion
}
}
[DesignerCategory("Code")]
public class PictureBoxEx : PictureBox
{
public PictureBoxEx() : this(new Size(525, 700)) { }
public PictureBoxEx(Size size)
{
SetStyle(ControlStyles.Selectable | ControlStyles.UserMouse, true);
this.BorderStyle = BorderStyle.FixedSingle;
this.Size = size;
}
}
I've created a windows form that when I click on a button, it shows a panda moving.
It works when I add one Panda, but I want another panda to appear on button click. I'm trying to when I click the button for another time to show another panda! When I click the button my panda disappear and reappear again from it's start point and starts moving!
(for example clicking the button 3 times = having 3 pandas moving in my form)
That's the code for the class called "panda":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
namespace test_moving_pic
{
class panda
{
public Image img_panda;
public Rectangle rect_panda;
public panda(Image img, Rectangle rect)
{
this.img_panda = img;
this.rect_panda = rect;
}
}
}
and this is the code that I used for my Form:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace test_moving_pic
{
public partial class Form1 : Form
{
Image image;
Rectangle rect;
int direction = 3;
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
if (image != null && rect != null)
g.DrawImage(image, rect);
}
private void timer1_Tick(object sender, EventArgs e)
{
rect.X += this.direction;
rect.Y += this.direction;
if (rect.X <= 100 && rect.Y <= 100)
{
rect.X += this.direction;
rect.Y += this.direction;
}
else
{
rect.Y += this.direction;
if (rect.Y >= 100)
{
rect.Y = 100;
rect.X += this.direction;
}
}
Invalidate();
}
private void button1_Click(object sender, EventArgs e)
{
panda p = new panda(Image.FromFile("C:\\Users\\hsnha\\OneDrive\\Desktop\\Panda.png"), new Rectangle(20, 20, 70, 70));
image = p.img_panda;
rect = p.rect_panda;
}
}
}
Try this:
public partial class Form1 : Form
{
List<panda> pandaList = new List<panda>();
int direction = 3;
class panda
{
public Image img_panda;
public Rectangle rect_panda;
public panda(Image img, Rectangle rect)
{
this.img_panda = img;
this.rect_panda = rect;
}
}
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
foreach (panda p in pandaList)
g.DrawImage(p.img_panda, p.rect_panda);
}
private void timer1_Tick(object sender, EventArgs e)
{
foreach (panda p in pandaList)
{
p.rect_panda.X += this.direction;
p.rect_panda.Y += this.direction;
if (p.rect_panda.X <= 100 && p.rect_panda.Y <= 100)
{
p.rect_panda.X += this.direction;
p.rect_panda.Y += this.direction;
}
else
{
p.rect_panda.Y += this.direction;
if (p.rect_panda.Y >= 100)
{
p.rect_panda.Y = 100;
p.rect_panda.X += this.direction;
}
}
}
Invalidate();
}
private void button1_Click(object sender, EventArgs e)
{
pandaList.Add(new panda(Image.FromFile(#"C:\Users\hsnha\OneDrive\Desktop\Panda.png"), new Rectangle(20, 20, 70, 70)));
}
}
Form1_Paint is only going to draw one panda. You need to somehow save all the pandas you've created, and draw all of the pandas in the Paint method! You also need to update the position of all pandas in Tick.
For example:
Define a member in your class List<panda> pandas; and
private void button1_Click(object sender, EventArgs e)
{
panda p = new panda(Image.FromFile("C:\\Users\\hsnha\\OneDrive\\Desktop\\Panda.png"), new Rectangle(20, 20, 70, 70));
pandas.Add(p);
}
private void timer1_Tick(object sender, EventArgs e)
{
foreach (panda p in pandas)
{
Rectangle rect = p.rect_panda;
// Fix the rect like before
}
}
And similarly for Draw, loop over the pandas and draw each. Does this help you get unstuck?
This little program opens a windows form and draws 70 red rectangles, where the user clicks on the form.
Every time the user clicks, the rectangles disappear, and new ones are drawn on the new click-Point.
I want to make the rectangles to stay when the user clicks and draws a new set of rectangles.
How do i do that?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace tegnRektangel
{
public partial class Form1 : Form
{
int x;
int y;
bool mouseClicked = false;
Graphics g = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
}
private void Form1_Resize(object sender, EventArgs e)
{
Invalidate();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
if (mouseClicked)
{
g = panel1.CreateGraphics();
paintRectangel();
}
}
private void paintRectangel()
{
for (int i = 1; i <= 70; i++)
{
g.DrawRectangle(Pens.Red, x - 50-i*5, y - 40-i*5, 100, 80);
}
g.Dispose();
}//end paint
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
mouseClicked = true;
Point clickPoint = new Point(e.X,e.Y);
x = clickPoint.X;
y = clickPoint.Y;
panel1.Invalidate();
}
}
}
From MSDN:
The Graphics object that you retrieve through the CreateGraphics
method should not normally be retained after the current Windows
message has been processed, because anything painted with that object
will be erased with the next WM_PAINT message.
You can work around it like this:
In the click event, add the (x, y) coordinate to a list of coordinates.
In the paint event, iterate all these (x, y) coordinates and paint each rectangle.
Here is some code to demonstrate creating rectangles for each click, storing them, and painting all stored rectangles.
public partial class Form1 : Form
{
private List<Rectangle> Rectangles { get; set; }
public Form1()
{
InitializeComponent();
Rectangles = new List<Rectangle>();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (Rectangles.Count > 0)
e.Graphics.DrawRectangles(Pens.Red, Rectangles.ToArray());
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
for (int i = 1; i <= 70; i++)
{
Rectangles.Add(new Rectangle(e.X - 50 - i * 5, e.Y - 40 - i * 5, 100, 80));
}
Invalidate();
}
}
I have a program which dynamically creates movable pictureboxes when I click on buttons. I need to do something like when I click on the picturebox, this click adds to my dynamically created picturebox a new textbox when I can write descripiton of this picturebox(name,...). This textbox should be able to move with picturebox.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
List<PictureBox> pictureboxes = new List<PictureBox>();
public Form1()
{
InitializeComponent();
}
private void AddPictureBox(string imagePath)
{
var pb = new PictureBox();
pb.Name = "picturebox" + pictureboxes.Count;
pb.Location = new Point(pictureboxes.Count * 100, 100);
pb.Size = new Size(70, 70);
pb.BorderStyle = BorderStyle.None;
pb.SizeMode = PictureBoxSizeMode.StretchImage;
this.Controls.Add(pb);
pb.Image = Image.FromFile(imagePath);
pb.Refresh();
pb.MouseDown += new MouseEventHandler(picMouseDown);
pb.MouseMove += new MouseEventHandler(picMouseMove);
pb.MouseUp += new MouseEventHandler(picMouseUp);
pictureboxes.Add(pb);
Invalidate();
}
private void router_Click(object sender, EventArgs e)
{
AddPictureBox(#"D:\\router.jpg");
}
private void Form1_Load(object sender, EventArgs e)
{
}
int x = 0;
int y = 0;
bool drag = false;
private void picMouseDown(object sender, MouseEventArgs e)
{
// Get original position of cursor on mousedown
x = e.X;
y = e.Y;
drag = true;
}
private void picMouseMove(object sender, MouseEventArgs e)
{
if (drag)
{
PictureBox pb = (PictureBox)sender;
// Get new position of picture
pb.Top += e.Y - y;
pb.Left += e.X - x;
pb.BringToFront();
Invalidate();
}
}
private void picMouseUp(object sender, MouseEventArgs e)
{
drag = false;
}
private void switch1_Click(object sender, EventArgs e)
{
AddPictureBox(#"D:\HP ProBook 450\Desktop\Grafika\switch1.png");
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void pc_Click(object sender, EventArgs e)
{
AddPictureBox(#"D:\HP ProBook 450\Desktop\pc.jpg");
}
private void server_Click(object sender, EventArgs e)
{
AddPictureBox(#"D:\HP ProBook 450\Desktop\server.png");
}
}
Thanks for any help :).
You can add a TextBox to a PictureBox in code like this:
TextBox newTextBox = new TextBox();
newTextBox.Parent = yourPictureBox;
// place it e.g. to the left bottom:
newTextBox.Location = new Point(10, yourPictureBox.Height - newTextBox.Height);
Note that this will add the TextBox to the Controls collection of the PB; so it will sit on top of the PictureBox; so, yes, it will move with the PictureBox but it will also hide a part or the PB!
If instead you simply want to group them, add them both to something like a Panel, again by setting that as their Parent!
Also note that you can't do this in the Designer; PictureBox is not really meant to act as a Container..
It doesn't matter how the PictureBox was created, as long as you have a reference to it.