How to draw points on a panel with an image - c#

I have a panel named dPanel. I set the the backgroundImage of that panel with an image named dImage.Now I want to draw points on the panel, in other words I want to color the panel by using mouse.I want to be able to save the drawing and the image together later. My codes do this but the picture lights up during drawing and its very slow.Here is my code:
private void drawP_MouseDown(object sender, MouseEventArgs e)
{
if (!drawbool)
{
dStartPoint = e.Location;
drawbool = true;
}
drawP.Invalidate();
}
private void drawP_MouseMove(object sender, MouseEventArgs e)
{
if (drawbool)
{
dStartPoint = e.Location;
drawP.Invalidate();
}
}
private void drawP_MouseUp(object sender, MouseEventArgs e)
{
if (drawbool)
{
drawbool = false;
}
}
private void drawP_Paint_1(object sender, PaintEventArgs e)
{
if (drawbool)
{
int dStartX = dStartPoint.X;
int dStartY = dStartPoint.Y;
e.Graphics.DrawEllipse(dP, dStartX, dStartY, 2, 2);
Bitmap dPPB = new Bitmap(drawP.Width, drawP.Height);
drawP.DrawToBitmap(dPPB, new Rectangle(0, 0, drawP.Width, drawP.Height));
drawP.BackgroundImage = (Image)dPPB;
}
}
Whani's the solution? Thanks in advance.

Check out this great example about drawing on panel: Painting on a Panel.
Later you can save your drawing just by invoking panel's method DrawToBitmap.

Related

Method to create a workspace to draw on in C#

I'm new to c#, coming from a python / wxpython background. I'm still very inexperienced.
I'm trying to create a user workspace that allows objects that have a representative shape (box or circle) to be placed. I'd like the user to be able to pan and zoom within the workspace. Eventually I want to have the items have attributes and be able to be connected together with lines.
I created a simple c# app that allows me to paint squares over a tiled .png grid background, but I can't figure out to set up a real workspace to pan or zoom.
At this stage some high level suggestions would be great.
Here is my code just FYI (be kind)
public partial class MainForm : Form
{
bool global_draw_redbox = false;
public MainForm()
{
InitializeComponent();
}
private void redbox(Point mousepos)
{
System.Drawing.Graphics graphicsObj;
graphicsObj = CreateGraphics();
Pen myPen = new Pen(System.Drawing.Color.Red, 3);
Rectangle myRectangle = new Rectangle(mousepos.X - 125, mousepos.Y - 100, 250, 200);
graphicsObj.DrawRectangle(myPen, myRectangle);
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
var relativePoint = this.PointToClient(Cursor.Position);
if (global_draw_redbox)
{
//Draw the object based on the mouse position
redbox(relativePoint);
//Reset the flag so we draw just one
global_draw_redbox = false;
}
else
{
MessageBox.Show("No object selected");
}
}
private void Form1_MouseDoubleClick(object sender, MouseEventArgs e)
{
MessageBox.Show("Test Mouse Double Click");
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
var relativePoint = this.PointToClient(Cursor.Position);
XY_Mouse_Position.Text = relativePoint.ToString();
}
private void boxToolStripMenuItem_Click(object sender, EventArgs e)
{
global_draw_redbox = true;
}
}

How to get picturebox pixel color on mousemove

I tried to make drag and drop application . I drawn rectangle in run time and I want to detect if user try to move this rectangle or not
this is my code
private bool Mouse_Down = false;
Rectangle re = new Rectangle(100, 100, 60, 60);
private void DrawRegion_Paint(object sender, PaintEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(Color.RoyalBlue), re);
}
private void DrawRegion_MouseMove(object sender, MouseEventArgs e)
{
if (Mouse_Down == true)
{
re.Location = e.Location;
if (re.Right > DrawRegion.Width)
{
re.X = DrawRegion.Width - re.Width;
}
if (re.Top < 0)
{
re.Y = 0;
}
if (re.Left < 0)
{
re.X = 0;
}
if (re.Bottom > DrawRegion.Height)
{
re.Y = DrawRegion.Height - re.Height;
}
Refresh();
}
}
private void DrawRegion_MouseUp(object sender, MouseEventArgs e)
{
Mouse_Down = false;
}
private void DrawRegion_MouseDown(object sender, MouseEventArgs e)
{
Mouse_Down = true;
}
For more details now this rectangle move either user click on this rectangle or in any empty space so I want to detect if clicked location color pixel is rectangle color pixel or not before moving rectangle how to do that ?
Note:DrawRegion is a picturebox
Sorry for bad English
You can use Rect.Contains() to detect if your Rectaingle contain your current location
private void DrawRegion_MouseClick(object sender,MouseEventArgs e)
{
if (re.Contains(e.Location))
Mouse_Down = true;
else
Mouse_Down = false;
}
check this https://msdn.microsoft.com/en-us/library/ms557979(v=vs.110).aspx

