Moving Between One Form to Another - C# - c#

I am currently creating a video game and coding the movement in a house between upstairs and downstairs. I'm using PictureBoxes in combination with an IntersectWith event to transition between forms.
Transition Code to go Upstairs:
if(picPlayer.Bounds.IntersectsWith(picUpstairsTransition.Bounds))
{
MapFrmHouseUpstairs upstairs = new MapFrmHouseUpstairs();
this.Hide();
upstairs.ShowDialog();
}
Transition Code to Go Back Downstairs:
if(picPlayer.Bounds.IntersectsWith(picGoDownstairs.Bounds))
{
MapFrmHouse goDownstairs = new MapFrmHouse();
this.Hide();
goDownstairs.ShowDialog();
picPlayer.Location = new Point(497, 103);
}
The issue I have is that when the player enters the house, he starts at the front. When he tries to come back from upstairs, the character is moved back to the front instead of the base of the stairs. Is there anyway I could create a method within MapFrmHouse such as:
public void fromDownstairs{picPlayer.Location = new Point(x,y);}
And call it when going downstairs?

First of all you'd better use a game engine to design games like Unity which is much easier and more fun. This might be a learning task for you though which I don't blame :)
You can send information between forms in Windows Forms in many ways, two of which seems to fulfill your needs:
Using a higher level modifier for objects
Initializing values in constructors
To do the first you set the modifier property of the picture box called picPlayer in your MapFrmHouse class from private to public then you can do exactly what you mentioned:
if(picPlayer.Bounds.IntersectsWith(picGoDownstairs.Bounds))
{
MapFrmHouse goDownstairs = new MapFrmHouse()
{
picPlayer.Location = new Point(x,y);
};
this.Hide();
goDownstairs.ShowDialog();
}
For the second method you should create an overload constructor in your MapFrmHouse and accept a Point value in it and then set it your value like this:
public MapFrmHouse(Point p)
{
InitializeComponent();
picPlayer.Location = p;
}
And then use it in your code like this:
if(picPlayer.Bounds.IntersectsWith(picGoDownstairs.Bounds))
{
MapFrmHouse goDownstairs = new MapFrmHouse(new Point(x,y));
this.Hide();
goDownstairs.ShowDialog();
}
I hope this helps :)

Related

Accessing form controls from a different class

