Okay, so I needed to make a simple animation in c# to use as a loading icon. This worked all fine and good so lets take this square as an example
PictureBox square = new PictureBox();
Bitmap bm = new Bitmap(square.Width, square.Height);
Graphics baseImage = Graphics.FromImage(bm);
baseImage.DrawRectangle(Pens.Black, 0, 0, 100, 100);
square.Image = bm;
So with that I made my animation and everything here worked, but then I realized that I need my animation to be in a class so I can call it from my co workers programs to use the animation. This is where the problem came in, I made my class and I did everything the same way but in a class instead of the form I then called my class from my form but the screen was blank and there was no animation. Is there something that needs to be passed in order to do this?
namespace SpinningLogo
{//Here is the sample of my class
class test
{
public void square()
{
PictureBox square = new PictureBox();
Bitmap bm = new Bitmap(square.Width, square.Height);
Graphics baseImage = Graphics.FromImage(bm);
baseImage.DrawRectangle(Pens.Black, 0, 0, 100, 100);
square.Image = bm;
}
}
}
private void button1_Click(object sender, EventArgs e)
{//Here is how I call my class
Debug.WriteLine("11");
test square = new test();
square.square();
}
Pass your test class a reference to the PictureBox that is on the form:
namespace SpinningLogo
{
class test
{
public void square(PictureBox thePB)
{
Bitmap bm = new Bitmap(thePB.Width, thePB.Height);
Graphics baseImage = Graphics.FromImage(bm);
baseImage.DrawRectangle(Pens.Black, 0, 0, 100, 100);
thePB.Image = bm;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
test square = new test();
square.square(myPictureBox); //whatever the PictureBox is really named
}
You could also pass the Form itself (using this), but then you'd still have to ID the PictureBox control (I assume).
You should pass to your test class Form instance, and not define PictureBox in test class. PictureBox should be field of Form, and by Form instance u will get access to your PictureBox.
Related
I'm trying to dynamically create a picture box by clicking a button. However, I want to have the code that creates the picture box (and also creates some graphs in that picture box) in a dll file. When i move the code from my main form to a method in a dll file and then call that method in the button click event in my main form nothig happens.
I've been searching high and low for an answer but with little success. The most relevant thing that I found is here. However, I struggle to create an instance of my main form to pass to the method in the dll...The answer might be bluntly obvious but I am very new to c#... Also, I am using Visual Studio 2013 if that is of any relevance.
Here is the method in the dll:
namespace DrillGraph
{
public class DrillGraph : UserControl
{
public DrillGraph() { }
public void CreateGraph()
{
PictureBox pb = new PictureBox();
pb.Dock = DockStyle.Fill;
pb.BackColor = Color.Bisque;
pb.Name = "pb";
pb.Size = new Size(50, 50);
pb.Location = new Point(20, 20);
Graphics g = pb.CreateGraphics();
g.DrawEllipse(new Pen(Color.Red), 0, 0, 50, 50);
this.Controls.Add(pb);
}
}
}
And this is what i have in my main form:
using DrillGraph;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
DrillGraph.DrillGraph dg = new DrillGraph.DrillGraph();
private void button1_Click(object sender, EventArgs e)
{
dg.CreateGraph();
}
}
}
Adding where? you should provide the reference in your dll.
public void CreateGraph(Panel pnl)
{
PictureBox pb = new PictureBox();
pb.Dock = DockStyle.Fill;
pb.BackColor = Color.Bisque;
pb.Name = "pb";
pb.Size = new Size(50, 50);
pb.Location = new Point(20, 20);
Graphics g = pb.CreateGraphics();
g.DrawEllipse(new Pen(Color.Red), 0, 0, 50, 50);
pnl.Controls.Add(pb);
}
Then call below code
dg.CreateGraph(YourPanelName From Form);
I am trying to draw circles using Bitmap.
Each time I click the mouse, the circle I previously drew is moved to the new position.
What I want to happen is: Each time I click the mouse, a new circle is created/drawn at the position I clicked and all previously drawn circles remain without moving.
I am working with the following code:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace multirectangle
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
Bitmap background;
Graphics scG;
Rectangle rectangleObj;
private Point clickCurrent = Point.Empty;
private Point clickPrev = Point.Empty;
private void Form1_Load(object sender, EventArgs e)
{
background = new Bitmap(Width, Height);
rectangleObj = new Rectangle(10, 10, 30, 30);
scG = Graphics.FromImage(background);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
clickCurrent = PointToClient(Cursor.Position);
clickPrev = clickCurrent;
if (clickPrev == Point.Empty) return;
rectangleObj.X = clickPrev.X - rectangleObj.Height / 2;// +radius;
rectangleObj.Y = clickPrev.Y - rectangleObj.Width / 2;
Refresh();
}
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.DrawImage(Draw(), 0, 0);
}
public Bitmap Draw()
{
Graphics scG = Graphics.FromImage(background);
Pen myPen = new Pen(System.Drawing.Color.Red, 3);
scG.Clear(SystemColors.Control);
scG.DrawEllipse(myPen, rectangleObj);
return background;
}
}
}
Your English was a little confusing. If I'm understanding your problem correctly, right now the only thing that's being drawn is the new circle where the click was, and you want all the old ones to persist as well? In which case, there are two options:
Don't clear the bitmap before you draw. scG.Clear(SystemColors.Control); will clear the bitmap you just drew. If you remove that line and don't clear the bitmap, then the next time you click, it will then draw the new ellipse right on top of the last bitmap.
If you want a fresh drawing/bitmap everytime, you would need a list of your rectangleObj . Each time you click, you add that point to your rectangleObj collection. Then in your draw method, you would iterate through the collection and draw all of them.
I notice a few things. First, in Form1_MouseDown(), you have this:
clickCurrent = PointToClient(Cursor.Position);
clickPrev = clickCurrent;
You are overwriting the old position (clickPrev) before you even save it. If you want to keep both positions, you should put them in a simple structure, like a List. When you get a new point, just Add() it to the list. Then, in your Draw() routine, loop over all the elements in the list and draw them all.
If you just want two positions--and only two--just swap your statements like this:
clickPrev = clickCurrent;
clickCurrent = PointToClient(Cursor.Position);
And you'll have to allocate another rectangle object for the drawing, although it would make more sense to take care of this in the Draw() routine.
Swap the position of the following statements
clickCurrent = PointToClient(Cursor.Position);
clickPrev = clickCurrent;
I think you are assigning the clickCurrent to clickPrevious after you initialize clickCurrent. It needs to be the other way.
Please try this
Rectangle rectangleObj;
Bitmap background;
Graphics scG;
Pen myPen;
private void Form1_Load(object sender, EventArgs e)
{
rectangleObj = new Rectangle(10, 10, 30, 30);
background = new Bitmap(Width, Height);
scG = Graphics.FromImage(background);
myPen = new Pen(Color.Red, 3);
BackgroundImage = background;
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
var point = PointToClient(Cursor.Position);
rectangleObj.X = point.X - rectangleObj.Height / 2;
rectangleObj.Y = point.Y - rectangleObj.Width / 2;
scG.DrawEllipse(myPen, rectangleObj);
Refresh();
}
OnPaint and Draw methods removed. As well as clickCurrent and clickPrev fields.
When you change the form size (for example, maximize it), Bitmap and Graphics remain the same, so you get this effect. To avoid this, you need to add the event handler
private void Form1_SizeChanged(object sender, EventArgs e)
{
background = new Bitmap(Width, Height);
scG = Graphics.FromImage(background);
BackgroundImage = background;
}
Note that each time you resize the form, all previously drawn is erased. If this is undesirable, a different approach is needed for drawing. Let me know, I will give another example.
I'm trying to copy from the screen the position of a PictureBox. My code looks like this:
Form1.cs:
_recorder = new ScreenRecord();
_recorder.StartRecording(
pictureBox1,
pictureBox1.RectangleToScreen(new Rectangle())
);
ScreenRecord.cs:
class ScreenRecord
{
private ScreenBitmap scBitmap;
public void StartRecording(PictureBox cam, Rectangle rect)
{
scBitmap = new ScreenBitmap(cam, rect);
cam.Image = scBitmap.GetBitmap();
}
}
ScreenBitmap.cs:
class ScreenBitmap
{
private PictureBox camBox;
private Rectangle camLocation;
public ScreenBitmap(PictureBox cam, Rectangle rect)
{
camBox = cam;
camLocation = rect;
}
public Bitmap GetBitmap()
{
Bitmap screenBitmap = GetScreen();
return screenBitmap;
}
private Bitmap GetScreen()
{
Bitmap scBitmap = new Bitmap(camBox.Width, camBox.Height);
Graphics g = Graphics.FromImage(scBitmap);
g.CopyFromScreen(
camLocation.X,
camLocation.Y,
0,
0,
new Size(camBox.Width, camBox.Height)
);
return scBitmap;
}
}
I'm getting the pictureBox1 rectangle and then copying from the screen, but it looks like its not working. If I try the following code:
g.CopyFromScreen(
camLocation.X,
121,
0,
0,
new Size(camBox.Width, camBox.Height)
);
where 121 is a random number it works (I get an image, not the part I want, but it works) so the Y coordinate of the rectangle may be wrong? Or I'm missing something...
This will get you what is behind the PictureBox, with the opacity trick. The rest you can easily transfer to your code:
//just when you are about to capture screen take opacity and later restore it.
this.Opacity = 0.0;
Point first = PointToScreen(pictureBox1.Location);
Bitmap bit = new Bitmap(pictureBox1.Width, pictureBox1.Height);
Graphics g = Graphics.FromImage(bit);
g.CopyFromScreen(first.X,first.Y, 0, 0, pictureBox1.Size);
this.Opacity = 1.0;
pictureBox1.Image = bit;
You can test this code by creating a new WinForms project, add a Button and a PictureBox, and place this code in the Button's Click event handler.
I've been reading stackoverflow for a while now just to learn, and I've come across a situation where I can finally ask a question. I'm making a Simon Says type memory game, where I flash shapes at the user, and the user has to click a button in the same order the shapes were shown to them. I want to draw the shape that I'm drawing on the screen within the button that they are clicking because it's much easier to remember and compare shapes to shapes rather than shapes to a button that says the shapes name.
Hopefully my question is clear, and thanks for taking a look!
Yes, you can set the Image property of Button. Alternatively, you can draw non-rectangular buttons, that is, buttons of any shape. The following code demonstrates both techniques:
using System;
using System.Drawing;
using System.Windows.Forms;
class ShapeButton : Button {
public Action<PaintEventArgs> DoPaint { get; set; }
protected override void OnPaint(PaintEventArgs e) {
if (DoPaint != null) { DoPaint(e); }
}
}
static class Program {
static void Main() {
// Ellipse button
ShapeButton ellipseButton = new ShapeButton();
ellipseButton.Location = new Point(10, 10);
ellipseButton.Size = new Size(80, 80);
ellipseButton.DoPaint = delegate(PaintEventArgs e) {
Graphics graphics = e.Graphics;
SolidBrush brush1 = new SolidBrush(SystemColors.ButtonFace);
graphics.FillRectangle(brush1, 0, 0, ellipseButton.Width, ellipseButton.Height);
SolidBrush brush2 = new SolidBrush(Color.Red);
graphics.FillEllipse(brush2, 0, 0, ellipseButton.Width, ellipseButton.Height);
};
ellipseButton.Click += delegate(object sender, EventArgs e) {
MessageBox.Show("Ellipse!");
};
// Triangle button
ShapeButton triangleButton = new ShapeButton();
triangleButton.Location = new Point(100, 10);
triangleButton.Size = new Size(80, 80);
triangleButton.DoPaint = delegate(PaintEventArgs e) {
Graphics graphics = e.Graphics;
SolidBrush brush1 = new SolidBrush(SystemColors.ButtonFace);
graphics.FillRectangle(brush1, 0, 0, triangleButton.Width, triangleButton.Height);
SolidBrush brush2 = new SolidBrush(Color.Green);
Point[] points = {
new Point(triangleButton.Width / 2, 0),
new Point(0, triangleButton.Height),
new Point(triangleButton.Width, triangleButton.Height)
};
graphics.FillPolygon(brush2, points);
};
triangleButton.Click += delegate(object sender, EventArgs e) {
MessageBox.Show("Triangle!");
};
// Star button (using image)
Button starButton = new Button();
starButton.Location = new Point(190, 10);
starButton.Size = new Size(80, 80);
starButton.Image = new Bitmap("Star.png");
starButton.Click += delegate(object sender, EventArgs e) {
MessageBox.Show("Star!");
};
// The form
Form form = new Form();
form.Text = "Shape Button Test";
form.ClientSize = new Size(280, 100);
form.Controls.Add(ellipseButton);
form.Controls.Add(triangleButton);
form.Controls.Add(starButton);
form.ShowDialog();
}
}
Result (after clicking on the triangle button):
In winforms to change the button's image at runtime you can use something like this:
button1.Image = new Bitmap(Image.FromFile(#"Pictures\Koala.jpg"));
It should be added to event handler. For example if you want to show the image when the button is clicked you subscribe to Click event of the button and add the code into the handler method:
private void button1_Click(object sender, EventArgs e)
{
button1.Image = new Bitmap(Image.FromFile(#"Pictures\Koala.jpg"));
}
In my example,
I have a pictureBox to show, two buttons, one to control, one to be drawn.
//odd display, even draw
int count = 0;
Image storePicture;
//whenever the background image changed,store it
private void pictureBoxShow_BackgroundImageChanged(object sender, EventArgs e)
{
//you can stored to a Image array if you have series pictures to show
storePicture = pictureBoxShow.BackgroundImage;
}
private void buttonControl_Click(object sender, EventArgs e)
{
count++;
//odd show picture, even draw picture on button
if (count % 2 == 1)
pictureBoxShow.BackgroundImage = new Bitmap("shapes.JPG");
else
{
//in case you want to clear text on the button
buttonDrawn.Text = null;
//recreate the picture so that it fit the button size
buttonDrawn.Image = new Bitmap(storePicture, new Size(buttonDrawn.Width, buttonDrawn.Height));
}
}
Please remember to attach the handlers to corresponding events. ^^
Why not using PictureBox instead of Buttons.
you have just to add your task to its event/OnClick
Of course you can load any Image to any PictureBox in runtime
The code above is great, however you can click outside the circle within a square containing the circle and get the click event.
If you want to capture the click only if the user clicks inside the shape you have to set the region property with something like this
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(0, 0, 100, 100);
Button1.Region = new Region(gp);
}
}
I have a pictureBox1 with image inside and when i click on it its drawing points.
Now i added a reset button i called it when i click on it its should clear all the drawings i did on the pictureBox and leavethe image inside without the drawings on it.
I did:
private void button4_Click(object sender, EventArgs e)
{
Graphics graphics;
graphics = pictureBox1.CreateGraphics();
graphics.DrawImage(pictureBox1.Image, 0, 0);
}
So i draw a lot of points on pictureBox1 then click the button and all points are gone but then once i click on the picturebox1 again i see also the new points but also the old points i did before the clearing.
How can i clear the old drawings so it wont show up on the next clicks ?
This is the paint event: Moved the paint event to a new class:
public static void Paint(List<PointF> pb1points, GraphicsPath pb1gp, Point movingPoint, PictureBox pictureBox1, Graphics e)
{
e.Clear(Color.White);
e.DrawImage(pictureBox1.Image, movingPoint);
Pen p;
p = new Pen(Brushes.Green);
foreach (PointF pt in pb1points)
{
e.FillEllipse(Brushes.Red, pt.X, pt.Y, 3f, 3f);
}
using (Pen pp = new Pen(Color.Green, 2f))
{
pp.StartCap = pp.EndCap = LineCap.Round;
pp.LineJoin = LineJoin.Round;
e.DrawPath(pp, pb1gp);
}
}
You can try using Graphics.Clear().
Reference: http://msdn.microsoft.com/en-us/library/system.drawing.graphics.clear(v=vs.110).aspx
setting the Image property to null should work.
picBox.Image = null;
Ii it's not worked ,you might be used the InitialImage property to display your image.
pictBox.InitialImage = null;
Please refer the link:
Clear image on picturebox
This is working:
private void button4_Click(object sender, EventArgs e)
{
Graphics graphics;
graphics = pictureBox1.CreateGraphics();
graphics.DrawImage(pictureBox1.Image, 0, 0);
pb1points = new List<PointF>();
}