How to pan Image inside PictureBox

I have a custom PictureBox which can zoom in using MouseWheel event. Now I want to add a panning feature to it. I mean when PictureBox is in zoomed state, if user left clicks and holds the click then move the mouse, the image would pan within the picturebox.
Here is my code but unfortunately it does not work! I don't know where to look anymore...
private Point _panStartingPoint = Point.Empty;
private bool _panIsActive;
private void CurveBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Focus();
_panIsActive = true;
_panStartingPoint = e.Location;
}
}
private void CurveBox_MouseUp(object sender, MouseEventArgs e)
{
_panIsActive = false;
}
private void CurveBox_MouseLeave(object sender, EventArgs e)
{
_panIsActive = false;
}
private void CurveBox_MouseMove(object sender, MouseEventArgs e)
{
if(_panIsActive && IsZoomed)
{
var g = CreateGraphics(); //Create graphics from PictureBox
var nx = _panStartingPoint.X + e.X;
var ny = _panStartingPoint.Y + e.Y;
var sourceRectangle = new Rectangle(nx, ny, Image.Width, Image.Height);
g.DrawImage(Image, nx, ny, sourceRectangle, GraphicsUnit.Pixel);
}
}
I am suspecting the MouseMove event...I am not sure if anything happens in this event and/or nx and ny does contain correct point.
Any helps/tips is really appriciated!
I think the math is backwards. Try it like this:
private Point startingPoint = Point.Empty;
private Point movingPoint = Point.Empty;
private bool panning = false;
void pictureBox1_MouseDown(object sender, MouseEventArgs e) {
panning = true;
startingPoint = new Point(e.Location.X - movingPoint.X,
e.Location.Y - movingPoint.Y);
}
void pictureBox1_MouseUp(object sender, MouseEventArgs e) {
panning = false;
}
void pictureBox1_MouseMove(object sender, MouseEventArgs e) {
if (panning) {
movingPoint = new Point(e.Location.X - startingPoint.X,
e.Location.Y - startingPoint.Y);
pictureBox1.Invalidate();
}
}
void pictureBox1_Paint(object sender, PaintEventArgs e) {
e.Graphics.Clear(Color.White);
e.Graphics.DrawImage(Image, movingPoint);
}
You aren't disposing your graphic object, and CreateGraphics is just a temporary drawing anyway (minimizing would erase it) so I moved the drawing code to the Paint event and am just invalidating as the user is panning.

2D Array of RectangleShapes

