I am having trouble doing something that I would have though to have been quite simple, all I am trying to do is to call a method from another class, heres how I am calling the method:
Gimjes_2D_Game_Framework1.Characters.Character_One.Create();
and here is the contents of the method I am trying to call:
public static void Create()
{
Form1 f = new Form1();
System.Windows.Forms.PictureBox s = new System.Windows.Forms.PictureBox();
//location of image (in thia case it is from resources):
s.BackgroundImage = Gimjes_2D_Game_Framework1.Properties.Resources.DefaultSprite;
//Set to height and width of image:
s.Height = 64;
s.Width = 64;
s.Size = new System.Drawing.Size(60, 60);
s.Location = new System.Drawing.Point(50, 50);
f.Controls.Add(s);
}
Try adding
f.Show();
or
f.ShowDialog();
to the end of your Create method.
Otherwise, you're making a form, and never displaying it.
Show gives you a modeless form, and ShowDialog gives you a modal dialog.
See documentation here for more information.
If you intend to return a Form1 object, to be shown at a later point, you need to change your method to:
public static Form1 Create()
{
Form1 f = new Form1();
...
return f;
}
Related
I have a total of 6 forms. In my mainForm, I have 5 buttons to open the other forms inside the panel. what i know is something like this:
form1 f1 = new form1();
f1.TopLevel = false;
f1.Dock = DockStyle.Fill;
this.panelMid.Controls.Add(f1);
f1.show();
now, since I have 5 other forms, I want to make a function that would make me open the forms without re-typing those code in every button event.
My problem is that I don't know to pass the form into a function as parameter.
DRY 101, based on your code, with some generics chucked in
public void MyAwesomeFormShower<TForm>()
where TForm : Form, new()
{
var form = new TForm();
// common code here
form.TopLevel = false;
form.Dock = DockStyle.Fill;
///this.panelMid.Controls.Add(f1); // < who knows what this does, however don't do it
form.Show();
}
Usage
MyAwesomeFormShower<MyLovelyHorseForm>();
Or if you want to get fancy
public void MyAwesomeFormShower<TForm>(Action<TForm> action = null)
where TForm : Form, new()
{
var form = new TForm();
// common code here
form.TopLevel = false;
form.Dock = DockStyle.Fill;
action?.Invoke();
form.Show();
}
Usage
MyAwesomeFormShower<MyLovelyHorseForm>();
// or
MyAwesomeFormShower<MyLovelyHorseForm>((form) =>
{
// Specialised form stuff here
// that is specific to MyLovelyHorseForm
});
having a bit of a problem changing the label text when a button is pressed. my code looks like this. i searched a bit in this forum and tried this solution in form1 i have this code.
public string info
{
get
{
return label11.Text;
}
set
{
label11.Text = value;
}
}
in class search i have this
public void fighting()
{
character tom = new character();
Form1 f = new Form1();
Random explore = new Random();
int exploration = explore.Next(0, 3);
if (character.location == "Forest" || character.location == "Dungeon")
{
switch (exploration)
{
case 0:
f.info = "You didnt find anything";
f.Refresh();
f.herodamage = exploration.ToString();
break;
...
the button has this
public void button8_Click(object sender, EventArgs e)
{
Search find = new Search();
find.fighting();
}
what am i doing wrong? everytime i press the button the text wont change but it works because it does change a buttons text.
Fighting method is creating a new instance of Form1, different from your UI.
While it is updating label1.Text, it refers to different Form1.
My suggestion is for refactoring of your code to make responsibilities more clear.
Something like
var info = find.fighting(); // Where fighting returns string, instead of creating new Form1 and setting value, just return the value.
this.info = info;
If you still insist to update UI from search method, which is not correct way to approach this problem, you can pass around Form1 from the parameter.
Search find = new Search(this); // Store it as instance of Search class.
find.fighting(); // fighting should never create new instance of Form1 (reason of problem you are facing)
Instead of creating a new instance of Form1 you need to get a reference to the already existing instance of this form.
One simple way to do this is to use the Application.OpenForms property:
character tom = new character();
Form1 f = Application.OpenForms.OfType<Form1>().FirstOrDefault();
Random explore = new Random();
...
I want to animate buttons in c#. So i create a method called HoverMouseBut() as follows.
public void HoverMouseBut(Button name,Image img, int w, int h)
{
name.Image = Resources.img;
name.ForeColor = Color.FromArgb(232, 126, 4);
name.Size = new Size(w, h);
name.Font = new Font("Segoe UI", 12, FontStyle.Regular);
name.TextAlign = ContentAlignment.BottomCenter;
name.ImageAlign = ContentAlignment.MiddleCenter;
}
I called this method as follows;
private void addo_MouseHover(object sender, EventArgs e)
{
HoverMouseBut(addo,Add2,250,160);
}
This gave me a syntax error. I changed the method without image parameter and see.Then it worked.But I want to change the image of the button as well.How could I do this? Whats wrong with my code?
*Add2 is an image in resources .
You are using C# and forms are like other properties in C#. Therefore you have different options to do that.
One of the easiest ones is to have a public property of your needed type in your second form and use that to pass data
class Form2
{
public string myStringField{get;set;}
}
class Form1
{
myMethod()
{
....
var newForm= new Form2();
newForm.myStringField="Something";
}
}
However, if your Form2 can not exist without your field, it make sense to put your filed in the constructor
class Form2
{
public Form2 (string myStringField)
{...}
}
class Form1
{
myMethod()
{
....
var newForm= new Form2("Something");
}
}
If you are trying to pass an Image to the method for use, why did you set name.Image = Resources.img ?
Changing it to name.Image = img might work
I am trying to print automatically a series of Windows-Forms. I don't need to show them. The code examples I found on the internet work only when I display the Form with show()! I need to initialize the form with data and send it to the printer Here is the code I am using:
public partial class Form2_withoutShow : Form{
PrintDocument PrintDoc;
Bitmap memImage;
public Form2_withoutShow (Data data)
{
InitializeComponent();
/*
Initialize Data (texboxes, charts ect.) here
*/
this.PrintDoc = new PrintDocument();
this.PrintDoc.PrintPage += PrintDoc_PrintPage;
this.PrintDoc.DefaultPageSettings.Landscape = true;
}
public void Print()
{
this.PrintDoc.Print();
}
void PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
{
int x = SystemInformation.WorkingArea.X;
int y = SystemInformation.WorkingArea.Y;
int width = this.Width;
int height = this.Height;
Rectangle bounds = new Rectangle(x, y, width, height);
Bitmap img = new Bitmap(width, height);
this.DrawToBitmap(img, bounds);
Point p = new Point(10, 10);
e.Graphics.DrawImage(img, p);
}
private void Form2_withoutShow_Load(object sender, EventArgs e)
{
// remove TITLEBar
this.ControlBox = false;
this.Text = String.Empty;
}
}
I call the Print() method from another class in for-loop and pass the Data to be initialized through the constructor.
The MSDN example captures the part on the screen where the forms should be displayed. This doesn't work for me. The approach I am using now yields only the print of the empty Window if I don't call show(). How do I get the data into the form without having to call the show() method? Approaches like mimize the windows when displaying it, also don't work because that is also the print result: a minimized window.
Before showing the form, the form and its controls are not in Created state. To force the form and its controls to be created it's enough to call internal CreateControl(bool fIgnoreVisible) method of your form:
var f = new Form1();
var createControl = f.GetType().GetMethod("CreateControl",
BindingFlags.Instance | BindingFlags.NonPublic);
createControl.Invoke(f, new object[] { true });
var bm = new Bitmap(f.Width, f.Height);
f.DrawToBitmap(bm, new Rectangle(0, 0, bm.Width, bm.Height));
bm.Save(#"d:\bm.bmp");
Also remove codes which you have in your form Load event handler, and put them in constructor of your form.
Note
There are also other workarounds for the problem:
For example you can show the form in a location outside of boundary of the screen and then hide it again. Set the Location to (-32000, -32000) and set StartPosition to be Manual then Show and Hide the form before drawing to bitmap.
Or as another example, you can show the form with Opacity set to 0 and then Show and Hide the form before drawing to bitmap.
I have a program, which creates one pictureBox in Form1, and then creates an instance of a class that I called InitialState. The InitialState puts the source to the Image so that it is displayed, and after some time has passed, for which I used a Timer, it creates the next class, MainMenuState. Now, in that MainMenuState class that I've created, I would like to create another pictureBox and make it display on that Form1. Later on, I would like to make the pictures inside it change a bit, and then (possibly) destroy that pictureBox. After that, the program enters the next state (which is in yet another class), and again I would like that class to add a picture box to the original form, and so on.
Basically, I would like to dynamically add controls to the main Form1, but not in the said form, but from the classes I create later on. I've been searching on the internet for a way to do that, and it seems like I would have to use a delegate in order to invoke the Controls.Add method of the Form1 class. I've tried that, and the code compiles, but the pictureBox still doesn't show up.
Here's my code:
Form1 class:
public const string RESOURCE_PATH = "C:/Users/Noel/Documents/Visual Studio 2010/Projects/A/Resources/Animations/";
public Form1()
{
InitializeComponent(); //here, the first pictureBox shows
iInitializeComponent();
zacetnaAnimacija.Dock = DockStyle.Fill; //zacetnaAnimacija is the first pictureBox that appears
zacetnaAnimacija.Anchor = AnchorStyles.Top | AnchorStyles.Left;
zacetnaAnimacija.SizeMode = PictureBoxSizeMode.StretchImage;
InitialState intialState = new InitialState(this, zacetnaAnimacija); //entering InitialState
}
InitialState class:
class InitialState : State
{
System.Timers.Timer initialTimer;
PictureBox pictureBox1;
Form1 form;
public InitialState (Form1 form, PictureBox pictureBox1) {
this.form = form;
GifImage zacetnaSlika = new GifImage(Form1.RESOURCE_PATH + "Presenting.gif"); //this is just a .gif picture I'm displaying
Image trenutnaSlika = zacetnaSlika.GetFrame(0); //a method that plays the .gif
pictureBox1.Image = trenutnaSlika; //makes the first .gif display
this.pictureBox1 = pictureBox1;
initialTimer = new System.Timers.Timer(2500);
initialTimer.Enabled = true;
initialTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
initialTimer.Enabled = false;
MainMenuState menuState = new MainMenuState(form, pictureBox1); //enters main menu state with the Form1 argument passed on
}
MainMenuState class:
class MainMenuState : State
{
Form1 form;
public MainMenuState (Form1 form, PictureBox pictureBox1) {
this.form = form;
GifImage zacetnaSlika = new GifImage(Form1.RESOURCE_PATH + "animated.gif");
Image trenutnaSlika = zacetnaSlika.GetFrame(0);
pictureBox1.Image = trenutnaSlika; //this simply makes another .gif appear in the picture box instead of the first one
PictureBox a = new PictureBox(); //HERE'S my problem, when I want to add ANOTHER pictureBox to that form.
a.BackgroundImage = trenutnaSlika;
a.Location = new System.Drawing.Point(0, 0);
a.Name = "zacetnaAnimacija";
a.Size = new System.Drawing.Size(150, 150);
a.TabIndex = 1;
a.TabStop = false;
AddControl(a); //calling the delegate
}
public delegate void AddControls(PictureBox a);
public void AddControl(PictureBox a)
{
if (form.InvokeRequired)
{
AddControls del = new AddControls(AddControl);
form.Invoke(del, new object[] { a });
}
else
{
form.Controls.Add(a);
}
}
As I've said, the code compiles, but it doesn't create the PictureBox a on the Form1, when the MainMenuState is created. The thing is, if I don't use the delegate in the MainMenuState and just try to do something like form.Controls.Add(a), then I get a "cross-thread operation not valid" exception, and it doesn't even compile. That's why I used the delegate, but even now, it doesn't work.
Can someone please help me?
initialTimer = new System.Timers.Timer(2500);
That's part of the reason you're having trouble. The Elapsed event runs on a threadpool thread, forcing you to do the BeginInvoke song and dance. Use a System.Windows.Forms.Timer instead, its Tick event runs on the UI thread.
You'll also run into trouble with memory management, these classes need to implement IDisposable.
Oh my God, I just found the reason X_x
It was the fact that since the first pictureBox was covering the entire form, and the second one, which was created by the delegate, showed behind it! I just need to bring it to front!
Thank you guys, nonetheless, I probably wouldn't have come to that without you.
Edit: However, may I ask how to bring that control to the front? The a.BringToFront() function doesn't seem to work.
Instead of
form.Invoke(del, new object[]{a});
try:
form.Invoke(new ThreadStart(delegate
{
form.Controls.Add(a);
}
));