C# - Keeping the values from functions - c#

I want to call a function like Spawn() in this case, but without losing values from it after calling it (for example, I want entityPicture to still be available after I call Spawn(), so I can use it later on MainWindow_KeyDown() function). Same with X and other variables like that.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace EpicGame
{
public partial class MainWindow : Form
{
public MainWindow()
{
InitializeComponent();
}
public void MainWindow_Load(object sender, EventArgs e)
{
int EntityCount = 0;
Background.ImageLocation = "Background.jpg";
Background.SizeMode = PictureBoxSizeMode.AutoSize;
Spawn(600, 600, EntityCount, "Player 1.png"); EntityCount++;
}
// Controls
public void MainWindow_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.D) MoveRight();
entityPicture.Location = new Point(X, Y);
}
// Movement
public void MoveRight()
{
X++;
}
// Entity spawning
public void Spawn(int X, int Y, int ID, string Path)
{
PictureBox entityPicture = new PictureBox();
Image Entity = Image.FromFile(Path);
entityPicture.Image = Entity;
entityPicture.SizeMode = PictureBoxSizeMode.AutoSize;
entityPicture.Location = new Point(X, Y);
entityPicture.BackColor = Color.Transparent;
Controls.Add(entityPicture);
entityPicture.BringToFront();
}
private void Background_Click(object sender, EventArgs e)
{
}
}
}

You can declare it public in the form class like:
public partial class MainWindow : Form
{
PictureBox entityPicture = new PictureBox();
}
I don't know the type of entityPicture so just used PictureBox as example, you use the correct type.

Your root issue is one of scope. Have a look at this video, it walks through your exact issue: https://www.youtube.com/watch?v=NemPMKTxM7w
You can technically move entityPicture to the top of the class, however given this appears to be a WinForms window, I would add the PictureBox via the designer so it's only declared once. If you declare it at the class level and reinitialize it in Spawn (i.e. = new PictureBox()) repeatedly, you're going to create a memory leak.

Related

Windows Forms, accessing picturebox from class in main form