I am developing a very rudimentary drawing program: A 2D grid comprised of multiple RectangleShapes, around 20x30 pixels each, which when clicked change color based on user RGB input, which works just fine:
Color SelectedColor = new Color();
private void Pixel_1_1_Click(object sender, EventArgs e) // on Rectangle click
{
Pixel_1_1.FillColor = SelectedColor; // change to currently desired color.
}
Since the number of squares is rising dramatically, I'm looking for a way to arrange the "pixel" rectangles into a 2D array. (I really don't want to have to make a Pixel_Click method for every single Rectangle on the screen!) Hoping eventually to be able to call something like:
private void Pixel_[x]_[y]_Click(object sender, EventArgs e)
{
Pixel_[x]_[y].FillColor = SelectedColor;
}
My friends suggest the use of an anonymous delegate, but I don't understand how to fully use one to solve my problem.
What would be the best way to generate a 2D array of rectangles in a C# Windows Form? And once generated, how can I access them with a single method for variant values of x and y?
While you are probably correct in thinking of each rectangle as an object, it probably isn't correct to think of each rectangle as a windows control, especially since you have so many of them.
So try creating your own rectangle object:
public class MyRect {
public Color FillColor { get; set; }
public Rectangle Rectangle { get; set; }
public MyRect(Rectangle r, Color c) {
this.Rectangle = r;
this.FillColor = c;
}
}
Now you just need to keep a list of your objects and paint on a single Panel control (or PictureBox) all of your rectangles:
private List<MyRect> myRectangles = new List<MyRect>();
public Form1() {
InitializeComponent();
myRectangles.Add(new MyRect(new Rectangle(10, 10, 64, 16), Color.Blue));
myRectangles.Add(new MyRect(new Rectangle(20, 48, 16, 64), Color.Red));
}
private void panel1_Paint(object sender, PaintEventArgs e) {
foreach (MyRect mr in myRectangles) {
using (SolidBrush sb = new SolidBrush(mr.FillColor)) {
e.Graphics.FillRectangle(sb, mr.Rectangle);
}
}
}
To handle the "click" event of the rectangles, you just handle the MouseDown or MouseClick event of your container control and determine yourself which rectangle is being clicked on:
void panel1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
foreach (MyRect mr in myRectangles) {
if (mr.Rectangle.Contains(e.Location)) {
ChangeColor(mr, Color.Green);
}
}
panel1.Invalidate();
}
}
private void ChangeColor(MyRect mr, Color newColor) {
mr.FillColor = newColor;
}
If you want to maintain the rectangles as components on screen then you can assign all of them the same click event, the click event will have a little dropdown to pick an existing event. To know which recantangle was clicked use the sender parameter ((Pixel)sender).FillColor = SelectedColor;
For ease I would recommend using something like a panel and drawing rectangles on it, That means you only have a single click event to deal with. So now your question becomes "How do I draw a grid of rectangles on a panel" and "How do I know which rectangle was clicked"
So for the first part you could use this not the very efficient way.
Create a class which stores the information about your pixels
class MyPixel
{
public Color PixelColour;
public Rectangle Bounds;
}
Keep a list of them in memory
List<MyPixels> MyGrid = new List<MyPixels>();
then in the onpaint event of the panel Draw the pixels on the panel
foreach(MyPixel Pixel in MyGrid)
{
using(Brush B = new SolidBrush(Pixel.PixelColor))
{
e.Graphics.DrawRectangle(B, Pixel.Bounds);
}
}
Now in the click event you'll need to know which pixel was clicked
foreach(MyPixel Pixel in MyGrid)
{
if (Pixel.Bounds.Contains(e.Location))
{
PixelClicked(Pixel);
}
}
I believe you're going about this the wrong way. What you want to do is to draw directly into a bitmap. Here is some code that uses a PictureBox to allow the user to draw into it.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Pen _pen;
private bool _mouseDown;
private int _startX;
private int _startY;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
_pen = new Pen(Color.Black);
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
_mouseDown = true;
_startX = e.X;
_startY = e.Y;
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
_mouseDown = false;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (_mouseDown)
{
using (var graphics = Graphics.FromImage(pictureBox1.Image))
{
graphics.DrawLine(_pen, _startX, _startY, e.X, e.Y);
_startX = e.X;
_startY = e.Y;
}
pictureBox1.Invalidate();
}
}
}
}
This is the normal method to write a painting app and is quite performant as well. You can also easily save, write new tools or manipulate images better in this way.

How to get the Coordinates of a Custom Image Cursor in c#?

Bitmap hh = (Bitmap)System.Drawing.Bitmap.FromFile("example.png");
Graphics.FromImage(hh);
IntPtr ptr = hh.GetHicon();
Cursor c = new Cursor(ptr);
this.Cursor = c;
I use this code to create a custom image cursor. I want to retrieve the coordinates of this custom image cursor when on a Click event. So that these coordinates can be used to draw the image of this cursor in a picture box when clicked on the image loaded in the picture box. I'm doing this in C#.
I tried another approach
public partial class Form1 : Form
{
private Bitmap _bmp = new Bitmap(250, 250);
public Form1()
{
InitializeComponent();
panel1.MouseDown += new MouseEventHandler(panel1_MouseDown);
panel1.Paint += new PaintEventHandler(panel1_Paint);
using (Graphics g = Graphics.FromImage(_bmp))
g.Clear(SystemColors.Window);
}
private void pictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
Point mouseDownLocation = new Point(e.X, e.Y);
label1.Text = mouseDownLocation.X.ToString();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(_bmp, new Point(0, 0));
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
using (Graphics g = Graphics.FromImage(_bmp))
{
g.DrawString("Mouse Clicked Here!", panel1.Font, Brushes.Black, e.Location);
}
panel1.Invalidate();
}
private void button1_Click(object sender, EventArgs e)
{
panel1.Image.Save(#"C:\test.jpg", ImageFormat.Jpeg);
}
But when i try so save the image i get an Exception: Object reference not set to an instance of an object.
Please note that panel1 in the code above refers to a picture box
To get the coordinates of the mouse on a PictureBox you should not handle the OnClick event but the OnMouseDown, for example in this way:
private void pb_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
Point mouseDownLocation = new Point(e.X, e.Y);
}
now you have the mouseDownLocation which contains the coordinates you were looking for.
i know the way to get the coordinate of mouse you can code it like
Cursor.Position.X and Cursor.Position.Y to get the Coordinate under the mouse

Categories

Resources