Click here to Skip to main content
15,867,308 members
Articles / Desktop Programming / Windows Forms

Splash and Login Forms (Problems and Solutions)

Rate me:
Please Sign up or sign in to vote.
4.50/5 (22 votes)
10 Apr 2023CPOL4 min read 87.9K   4.5K   90   1
The more perfect description of the creation the Splash and the Login forms with full source code

LoginTest_v1/LoginTestLoginF.png

LoginTest_v1/LoginTestSplashF.png


"An investment in knowledge always pays the best interest."
Benjamin Franklin

Introduction

In this article, I would like to discuss problems the Splash \ Login Forms creating. I often stumble on the questions of the novice programmers about the Splash \ Login Forms on the forums. In my opinion, the answers on these questions often don't give a comprehensive information. So I decided to write the article. It fully describes these problems and solutions.

At first, I would like to discuss a question - What causes these problems to arise? In my opinion it is connected with an insufficient information or a fuzzy concept about the Windows architecture and Windows processes when we start executing program in the Windows systems. Here's the main problem. So let's resolve it. I am not going to retell a big good books about Windows, there is no point. I only want to let you have the opportunity to know about the creation of the instance program in Windows. That will give you an understanding of how to create the Splash \ Login Forms.

What is a Process?

First, we'll discuss a definition of "process in Windows". The Process - it is a copy of the executable program, and it consists of two components:

  1. An object of the kernel, through which the operating system manages the process. It keeps the static information about the process.
  2. An address space that contains executable code and data of the process.

The process itself does nothing, i.e., it is inert. To make it do something, it should have at least one thread. The thread is responsible for the execution of code in the address space of the process. Therefore, when the process is starting, the operating system automatically creates the main thread, which in turn can generate other threads. In addition, if we want our application to respond to the mouse moving, the button clicking, and so on, we have to create a message loop in the thread. So we have some structure: process - thread - a message loop. If we want to close the program, we need to close the main message loop. It happens when you close the main form or doing method Application.Exit(), as well as the method ExitThread() in the main thread.

How Do I Do It?

All discussed above, Visual Studio creates automatically, when we choose to create a project template with Windows Forms Application. Armed with this knowledge, take a look at the code, which we all certainly have repeatedly seen:

C#
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

When you call a method Application.Run (new Form1 ()), we create a new thread that creates a message loop, and an object of class Form and shows it. Let us carefully consider this method. This method is overloaded, and may have the following options:

  1. Run()
  2. Run(ApplicationContext)
  3. Run(Form)

(For additional information, see this link.)

We are not interested in the first overloaded method in the context of this article, unless, of course, you decide to create something in the unsafe code, the third method we have already discussed. But the second is what we will be particularly interesting in. This creates the object class ApplicationContext, which is responsible for creating the thread and the standard cycle of message. Now everything is pretty simple - we must create a descendant class LoginTestContext of class ApplicationContext, which we will create a logic with application forms:

C#
public class LoginTestContext: ApplicationContext
{
    // here we can declare the all forms application and manage it directly
    //(show, close, set as MainForm and so on) 
    private frmLogIn fLogin;
    private frmMain fMain;

    public LoginTestContext()
    {     
      CreateSplashForm();

      CreateLoginForm();
    }
}

(For additional information, see this link.)

And our entry point into the application will look as follows:

C#
[STAThread]
static void Main()
{
     Application.EnableVisualStyles();
     Application.SetCompatibleTextRenderingDefault(false);

     //Run the application with our context. It is splash, log and main forms
     Application.Run(new LoginTestContext());    
}

Creating the Splash Form

That's it! The Splash form is displayed when we need it and at the time that we need. Here, in place of slumber thread, you can do something really necessary, such as loading any resources, while showing progress bar or some other kind of information.

