-1

So I have a form which creates another form and calls it using Form.ShowDialog(), however at some point during the run the new form disappears. I can tell it is still running as I set a timer which, when finished, shows a message box. The message box still shows after the allocated time but the form is no longer visible.

To call the form I have used this code:

Player currentUser = new Player(); //Player is a class I've created

private void Game(int PlayerCount)
{
    Current.Hide();
    for (int i = 0; i < PlayerCount; i++)
    {
        currentUser = GloVar.CurrentPlayers[i];
        CashBuilder cb = new CashBuilder(currentUser);
        cb.ShowDialog();
    }
 }

The form 'cb' shows and I can interact with it until I press a button. There is a method in the form to check is an answer (there are four buttons, one is correct) is correct.

private void IsCorrect(int i)
{
    if (CorrectAnswer == i) 
    {
        lblFeedback.Text = "Correct."; 
        AnsweredCorrectly++; //add to the answered correctly list
        Timer2.Start(); //this timer is used to increment a value of money, it does not call on anything else and lasts 1.5 seconds.
    }
    else
    {
        lblFeedback.Text = correctAnswer;
    }
    QuestionsAnswered++; //add to questions answered
    Generate_Question(); //bring a new question
}

The form SEEMS (I cannot clarify 100%) to stay visible if answers alternate between correct and incorrect. However if I answer correct then correct (or incorrect and incorrect) the form disappears.

I have a method for closing the form but this is not touched until the timer is up.

I have searched for about a week now to find a solution, tried multiple threads (got the threads to work but still encountered this problem), and I cannot think on anything else.


EDIT

This is the entire source code for CashBuilder

public partial class CashBuilder : Form
{
    public static CashBuilder current;
    private static int QuestionID; //Identifies the loctaion of the question
    private static int CorrectAnswer; //holds the place of the correct answer
    private static int CountDown = 60; //hold a count of 60, one foe earch second. This adds to a minute.
    private static int QuestionsAnswered = 0; //how many questions have been answered
    private static int AnsweredCorrectly = 0; //out of those how many correctly
    private static int CashWon = 0; //chash won, £1000 per correct answer
    private static int Wait = 10; //holds ten ticks for the second timer
    private static Timer Timer1; //One minute, used to time the Cash Builder round
    private static Timer Timer2; //One fifth of a second, used for adding £1000 to cash wont every correct answer. Looks like a gameshow
    private static Player User;



    public CashBuilder(Player user)
    {
        InitializeComponent();
        current = this;
        User = user;
        pctAvatar.Image = Image.FromFile(GloVar.Avatar(User.ID));
        Generate_Question();
        btnCash.Text = "£0000"; //sets initial Cash Won lable to nothing
        Timer1 = new Timer(); //Creates a new timer
        Timer1.Tick += new EventHandler(timer_Tick);
        Timer1.Interval = 1000; //1 second
        Timer1.Start(); //Starts timer, this is the begining of the round
        btnTime.Text = "Time Left: " + CountDown.ToString();
        Timer2 = new Timer();
        Timer2.Tick += new EventHandler(Timer2_Tick);
        Timer2.Interval = 20; //0.02 seconds
    }

    void timer_Tick(object sender, EventArgs e)
    {
        CountDown--; //takes one away from time left
        btnTime.Text = "Time Left: " + CountDown.ToString(); //shows the user
        if (CountDown == 0) //if theres no time left
        {
            Timer1.Stop(); //stop timer
            Enough();
        }
    }

    private void Timer2_Tick(object sender, EventArgs e)
    {
        Wait--;
        CashWon += 100; //adds 100 to the cash won. Ticks ten times therefore end will be +1000
        btnCash.Text = "£" + CashWon.ToString(); //shows user
        if (Wait == 0)
        {
            Timer2.Stop();
            Wait = 10; //resets the tick count for a later question
        }
    }

    private void Generate_Question()
    {
        Random rnd = new Random();  //used to generate a random value (only integers in this case) within parameters given

        do
        {
            QuestionID = rnd.Next(82); //there are only 82 questions, references as a zero-index. Cannot generate 82.
        } while (GloVar.QuestionsAsked.Contains(QuestionID)); //continue loop if question has already been asked
        GloVar.QuestionsAsked.Add(QuestionID); //if question hasnt been asked, add it to the list of asked questions
        btnQuestion.Text = GloVar.Questions[(QuestionID * 6) + 1]; //show the question on the form


        List<int> AnswerPlacement = new List<int>(); //used to see what answers have already been placed
        int[] Answers = new int[4]; //holds placevalues for the answers
        for (int i = 0; i < 4; i++)
        {
            do
            {
                Answers[i] = rnd.Next(4); //generates random placevalue
            } while (AnswerPlacement.Contains(Answers[i])); //while the placevalue entered is already used
            AnswerPlacement.Add(Answers[i]); //show the placevalue has been used
            if (Answers[i] == 0)
            {
                CorrectAnswer = i;
            }
        }

        btnAns1.Text = GloVar.Questions[(QuestionID * 6) + Answers[0] + 2]; //giving buttons their answers
        btnAns2.Text = GloVar.Questions[(QuestionID * 6) + Answers[1] + 2];
        btnAns3.Text = GloVar.Questions[(QuestionID * 6) + Answers[2] + 2];
        btnAns4.Text = GloVar.Questions[(QuestionID * 6) + Answers[3] + 2];

        AnswerPlacement.Clear();
        lblFeedback.Text = "";
    }