I'm making a game where I want to make things fall down and the player should try to catch it.
Currently, my items which are falling are drawn and made in a class separated from the main form, so when I try to access them from the main form where I control the gravitation.I can't seem to find the picturebox (picCoin).
Could you please take a look at my code and come with some solution?
This is the class were i create Coins
class Coin
{
private PictureBox picCoin = new PictureBox();
public Coin()
{
picCoin.BackColor = Color.Transparent;
picCoin.ImageLocation = #"C:\Users\sebfre1104\source\repos\SPEL\SPEL\Resources\hamburger.png";
picCoin.Width = 100;
picCoin.Height = 100;
picCoin.SizeMode = PictureBoxSizeMode.StretchImage;
}
public void DrawTo(Form f)
{
f.Controls.Add(picCoin);
}
public Rectangle getBounds()
{
return picCoin.Bounds;
}
public void setposition(int x, int y)
{
picCoin.Location = new Point(x, y);
}
}
i want to reach this picCoin in my main form so i can add gravity in private void TimerGravitation_Tick(object sender, EventArgs e)
public partial class Form1 : Form
{
bool IsJumping = false;
List<Coin> clist = new List<Coin>();
int poƤng = 0;
public Form1()
{
InitializeComponent();
}
private void TimerGravitation_Tick(object sender, EventArgs e)
{
if(!picSpelare.Bounds.IntersectsWith(picMark.Bounds) && IsJumping==false)
{
picSpelare.Top += 10;
}
}
I would be very grateful with any tips as this is my final project in class.
i dont know if i understanded question correctly but make picCoin public
make
private PictureBox picCoin = new PictureBox();
to
public PictureBox picCoin = new PictureBox();
At first, you should follow Umut Arpat's answer (turn picCoin from private to public).
Then you should initialize the Coin class in Form1 constructor like this:
private Coin _coin;
public Form1()
{
InitializeComponent();
_coin = new Coin();
}
And then you should add picture box from Coin class to list of Form1 controls like this:
this.Controls.Add(_coin.picCoin)
You can do that in Form1 constructor too.
Don't add PictureBox to Controls of the form from the Coin class (method DrawTo()).
class Coin
{
private PictureBox picCoin = new PictureBox();
public PictureBox Box {
get { return picCoin};
set { picCoin = value};
}
....
}
To use/access the box:
clist[i].Box // This is what you want

How do I call a public methods in my 'public class' (as c# module) in c#?

There are only (3) things I need to know in here.
Firstly, there is only (1) button (close_button) in this form. Here's my frm_main.cs code:
public partial class frm_main : Form
{
public_class pc = new public_class();
public frm_main()
{
InitializeComponent();
this.Load += new System.EventHandler(frm_main_Load);
}
private void close_button_Click(object sender, EventArgs e)
{
this.Close();
}
private void frm_main_Load(object sender, EventArgs e)
{
pc.screen_adjust(close_button);
}
}
And here's my public_class.cs code:
public partial class public_class
{
public int cl_b;
public void screen_adjust(Button b)
{
cl_b = frm_main.ActiveForm.Width;
frm_main.ActiveForm.Width = Screen.PrimaryScreen.Bounds.Width;
frm_main.ActiveForm.Height = Screen.PrimaryScreen.Bounds.Height;
b.Left += frm_main.ActiveForm.Width - cl_b;
}
}
The aim of this borderless program is to auto-stretch the form to the whole screen. Now, what I'd like to learn is:
Did I do a correct "VB.net module" in C# properly?
How do I call the methods in public_class.cs without using the 'public_class pc = new public_class();' and 'pc.screen_adjust(close_button);'?
In the public_class.cs, for example, if I want to change the close_button's text, how should I do it? I can't do frm_main.close_button afterall...
Thanks!

C# paint graphics from class in picturebox with mouse click

I want to paint a graphics object from a method (paint) I created in a separate class (Paintball). I want it to paint in a picturebox only when I left-click with my mouse and I want the point where I shoot to be stored in a List. When I try the code below, it doesn't shoot. Below is the class Paintball.
{
private List<Point> myClick;
public Paintball()
{
myClick = new List<Point>();
}
public void add(Point location)
{
myClick.Add(location);
}
public void paint(Graphics g, Point point)
{
g.FillEllipse(Brushes.Blue, point.X, point.Y, 20, 20);
}
}
}
This is form1 below.
namespace AmazingPaintball
{
public partial class Form1 : Form
{
Random positionX = new Random();
Random positionY = new Random();
Target einstein;
int count;
List<Point> ballList = new List<Point>();
Paintball gun;
public Form1()
{
InitializeComponent();
Point point = new Point(positionX.Next(0, 638), positionY.Next(0, 404));
einstein = new Target(point);
ptrEinstein.Location = point;
gun = new Paintball();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
ptrEinstein.Location = einstein.Move(e.KeyData);
pictureBox1.Update();
pictureBox1.Refresh();
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
count++;
gun.add(e.Location);
pictureBox1.Refresh();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (var Paintball in ballList)
{
gun.paint(e.Graphics, this.PointToClient(Cursor.Position));
pictureBox1.Refresh();
}
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
pictureBox1.Refresh();
}
}
}
Please let me know if you know what has to be edited/created. Thank You
Your original code has many mistakes. Let's try to simplify what you are doing and tackle simply storing a list of points and drawing them to the picturebox.
public partial class Form1 : Form
{
List<Point> ballList = new List<Point>();
public Form1()
{
InitializeComponent();
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
ballList.Add(e.Location);
pictureBox1.Refresh();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (Point pBall in ballList)
{
e.Graphics.FillEllipse(Brushes.Blue, pBall.X, pBall.Y, 20, 20);
}
}
}
Here we have a list, we add the click points to it in the click handler and paint them in the paint handler. Once you get comfortable with this, perhaps move to the next task in your program and ask a new question if you get stuck with the next feature.
Ok, I've got a bit of time, so let's look at your paintball class. I've renamed it Paintballs since it contains many of them and this name is more appropriate. If you want to keep the list of points private that's ok. You are trying to implement a Paint method in the class, but it takes a Point as argument and does not operate on any of the class's instance state - this probably isn't what you want. Consider now :
public class Paintballs
{
private List<Point> myClick;
public Paintballs()
{
myClick = new List<Point>();
}
public void Add(Point location)
{
myClick.Add(location);
}
public void Paint(Graphics g)
{
foreach (Point p in myClick)
{
g.FillEllipse(Brushes.Blue, p.X, p.Y, 20, 20);
}
}
}
Here we have a public Paint method that will draw all of the paintballs in the class to any graphics instance you pass to it. Now your form code would look like :
public partial class Form1 : Form
{
Paintballs pBalls = new Paintballs();
public Form1()
{
InitializeComponent();
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
pBalls.Add(e.Location);
pictureBox1.Refresh();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
pBalls.Paint(e.Graphics);
}
}
So we've simplified the form code by pushing the painting method into the paintballs class itself. This makes the class responsible for knowing what the paintballs look like, how many there are, where they are, and how to draw them to a Graphics object. This is step 1 in encapsulating responsibility.
You're drawing from a list of points stored in that ballList variable. However, you've never added any points to that list.
Make the myClick list in Paintball public and, in the pictureBox1_Paint method, iterate through that list instead of ballList.

Flashing ToolStripButton

I am using a ToolStrip with a number of ToolStripButtons.
What I would like is to be able to flash one of the buttons to get the user's attention.
For example, if they have made changes to information and need to click the Save button.
If this were a normal button I could do this using a Timer and periodically changing the BackColor however this doesn't work with a ToolStrip.
I could create a Renderer subclass and assign it to the ToolStrip but this appears to only get used in specific situations - i.e. it's event driven.
Does anyone have any ideas?
Well, just use a custom renderer so you can change the color of the button's background. With a timer that blinks it. Add a new class to your project and paste this code:
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Windows.Forms;
class BlinkingButtonRenderer : ToolStripProfessionalRenderer {
public BlinkingButtonRenderer(ToolStrip strip) {
this.strip = strip;
this.strip.Renderer = this;
this.strip.Disposed += new EventHandler(strip_Disposed);
this.blinkTimer = new Timer { Interval = 500 };
this.blinkTimer.Tick += delegate { blink = !blink; strip.Invalidate(); };
}
public void BlinkButton(ToolStripButton button, bool enable) {
if (!enable) blinkButtons.Remove(button);
else blinkButtons.Add(button);
blinkTimer.Enabled = blinkButtons.Count > 0;
strip.Invalidate();
}
protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e) {
var btn = e.Item as ToolStripButton;
if (blink && btn != null && blinkButtons.Contains(btn)) {
Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);
e.Graphics.FillRectangle(Brushes.Black, bounds);
}
else base.OnRenderButtonBackground(e);
}
private void strip_Disposed(object sender, EventArgs e) {
blinkTimer.Dispose();
}
private List<ToolStripItem> blinkButtons = new List<ToolStripItem>();
private bool blink;
private Timer blinkTimer;
private ToolStrip strip;
}
Sample usage in a form with a Toolstrip containing a button:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
blinker = new BlinkingButtonRenderer(toolStrip1);
}
private void toolStripButton1_Click(object sender, EventArgs e) {
blink = !blink;
blinker.BlinkButton(toolStripButton1, blink);
}
private bool blink;
private BlinkingButtonRenderer blinker;
}

