Login Dialog Boxes


 

Overview

A login dialog box is a window that allows users of a (restricted) group to provide credentials such as a username and a password in order to get access to a restricted area. In order to provide this functionality to your users, you have various options. You can create a simple and small database that has a table of usernames and passwords. Instead, in this lesson, we will use the file processing features of the C FILE structure to validate users credentials using a simple text file.

To create a file that would hold a list of users credentials, you can start by creating an application. You should at least provide a login dialog box that is presented to a user who needs to login. 

 

The login dialog box

Notice that the Submit button is disabled (Enabled: false). This allows us to enable it only if each one of both edit boxes contains a string. This can be implemented as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmLogin::edtUsernameChange(TObject *Sender)
{
    if( (edtUsername->Text == "") || (edtPassword->Text == "") )
        btnSubmit->Enabled = False;
    else
        btnSubmit->Enabled = True;
}
//---------------------------------------------------------------------------
void __fastcall TfrmLogin::edtPasswordChange(TObject *Sender)
{
    if( (edtUsername->Text == "") || (edtPassword->Text == "") )
        btnSubmit->Enabled = False;
    else
        btnSubmit->Enabled = True;
}
//---------------------------------------------------------------------------

When a user logs in, his or her credentials must be checked. This means that, before users can login, there must be a list that will process this checking. As stated for this exercise, we will use a text file. We will also allow a user to create a new account if necessary. To do this, you can add a second dialog box with a design as follows:

New Account Setup

Once again, the Submit button is disabled. It will be enabled only if each of the three edit boxes has a string. This aspect can be taken care of with the following:

 

//---------------------------------------------------------------------------
void __fastcall TfrmNewAccount::edtUsernameChange(TObject *Sender)
{
    if( (edtUsername->Text == "") ||
        (edtPassword->Text == "") ||
        (edtConfirm->Text  == "") )
        btnSubmit->Enabled = False;
    else
        btnSubmit->Enabled = True;
}
//---------------------------------------------------------------------------
void __fastcall TfrmNewAccount::edtPasswordChange(TObject *Sender)
{
    if( (edtUsername->Text == "") ||
        (edtPassword->Text == "") ||
        (edtConfirm->Text  == "") )
        btnSubmit->Enabled = False;
    else
        btnSubmit->Enabled = True;
}
//---------------------------------------------------------------------------
void __fastcall TfrmNewAccount::edtConfirmChange(TObject *Sender)
{
    if( (edtUsername->Text == "") ||
        (edtPassword->Text == "") ||
        (edtConfirm->Text  == "") )
        btnSubmit->Enabled = False;
    else
        btnSubmit->Enabled = True;
}
//---------------------------------------------------------------------------

Account Setup

To create a file that holds the list of credentials, you can use your knowledge of C file processing to create a file. When a user is setting up a new account, he can fill out the user name, the password, and a confirmation of the password. Once the account is ready, the user can click a button to send it to the file. Unless you have another particular way you are dealing with this, you should make sure that the credentials are stored incrementally, meaning when a user enters new information, you should add it to the end of the file and avoid erasing the existing file. Such a file can be created with the a or the a+ file mode of the fopen() function. This could be done as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmNewAccount::btnSubmitClick(TObject *Sender)
{
    FILE *Streamer;
    char Username[20], Password[20];

    if( SameText(edtPassword->Text, edtConfirm->Text) )
    {
        try {
            strcpy(Username, edtUsername->Text.c_str());
            strcpy(Password, edtPassword->Text.c_str());

            Streamer = fopen("ExActSet.erd", "a+");
            fprintf(Streamer, "%s ", Username);
            fprintf(Streamer, "%s\n", Password);
        }
        __finally
        {
            fclose(Streamer);
        }

        Close();
    }
    else
    {
        ShowMessage("The passwords do not match. Please try again");
        edtPassword->SetFocus();
    }
}
//---------------------------------------------------------------------------

User Login