C#
private static void CreateSplashForm()
{
     Form fSplash = new Form();
     fSplash.BackgroundImage = System.Drawing.Image.FromFile(@"backg.bmp");

     fSplash.BackgroundImageLayout = ImageLayout.Center;
     fSplash.FormBorderStyle = FormBorderStyle.None;
     fSplash.StartPosition = FormStartPosition.CenterScreen;
     fSplash.TopMost = true;
     
     //it sets transparency for the background of image
     fSplash.TransparencyKey = System.Drawing.Color.White;
     
     //set the splash form size and we are sure the image fit to the form
     fSplash.Width = (int)fSplash.BackgroundImage.PhysicalDimension.Width;
     fSplash.Height = (int)fSplash.BackgroundImage.PhysicalDimension.Height;

     fSplash.Show();
     System.Threading.Thread.Sleep(2000);
     fSplash.Close();
}

Creating the Login Form

Now we'll discuss the problem of the Login form establishing. The Login form follows after the Splash form. The Login form in any case should be closed. When it is closing itself, we must determine whether the login is made in the application:

C#
private void CreateLoginForm()
{
    fLogin = new frmLogIn();
    fLogin.Closed += new EventHandler(fLogin_Closed);
    fLogin.TopMost = true;
    fLogin.Show();
}
     
void fLogin_Closed( object sender, EventArgs e )
{
    if (LWork.LoginWork.Login)
    {
        fMain = new frmMain();
        this.MainForm = fMain; //set the main message loop application in this form
        fMain.Show();
    }
    else
    {
        ExitThread();
    }
}

The registration process is implemented in a static class LoginWork.

C#
public static void DoLogin( string NikName, string Password )
{
    if (IsExistNikName(NikName))
    {
        if (_user.Password == HashString(Password))
        {
          _Logged = true;
        }
    }
    else
        _Logged = false;
}

The search function of the user name in the list IsExistNikName (string name) is implemented using lambda expression UserData => UserData.Nikname == NikName. In this case, the explanation the entity lambda expressions is too simple. For more information about the lambda expression, see this link.

C#
private static bool IsExistNikName( string NikName )
{
    if (_UserDataList.Count == 0)
    {
        return false;
    }

     //here I use a lambda expression for the searching the nikname 
     //in the user data list
     _user = _UserDataList.FirstOrDefault(UserData => UserData.Nikname == NikName);

     if (String.IsNullOrEmpty(_user.Nikname))
     {
        return false;
     }

    return true;
}

For security, the user's password is hashed using the function:

C#
public static string HashString( string s )
{
     //encode string to the array of bytes
     byte[] data = Encoding.Default.GetBytes(s);

     //hashing
     MD5 md5 = new MD5CryptoServiceProvider();
     byte[] result = md5.ComputeHash(data);
     
     //do hexadecimal-formatted string
     StringBuilder sb = new StringBuilder();
     foreach (byte item in result)
     {
        sb.Append(item.ToString("X"));
     }

     return sb.ToString();
}

The processes of saving, load the data registered users are implemented using XML Serialization and UserData structure. The data is stored locally in the XML file:

C#
[Serializable]
public struct UserData
{
    private string _Name;

    public string Name
    {
      get { return _Name; }
      set { _Name = value; }
    }

    private string _Nikname;

    public string Nikname
    {
      get { return _Nikname; }
      set { _Nikname = value; }
    }

    private string _Password;

    public string Password
    {
      get { return _Password; }
      set { _Password = value; }
    }
}

Conclusion

That is all I wanted to tell you on this topic. I hope I succeeded in revealing the topic of this article fully. The implementation of the classes registration form and Login form, I think, will not cause any difficulty in understanding, but if you have any questions please write, I'll answer everyone.

Good coding!

History

  • Initial release: 31 August, 2010
  • Changed the code version: 3 September, 2010

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Czech Republic Czech Republic
My name is Vladimir Knyazkov. I am MCP (ID: 8647484, Transcript ID (995538)).

Comments and Discussions

 
GeneralMy vote of 4 Pin
Member 1370414311-Apr-23 22:39
Member 1370414311-Apr-23 22:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.