Programmatically put an image into the form which is not active?

I want programmatically put an image into the form which is not active.
Image myImage = new Image();
gfx = Form.ActiveForm.CreateGraphics();
gfx.DrawImage(myImage, 0,0);
It's will be working perfectly only if the form is active, but it's make no sense when the form is not active, just returns me an error:
In an instance of an object reference not set to an object.
how to handle the form which is not active in my application and put a picture to it?
upd 1
I did instance, and turned on DoubleBuffered property (true) but nothing happens:
Form1 form = new Form1();
gfx = form.CreateGraphics();
gfx.DrawImage(bmp, 0, 0);
upd 2 More Source, it's my added class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
namespace testimg
{
class doimg
{
public void picture()
{
// some staffs to get a picture, so it's in bmp object now.
gfx = this. // watch picture below
gfx.DrawImage(bmp, 0, 0);
// I tried to use PictureBox, but it's the same issue (I can't handle it on a form)
PictureBox pb = new PictureBox();
pb.CreateGraphics();
pb.DrawToBitmap(bmp,pb.ClientRectangle);
}
}
}
and a picture for the Arif Eqbal solution: no graph methods for this (pic)
upd 3
The full source what I have (timer is on a 10 sec)
Form1.cs
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 testimg
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
doimg pic = new doimg();
pic.picture();
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Enabled = true;
}
}
}
doimg.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
namespace testimg
{
class doimg
{
public void picture()
{
// some staffs to get a picture, so it's in bmp object now.
Bitmap bmp = new Bitmap(200, 200, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics gfx = Graphics.FromImage(bmp);
gfx = Form1.ActiveForm.CreateGraphics(); // works well with active form
gfx.DrawImage(bmp, 0, 0);
}
}
}
and whole archive with project http://www.filedropper.com/testimg
as you can see all running well while the program is active. Still need help.
On your Form2, try to set it up like this:
public partial class Form2 : Form {
public Image MyImage { get; set; }
public Form2() {
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e) {
if (MyImage != null) {
e.Graphics.DrawImage(MyImage, 0, 0);
}
base.OnPaint(e);
}
}
Then from your active form, you can call the other form to draw itself:
public partial class Form1 : Form {
Form2 f2 = new Form2();
public Form1() {
InitializeComponent();
f2.Show();
}
private void button1_Click(object sender, EventArgs e) {
f2.MyImage = myImage;
f2.Invalidate();
}
}
Part of the problem is that when you are setting your bitmap the Form is not updating, expecially if it is minimized or doesn't have focus. You also have the issue that since it is not being set in the Paint Event Handler you have no retention of the Image. Try something like this, Note the Invalidate call and the Timer was set for 10,000 ms. This is a variation of #LarsTech's answer if you are working with multiple Forms his is the way to go.
public partial class Form1 : Form
{
Bitmap myImage;
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
myImage = new Bitmap("Your Image Name Here");
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (myImage != null)
e.Graphics.DrawImage(myImage,0,0);
}
}
Modifed my Example to work with the OP's structure:
My original example does work when the form does not have focus. Your main problem with the error is using Form1.ActiveForm when it is not the active form, it will return null which is causing your error. Use the Forms Paint Event and Invalidate the Form to insure that the Image is painted.
Form1.cs
namespace testimg
{
public partial class Form1 : Form
{
Bitmap myImage;
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
myImage = doimg.picture();
Invalidate();
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (myImage != null)
e.Graphics.DrawImage(myImage,0,0);
}
}
}
doimg.cs
namespace testimg
{
static class doimg
{
static Color[] clr = new Color[] { Color.Red, Color.Blue, Color.Black, Color.Violet, Color.Wheat };
static int count = 0;
static public Bitmap picture()
{
// some staffs to get a picture, so it's in bmp object now.
Bitmap bmp = new Bitmap(200, 200, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
// Added some drawing to bitmap to test functionality
Graphics gfx = Graphics.FromImage(bmp);
gfx.FillEllipse(new SolidBrush(clr[count]),new Rectangle(0,0,199,199));
gfx.Dispose();
if (count >= 4)
count = 0;
else
count += 1;
return bmp;
}
}
}
You have to create an instance of your form.. regardless of whether it's visible and active.
Example:
Image myImage = new Image(); // load image
MyForm form = new MyForm();
gfx = form.CreateGraphics();
gfx.DrawImage(myImage, 0, 0);
Then you will be able to call form.Show() when you want to show the form.
(Note, you'll probably also have to set DoubleBackBuffer on the form to true.
I think I can make a sense of it...is it that your code to Get the instance of the form and draw on it run on a timer? And your application has just one form? And you run into issues when the Application is not Active?
If Yes then replace the line
Form.ActiveForm.CreateGraphics();
with
this.CreateGraphics();
Form.ActiveForm gives the reference of the currently Active Form for the Application, if you write this code on say a Button click you are bound to get the name of the Form on which the Button was clicked. However, if the code is on a timer it might give the instance of the Active form or Null if the entire application is not Active.
As you have mentioned in one of the comments that you do not have any other form, it appears that your application has just one form and this code is running on the only form in the app so this.CreateGraphics should suffice. However, if your application has more than one form then Form.ActiveForm is a legitimate code but you need to take care of the scenario when no form is active i.e. the application itself is not active.
EDIT:
I think you need to pass the instance of the Form on which you want to draw to this class. Make a properry and set the property value to the instance of the form, you might pass it in the constructor as well...using Form.ActiveForm was not a bad idea here but for 2 reasons, tomorrow if you had more than one form in your app it will draw randomly on whicheever is active, second as in your current case if the app is not active you will not get hold of the instance...since you have only one form in your app I suppose you would be creating the instance of this Class on the form so may be you can add a property
public Form ParentForm { get; set; }
in the class and set it as
myClassObject.ParentForm = this;
on the form when you create an instance of this class and then say
ParentForm.CreateGraphics
in the class

Categories

Resources