After the file has been created, make sure that it contains at least one record. Otherwise, nobody would be able to login. Once the file contains one or a few records, you can present the login dialog box to whoever needs to login. When the user clicks a button, you check his or her credentials against the accounts on the list. You should make sure that a username and a password are compared with a combination of a username and a corresponding password. Here is a way you can do this (and here is the whole source file of the login dialog box:

//---------------------------------------------------------------------------

#ifndef LoginH
#define LoginH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Buttons.hpp>
//---------------------------------------------------------------------------
class TfrmLogin : public TForm
{
__published:	// IDE-managed Components
    TLabel *Label1;
    TLabel *Label2;
    TEdit *edtUsername;
    TEdit *edtPassword;
    TBitBtn *btnNewAccount;
    TBitBtn *btnSubmit;
    TBitBtn *BitBtn1;
    TLabel *Label3;
    void __fastcall btnNewAccountClick(TObject *Sender);
    void __fastcall BitBtn1Click(TObject *Sender);
    void __fastcall btnSubmitClick(TObject *Sender);
    void __fastcall edtUsernameChange(TObject *Sender);
    void __fastcall edtPasswordChange(TObject *Sender);
private:	// User declarations
public:		// User declarations
    __fastcall TfrmLogin(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TfrmLogin *frmLogin;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdio.h>
#pragma hdrstop

#include "Login.h"
#include "AccountSetup.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmLogin *frmLogin;
//---------------------------------------------------------------------------
__fastcall TfrmLogin::TfrmLogin(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TfrmLogin::btnNewAccountClick(TObject *Sender)
{
    frmNewAccount->edtUsername->Text = "";
    frmNewAccount->edtPassword->Text = "";
    frmNewAccount->edtConfirm->Text  = "";

    frmNewAccount->ShowModal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmLogin::BitBtn1Click(TObject *Sender)
{
    Close();
}
//---------------------------------------------------------------------------
void __fastcall TfrmLogin::btnSubmitClick(TObject *Sender)
{
    FILE *Streamer;
    char TypedUsername[20], TypedPassword[20];  
    char FileUsername[20],  FilePassword[20];
                                
    strcpy(TypedUsername, edtUsername->Text.c_str());
    strcpy(TypedPassword, edtPassword->Text.c_str());

    try {
        Streamer = fopen("ExActSet.erd", "r");

        while( !feof(Streamer) )
        {
            fscanf(Streamer, "%s", FileUsername);
            if( AnsiStrComp(TypedUsername, FileUsername) == 0 )
            {
                fscanf(Streamer, "%s", FilePassword);
                if( AnsiStrComp(TypedPassword, FilePassword) == 0 )
                {
                    ShowMessage("Successful");
                    return;
                }
            }
            if( feof(Streamer) )//else
            {
                ShowMessage("Invalid Credentials. Please try again");
                edtPassword->SetFocus();
            }
        }
    }
    __finally
    {
        fclose(Streamer);
    }
}
//---------------------------------------------------------------------------
void __fastcall TfrmLogin::edtUsernameChange(TObject *Sender)
{
    if( (edtUsername->Text == "") || (edtPassword->Text == "") )
        btnSubmit->Enabled = False;
    else
        btnSubmit->Enabled = True;
}
//---------------------------------------------------------------------------
void __fastcall TfrmLogin::edtPasswordChange(TObject *Sender)
{
    if( (edtUsername->Text == "") || (edtPassword->Text == "") )
        btnSubmit->Enabled = False;
    else
        btnSubmit->Enabled = True;
}
//---------------------------------------------------------------------------

Just in case, here are the header and the source files of the other dialog box:

//---------------------------------------------------------------------------

#ifndef AccountSetupH
#define AccountSetupH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Buttons.hpp>
//---------------------------------------------------------------------------
class TfrmNewAccount : public TForm
{
__published:	// IDE-managed Components
    TLabel *Label1;
    TLabel *Label2;
    TEdit *edtUsername;
    TEdit *edtPassword;
    TLabel *Label3;
    TEdit *edtConfirm;
    TBitBtn *btnSubmit;
    TBitBtn *btnCancel;
    void __fastcall edtUsernameChange(TObject *Sender);
    void __fastcall edtPasswordChange(TObject *Sender);
    void __fastcall edtConfirmChange(TObject *Sender);
    void __fastcall btnSubmitClick(TObject *Sender);
private:	// User declarations
public:		// User declarations
    __fastcall TfrmNewAccount(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TfrmNewAccount *frmNewAccount;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdio.h>
#pragma hdrstop

#include "AccountSetup.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmNewAccount *frmNewAccount;
//---------------------------------------------------------------------------
__fastcall TfrmNewAccount::TfrmNewAccount(TComponent* Owner)
    : TForm(Owner)
{

}
//---------------------------------------------------------------------------
void __fastcall TfrmNewAccount::edtUsernameChange(TObject *Sender)
{
    if( (edtUsername->Text == "") ||
        (edtPassword->Text == "") ||
        (edtConfirm->Text  == "") )
        btnSubmit->Enabled = False;
    else
        btnSubmit->Enabled = True;
}
//---------------------------------------------------------------------------
void __fastcall TfrmNewAccount::edtPasswordChange(TObject *Sender)
{
    if( (edtUsername->Text == "") ||
        (edtPassword->Text == "") ||
        (edtConfirm->Text  == "") )
        btnSubmit->Enabled = False;
    else
        btnSubmit->Enabled = True;
}
//---------------------------------------------------------------------------
void __fastcall TfrmNewAccount::edtConfirmChange(TObject *Sender)
{
    if( (edtUsername->Text == "") ||
        (edtPassword->Text == "") ||
        (edtConfirm->Text  == "") )
        btnSubmit->Enabled = False;
    else
        btnSubmit->Enabled = True;
}
//---------------------------------------------------------------------------
void __fastcall TfrmNewAccount::btnSubmitClick(TObject *Sender)
{
    FILE *Streamer;
    char Username[20], Password[20];

    if( SameText(edtPassword->Text, edtConfirm->Text) )
    {
        try {
            strcpy(Username, edtUsername->Text.c_str());
            strcpy(Password, edtPassword->Text.c_str());

            Streamer = fopen("ExActSet.erd", "a+");
            fprintf(Streamer, "%s ", Username);
            fprintf(Streamer, "%s\n", Password);
        }
        __finally
        {
            fclose(Streamer);
        }

        Close();
    }
    else
    {
        ShowMessage("The passwords do not match. Please try again");
        edtPassword->SetFocus();
    }
}
//---------------------------------------------------------------------------

  Copyright 1998-2003 FunctionX, Inc.