I am creating a windows form application using c#. My form has labels, list-boxes and buttons, all of which need to be edited. They are edited from a different class, and further will need the values in the labels to perform other logic.
My problem is accessing these controls from other classes. I tried making an instance of the form and using it like this:
Form frm = new Form();
myVar = frm.lblMylabel.Text;
However, using a breakpoint, I followed the code, and it loops between the above instance being created, and the start of the Form code, which calls the class again where the instance was created.
I have tried to find the answer online, however they don't seem applicable to what I am trying to do, and whilst I am unsure how to do it, they appear to be overly complex.
So, my question it: is there a relatively simple way to be able to access values and edit values from controls in a form from another class?
Thanks in advance.
EDIT - Breakpoint starts at Point 3, '=new Form();'.
Loops to Point 1.
Point 2 calls GamePlay().
Reaches Point 3 and loop restarts.
public partial class frmGame : Form //Point 1
{
public frmGame()
{
InitializeComponent();
Game.GamePlay(); //Point 2
}
class Game{
public static void GamePlay()
{
frmGame form = new frmGame(); //Point 3
form.lstPrevious1.Items.Add("Item Number");
}
}
Your problem has nothing to do with accessing properties of a different class, you are just producing a recursive loop:
At Point 3, within the method GamePlay you create a new instance of frmGame. When creating an instance (an object), its constructor is called. In this case, your constructor is the method public frmGame().
Within this constructor, you now call GamePlay (Point 2), which, as we saw from before, again creates a new instance of frmGame (Point 3 again), also again calling its constructor (Point 1).
At this point, you have already two forms created (although not shown yet).
Very soon you will receive a stack overflow.
One possible solution: Move the line creating your instance into a different method that is guaranteed to be called only once at program start:
public partial class frmGame : Form //Point 1
{
public frmGame()
{
InitializeComponent();
Game.GamePlay(); //Point 2
}
}
class Game{
public static void GameStart(){
frmGame form = new frmGame(); //Point 3
}
public static void GamePlay()
{
form.lstPrevious1.Items.Add("Item Number");
}
}

How make so that by pressing the button in one form created object and passed to the other?

I creating a simple app working with maps on c#, using GMap.NET control for it. So, my question is: I want to make a polygons, polylines and markers in one form using another. My code relating to it is:
First form (MapModule):
GMapOverlay polygonOverlay = new GMapOverlay("polygons");
GMapOverlay markersOverlay = new GMapOverlay("markers");
GMapOverlay polylineOverlay = new GMapOverlay("polylines");
Second form (NewFile):
public MapModule _MapModule;
public Newfile(MapModule MapModule)
{
InitializeComponent();
_MapModule = MapModule;
}
private void addpolygon_Click(object sender, EventArgs e)
{
GMapPolygon polygon = new GMapPolygon(points, "What you need");
_MapModule.polylineOverlay.Polygons.Add(polygon);
}
The output is:
'GoogleMaps.MapModule.polylineOverlay' is inaccessible due to its
protection level
I think, it must be very simple, but I am completely new in programming.
.
The first quick and dirty option is to make that object public:
public GMapOverlay polylineOverlay = new GMapOverlay("polylines");
But that's not a good practice, as this way you are breaking the encapsulation principle and you lose control about what happens with your object. If that variable at some point has garbage, it will be harder for you to know why that occurred.
An alternative is to create a getter, so the reference can be accessed publicly although not modified.
private GMapOverlay polylineOverlay = new GMapOverlay("polylines");
public GMapOverlay PolylineOverlay
{
get
{
return this.polylineOverlay;
}
}
The containing class can access both, but other classes can access only the public property.
Also, if you don't want this object to be created until it's first used, you could do this instead:
private GMapOverlay polylineOverlay;
public GMapOverlay PolylineOverlay
{
get
{
if (this.polylineOverlay == null)
this.polylineOverlay = new GMapOverlay("polylines")
return this.polylineOverlay;
}
}
Although in this case, you should use the public property inside your class, or instantiate it somewhere else.

Single reusable function to open a single instance of form

I am trying to create a reusable function that can open a single instance of form. Means if a form is not already open it should create and show the new form and if already open it should bring the existing form to front.
I was using the following function,
if (Application.OpenForms["FPSStorageDemo"] == null)
{
FPSStorageDemo fp = new FPSStorageDemo();
fp.Name = "FPSStorageDemo";
fp.Show();
}
else
{
((FPSStorageDemo)Application.OpenForms["FPSStorageDemo"]).BringToFront();
}
But I have to write this code again and again whereever I have to open a form. But I need a single reusable function that can do this job.
I wrote a function like,
void OpenSingleInstanceForm(Type TypeOfControlToOpen)
{
bool IsFormOpen = false;
foreach (Form fm in Application.OpenForms)
{
if (fm.GetType() == TypeOfControlToOpen)
{
IsFormOpen = true;
fm.BringToFront();
break;
}
}
if (!IsFormOpen)
{
Object obj = Activator.CreateInstance(TypeOfControlToOpen);
//obj.Show(); //Here is the problem
}
}
But at the end I don't know how to show the new form instance. Can anybody suggest how to do it? Is this wrong or there is another way to do this?
Thanks in advance.
public static class FormUtility
{
public static FormType GetInstance<FormType>() where FormType : Form, new()
{
FormType output = Application.OpenForms.OfType<FormType>().FirstOrDefault();
if(output == null)
{
output = new FormType();
}
//you could add the show/bring to front here if you wanted to, or have the more general method
//that just gives a form that you can do whatever you want with (or have one of each).
return output;
}
}
//elsewhere
FormUtility.GetInstance<Form1>.BringToFront();
I'd also like to take the time to mention that while having methods like this are quick and easy to use, in most cases they are not good design. It leads you to the practice of just accessing forms globally rather than ensuring that when forms need to communicate with each other they do so by exposing the appropriate information through the appropriate scope. It makes programs easier to maintain, understand, extend, increases reusability, etc. If you have trouble determining how best for two or more forms to communicate without resorting to public static references to your forms (which is exactly what Application.OpenForms is) then you should feel free to post that question here for us to help you solve.
You are looking for Singleton
Check this Implementing Singleton in C#

How to run a C# winform in an XNA C# project

I am trying to use the PDFsharp library in an XNA game. The example code I am trying to get to work is:
static void Main()
{
Renderer renderer = new Renderer();
PreviewForm form = new PreviewForm();
form.RenderEvent = new PagePreview.RenderEvent(renderer.Render);
Application.Run(form);
}
But I don't know how to get this to run in XNA.
Is it possible to pass the graphics that are passed to the winform to the XNA graphics engine instead?
update 2
It appears that the original links to MSDN have been broken, I can't seem to find them on MSDN anymore, if someone does, please update the post. In the mean time you may want to check out this codeproject article -- http://www.codeproject.com/Articles/21330/Easy-Rendering-with-XNA-Inside-a-Windows-Form
update after a quick check, looks like the first link at (See also: XNA and WinForms) is the same one I found.
I recommend you look into mixing winforms and XNA, try this: http://create.msdn.com/en-US/education/catalog/sample/winforms_series_1
The First thing you need to do is to create the login form.
in this form create the fields you need as public properties
public string userName {get;set;}
public string password {get;set;}
in the login form you need to write the user info to those properties:
private void btnOk_Click(object sender,EventArgs e)
{
this.userName = txtName.Text;
this.password = txtPass.Text;
this.Close();
}
then, in the game (in the part you need) write something like this:
using (var form = new frmLogin())
{
var result = form.ShowDialog();
if (result == DialogResult.OK)
{
string user = form.userName;
string pass = form.password;
}
}
But as an FYI - winforms don't look so good in XNA
Hope it helps

C# WinForms: Waiting for a button press inside an infinite loop

I'm making a simple Guess-The-Number game with a GUI. I need to wait on a loop waiting for the user to input a number in a text box and press "OK". How do I wait for an event inside a loop?
Note: I don't want message boxes. This is done in the main window, hence the need to wait for input.
EDIT: I should have explained myself better. I know that there's a loop inside the GUI. What I want is another loop inside a method. Maybe there's a better way to do this. I could code stuff inside the button's event handler, now that I think about it. Although I'd need global variables. Whataver, I'll think about it, but I hope my question is clearer now.
EDIT 2: Sorry that my question wasn't clear and the edit didn't do much help. First of all, the code is too big to be posted here. I'd probably have to post a screenshot of the GUI, so it wouldn't be of much use. Basically, I have two fields, "Max number" and "Number of allowed guesses". The user enters these two and clicks "Play". A new panel becomes available, with a text box and a "Guess" button. The user enters a guess, and the program checks to see if it's correct.
The purpose of the second infinite loop is to avoid global variables. See, each time the user clicks "Play", the game has to generate a new random number as the correct guess. If everything is done inside a method, no problem. But if the "Guess" button's event handler is called multiple times, the number has to be stored as an instance variable of the Form. Sure, it's not big deal, but I think the number should be a property of the method directing the current game, not of the Form.
I'd also have to keep track of the remaining number of guesses outside of the method. Again, it's no big deal. I just want to avoid globals if I can.
Again, I'm sorry that my question wasn't too clear. I'm kind of tired, and I didn't feel like writing too much. If this still isn't clear, then don't bother. I'll think of something.
C# automatically loops infinitely waiting for events until your form is closed. You just need to respond to the button click event.
Jason Down's suggestion is wise, create a new GuessingGame class and add it to your project. I know you're worried about "global variables" (which everyone is taught in school never to use unless you absolutely have to), but think about your design specifications for a minute.
But if the "Guess" button's event handler is called multiple times, the number has to be stored as an instance variable of the Form. Sure, it's not big deal, but I think the number should be a property of the method directing the current game, not of the Form.
As an alternative, store an instance of your GuessingGame class in the form. This is not a global variable! You said so yourself, the point of the game is keep track of the guesses and generate new numbers to guess every time "Play" is clicked. If you store an instance of the game in the form then open another form (e.g. a Help or About box), then the game's instance would not be available (thus, not global).
The GuessingGame object is going to look something like:
public class GuessingGame
{
private static Random _RNG = new Random();
private bool _GameRunning;
private bool _GameWon;
private int _Number;
private int _GuessesRemaining;
public int GuessesRemaining
{
get { return _GuessesRemaining; }
}
public bool GameEnded
{
get { return !_GameRunning; }
}
public bool GameWon
{
get { return _GameWon; }
}
public GuessingGame()
{
_GameRunning = false;
_GameWon = false;
}
public void StartNewGame(int numberOfGuesses, int max)
{
if (max <= 0)
throw new ArgumentOutOfRangeException("max", "Must be > 0");
if (max == int.MaxValue)
_Number = _RNG.Next();
else
_Number = _RNG.Next(0, max + 1);
_GuessesRemaining = numberOfGuesses;
_GameRunning = true;
}
public bool MakeGuess(int guess)
{
if (_GameRunning)
{
_GuessesRemaining--;
if (_GuessesRemaining <= 0)
{
_GameRunning = false;
_GameWon = false;
return false;
}
if (guess == _Number)
{
_GameWon = true;
return true;
}
else
{
return false;
}
}
else
{
throw new Exception("The game is not running. Call StartNewGame() before making a guess.");
}
}
}
This way, all the data related to the game is encapsulated within the class. Hooking up the events is easy in the codebehind of the form:
GuessingGame game = new GuessingGame();
private void btnPlay_Click(object sender, EventArgs e)
{
int numberOfGuesses = Convert.ToInt32(txtNumberOfGuesses.Text);
int max = Convert.ToInt32(txtMax.Text);
game.StartNewGame(numberOfGuesses, max);
}
private void btnGuess_Click(object sender, EventArgs e)
{
int guess = Convert.ToInt32(txtGuess.Text);
bool correct = game.MakeGuess(guess);
if (correct)
lblWin.Visible = true;
if (game.GameEnded)
{
// disable guess button, show loss label
}
}
You should probably look for a book to actually learn windows programming.
The very basics:
1) There is already an infinite loop deep down in the windows code somewhere. Any windows program is constantly looping and scanning for input.
2) Once input is found, this loop fires off an Event.
3) Your mission, should you choose to accept it, is to write event handlers to handle those events.
you are most likely doing it wrong as it has already been pointed out, but you can use this
Application.DoEvents();
to process events when you are on an actual loop
to do it the right way
- don't use a loop
- use an edit box for the input, then a button
- implement the button onclick event
Yes, and What if I am waiting for Speech events, it could happen anytime event when a function is running, I need to handle that without recursively call a function

Categories

Resources