    private void btnAns1_Click(object sender, EventArgs e)
    {
        IsCorrect(0);
    }

    private void btnAns2_Click(object sender, EventArgs e)
    {
        IsCorrect(1);
    }

    private void btnAns3_Click(object sender, EventArgs e)
    {
        IsCorrect(2);
    }

    private void btnAns4_Click(object sender, EventArgs e)
    {
        IsCorrect(3);
    }

    private void btnPass_Click(object sender, EventArgs e)
    {
        Generate_Question();
        QuestionsAnswered++;
    }

    private void IsCorrect(int i)
    {
        if (CorrectAnswer == i) //if the place of the button value given and the correct answer are the same
        {
            lblFeedback.Text = "Correct."; //show the user their awesomeness
            AnsweredCorrectly++; //add to the answered correctly list
            Timer2.Start(); //this timer adds the newly gained £1000
        }
        else
        {
            lblFeedback.Text = Convert.ToString(SSDTheChase.GloVar.Questions[(QuestionID * 6) + 2]); //show their failure
        }
        QuestionsAnswered++; //add to questions answered
        Generate_Question(); //bring a new question
    }

    private void Enough()
    {
        btnAns1.Text = ""; //set all buttons and lables used for a question equal to zero
        btnAns2.Text = "";
        btnAns3.Text = "";
        btnAns4.Text = "";
        btnQuestion.Text = "";
        CountDown = 60; //resetting time
        MessageBox.Show("Time's up." + Environment.NewLine + QuestionsAnswered + " Questions Answered." + Environment.NewLine + AnsweredCorrectly + " Answered Correctly.");
        User.CashGame = CashWon; //setting the users cash won this game.

        current.Close(); //close the form.
    }
}
  • Also are there any form closing in `Generate_Question();` ? – Markiian Benovskyi Feb 20 '18 at 11:20
  • 6
    Add an event handler for the FormClosing event and set a breakpoint on it. The stack trace ought to show you why it decided to close. Current.Hide() is a candidate btw, but you posted code that nobody could possibly test and we do avoid trying to guess at it. – Hans Passant Feb 20 '18 at 11:25
  • @MarkBenovsky the method Generate_Question() is now included, in the course code – Ryan O'Loughlin Feb 20 '18 at 11:33
  • @HansPassant the form doesn't close, it just seems to lose visibility.. Sorry about the code, first time posting here. – Ryan O'Loughlin Feb 20 '18 at 11:35
  • You probably wanted to achieve a singleton with that `static current`? A singleton is created in other way, search the web for it. If not, just remove that, your class inherits `Form` so you can just call `Close()` without any references, if your form losses visibility, try to debug your code and find out after what part of code it is hidden – Markiian Benovskyi Feb 20 '18 at 11:37
  • @MarkBenovsky The form looses visibility after the buttons dedicated to answers (i.e. btnAns1_Click() or btnPass_click() )have run their methods. So say I click btnAns3, the method is called, the answer is checked, a new question is generated and then the method returns to btnAns3_Click(), the method ends and then the form looses visibility – Ryan O'Loughlin Feb 20 '18 at 12:09
  • @mjwills Removed all occurrences of current on all forms and re-coded them for either this. or left 'this' out where unneeded. This didn't change anything in the build however – Ryan O'Loughlin Feb 20 '18 at 12:17
  • @BugFinder I used 'current' when calling a form from another form as I personally found it nicer but ultimately it doesn't matter – Ryan O'Loughlin Feb 20 '18 at 12:18
  • @mjwills the Close() method is not being reached when the form disappears, but when the timer stops (the timer continues for its full 60 seconds when the form goes away) then the Close() method is reached. – Ryan O'Loughlin Feb 20 '18 at 12:25
  • @mjwills would you suggest sharing the entire solution or just the two forms being used, the global variables and the class Player? – Ryan O'Loughlin Feb 20 '18 at 12:50
  • What did [mcve] suggest? – mjwills Feb 20 '18 at 20:03

1 Answers1

0

Partial answer as I can't comment but is there a reason you're calling cb.ShowDialog() rather than cb.Show()? The behaviour you're describing sounds like that of a message box (see here in the remarks section)

My first thoughts were that when you give two consecutive correct (or incorrect) answers that it's acting like a message box and returning cb.DialogResult.Yes(or .No). Message boxes don't just close like forms, they make themselves hidden until .Dispose() is called.

Rowie
  • 148
  • 9