Hey mates, I hope you read my post about showing progressbar window before loading our game (http://haxpor.org/2010/03/progressbar-window-before-loading-your-game/). This post is going to fix the issue of freezing phenomenon !!
I just relook again and with the inspiration from my mates, winalden (you can reach him at http://theblogfor.net) which suggests me about the separating of UI thread and worker thread, although his suggestion is not related much in this post but he helps me realize something important when setting/modifying the property through UI Controls.
The root of problem is the previous code doesn’t process all events inside the checking loop. So key, and mouse event are not going to be processed. That freezing is because when moving the form we generate the mouse event which won’t be processed in window form.
The solution is that we will explicitly and manually call the method to process out all the queued messages attached to this progressbar window form.
See that piece of code here.
... // delay for 100 ms Thread.Sleep(100); // then process all the left message in the queue of this form Application.DoEvents(); ...
Every time we have delayed then we will process all the waiting message manually. Application.DoEvents() will do the trick.
Let’s see the full source code.
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; using System.Threading; using RealKo.Framework; namespace TestRealKoEngine { public partial class LoadingMessageForm : Form { private float preCheckPoint = 0; private float checkPoint = 0; private int totalNumberOfCheckPoints = 0; private bool isBegined = false; private bool isLoading = true; private bool isMakeIllusion = false; Game1 owner; /// <summary> /// Gets or sets whether the progressbar of this form will make an illusion of loading to users. /// </summary> /// <remarks>This property must be set before invoking BeginLoading() method. Default is false.</remarks> public bool IsMakeIllusion { get { return isMakeIllusion; } set { isMakeIllusion = value; } } /// <summary> /// Create a loading message form. /// </summary> /// <param name="totalNumberOfCheckPoints">Total number of check points</param> public LoadingMessageForm(int totalNumberOfCheckPoints, Game1 owner) { // set the game owner this.owner = owner; // set the number of check points this.totalNumberOfCheckPoints = totalNumberOfCheckPoints; InitializeComponent(); // set the minimum, and maximum point of progress bar progressBar.Minimum = 0; progressBar.Maximum = 100; } /// <summary> /// Begin the loading process. /// </summary> public void BeginLoading() { // this thread can be start only once if (!isBegined) { isBegined = true; // create a separate thread to handle the checking of check points process Thread thread = new Thread(new ThreadStart(this.LoadingCheck)); thread.IsBackground = true; thread.Start(); } } /// <summary> /// This is the thread worker function. /// </summary> private void LoadingCheck() { //show the window (this could be furthur fixed to allow user to move the windows) this.Show(); while (isLoading) { // check for our check points (this means the main program has triggers this form to update the check point) if (preCheckPoint != checkPoint) { int point = (int)Math.Ceiling(checkPoint / totalNumberOfCheckPoints * 100.0f); if (point > progressBar.Value) { // update to progress bar progressBar.Value = point; // update the message of label this.label.Text = "Loading, please wait... [" + progressBar.Value + " %]"; } } // self increment to make an illusion to users seeing its progress // increment it until not more than 98 percent then stop // (do this only when we want to make illusion to users) if (isMakeIllusion && progressBar.Value < 98) { progressBar.Value += 1; // update the message of label this.label.Text = "Loading, please wait... [" + progressBar.Value + " %]"; } // check if we finish loading else if (progressBar.Value >= progressBar.Maximum) { isLoading = false; // update the message of label this.label.Text = "Loading completed"; } // delay for 100 ms Thread.Sleep(100); // then process all the left message in the queue of this form Application.DoEvents(); } this.Close(); } /// <summary> /// Update the check points. /// </summary> public void IncrementCheckPoint() { preCheckPoint = checkPoint; checkPoint++; } private void cancelButton_Click(object sender, EventArgs e) { // quit the game (delay in time as we didn't check in the main code) // note that we directly call the exit code from our Game class. owner.Exit(); this.Close(); } } }
Note here from the code above that, I use that piece of code integrating and working with my RealKo Engine, to just show the loading progress while loading the huge resource, and that form also allows users to click on cancel button to quit the program immediately thus this will let not user to wait until the program is fully loaded and quit later on by hitting escape button. One feature is also added into this class is that now users can choose to enable the “illusion mode” or not, if that mode is turned on then the progress will be like the old one (always running by 1 every interval), but if it’s turned off then it will show the actual progress of loading, but if your check points set with this form is not high enough then the sudden changes of progress cannot be avoided.
The following line of code is to turn on the “illusion mode”.
... // loading form loadingForm = new LoadingMessageForm(3, this); loadingForm.IsMakeIllusion = true; loadingForm.BeginLoading(); ...
IsMakeIllusion must be set before calling BeginLoading() method.
Modify and adapt from the code above, and create your form adhering to your desire then you could have a flexible progressbar window form.
Download: Progressbar-fixed source code


Like










