C# Game Menu Form ( Username, Start, Exit ) - c#

i'm new to the programming went through few tutorials and sample projects and then started to create my own text based adventure game with some UI.
So what i'd like to achieve with the beginning of my project is, when user launches exe, i'd like to greet them with a username input screen with Start and Exit buttons and then close that form, launch a new form which i'll put in the game's main interface.
So, when i click the "Start" Button, it'll read the username from the textbox, save it to a string, close the form and launch a new form with also using the name screen in the game's main interface.
My question is, How can i link the start button from the below code to a new Form, also closing the current AUJFM_Login form, which will also be able to read the string username.
I have tried few things but after a few attempts, i just left it with the button functions. It's not much but here is the basics of it:
The Greeting screen will be called AUJFM_Login, and the main interface will be called AUJFM.
namespace AUJFM
{
public partial class AUJFM_Login : Form
{
public AUJFM_Login()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
string UserName = nameBox.Text;
}
private void btnExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
}

You can try the code below for the “Start” button click. I added a method to check the user name as it seems like sending an invalid user name to the next form is simply a waste of time. You will have to adjust this method to check for the valid users. Hope this is what you are looking for.
private void btnStart_Click(object sender, EventArgs e) {
string userName = nameBox.Text;
if (ValidUserName(userName)) {
SecondForm nextForm = new SecondForm(userName);
nextForm.Show();
this.Hide();
} else {
// user name not valid
}
}
private bool ValidUserName(String userName) {
// logic to check if user name is valid
return true;
}
Then in the second form constructor, change the signature to accept the user name string.
public SecondForm(string userName) {
InitializeComponent();
textBox1.Text = userName;
}

If you have a form for the main window (Let's call it MainForm),
you can do:
MainForm mainForm = new MainForm();
mainForm.Show();
The main window would then appear.
To close the login form, you could do
this.Hide();
Since closing the form from which the application runs would close the entire application.

Related

Switching between Window Forms does not seem to work

Hey there StackOverflow community!
So I've been working on an application that checks if the user has entered valid credentials in a Login() form, then it switches over to an Intro_Sequence() form (where a .mp4 file is played in fullscreen mode) as a sort of aesthetic addition to the app. So far so good, no problems whatsoever.
The problem comes right after the Intro ends, where supposedly the application should switch over to a third form, called Main().
I have implemented a check whenever Windows Media Player (aka axWMPLib) changes its PlayState to see whether it has finished the playback.
If it has, then the Hide() event is called to conceal the current Form's window, then main.ShowDialog() should open the third form.
Afterwards, I call the Close() event to close the previous Form's window entirely.
Here is the code so far:
public partial class Intro_Sequence : Form
{
public static string Username;
public Intro_Sequence(string username)
{
InitializeComponent();
Username = username;
FormBorderStyle = FormBorderStyle.None;
Bounds = Screen.PrimaryScreen.Bounds;
TopMost = true;
intro.uiMode = "none";
intro.URL = AppDomain.CurrentDomain.BaseDirectory + "\\Intro.mp4";
intro.enableContextMenu = false;
DisableMouseClicks();
}
private void DisableMouseClicks()
{
if (this.Filter == null)
{
this.Filter = new MouseClickMessageFilter();
Application.AddMessageFilter(this.Filter);
}
}
private MouseClickMessageFilter Filter;
private const int LButtonDown = 0x201;
private const int LButtonUp = 0x202;
private const int LButtonDoubleClick = 0x203;
public class MouseClickMessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case LButtonDown:
case LButtonUp:
case LButtonDoubleClick:
return true;
}
return false;
}
}
private void Intro_Sequence_Load(object sender, EventArgs e)
{
}
private void intro_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if(intro.playState == WMPLib.WMPPlayState.wmppsMediaEnded)
{
Main main = new Main(Username);
this.Hide();
main.ShowDialog();
this.Close();
}
}
}
As you can see I have also added a filter to block clicks during playback, so as not to allow the user to pause it.
However, when I execute this code, it works perfectly fine until it finishes the video and then closes abruptly.
I tried putting breakpoints and everything seems to be fine.
It does call everything I tell it to call, yet the form doesn't even appear.
I have also tried several other alternatives, like not closing the Form at all, calling Show() instead of ShowDialog() and even not Hiding it at all.
It is as if it either freezes there or closes instantly without any sign of the Main form showing.
I also tried calling the Main() form from the Login() and it works perfectly from there.
I really don't know what is going on.
Any help would be appreciated.
How about something like this?
There are three forms. There's a Login form (in this case, it's just an empty form - you close it by clicking on the red X). It is popped up modally from within the Main form (while the main form is hidden).
There's a Splash screen on which your video is to play. I fake out the video by using await Task.Delay(4000); to get a pause. After the 4 second delay, I raise an event (equivalent to your media player event). What I do is show this modally from the main form. I put the event handler in this form; when the event is raised, I close the splash screen modal. The entire (non-designer) code for that form looks like (and, since there are no controls on this form, the designer code is pretty lean):
public partial class SplashScreen : Form
{
public event EventHandler SplashFinished;
public SplashScreen()
{
InitializeComponent();
this.SplashFinished += SplashScreen_SplashFinished;
}
private async void SplashScreen_Load(object sender, EventArgs e)
{
await Task.Delay(4000);
SplashFinished?.Invoke(this, new EventArgs());
}
private void SplashScreen_SplashFinished(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
Then there's the Main form. It gets fired up in the normal way from Program.cs:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
The only thing that I added to that form (from the out-of-the-box code) is:
private void Form1_Load(object sender, EventArgs e)
{
this.Hide();
var login = new LoginForm();
//should really check this, but for now
login.ShowDialog(this);
var splash = new SplashScreen();
splash.ShowDialog(this);
this.Show();
}
So, when the app starts, the user is shown the login form (the main form is hidden). He does what is needed to do (and the result is checked in the main form's Form1_Load handler.
If everything is cool, a new SplashScreen form is created and shown modally. When it pops up, the video starts (in this case, the video is simply an asynchronous timer). When the video ends, the SplashScreen handles the finished event, and uses it to close itself.
Once control returns to the main form, it displays itself.

bringing a windows form, form to the front without minimising other windows

Hi I'm relatively new to C# and completely new to windows form and basically trying to create a subliminal messaging program that at timed intervals will quickly display a message for it to then be hidden again.
I've managed to by looking through various other posts created another form that will pop up and then hide very quickly using
msgObject.Activate();
that brings the form to the front. However it is stopping me from being able to type when I'm working and I basically wanting to know if it is possible to make some kind of message or form appear at the front of all my other programs without it interrupting my current work or opening or closing of other windows and tasks if that makes sense. As currently it brings the form to the front of everything but will also stop me from being able to type etc.
I'm not sure if this is possible with my current method of using a form but if there is a way of achieving the result I'm after I'd be very grateful to find out
Thanks.
Here is more of my code to clarify
public partial class FormHomePage : Form
{
private bool startSubliminal = false;
msg msgObject = new msg();
List<string> subliminalMessages = new List<string>();
public FormHomePage()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
if (startSubliminal)
{
msgObject.Show();
msgObject.BringToFront();
msgObject.Activate();
}
}
private void button1_Click(object sender, EventArgs e)
{
subliminalMessages.Add(txtBox1.Text);
msgObject.LabelText = txtBox1.Text;
txtBox1.Text = string.Empty;
startSubliminal = true;
msgObject.Show();
msgObject.BringToFront();
}
private void timer2_Tick(object sender, EventArgs e)
{
msgObject.Hide();
}
}
How are you showing the second form (the message form) in the first place? You're probably using .Show() (right?), which will make the form "steal" the focus anyway. The same applies to .Activate() and .BringToFront().
Instead, what you can do is to show the message form and make sure it stays on top the current form, and then activate the current/main form once again.
Something like this should work:
var frm = new YourMsgForm();
frm.Show(this);
this.Activate();
Here's a demonstration:
Note that I used .Show(this) instead of .Show(), that's in order to set the current form as the Owner of the new one, that way we guarantee that the new form will stay on top of the current one. This is equivalent to calling frm.Owner = this; then frm.Show();.
Another way to make sure the form stays on top is by setting the TopMost property instead of the Owner property. However, doing so will make the new form on top of the other windows as well (not just your application).

Handling data between multiple Forms

I am working on a program that generates a PDF file. Before the final generation of the file, I want to give the user the option to edit a portion of the file (The title of the graph that is about to be created). I want this to show up in a new form when the user clicks a button to export the PDF. Here is an outline of what I am trying to do...
private void button4_Click(object sender, EventArgs e) // Test PDF Code!
{
Form2 NewPDF = new Form2(chart3.Titles[chart3.Titles.IndexOf("Header")].Text.ToString().Substring(0, chart3.Titles[chart3.Titles.IndexOf("Header")].Text.ToString().Length - 4));
NewPDF.Show();
if (NewPDF.Selected == true)
{
// Create PDF, open save file dialog, etc
}
}
And here is the Form that is being opened by this button click...
public partial class Form2 : Form
{
public bool Selected
{
get;
set;
}
public String GraphName
{
get;
set;
}
public Form2(String FileName)
{
InitializeComponent();
textBox1.Text = FileName;
GraphName = FileName;
Selected = false;
}
public void button1_Click(object sender, EventArgs e)
{
GraphName = textBox1.Text;
this.Selected = true; // After the button is selected I want the code written above to continue execution, however it does not!
}
}
As of now, when I click on the button in Form2, nothing happens, there is something about the communication between the two Forms that I am not understanding!
You should change your Form2.GraphName like below
public String GraphName
{
get { return textBox1.Text }
}
then change your new Form2 creation like below, test it since I haven't run this through VS, but should work :)
private void button4_Click(object sender, EventArgs e) // Test PDF Code!
{
// why on earth were you doing .Text.ToString()? it's already string...
Form2 NewPDF = new Form2(chart3.Titles[chart3.Titles.IndexOf("Header")].Text.Substring(0, chart3.Titles[chart3.Titles.IndexOf("Header")].Text.Length - 4));
// show as a dialog form, so it will wait for it to exit, and set this form as parent
NewPDF.ShowDialog(this);
if (NewPDF.Selected == true)
{
// get the name from the other form
string fileName = NewPDF.GraphName;
// Create PDF, open save file dialog, etc
}
}
The answer to your problem is quite simple.
NewPDF.Show();
Show() does not pause execution of the calling form. Therefore, the check underneath that that verifies the Selected property if true will never execute properly, since that check is reached and verified just as the form starts appearing. ShowDialog() does pause execution and waits for the called form to close.
That aside; I would recommend one of two other ways to communicate between forms;
Use a global variable. Declare a variable holding the graph's name somewhere in a public module. Call the dialog that asks the user to input a name with ShowDialog(), since that pauses execution of the calling form until the called form returns a result.
if(Form.ShowDialog() == DialogResult.OK) {
// Save pdf, using title in global variable
}
Make sure to set the DialogResult in the called form before Close()-ing it.
Pass an instance variable of the calling form to the called name-input form to the constructor and save it. That way, if you expose the graph name property as a public property, you should be able to access it from the called form in the code that closes the form, which is your:
public void button1_Click(object sender, EventArgs e)
{
callingFormInstance.GraphNameProperty = textBox1.Text;
Close();
}
Hope that helps. Cheers!

ObjectDisposedException when Multiple Forms Are Open

My C# Winform application encounters the situation where it cannot access a disposed object. The disposed object is a form (frmQuiz) that is opened from a button on the login form.
The Situation:
My application typically has two or three forms open at the same time. The Program.cs file runs form frmLoginBackground, which is just a semi-transparent background that covers the computer screen. The load event for this form opens the second form, frmLogin, which includes a button that opens frmQuiz, which is a simple form with a few math questions on it.
The code in frmLogin that opens frmQuiz looks like this:
private void btnTakeQuizNow_Click(object sender, EventArgs e)
{
frmQuiz quiz = new frmQuiz();
quiz.TakeQuizNow("take_quiz_now", Convert.ToInt32(comboQuizMeNow.SelectedValue)); //Pass the form a quiz id number.
quiz.Show();
}
When frmQuiz opens both it and frmLogin are open and accessible.
The frmLogin also contains a password control that opens the administration form by first opening frmSplash, which is a "Please Wait..." splash form based on a timer. The timer Tick event launches frmAdmin, which is the administration form. The code in frmLogin looks like this:
private void btnPasswordSubmit_Click(object sender, EventArgs e)
{
//Password verification code snipped.
frmSplash objSplash = new frmSplash();
objSplash.Show();
//this.Hide();
this.Close();
}
And the code in frmSplash looks like this:
private void timer1_Tick(object sender, EventArgs e)
{
frmAdmin objfrmAdmin = new frmAdmin ();
objfrmAdmin.Show();
this.Close();
}
When frmAdmin opens then frmLogin is no longer accessible; however, frmAdmin contains a 'Return to Login Screen' button with code like this:
private void btnReturnToLogin_Click(object sender, EventArgs e)
{
exitWarnings("return_to_login");
}
private void exitWarnings(string action)
{
//Warning message code snipped.
if (action == "return_to_login")
{
frmLogin objLogin = new frmLogin();
objLogin.Show();
}
}
The frmLoginBackground remains open until the application exits.
The Problem:
Everything works fine when frmLogin first opens and the button is clicked to open frmQuiz. The quiz form opens a runs fine. However, after logging into the administration form (which closes or hides the login form) and then clicking the 'Return to Login Screen' link, then, after frmLogin reappears, the object disposed exception occurs when clicking the button to open frmQuiz. Visual Studio highlights in yellow the "quiz.Show();" line of code. The exception occurs regardless of weather I use "this.Close();" or "this.Hide();" in the btnPasswordSubmit_Click event.
Can anyone suggest a solution that allows me to open frmQuiz after returning to frmLogin from frmAdmin.
Cheers, Frederick
Since you create a new instance for quizz just before the quizz.Show() it cannot be quizz itself that throws the exception.
Take a good look at the constructor and FormCreate event of frmQuiz. It looks like that is where the dead horse is being kicked.

Create a Login Form

I have a form that I want to provide some security on, but up to this point I've only created one form that does all of my work. I want to create a new form that pops up in front of my main form right when the application launches. Then validates the password entered against a MySQL database. I have all of the MySQL stuff down, but wondering how to make another form pop up in front of my main form which disables the main form, waits for the password form to validate, then disappears once the form is validated and lets the user perform their work. I'll also need to transfer the authenticated user's info back to my main form.
You can create a new form and then use the ShowDialog function. If you show the form from your main form it will be displayed in a modal fashion.
Create this in a login style and close the form if the user is authenticated or show an error if the username and password are incorrect.
From MSDN:
public void ShowMyDialogBox()
{
Form2 testDialog = new Form2();
// Show testDialog as a modal dialog and determine if DialogResult = OK.
if (testDialog.ShowDialog(this) == DialogResult.OK)
{
// Read the contents of testDialog's TextBox.
this.txtResult.Text = testDialog.TextBox1.Text;
}
else
{
this.txtResult.Text = "Cancelled";
}
testDialog.Dispose();
}
I prefer to use ApplicationContext for this kind of log on form <--> shell form switching behavior.
Your main method:
public static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyFancyContext());
}
And an implementation for MyFancyContext:
public class MyFancyContext : ApplicationContext
{
private LogOnForm logOnForm;
private ShellForm shellForm;
public MyFancyContext()
{
this.logOnForm = new LogOnForm();
this.MainForm = this.logOnForm;
}
protected override void OnMainFormClosed(object sender, EventArgs e)
{
if (this.MainForm == this.logOnForm
&& this.logOnForm.DialogResult == DialogResult.OK)
{
// Assume the log on form validated credentials
this.shellForm = new ShellForm();
this.MainForm = this.shellForm;
this.MainForm.Show();
}
else
{
// No substitution, so context will stop and app will close
base.OnMainFormClosed(sender, e);
}
}
}
The MainForm is the form that is currently receiving messages.
The advantage of this type of setup is that if you want to do things like hide the shell form after some idle timeout and redisplay the log on form, we have one class where this functionality takes place.
You can call showdialog(loginform) from the main form's constructor and return true if successful or change the startup for to the login form before the main form loads. Show dialog is modal.

Categories