DELPHI用户登录方案

来源:互联网 发布:比基尼 淘宝 编辑:程序博客网 时间:2024/05/27 00:49

3.2  用户登录方案

在进入一个系统时,必须先在登录窗体中输入正确的用户名和密码才能进入。这样可以确保系统的安全性和保密性,登录窗体的制作按照系统的大小及用处,可以分为不同的登录窗体样式,在系统第一次登录前,首先要对操作员信息进行相应的设置。本节将对登录窗体及操作员管理窗体的制作过程进行详细的说明。

3.2.1  简单用户登录

简单用户登录,是指在登录窗体中只通过用户名及密码进行登录,用户登录后可以对系统中的数据进行任意操作。这是最简单的登录方式。

1.方案分析

在登录窗体中,输入用户名和密码,单击确定(或登录)按钮,系统将在数据表中查找有无相同的记录,如果有则进入主窗体;如果没有则给出错误提示。下面给出简单用户登录的流程图,如图3.3所示。

图3.3  简单用户登录流程图

在制作简单用户登录方案时,主要有以下几个难点:

(1)怎样在用户数据表中对用户名及密码进行添加或修改。

(2)如何在添加用户名时,提示用户名已经存在。

2.实施过程

在开发一些小型的超市管理软件时,因为超市的范围较小,不需要使用权限来制约用户,这时就可以使用简单用户登录方案。下面以一个小型超市为例,介绍简单登录方案的制作过程。

*    实例位置:光盘/mr/3/3.2/3.2.1/01

本方案实现的简单登录窗体,如图3.4所示。窗体中要有用户名及密码的输入文本框,为了使输入的密码处于保密状态,将密码文本框中的字符用“*”来表示。当用户名和密码正确时,单击“确定”按钮,将进入主窗体。

图3.4  简单登录窗体

在制作登录窗体前,首先要在数据库中制作一个用户表(tb_Briefness_User),该数据表记录了本系统的合法用户名及密码。tb_Briefness_User数据表的关系图如图3.5所示。

图3.5  tb_Briefness_User数据表的关系图

在设计tb_Briefness_User数据表时,为了能够对添加的用户名进行自动排号,可以将数据表中的ID字段设为数字型,并将标识设为“是”,这样,在添加记录时,就会在ID字段中自动添加编号,用户名和密码都是以字符串型式进行读取的,将其设置成字符型。

在主窗体中可以调用“操作员管理”窗体对用户的相关信息进行编辑,如图3.6所示。

图3.6  操作员管理

程序各窗体中相关组件说明,如表3.2所示。

表3.2                               各窗体的相关组件

对象名

对象类型

属性

DataModule1

TDataModule

Name

DataModule1

ADOConnection1

TADOConnection

ConnectionString

连接数据库

ADO_User

TADOQuery

Connection

ADOConnection1

ADOQuery1

ADOQuery2

Frm_Interface

TForm

Caption

超市销售系统

MainMenu1

TMainMenu

Items

添加下拉菜单

Frm_Enter

TForm

BorderStyle

bsNone

Edit1

TEdit

Ctl3D

False

Edit2

PasswordChar

*

Ctl3D

False

SpeedButton1

TSpeedButton

Flat

True

Frm_ManageUser

TForm

Caption

操作员管理

ToolBar1

TToolBar

Align

alClient

DBGrid1

TDBGrid

Columns

将该组件的英文字段名改为中文

使用TDataModule窗体来存放ADO组件,是为了方便调用TADOQuery组件,也可以重复调用同一个TADOQuery组件。

*   说明:为了能够节省内存空间,可以将主窗体和数据模式窗体以外的窗体设为动态窗体,可以单击Project菜单的OPtions莱单项,在弹出的“Project Option for Project1.exe”对话框中,将Auto-create forms文本框中的除DataModule1和Frm_Interfac窗体以外的所有窗体,全部导入到右边的Available forms文本框中,单击“OK”按钮,这样就可以动态调用子窗体。

  注意:在Auto-create forms文本框中,DataModule1窗体必需在Frm_Interfac窗体的上面,因为在运行程序时,首先要连接数据库,然后才能对应用程序进行操作,当DataModule1窗体在下面时,运行工程后,将无法连接数据库。

将“超市销售系统”窗体设为主界面,在该窗体的OnShow事件中调用“登录”窗体。代码如下:

procedure TFrm_Interface.FormShow(Sender: TObject);

begin

  Application.CreateForm(TFrm_Enter,Frm_Enter);

  Frm_Enter.ShowModal;

  Frm_Enter.Free;

end;

在运行程序时,首先调用的是主窗体,可以根据上面的代码,在主窗体显示前先显示“登录”窗体,下面对“登录”窗体进行详细介绍。

为了能在“登录”窗体显示时,将用户名和密码以空文本框进行显示,在该窗体的OnShow事件中将用户名和密码文本框进行清空。代码如下:

procedure TFrm_Enter.FormShow(Sender: TObject);

begin

  Edit1.Clear;

  Edit2.Clear;

end;

在用户名和密码文本框中输入用户名和密码,单击“确定”按钮,在该按钮的OnClick事件中对用户名和密码进行判断,是否与用户数据表(tb_Briefness_User)中的记录相同,如果相同,则进入主窗体,否则,清空用户名和密码文本框,重新登录。代码如下:

procedure TFrm_Enter.Button1Click(Sender: TObject);

begin

  with DataModule1.ADO_User do  //在用户数据表中查找用户名

  begin

    Close;

    SQL.Clear;

    SQl.Add('select * from tb_Briefness_User where User_Name='+''''+

Trim(Edit1.Text)+'''');

    Open;

    if RecordCount>0 then  //如果找到

    begin

      if FieldByName('User_Pass').AsString=Trim(Edit2.Text) then  //判断密码是否相同

      begin

        ifclose := 1;

        self.Close;

      end

      else

      begin

        showmessage('密码错误,请重新添写');

        Edit2.Clear;

        Edit2.SetFocus;

      end;

    end

    else

    begin

      showmessage('用户名错误,请重新添写');

      Edit1.Clear;

      Edit2.Clear;

      Edit1.SetFocus;

    end;

  end;

end;

在用户名和密码正确时,单击“确定”按钮,关闭的是“登录”窗体,在单击“取消”按钮或直接关闭“登录”窗体右上角的按钮时,关闭的是整个工程。可以用一个公共变量ifclose进行判断。当ifclose变量的值为0时,关闭的是整个工程,当ifclose变量的值为1时,关闭的是“登录”窗体本身。该过程可以在“登录”窗体的OnClose事件中实现。代码如下:

procedure TFrm_Enter.FormClose(Sender: TObject; var Action: TCloseAction);

begin

  if ifclose=0 then

    Application.Terminate;

end;

以上就完成了对“登录”窗体的制作过程,下面对“操作员管理”窗体的制作进行详细说明,该窗体主要是对用户名及密码进行添加、修改、删除的操作。

在“超市管理系统”窗体中,动态调用“操作员管理”窗体,可以在MainMenu1组件的下拉菜单项的OnClick事件中完成该操作。代码如下:

procedure TFrm_Interface.N36Click(Sender: TObject);

begin

  Application.CreateForm(TFrm_ManageUser,Frm_ManageUser);

  Frm_ManageUser.ShowModal;

  Frm_ManageUser.Free;

end;

通过以上代码,就可以在“超市管理系统”窗体中调用“操作员管理”窗体,在该窗体显示时,将数据库tb_Briefness_User数据表中的信息显示在DBGrid1组件中,以便用户在DBGrid1组件中对用户信息进行查看。代码如下:

procedure TFrm_ManageUser.FormShow(Sender: TObject);

begin

  //将“保存”和“取消”按钮设为不可用状态

  ToolButton4.Enabled := False;

  ToolButton5.Enabled := False;

  //将显示用户名和密码的文本框设为不可用状态,使其不能随便更改信息

  Edit1.Enabled := False;

  Edit2.Enabled := False;

  with DataModule1.ADO_user do

  begin

    Close;

    SQL.Clear;

    SQL.Add('select * from tb_Briefness_User');

    Open;

  end;

  DataModule1.DataSource1.DataSet := DataModule1.ADO_user;

  self.DBGrid1.DataSource := DataModule1.DataSource1;

  if DataModule1.ADO_user.RecordCount>0 then

    ShowUser(Edit1, Edit2, DataModule1.ADO_user)

  else

  begin

    Edit1.Clear;

    Edit2.Clear;

  end;

end;

自定义过程ShowUser(),指定数据表中的信息在已设定的文本框中进行显示。代码如下:

procedure TFrm_ManageUser.ShowUser(E1, E2: TEdit; ADOQuer: TADOQuery);

begin

  ADOQuer.First;

  E1.Text := ADOQuer.fieldbyname('User_Name').AsString;

  E2.Text := ADOQuer.fieldbyname('User_Pass').AsVariant;

end;

ShowUser()过程的参数说明如表3.3所示。

表3.3                           ShowUser()过程的参数说明

参数

说明

E1, E2

TEdit类型,要进行赋值的文本框

ADOQuer

TADOQuery类型,用于获取数据表信息的数据源

在该窗体中,单击DBGrid1组件中的记录,将该记录中的信息显示在Edit1和Edit2中,这样可以更清楚的观察当前所选用户的信息,实现代码如下:

procedure TFrm_ManageUser.DBGrid1CellClick(Column: TColumn);

begin

  Edit1.Text := DataModule1.ADO_User.FieldByName('User_Name').AsString;

  Edit2.Text := DataModule1.ADO_User.FieldByName('User_Pass').AsVariant;

end;

  注意:为了能对登录用户的信息进行保密,在DBGrid1组件中,不显示用户密码,在Edit2组件中显示用户密码时,将密码以“*”进行显示。

在该窗体中,主要是对登录用户的信息进行添加和修改的操作,在窗体上面的ToolBar1组件中,放置了“添加”和“修改”按钮,这两个按钮并没有实现添加和修改的功能,只是让Edit1和Edit2组件处于可编辑状态,而真正的添加和修改过程是在“保存”按钮中实现的。

“添加”按钮是将Edit1和Edit2组件处于可编辑状态,并将组件中的信息进行清空,以便用户向文本框内添加信息。代码如下:

procedure TFrm_ManageUser.ToolButton1Click(Sender: TObject);

begin

  AddAmend := 1;

  EnabledTF(ToolButton1,False,True);

  Edit1.Clear;

  Edit2.Clear;

end;

公共变量AddAmend用于在“保存”按钮中判断,当前执行的是添加操作,还是修改操作。

自定义过程EnabledTF()是将ToolBar1组件中与本次操作的无关按钮设为不可用状态。代码如下:

procedure TFrm_ManageUser.EnabledTF(Ename: TToolButton; T,F : Boolean);

begin

  ToolButton1.Enabled := T;

  ToolButton2.Enabled := T;

  ToolButton3.Enabled := T;

  ToolButton4.Enabled := F;

  ToolButton5.Enabled := F;

  Ename.Enabled := F;

  Edit1.Enabled := F;

  Edit2.Enabled := F;

end;

EnabledTF()过程的参数说明如表3.4所示。

表3.4                           EnabledTF()过程的参数说明

参数

说明

Ename

当前所单击的按钮名称

T,F

Boolean类型,值可以是True或False

“修改”按钮是将Edit1和Edit2组件处于可编辑状态,用户可以根据Edit1和Edit2组件中的信息对当前记录进行修改。代码如下:

procedure TFrm_ManageUser.ToolButton2Click(Sender: TObject);

begin

  AddAmend := 2;

  EnabledTF(ToolButton2,False,True);

end;

单击“添加”或“修改”按钮,对Edit1和Edit2组件中的信息进行编辑后,就可以通过“保存”按钮,对相关信息进行保存,当用户名已存在时,将弹出提示框,提示重新输入。代码如下:

procedure TFrm_ManageUser.ToolButton4Click(Sender: TObject);

begin

  if ((Edit1.Text<>'')and(Edit2.Text<>'')) then

  begin

    with DataModule1.ADOQuery2 do

    begin

      Close;

      SQL.Clear;

      SQL.Add('select * from tb_Briefness_User where User_Name='+''''+

DataModule1.ADO_user.fieldbyname('User_Name').AsString+'''');

      Open;

      if DataModule1.ADOQuery2.RecordCount>0 then  //判断当前添加或修改的用户名是否存在

      begin

        showmessage('当前用户已存在,请重新输入用户信息。');

        Edit1.Clear;

        Edit2.Clear;

        Exit;

      end;

      Close;

      SQL.Clear;

      SQL.Add('select * from tb_Briefness_User where ID='+IntToStr

(DataModule1.ADO_user.fieldbyname('ID').AsInteger));

      Open;

      if AddAmend=1 then  //当AddAmend变量为1时,添加记录

        Insert

      else if AddAmend=2 then  //当AddAmend变量为2时,修改记录

        Edit

      else

      begin

        Exit;

      end;

      //将编辑后的信息存入到数据库中

      FieldByName('User_Name').AsVariant :=Trim(Edit1.Text);

      FieldByName('User_Pass').AsVariant :=Trim(Edit2.Text);

      Post;  //对数据库进行保存

    end;

    EnabledTF(ToolButton4,True,False);  //恢复按钮的可用状态

    //使DBGrid1组件中的信息显示编辑后的数据信息

    DataModule1.ADO_user.Active := False;

    DataModule1.ADO_user.Active := True;

  end

  else

    showmessage('请将信息添写完整。');

end;

如果不想对tb_Briefness_User数据表中的信息进行添加或修改时,可以单击“取消”按钮,该按钮与“添加”和“修改”按钮相同,并没有实质上的作用,只是将其他按钮恢复为原始状态。代码如下:

procedure TFrm_ManageUser.ToolButton5Click(Sender: TObject);

begin

  EnabledTF(ToolButton5,True,False);

  ShowUser(Edit1, Edit2, DataModule1.ADO_user);

end;

  注意:在用ADO组件的Insert和Exit方法对数据表中的数据进行添加和修改时,可以用Cancel方法来取消这两个方法的操作。

有些用户可能因为某些原因,不可以再使用本系统,那么,就需要在数据表中删除无用的用户名,以防止其再进入本系统,这一操作,可以用“操作员管理”窗体中“删除”按钮来完成,在DBGrid1组件中选中要删除的用户记录,单击“删除”按钮,将tb_Briefness_User数据表中的指定记录进行删除。代码如下:

procedure TFrm_ManageUser.ToolButton3Click(Sender: TObject);

begin

  if Application.MessageBox('是否删除当前用户?','提示',MB_YesNo+MB_ICONQUESTION)

=IDYes then

  begin

    DataModule1.ADOQuery2.Delete;

    EnabledTF(ToolButton5,True,False);

    DataModule1.ADO_user.Active := False;

    DataModule1.ADO_user.Active := True;

    ShowUser(Edit1, Edit2, DataModule1.ADO_user);

  end;

end;

在删除用户记录时,为了避免错误删除,可以用Application对象中的MessageBox()方法(该方法将弹出一个对话框,在该对话框中将显示提示信息及“是”、“否”两个按钮)来进行判断,当单击“是”按钮,将执行删除操作,单击“否”按钮,将不作任何操作。

3.补充说明

在对用户信息进行添加、修改时,为了能让操作者在DBGrid1组件中看到操作步骤,可以将Insert方法、Edit方法和Post方法在不同的单击事件中执行。

下面用4个按钮对其操作过程进行讲解。这4个按钮分别是“添加”、“修改”、“保存”和“取消”按钮。

首先用ADO组件ADO_user将tb_Briefness_User数据表中的信息与DBGrid1组件相连接,为了能够在DBGrid1组件上显示添加和修改的效果,添加和修改操作必需在ADO组件ADO_user上执行。

下面是在“添加”按钮的OnClick事件实现用户数据的添加操作。在单击“添加”按钮时,将在DBGrid1组件的第一行添加一个空记录,并在空记录前以“*”符号作为标识。代码如下:

procedure TFrm_ManageUser.ToolButton1Click(Sender: TObject);

begin

  DataModule1.ADO_user.Insert;

  AddAmend := 1;

  EnabledTF(ToolButton1,False,True);

  Edit1.Clear;

  Edit2.Clear;

end;

效果如图3.7所示。

图3.7  记录添加效果

下面是在“修改”按钮的OnClick事件中实现用户数据的修改操作,在单击“修改”时,将在已选中的记录的前面以“Ⅰ”符号作为标识。代码如下:

procedure TFrm_ManageUser.ToolButton2Click(Sender: TObject);

begin

  DataModule1.ADO_user.Edit;

  EnabledTF(ToolButton2,False,True);

end;

效果如图3.8所示。

图3.8  记录修改效果

在对记录进行添加和修改之后,便可以用“保存”对其数据进行保存。代码如下:

procedure TFrm_ManageUser.ToolButton4Click(Sender: TObject);

begin

  if ((Edit1.Text<>'')and(Edit2.Text<>'')) then

  begin

    with DataModule1.ADO_user do

    begin

      if AddAmend=1 then  //向数据表中添加数据时,该IF语句必需执行,否则程序找不到添加语句

      begin

        Insert;

        AddAmend := 0;

      end;

      FieldByName('User_Name').AsVariant :=Trim(Edit1.Text);

      FieldByName('User_Pass').AsVariant :=Trim(Edit2.Text);

      Post;

    end;

    EnabledTF(ToolButton4,True,False);

    DataModule1.ADO_user.Active := False;

    DataModule1.ADO_user.Active := True;

  end

  else

    showmessage('请将信息添写完整。');

end;

  注意:当Insert方法与Post方法在不同的事件进行操作时,Insert方法可能会无效,所以在保存添加记录前,用Insert方法再执行一次添加操作。

如果不想对正在添加或修改的用户记录进行保存,可以单击“取消”按钮。代码如下:

procedure TFrm_ManageUser.ToolButton5Click(Sender: TObject);

begin

  DataModule1.ADO_user.Cancel;

  AddAmend := 0;

  EnabledTF(ToolButton5,True,False);

  ShowUser(Edit1, Edit2, DataModule1.ADO_user);

end;

  注意:以上所用到的自定义过程EnabledTF()、ShowUser(),请到本节中的实施过程中查看相关内容。

3.2.2  用户级别登录

用户级别登录顾名思义就是将登录的用户分成不同的级别,以不同的权限进行登录,这种登录方式可以将用户的使用权限分为不同的等级,以防止一些普通用户对程序的错误操作。本节主要对用户级别登录方案的制作过程进行讲解。

1.方案分析

在制作应用程序时,会设定一个权限最高的用户,该用户可以对程序中的所有数据进行操作,而其他的普通用户,只能在该程序中进行数据的查看,或者部分修改里面的数据。下面给出用户级别登录的流程图,如图3.9所示。

*   说明:在制作一些简单的应用程序时,可以直接根据用户级别的标识对用户的操作权限进行判断。在本方案中,用户级别的标识是存放在“用户登录表”中,通过对指定标识的设置,将固定用户的操作范围,标识(权限)是不允许进行修改的。为了使读者能够更好的了解单标识权限的应用,将与用户级别登录一同讲解。

图3.9  用户级别登录流程图

在制作用户级别登录方案时,主要有以下几个难点:

(1)如何限定登录时的错误次数。

(2)在添加用户信息时,如何在程序中自动添加用户编号。

2.实施过程

在开发一些中小型管理软件时,为了能够更好的对其进行管理,可以将操作员分成不同的等级,等级越高,对管理软件的操作权限就越大;等级越低,操作的权限就越小。下面以一个工资管理系统为例,介绍用户级别登录方案的制作过程。该方案对登录失败的次数进行了累计,当超出一定次数时,将自动退出系统。

*    实例位置:光盘/mr/3/3.2/3.2.2/01

在制作用户级别登录窗体时,窗体中要有用户名、密码和用户级别的输入文本框,为了使输入的密码处于保密状态,将密码文本框中的字符用“*”来表示,如图3.10所示。当用户名、密码和用户级别正确时,单击“确定”按钮,将进入主窗体。

图3.10  用户级别登录窗体

在制作登录窗体前,首先要在数据库中制作一个用户表(tb_Distinction_User),该数据表记录了本系统的合法用户名、密码和用户级别。tb_Distinction_User数据表的关系图如图3.11所示。

图3.11  tb_Distinction_User数据表的关系图

在主窗体中可以调用“操作员管理”窗体对用户的相关信息进行编辑,如图3.12所示。

图3.12  操作员管理窗体

本方案中的各窗体的相关组件与3.2.1节中的窗体结构相似,在这里不做讲解。

下面对登录窗体的制作过程进行详细说明。

在本方案中,“登录”窗体并不是主窗体,“工资管理系统”窗体被设置为主窗体,“登录”窗体只是调用窗体,这是因为,在关闭“登录”窗体时,并不一定关闭整个工程,而关闭“工资管理系统”窗体时,将关闭整个工程,所以才将“工资管理系统”窗体设为主窗体,“登录”窗体设为调用窗体。

在运行程序时,首先显示的是主窗体,那么如果在显示主窗体前,先显示“登录”窗体呢,可以在主窗体的OnShow事件中调用“登录”窗体。代码如下:

procedure TFrm_Interface.FormShow(Sender: TObject);

begin

  Application.CreateForm(TFrm_Enter,Frm_Enter);

  Frm_Enter.ShowModal;

  Frm_Enter.Free;

end;

在显示“登录”窗体时,首先要将用户名、密码和用户级别文本框中的数据进行清空,该操作可以在“登录”窗体的OnShow事件完成。代码如下:

procedure TFrm_Enter.FormShow(Sender: TObject);

begin

  Edit1.Clear;

  Edit2.Clear;

  ComboBox1.Text := '';

end;

“登录”窗体显示后,在该窗体中输入用户名、密码和用户级别,单击“确定”按钮,在该按钮的OnClick事件中对用户名、密码和用户级别进行判断,如果与数据表(tb_Briefness_User)中的某行记录相同,则进行主窗体,否则,清空用户名、密码和用户级别的文本框,进行重新输入,当登录次数超出3次时,退出本系统。代码如下:

procedure TFrm_Enter.SpeedButton1Click(Sender: TObject);

var

  M,J : Integer;

  E : Boolean;

begin

  E := True;  //标记用户登录是否失败

  M := 0;

  J := 0;

  with DataModule1.ADO_User do  //查找符合输入用户名的记录

  begin

    Close;

    SQL.Clear;

    SQl.Add('select * from tb_Distinction_User where User_Name='+''''+

Trim(Edit1.Text)+'''');

    Open;

  end;

  if DataModule1.ADO_User.RecordCount>0 then

  begin

    if DataModule1.ADO_User.FieldByName('User_Pass').AsVariant=Trim(Edit2.Text) then

    begin

      //如果用户名和密码都相同,判断权限是否相同

      if DataModule1.ADO_User.FieldByName('User_Distinction').AsVariant=Distin then 

      begin

        J := 1;

      end

      else

      begin  //权限错误进行提示

        showmessage('级别错误码,请重新选择');

        ComboBox1.Text := '';

        ComboBox1.SetFocus;

        E := False;

      end;

      M := 1;

    end;

    if (M=1)and(J=1) then  //当用户名、密码及权限正确时,进入主窗体

    begin

      ifclose := 1;

      self.Close;

    end

    else

    begin

      if M<>1 then  //密码错误进行提示

      begin

        showmessage('密码错误,请重新添写');

        Edit2.Clear;

        Edit2.SetFocus;

        E := False;

      end;

    end;

  end

  else

  begin  //没有用户名进行提示

    showmessage('用户名错误,请重新添写');

    Edit1.Clear;

    Edit2.Clear;

    Edit1.SetFocus;

    E := False;

  end;

  if E=False then  //当登录失败时,进行计数

    EClose := EClose+1;

  if EClose>=3 then  //超出3次登录,退出本系统

  begin

    showmessage('登录用户已超出3次登录次数。');

    SpeedButton2.OnClick(Sender);

  end;

end;

关闭“登录”窗体有两种方式,一是关闭当前窗体,二是关闭整个工程。在系统登录成功后,关闭的是“登录”窗体本身,当单击“登录”窗体的“取消”按钮时,关闭的是整个工程。本实例是用一个变量ifclose在“登录”窗体的OnClose事件中来进行判断,当ifclose变量等于0时,关闭整个工程,否则,只关闭本窗体。代码如下:

procedure TFrm_Enter.FormClose(Sender: TObject; var Action: TCloseAction);

begin

  if ifclose=0 then

    Application.Terminate;

end;

以上过程就完成了用户级别登录窗体的制作。下面对“操作员管理”窗体的制作过程进行详细的介绍。

在“操作员管理”窗体显示时,首先要将用户名、密码、用户级别的文本框设为不可用状态,然后,将用户表(tb_Distinction_User)中的信息显示在DBGrid1组件上,并将表中的第一条记录信息显示在相应的文本框内。代码如下:

procedure TFrm_ManageUser.FormShow(Sender: TObject);

begin

  ToolButton4.Enabled := False;

  ToolButton5.Enabled := False;

  Edit1.Enabled := False;

  Edit2.Enabled := False;

  Edit3.Enabled := False;

  ComboBox1.Enabled := False;

  with DataModule1.ADO_user do

  begin

    Close;

    SQL.Clear;

    SQL.Add('select * from tb_Distinction_User');

    Open;

  end;

  DataModule1.DataSource1.DataSet := DataModule1.ADO_user;

  self.DBGrid1.DataSource := DataModule1.DataSource1;

  if DataModule1.ADO_user.RecordCount>0 then

    ShowUser(Edit1, Edit2, Edit3, ComboBox1, DataModule1.ADO_user)

  else

  begin

    Edit1.Clear;

    Edit2.Clear;

  end;

end;

自定义过程ShowUser()是将指定数据表中的信息在已设定的文本框中进行显示。代码如下:

procedure TFrm_ManageUser.ShowUser(E1, E2, E3 : TEdit; CBox: TComboBox;

ADOQuer: TADOQuery);

begin

  E1.Text := ADOQuer.fieldbyname('User_Name').AsString;

  E2.Text := ADOQuer.fieldbyname('User_Pass').AsString;

  E3.Text := ADOQuer.fieldbyname('User_ID').AsString;

  if ADOQuer.fieldbyname('User_Distinction').AsInteger=1 then

    CBox.Text := '高级用户';

  if ADOQuer.fieldbyname('User_Distinction').AsInteger=2 then

    CBox.Text := '普通用户';

end;

ShowUser()过程的参数说明如表3.5所示。

表3.5                           ShowUser()过程的参数说明

参数

说明

E1,E2,E3

TEdit类型,要进行赋值的文本框

CBox

TComboBox类型,要进行赋值的下拉列表框

ADOQuer

TADOQuery类型,用于获取数据表信息的数据源

显示“操作员管理”窗体后,就可以通过DBGrid1组件的OnClick事件在指定的文本框中显示当前所选中的用户信息。代码如下:

procedure TFrm_ManageUser.DBGrid1CellClick(Column: TColumn);

begin

  with DataModule1.ADO_user do

  begin

    Edit1.Text :=  fieldbyname('User_Name').AsString;

    Edit2.Text :=  fieldbyname('User_Pass').AsString;

    Edit3.Text :=  fieldbyname('User_ID').AsString;

    if fieldbyname('User_Distinction').AsInteger=1 then

      ComboBox1.Text := '高级用户';

    if fieldbyname('User_Distinction').AsInteger=2 then

      ComboBox1.Text := '普通用户';

  end;

end;

该窗体的主要功能并不是用于查看登录用户的信息,而是对登录用户进行添加、修改、删除,以及用户权限的设置。

在添加登录用户时,如果在数据库中将用户编号设为自动编号,那么,在删除最后一条记录后,再添加新记录时,记录编号并不是上一条记录编号值的下一个数字。为了能够确保编号不超出范围,编程人员可以用字符串的形式来设置登录用户的编号。这一过程可以在“添加”按钮的OnClick事件中完成。代码如下:

procedure TFrm_ManageUser.ToolButton1Click(Sender: TObject);

begin

  AddAmend := 1;

  Edit3.Text := ADDNumber(DataModule1.ADOQuery2,'tb_Distinction_User');

  EnabledTF(ToolButton1,False,True);

  Edit1.Clear;

  Edit2.Clear;

  ComboBox1.Text := '';

end;

自定义过程ADDNumber(),用于在添加记录时,自动生成下一个新的记录编号。代码如下:

function TFrm_ManageUser.ADDNumber(ADOQuer: TADOQuery;

  TabName: String): string;

var

  SDate : String;

  Int1 : Integer;

begin

  with ADOQuer do

  begin

    Close;

    SQL.Clear;

    SQL.Add('select * from '+TabName);

    Open;

  end;

  if ADOQuer.RecordCount>0 then

  begin

    ADOQuer.Last;

    Int1 := StrToInt(ADOQuer.FieldByName('User_ID').AsString);

    SDate := Format('%.4d',[Int1+1]);  //将编号的位数设定为4位

  end

  else

  begin

    SDate := '0001';

  end;

  result := SDate;

end;

ADDNumber()过程的参数说明如表3.6所示。

表3.6                           ADDNumber()过程的参数说明

参数

说明

ADOQuer

TADOQuery类型,用于获取指定数据表的信息

TabName

数据表名称

“修改”按钮只是设置了AddAmend变量的值,用于在“保存”按钮中时行判断。代码如下:

procedure TFrm_ManageUser.ToolButton2Click(Sender: TObject);

begin

  AddAmend := 2;

  EnabledTF(ToolButton2,False,True);

end;

自定义过程EnabledTF(),是将ToolBar1组件中与本次操作没有关系的按钮设为不可用状态。代码如下:

procedure TFrm_ManageUser.EnabledTF(Ename: TToolButton; T,F : Boolean);

begin

  ToolButton1.Enabled := T;

  ToolButton2.Enabled := T;

  ToolButton3.Enabled := T;

  ToolButton4.Enabled := F;

  ToolButton5.Enabled := F;

  Ename.Enabled := F;

  Edit1.Enabled := F;

  Edit2.Enabled := F;

end;

EnabledTF()过程的参数说明如表3.7所示。

表3.7                           EnabledTF()过程的参数说明

参数

说明

Ename

当前所单击的按钮名称

T,F

Boolean类型,值可以是True或False

在本方案中,“添加”和“修改”按钮并没有实现添加和修改的功能,只是对窗体中相关组件的显示方式进行了一下修改,通过对显示样式的修改,可以让操作者了解添加和修改的操作步骤。添加和修改的操作过程,在“保存”按钮的OnClick事件中完成。代码如下:

procedure TFrm_ManageUser.ToolButton4Click(Sender: TObject);

begin

  if ((Edit1.Text<>'')and(Edit2.Text<>'')and(Edit3.Text<>'')and(ComboBox1.Text

<>'')) then

  begin

    with DataModule1.ADOQuery2 do

    begin

      Close;

      SQL.Clear;

      SQL.Add('select * from tb_Distinction_User where User_Name='+''''+

DataModule1.ADO_user.fieldbyname('User_Name').AsString+'''');

      Open;

      if DataModule1.ADOQuery2.RecordCount>0 then  //判断用户名是否相同

      begin

        showmessage('当前用户已存在,请重新输入用户信息。');

        Edit1.Clear;

        Edit2.Clear;

        ComboBox1.Clear;

        Exit;

      end;

      Close;

      SQL.Clear;

      SQL.Add('select * from tb_Distinction_User where User_ID='+

DataModule1.ADO_user.fieldbyname('User_ID').AsString);

      Open;

      if AddAmend=1 then

        Insert

      else if AddAmend=2 then

        Edit

      else

      begin

        Exit;

      end;

      FieldByName('User_ID').AsString := Trim(Edit3.Text);

      FieldByName('User_Name').AsString := Trim(Edit1.Text);

      FieldByName('User_Pass').AsString := Trim(Edit2.Text);

      FieldByName('User_Distinction').AsInteger:= n;

      Post;

      DataModule1.ADO_User.Active := False;

      DataModule1.ADO_User.Active := TRue;

    end;

    EnabledTF(ToolButton4,True,False);

    DataModule1.ADO_user.Active := False;

    DataModule1.ADO_user.Active := True;

    ShowUser(Edit1, Edit2, Edit3, ComboBox1, DataModule1.ADO_user);

  end

  else

    showmessage('请将信息添写完整。');

end;

该窗体中的“删除”和“取消”按钮与3.2.1节“操作员管理”窗体中的“删除”和“取消”按钮相同,在这里不做讲解。

3.补充说明

在用户登录级别方案中,为了能够在数据库中快速的读取用户级别,将不同的级别以数字的形式进行表示。当在TDBGrid组件上显示用户信息时,“用户级别”列中只显示数字,这样,使操作员在观看TDBGrid组件时,很难判别操作员的相关级别。可以在TDBGrid组件的OnDrawColumnCell事件中对“用户级别”列中的信息进行重画,以中文进行显示。代码如下:

procedure TFrm_ManageUser.DBGrid1DrawColumnCell(Sender: TObject;

  const Rect: TRect; DataCol: Integer; Column: TColumn;

  State: TGridDrawState);

begin

  if Column.FieldName = 'User_Distinction' then

  begin

    if Column.Field.Value = 1 then

      DBGrid1.Canvas.TextRect(Rect,Rect.Left,Rect.Top,'高级用户');

    if Column.Field.Value = 2 then

      DBGrid1.Canvas.TextRect(Rect,Rect.Left,Rect.Top,'普通用户');

  end

  else

    DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);

end;

3.2.3  部门用户登录

在开发一些比效复杂的管理系统时,用户权限的分配是十分重要的,比如进销存管理系统,它就分为采购部、进货部、销售部、盘点部、财务部等,每个部门都有各自的权限,而且不允许修改其它部门的数据,这样,就应该在用户登录时,以不同的部门进行登录。本节将对部门用户登录的制作过程进行详细的说明。

1.方案分析

部门用户登录就是以不同的部门进入管理系统,以不同的权限对管理系统进行修改。这种登录方式,可以限定各部门的操作权限,防止操作人员对其他部门信息的错误更改。下面给出部门用户登录的流程图,如图3.13所示。

*   说明:在制作一些简单的应用程序时,可以直接根据部门级别的标识对用户的操作权限进行判断。在本方案中,用户级别的标识是存放在“用户登录表”中,通过对该标识的设置,将固定用户的操作范围,标识(权限)是不允许进行修改的。为了使读者能够更好的了解单标识权限的应用,将与部门用户登录一同讲解。

图3.13  部门用户登录的流程图

在制作部门用户登录方案时,主要有以下几个难点:

(1)如何以下拉列表的形式显示指定部门下的所有用户名。

(2)在添加用户信息时,不允许用户名重复。

2.实施过程

在开发一些部门划分比效清晰的管理软件时,可以将操作员以各个部门进行划分,在登录时,也只能用各部门下的用户名进行登录。下面以一个进销存管理系统为例介部门用户登录方案的制作过程。

*    实例位置:光盘/mr/3/3.2/3.2.3/01

在制作部门用户登录窗体时,窗体中要有部门、用户名和密码的输入文本框,为了使输入的密码处于保密状态,将密码文本框中的字符用“*”来表示,如图3.14所示。当部门、用户名和密码正确时,单击“确定”按钮,将进入主窗体。

图3.14  部门用户登录窗体

在制作登录窗体前,首先要在数据库中制作一个部门用户表(tb_Branch_User)和一个部门表(tb_Branch)。用户表记录了本系统的合法用户名、密码和部门名称。tb_Branch_User数据表的关系图如图3.15所示。

图3.15  tb_Branch_User数据表的关系图

部门表记录了本系统中所有部门的名称,tb_Branch数据表的关系图如图3.16所示。

图3.16  tb_Branch数据表的关系图

本方案之所以创建部门表,是因为在“登录”窗体的部门下拉列表中的信息是从tb_Branch数据表中获取的。在设置tb_Branch数据表时,将ID字段设为主键,并将该字段设为自动编号。

在主窗体中可以调用“操作员管理”窗体对用户的相关信息进行编辑,如图3.17所示。

图3.17  操作员管理窗体

本方案中的各窗体的相关组件与3.2.1节中的窗体结构相似,在这里不做讲解。

下面对用户部门窗体的制作过程进行详细的说明。

在制作管理系统时,只有在关闭主窗体时,才能关闭整个工程,这时,“登录”窗体只是被动态调用的窗体,要想在主窗体前显示“登录”窗体,可以在主窗体的OnShow事件中动态调用“登录”窗体。代码如下:

procedure TFrm_Interface.FormShow(Sender: TObject);

begin

  Application.CreateForm(TFrm_Enter,Frm_Enter);

  Frm_Enter.ShowModal;

  Frm_Enter.Free;

end;

在“登录”窗体显示时,首先要将部门、用户名和密码文本框中的信息进行清空,然后将部门(tb_Branch)数据表中的部门名称添加到“登录”窗体的部门下拉列表中,以便操作员在登录时进行选择,以上操作过程可以在“登录”窗体的OnShow事件中实现。代码如下:

procedure TFrm_Enter.FormShow(Sender: TObject);

begin

  Edit1.Clear;

  ComboBox1.Clear;

  ComboBox2.Clear;

  with DataModule1.ADOQuery1 do

  begin

    Close;

    SQL.Clear;

    SQL.Add('select * from tb_Branch');

    Open;

  end;

  with DataModule1.ADOQuery1 do

  begin

    if RecordCount>0 then

    begin

      while Not Eof do

      begin

        ComboBox1.Items.Add(FieldByName('Name').AsString);

        Next;

      end;

    end;

  end;

end;

在进入“登录”窗体后,操作员可以直接在部门下拉列表中选择已有的部门,为了能够更方便的进行登录操作,在选择完部门后,将自动在用户名下拉列表中添加当前部门下的所有用户名信息。该操作可以在部门下拉列表的OnChange事件中实现。代码如下:

procedure TFrm_Enter.ComboBox1Change(Sender: TObject);

begin

  if ComboBox1.Text = '' then

    Exit;

  with DataModule1.ADO_User do

  begin

    Close;

    SQL.Clear;

    SQL.Add('select * from tb_Branch_User where User_Branch='+''''

+Trim(ComboBox1.Text)+'''');

    Open;

  end;

  ComboBox2.Clear;

  if DataModule1.ADO_User.RecordCount>0 then

  begin

    while Not DataModule1.ADO_User.Eof do

    begin

      ComboBox2.Items.Add(DataModule1.ADO_User.FieldByName('User_Name').AsString);

      DataModule1.ADO_User.Next;

    end;

  end

  else

  begin

    showmessage('登录用户中没有'+ComboBox1.Text+'部门.');

    ComboBox1.ItemIndex := -1;

  end;

end;

为了能够确保操作员在没有选择部门和用户名时,就随意的进行登录,需要在窗体显示时,将“确定”按钮设为不可用,当选择用户名后,使“确定”按钮变为可用状态,同时查找部门和用户名相同的记录。这一过程可以在用户下拉列表的OnChange事件中实现。代码如下:

procedure TFrm_Enter.ComboBox2Change(Sender: TObject);

begin

  with DataModule1.ADO_User do

  begin

    Close;

    SQL.Clear;

    SQL.Add('select * from tb_Branch_User where User_Branch='+''''+Trim(ComboBox1.Text)

+''''+' and User_Name='+''''+ComboBox2.Text+'''');

    Open;

  end;

  Button1.Enabled := True;

end;

在密码文本框中输入密码后,便可以单击“确定”按钮,进行登录,因为本“登录”窗体是用同一个ADO组件以部门和用户名为条件进行查询,所以在“确定”按钮的OnClick事件中,可以直接对当前记录的密码进行判断,不需要再对部门和用户名进行查找。代码如下:

procedure TFrm_Enter.Button1Click(Sender: TObject);

begin

  if Edit1.Text<>'' then

  begin

    if DataModule1.ADO_User.FieldByName('User_Pass').AsString=Trim(Edit1.Text) then

    begin

      ifclose := 1;

      //用公共变量记录登录用户的相关信息

      Frm_Interface.User_Branch := Trim(ComboBox1.Text);

      Frm_Interface.User_ID := DataModule1.ADO_User.FieldByName('User_ID').AsString;

      Frm_Interface.User_Pop := DataModule1.ADO_User.FieldByName

('User_Popedom').AsInteger;

      Frm_Interface.User_Name := DataModule1.ADO_User.FieldByName

('User_Name').AsString;

      self.Close;

    end

    else

    begin

      Edit1.Text := '';

      showmessage('密码不正确,请重新输入。');

    end

  end

  else

    showmessage('请添写用户密码.');

end;

*   说明:Frm_Interface窗体中的User_Branch、User_ID、User_Pop变量是共有变量,用于记录登录用户的部门、编号和用户名。

以上就完成了对“登录”窗体的设置,下面对“操作员管理”窗体的制作过程进行详细说明。

在主窗体中,可以通过以下代码动态调用“操作员管理”窗体。

  Application.CreateForm(TFrm_ManageUser,Frm_ManageUser);

  Frm_ManageUser.ShowModal;

  Frm_ManageUser.Free;

在显示“操作员管理”窗体时,首先要将在登录时所选的部门名称为条件,在tb_Branch_User数据表中查询相关信息,并将所查询的信息显示在“操作员管理”窗体的DBGrid1组件上,同时将DBGrid1组件上的第一条信息显示在相对应的文本框中。例如以销售部门用户进行登录,“操作员管理”窗体的效果图如图3.18所示。

图3.18  以销售部门登录后的“操作员管理”窗体

以上操作可以在该窗体的OnShow事件中实现。代码如下:

procedure TFrm_ManageUser.FormShow(Sender: TObject);

var

  Str1 : String;

begin

  Edit1.Enabled := False;

  Edit2.Enabled := False;

  Edit3.Enabled := False;

  Edit4.Enabled := False;

  with DataModule1.ADO_user do

  begin

    Close;

    SQL.Clear;

    if Frm_Interface.User_Branch='总经理' then  //如果是总经理,显示所有用户信息

      Str1 := ''

    else  //按部门名称进行查询

      Str1 := ' where User_Branch='+''''+Frm_Interface.User_Branch+'''';

    SQL.Add('select * from tb_Branch_User'+Str1);

    Open;

    SNumber := FieldByName('User_ID').AsString;

  end;

  DataModule1.DataSource1.DataSet := DataModule1.ADO_user;

  self.DBGrid1.DataSource := DataModule1.DataSource1;

  if DataModule1.ADO_user.RecordCount>0 then

    ShowUser(Edit1, Edit2, Edit3, Edit4, DataModule1.ADO_user)

  else

  begin

    Edit1.Clear;

    Edit2.Clear;

    Edit3.Clear;

    Edit4.Clear;

  end;

end;

自定义过程ShowUser(),用于将当前记录的信息显示在指定的文本框中。

procedure TFrm_ManageUser.ShowUser(E1, E2, E3, E4 : TEdit; ADOQuer: TADOQuery);

begin

  E1.Text := ADOQuer.fieldbyname('User_ID').AsString;

  E2.Text := ADOQuer.fieldbyname('User_Name').AsString;

  E3.Text := ADOQuer.fieldbyname('User_Pass').AsString;

  E4.Text := ADOQuer.fieldbyname('User_Branch').AsString;

end;

ShowUser()过程的参数说明如表3.8所示。

表3.8                           ShowUser()过程的参数说明

参数

说明

E1, E2,E3,E4

TEdit类型,要进行赋值的文本框

ADOQuer

TADOQuery类型,用于获取数据表信息的数据源

在该窗体显示后,主要是在窗体中查看相应部门的操作员信息,以及对操作员信息进行添加、修改和删除的操作。

查看操作员信息,可以用鼠标双击DBGrid1组件中的信息记录,将当前所选信息显示在相应的文本框上,可以在DBGrid1组件的OnCellClick事件中实现,代码如下:

procedure TFrm_ManageUser.DBGrid1CellClick(Column: TColumn);

begin

  with DataModule1.ADO_user do

  begin

    Edit1.Text :=  fieldbyname('User_ID').AsString;

    Edit2.Text :=  fieldbyname('User_Name').AsString;

    Edit3.Text :=  fieldbyname('User_Pass').AsString;

    Edit4.Text :=  fieldbyname('User_Branch').AsString;

    SNumber := FieldByName('User_ID').AsString;

  end;

end;

在查看操作员信息时,也可以通过ADO组件的First(首记录)、Prior(上一条记录)、Next(下一条记录)、Last(尾记录)方法来移动该组件中的记录指针,实现在ADO组件中浏览记录的功能。可以用4个按钮来实现ADO组件的以上4个方法。在这里只对“上一条”按钮的操作过程进行讲解,其他按钮的操作过程与该按钮的操作过程基本相同,只是所用的方法不一样。代码如下:

procedure TFrm_ManageUser.ToolButton6Click(Sender: TObject);

begin

  DataModule1.ADO_user.Prior;  //记录向上移动一条

  MoveNote(ToolButton5,ToolButton6,ToolButton7,ToolButton8,DataModule1.ADO_user,

0,1,0,0);

  ShowUser(Edit1,Edit2,Edit3,Edit4,DataModule1.ADO_user);

end;

自定义过程MoveNote(),用于在记录移动时,控制按钮的可用状态,例如,当按钮已指向首记录时,再单击“上一条”按钮时,“首记录”和“上一条”按钮将设为不可用状态。代码如下:

procedure TFrm_ManageUser.MoveNote(TB1, Tb2, TB3, TB4: TToolButton;

  ADOQuer: TADOQuery; Int1, Int2, Int3, Int4: Integer);

begin

  if Int1=1 then

  begin

    TB1.Enabled := False;

    TB2.Enabled := False;

    TB3.Enabled := true;

    TB4.Enabled := true;

  end;

  if Int2=1 then

  begin

    if not ADOQuer.Bof then

    begin

      TB1.Enabled := true;

      TB2.Enabled := true;

      TB3.Enabled := true;

      TB4.Enabled := true;

    end

    else

    begin

      TB1.Enabled := false;

      TB2.Enabled := false;

      TB3.Enabled := true;

      TB4.Enabled := true;

    end;

  end;

  if Int3=1 then

  begin

    if not ADOQuer.Eof then

    begin

      TB1.Enabled := true;

      TB2.Enabled := true;

      TB3.Enabled := true;

      TB4.Enabled := true;

    end

    else

    begin

      TB1.Enabled := true;

      TB2.Enabled := true;

      TB3.Enabled := false;

      TB4.Enabled := false;

    end;

  end;

  if Int4=1 then

  begin

    TB1.Enabled := true;

    TB2.Enabled := true;

    TB3.Enabled := False;

    TB4.Enabled := False;

  end;

end;

MoveNote()过程的参数说明如表3.9所示。

表3.9                           MoveNote()过程的参数说明

参数

说明

TB1, Tb2, TB3, TB4

TToolButton类型,要设置可用状态的按钮

ADOQuer

TADOQuery类型,用于获取数据表信息的数据源

Int1, Int2, Int3, Int4

标识,用于记录当前执行的是那个按钮

下面重点对部门用户操用员的添加、修改、删除进行讲解。

在进行讲解前,首先要了解用户数据表(tb_Branch_User)的记录信息。如图3.19所示。

图3.19  用户数据表(tb_Branch_User)信息

在tb_Branch_User数据表中可以看到User_Popedom字段记录了各部门操作员的权限,每个部门都会有一个主管,主管只能对该部门下的操作员信息进行操作,而“总经理”的权限是最高的,不但可以对所有操作员的信息进行操作,还可以对各部门的主管进行任命。

在“操作员管理”窗体单击“添加”按钮,会调用“添加用户”窗体,在调用该窗体前,首先要根据Frm_Interface窗体的共有变量User_Pop来判断当前用户是否有添加其他操作员的权限,当User_Pop变量为0时,表示当前用户为普通用户,没有权限进行添加。调用“添加用户”窗体是在ToolButton1按钮的OnClick事件中完成的。代码如下:

procedure TFrm_ManageUser.ToolButton1Click(Sender: TObject);

begin

  if Frm_Interface.User_Pop<>0 then

  begin

    AddNum := ADDNumber(DataModule1.ADOQuery2,'tb_Branch_User');

    Application.CreateForm(TFrm_AddUser,Frm_AddUser);

    Frm_AddUser.ShowModal;

    Frm_AddUser.Free;

  end

  else

    showmessage('无权限添加操作员。');

end;

在调用“添加用户”窗体后,在窗体的OnShow事件中将部门表中的部门名称添加到该窗体的部门下拉列表中。然后,判断当前操作员是否为“总经理”,如果是,可以在添加操作员时,选择部门;如果只是部门主管,则只能在当前部门下添加新操作员。代码如下:

procedure TFrm_AddUser.FormShow(Sender: TObject);

begin

  Edit1.Text := Frm_ManageUser.AddNum;

  Edit2.Clear;

  Edit3.Clear;

  ComboBox1.Clear;

  with DataModule1.ADOQuery1 do

  begin

    Close;

    SQL.Clear;

    SQL.Add('select * from tb_Branch');

    Open;

  end;

  with DataModule1.ADOQuery1 do

  begin

    if RecordCount>0 then

    begin

      while Not Eof do  //向部门下拉列表中添加部门名称

      begin

        if FieldByName('Name').AsString<>'总经理' then

          ComboBox1.Items.Add(FieldByName('Name').AsString);

        Next;

      end;

    end;

  end;

  if Frm_Interface.User_Pop=3 then  //判断是否为部门主管

  begin

    ComboBox1.Text := Frm_Interface.User_Branch;

    ComboBox1.Enabled := False;  //将部门下拉列表设为不可用状态

  end;

  Button2.SetFocus;

end;

如果当前操作员是“总经理”,就可以在添加新操作员时,在部门下拉列表中选择部门后,使“部门主管”复选框变为可编辑状态。可以在下拉列表的OnChange事件中完成。代码如下:

procedure TFrm_AddUser.ComboBox1Change(Sender: TObject);

begin

  if Frm_Interface.User_Pop=1 then

    CheckBox1.Enabled := True

  else

    CheckBox1.Enabled := False;

end;

在设置“部门主管”复选框时,会在该复选框的OnMouseUp事件(鼠标松开)中,查找当前部门是否有部门主管,如果有,则弹出一个判断对话框,提示“已有部门主管,是否重新定义”,如图3.20所示。

图3.20  添加操用员时设为部门主管

如果单击“是”,则用变量P进行标识,并将复选框设为选中状态。代码如下:

procedure TFrm_AddUser.CheckBox1MouseUp(Sender: TObject;

  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

  if CheckBox1.Checked=true then

  begin

    with DataModule1.ADOQuery1 do

    begin

      Close;

      SQL.Clear;

      SQL.Add('select * from tb_Branch_User where User_Branch='+''''+ComboBox1.Text

+''''+' and User_Popedom>0');

      Open;

    end;

    if DataModule1.ADOQuery1.RecordCount>0 then

    begin

      if Application.MessageBox(Pchar('已经有'+ComboBox1.Text+'主管,是否重新定义?'),

'提示',MB_YESNO)=IDYes then

      begin

        p := 1;

        CheckBox1.Checked := True;

      end

      else

        CheckBox1.Checked := False;

    end;

  end;

end;

添加操作员的条件设置完成后,便可以单击“确定”按钮,将其插入到用户数据表中。可以在该按钮的OnClick事件中完成。代码如下:

procedure TFrm_AddUser.Button1Click(Sender: TObject);

begin

  if ((Edit1.Text<>'') and (Edit2.Text<>'') and (Edit3.Text<>'') and

(ComboBox1.Text<>'')) then

  begin

    with DataModule1.ADOQuery1 do  //查询数据表中是否有添加的用户名,如果有,重新输入

    begin

      Close;

      SQL.Clear;

      SQL.Add('select * from tb_Branch_User where User_Name='+''''+Edit2.Text+'''');

      Open;

    end;

    if DataModule1.ADOQuery1.RecordCount<1 then

    begin

      with DataModule1.ADO_User do

      begin

        if P=1 then  //如果要将新添加的操作员设为部门主管,就应将已有的部门主管先设为普通用户

        begin

          with DataModule1.ADOQuery2 do

          begin

            Close;

            SQL.Clear;

            SQL.Add('select * from tb_Branch_User where User_Branch='+''''+

Trim(ComboBox1.Text)+'''');

            Open;

            while Not Eof do

            begin

              if FieldByName('User_Popedom').AsInteger>0 then

              begin

                Edit;

                FieldByName('User_Popedom').AsInteger := 0;

                Post;

                Break;

              end;

              Next;

            end;

          end;

        end;

        DataModule1.ADO_User.Insert;  //添加操作员信息

        DataModule1.ADO_User.FieldByName('User_ID').AsString := Edit1.Text;

        DataModule1.ADO_User.FieldByName('User_Name').AsString := Edit2.Text;

        DataModule1.ADO_User.FieldByName('User_Pass').AsString := Edit3.Text;

        DataModule1.ADO_User.FieldByName('User_Branch').AsString := ComboBox1.Text;

        if CheckBox1.Checked=True then  //设置部门主管的标识

          DataModule1.ADO_User.FieldByName('User_Popedom').AsInteger := 3

        else

          DataModule1.ADO_User.FieldByName('User_Popedom').AsInteger := 0;

        DataModule1.ADO_User.Post;

      end;

      Close;

    end

    else

    begin

      Edit2.Clear;

      showmessage('用户名已存在');

    end;

  end

  else

    showmessage('请将信息添写完整。');

end;

在部门用户中修改操作员信息有两种,一种是上级对下级的修改;一种是登录用户只能对自已进行修改。

当单击“修改”按钮后,将调用“修改用户”窗体,在调用该窗体前,首先要根据Frm_Interface窗体的共有变量User_Pop来判断当前用户是否为普通用户(当User_Pop为0时,为普通用户),如果是普通用户,则只能对自已的用户名及密码进行修改,否则,可以对被管理的操作员进行修改。调用“修改用户”窗体是在ToolButton2按钮的OnClick事件中完成的。代码如下:

procedure TFrm_ManageUser.ToolButton2Click(Sender: TObject);

begin

  if Frm_Interface.User_Pop>0 then  //调用一个选择窗体

  begin

    Application.CreateForm(TFrm_AmendPopedom,Frm_AmendPopedom);

    Frm_AmendPopedom.ShowModal;

    Frm_AmendPopedom.Free;

  end

  else

  begin  //凋用自修改窗体

    Application.CreateForm(TFrm_AmendUser,Frm_AmendUser); 

    Frm_AmendUser.ShowModal;

    Frm_AmendUser.Free;

  end;

end;

当登录用户是部门主管时,则调用“选择修改权限”窗体(Frm_AmendPopedom),该窗体是一个选择窗体,通过该窗体即可以对当前部门下的所有操作员进行修改,也可以只对登录用户进行修改。如图3.21所示。

图3.21  “选择修改权限”窗体

在“选择修改权限”窗体显示时,首先要根据Frm_Interface窗体的共有变量User_Pop和User_Branch,修改第一个单选按钮的文本信息,使操作员在选择时知道修改的是那个部门下的操作员信息。以上操作可以在“选择修改权限”窗体的OnShow事件中完成。代码如下:

procedure TFrm_AmendPopedom.FormShow(Sender: TObject);

begin

  if Frm_Interface.User_Pop=1 then

    RadioButton1.Caption := '修改所有操作员信息'

  else

    RadioButton1.Caption := '修改'+Frm_Interface.User_Branch+'内的所有操作员信息';

end;

在该窗体中选择要操作的修改窗体单选按钮后,单击“确定”按钮,调用相应的修改窗体。代码如下:

procedure TFrm_AmendPopedom.Button1Click(Sender: TObject);

begin

  if ((RadioButton1.Checked=True) or (RadioButton2.Checked=True)) then

  begin

    if RadioButton1.Checked=True then  //调用部门操作员修改窗体

    begin

      Application.CreateForm(TFrm_Amend_All_User,Frm_Amend_All_User);

      Frm_Amend_All_User.ShowModal;

      Frm_Amend_All_User.Free;

      close;

    end;

    if RadioButton2.Checked=True then  //调用自修改窗体

    begin

      Application.CreateForm(TFrm_AmendUser,Frm_AmendUser);

      Frm_AmendUser.ShowModal;

      Frm_AmendUser.Free;

      close;

    end;

  end

  else

    showmessage('请选择一种修改方式');

end;

下面先对“部门操作员修改”窗体进行讲解,该窗体可以对当前部门中的所有操作员的信息进行修改。在窗体显示时,首先要将该部门下的所有操作员名称添加到用户名下拉列表中,然后将所有部门名称添加到部门下拉列表中。当登录用户为“总经理”时,将部门下拉列表和“部门主管”复选框设为可用状态,否则设为不可用。这是因为“总经理”可以修改任意部门的操作员信息,也可以重新设置部门主管,但部门主管只能对该部门的用户进行修改。以上操作可以在窗体的OnShow事件中完成。代码如下:

procedure TFrm_Amend_All_User.FormShow(Sender: TObject);

var

  i : Integer;

  Str1 : String;

begin

  Edit1.Clear;

  with DataModule1.ADOQuery2 do  //将当前部门下的所有用户名,添加到用户下拉列表中

  begin

    Close;

    SQL.Clear;

    if Frm_Interface.User_Branch='总经理' then

      Str1 := ''

    else

      Str1 := ' where User_Branch='+''''+Frm_Interface.User_Branch+'''';

    SQL.Add('select * from tb_Branch_User'+Str1);

    Open;

    if RecordCount>0 then

    begin

      ComboBox1.Clear;

      while Not Eof do

      begin

        ComboBox1.Items.Add(FieldByName('User_Name').AsString);

        next;

      end;

    end;

  end;

  ComboBox2.Clear;

  with DataModule1.ADOQuery2 do  //将部门名称添加到部门下拉列表中

  begin

    Close;

    SQL.Clear;

    SQL.Add('select * from tb_Branch');

    Open;

    if RecordCount>0 then

      while Not Eof do

      begin

        if Frm_Interface.User_Branch<>FieldByName('Name').AsString then

          ComboBox2.Items.Add(FieldByName('Name').AsString);

        next;

      end;

  end;

  //如果当前操作员是“总经理”,则部门下拉列表和“部门主管”复选框设为可用状态

  if Frm_Interface.User_Pop=1 then

  begin

    ComboBox2.Enabled := True;

    CheckBox1.Enabled := True;

  end

  else

  begin

    ComboBox2.Enabled := False;

    CheckBox1.Enabled := False;

  end;

end;

在用户下拉列表中选择用户名称后,将在“部门”文本框中显示所在部门,在“部门主管”复选框中显示其用户的权限,该操作可以在用户下拉列表的OnChange事件中完成。代码如下:

procedure TFrm_Amend_All_User.ComboBox1Change(Sender: TObject);

begin

  with DataModule1.ADOQuery2 do

  begin

    Close;

    SQL.Clear;

    SQL.Add('select * from tb_Branch_User where User_Name='+''''+ComboBox1.Text+'''');

    Open;

    ComboBox2.Text := FieldByName('User_Branch').AsString;

    if FieldByName('User_Popedom').AsInteger>0 then

    begin

      CheckBox1.Checked := True;

      n := 1;

    end

    else

    begin

      CheckBox1.Checked := False;

      n := 0;

    end

  end;

end;

  注意:以上方法只能在用户名为唯一的情况下,才可以应用。

在选择“部门主管”复选框时,首先要在该复选框的OnMouseUp事件中查找当前部门是否有部门主管,如果有,则弹出一个对话框,提示“已有部门主管,是否重新定义?”,如图3.22所示。

图3.22  修改操用员时重新设为部门主管

实现代码如下:

procedure TFrm_Amend_All_User.CheckBox1MouseUp(Sender: TObject;

  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

  if CheckBox1.Checked=true then

  begin

    with DataModule1.ADOQuery1 do  //查找当前用户是否为部门主管

    begin

      Close;

      SQL.Clear;

      SQL.Add('select * from tb_Branch_User where User_Branch='+''''+

Frm_Interface.User_Branch+''''+' and User_Popedom>0');

      Open;

    end;

    if DataModule1.ADOQuery1.RecordCount>0 then  //如果有记录,表是是部门主管

    begin

      if Application.MessageBox(Pchar('已经有'+Frm_Interface.User_Branch+'主管,

是否重新定义?'),'提示',MB_YESNO)=IDYes then

      Begin  //当同意重新设置部门主管时,选中“部门主管”复选框,并用变量P作为标识

        p := 1;

        CheckBox1.Checked := True;

      end

      else

        CheckBox1.Checked := False;

    end;

  end;

end;

在“部门操作员修改”窗体中对可修改的操作员信息设置完成后,便可以单击“确定”按钮,对其进行修改。代码如下:

procedure TFrm_Amend_All_User.Button1Click(Sender: TObject);

begin

  if ((ComboBox1.Text='') or (ComboBox2.Text='') or (Edit1.Text='')) then

    showmessage('请将修改条件添写完整。')

  else

  begin

    with DataModule1.ADOQuery2 do  //查找当前所选择的操作员信息

    begin

      Close;

      SQL.Clear;

      SQL.Add('select * from tb_Branch_User where User_Name='+''''+

ComboBox1.Text+'''');

      Open;

      Edit;  //对当前操作员信息进行修改

      FieldByName('User_Pass').AsString := Trim(Edit1.Text);  //重新设置操作员密码

      if ComboBox2.Enabled = True then

        FieldByName('User_Branch').AsString := Trim(ComboBox2.Text);  //重新设置部门

      //如果当前部门下有部门主管理,并且当前用户不是部门主管,执行以下代码

      if ((p=1) and (n=0)) then

      begin

        with DataModule1.ADOQuery1 do  //查找当前部门下的所有操作员

        begin

          Close;

          SQL.Clear;

          SQL.Add('select * from tb_Branch_User where User_Branch='+''''+

Trim(ComboBox2.Text)+'''');

          Open;

          while Not Eof do  //查找部门主管

          begin

            if FieldByName('User_Popedom').AsInteger>0 then

            begin

              Edit;

              FieldByName('User_Popedom').AsInteger := 0;  //撤消当前部门的部门主管

              Post;

              Break;

            end;

            Next;

          end;

        end;

        FieldByName('User_Popedom').AsInteger := 3;  //将要修改的操作员设为部门主管

      end

      else

      begin

        //当没有部门主管时,判断是否将当前操作员设为部门主管

        if ((P=0) and (CheckBox1.Checked=True)) then

          FieldByName('User_Popedom').AsInteger := 3

        else

          FieldByName('User_Popedom').AsInteger := 0;

      end;

      Post;

    end;

    DataModule1.ADO_User.Active := False;  //刷新ADO_User数据信息

    DataModule1.ADO_User.Active := True;

    Close;

  end;

  with DataModule1.ADO_user do  //刷新Frm_ManageUser窗体中的文本框信息

  begin

    Frm_ManageUser.Edit1.Text :=  fieldbyname('User_ID').AsString;

    Frm_ManageUser.Edit2.Text :=  fieldbyname('User_Name').AsString;

    Frm_ManageUser.Edit3.Text :=  fieldbyname('User_Pass').AsString;

    Frm_ManageUser.Edit4.Text :=  fieldbyname('User_Branch').AsString;

    Frm_ManageUser.SNumber := FieldByName('User_ID').AsString;

  end;

end;

以上就完成了对部门操作员的修改,下面对当前操作员的自修改过程进行讲解。

在“选择修改权限”窗体中选择“修改当前用户信息”单选按钮,如图3.17所示,单击“确定”按钮,便可以调用“修改用户”窗体,如图3.23所示。

图3.23  “修改用户”窗体

在“修改用户”窗体显示时,首先将当前登录的操作员名称,在该窗体的用户名文本框中进行显示,该操作可以在本窗体的OnShow事件中实现。代码如下:

procedure TFrm_AmendUser.FormShow(Sender: TObject);

begin

  Edit1.Clear;

  Edit2.Clear;

  Edit3.Clear;

  Edit4.Text := Frm_Interface.User_Name;

  Button2.SetFocus;

end;

在窗体显示后,便可以在窗体中输入用户名及密码,单击“确定”按钮,便可以对其进行修改。代码如下:

procedure TFrm_AmendUser.Button1Click(Sender: TObject);

begin

  if Edit4.Text<>'' then

  begin

    if Edit1.Text=Edit2.Text then  //判断输入的密码是否一致

    begin

      with DataModule1.ADOQuery1 do  //查找当前登录用户的信息

      begin

        Close;

        SQL.Clear;

        SQL.Add('select * from tb_Branch_User where User_Name='+''''+

Trim(Edit4.Text)+'''');

        Open;

        if DataModule1.ADOQuery1.RecordCount>0 then

          if Trim(Edit4.Text)<>Trim(Frm_Interface.User_Name) then

          begin

            showmessage('当前用户名已存在。');

            Edit4.Text := Frm_Interface.User_Name;

            Edit1.Clear;

            Edit2.Clear;

            Edit3.Clear;

            Exit;

          end;

        Close;

        SQL.Clear;

        SQL.Add('select * from tb_Branch_User where User_ID='+''''+

Trim(Frm_Interface.User_ID)+''''+' and User_Pass='+''''+Trim(Edit1.Text)+'''');

        Open;

        if RecordCount>0 then

        begin

          Edit;  //修改当前登录用户的用户名及密码

          FieldByName('User_Name').AsString := Trim(Edit4.Text);

          FieldByName('User_Pass').AsString := Trim(Edit3.Text);

          Post;

          with DataModule1.ADO_User do  //刷新Frm_ManageUser窗体中的信息

          begin

            Active := False;

            Active := True;

            Frm_ManageUser.Edit2.Text := FieldByName('User_Name').AsString;

            Frm_ManageUser.Edit3.Text := FieldByName('User_Pass').AsString;

            Frm_Interface.User_Name := Trim(Edit4.Text);

          end;

          self.Close;

        end

        else

        begin

          Edit1.Clear;

          Edit2.Clear;

          Edit3.Clear;

          showmessage('密码错误。')

        end;

      end;

    end

    else

    begin

      Edit1.Clear;

      Edit2.Clear;

      Edit3.Clear;

      showmessage('用户密码不一致,请重新输入.');

    end;

  end

  else

    showmessage('用户名不能为空.');

end;

在删除操作员信息时,也是按照部门等级来删除的,例如,总经理可以删除所有操作员的信息,而不能删除自己的信息;部门主管只能删除该部门下的操作员信息,而不能删除自己的信息,只能由总经理进行删除;普通操作员没有删除操作员信息的权限。“删除”按钮的相关代码如下:

procedure TFrm_ManageUser.ToolButton3Click(Sender: TObject);

begin

  if Frm_Interface.User_Pop<>0 then  //判断是否为普通操作员

  begin

    if Frm_Interface.User_Pop>0 then

    begin

      if Frm_Interface.User_Name=DataModule1.ADO_user.FieldByName

('User_Name').AsString then

        showmessage('操作员不能删除自己。')

      else

      begin

        //判断是否删除部门主管

        if DataModule1.ADO_user.FieldByName('User_Popedom').AsInteger>0 then

        begin

          if Application.MessageBox('是否删除部门主管?','提示',MB_YesNo+MB_ICONQUESTION)

=IDYes then

          begin

            DataModule1.ADO_user.Delete;

            DataModule1.ADO_user.First;

            ShowUser(Edit1, Edit2, Edit3, Edit4, DataModule1.ADO_user);

          end;

        end

        else

          if Application.MessageBox('是否删除当前用户?','提示',MB_YesNo+MB_ICONQUESTION)

=IDYes then

          begin   //删除当前所选择的操作员

            DataModule1.ADO_user.Delete;

            DataModule1.ADO_user.First;

            ShowUser(Edit1, Edit2, Edit3, Edit4, DataModule1.ADO_user);

          end;

      end;

    end;

  end

  else

    showmessage('无权限删除操作员。');

end;

3.补充说明

在对数据表中的数据进行浏览时,可以通过鼠标单击TDBGrid组件中的数据记录,将其选中的记录信息显示在指定的文本框中。那么,是否可以用键盘中的“↑”和“↓”键,在TDBGrid组件中上下移动记录时,将当前所选中的记录显示在指定的文本框中呢?可以应用ADO组件中的OnAfterScroll事件来完成,该事件是在记录集指针滚动后发生。实现代码如下:

procedure TForm1.ADOQuery1AfterScroll(DataSet: TDataSet);

begin

  if ADOQuery1.Active=true then

  begin

  with ADOQuery1 do

  begin

    Edit1.Text :=  fieldbyname('User_ID').AsString;

    Edit2.Text :=  fieldbyname('User_Name').AsString;

    Edit3.Text :=  fieldbyname('User_Pass').AsString;

    Edit4.Text :=  fieldbyname('User_Branch').AsString;

  end;

  end;

end;

3.2.4  局域网用户登录

在开发一些业务性比较强的管理软件时,管理软件不可能只有一个人使用,为了节省操作业务的时间,可以通过局域网,使多个用户同时进行操作。例如进销存管理系统,进货人员在进货的同时,销售人员可以进行货物的销售,而审核人员也可以对上一次货物的销售情况进行审核。这样,就需要多个用户同时进行登录,并对一个数据库进行操作。本节将对局域网用户登录窗体的制作进行详细说明。

1.方案分析

局域网用户登录就是在一个局域网中,多个客户端用户可以同时登录一个服务器端,并对该服务器端数据库中的内容进行修改。这种登录方式可以让多个不同权限的用户对管理软件同时进行操作,以节省多个用户操作的时间及流程。下面给出局域网用户登录的流程图,如图3.24所示。

图3.24  局域网用户登录的流程图

在制作局域网用户登录方案时,主要有以下几个难点:

(1)如何用ADO组件与局域网中的数据库相连接。

(2)如何在第一次登录时,配置服务器地址和数据库名后,以后会自动连接。

2.实施过程

在开发一些操作流程比较连贯的软件时,可以以局域网的方式,让多个用户同时进行操作。例如进销存管理系统,在进货部进货后,进货部操作员要进行信息的录入,信息录入后,要提示库存部操作员进行入库,而销售部在销售完货物时,要提示审核部操作员进行审核,查看库存货物是否不足,如果不足,则提示进货部操作人员某种货品应进货。下面以一个进销存管理系统为例,介绍部门用户登录方案的制作过程。

*    实例位置:光盘/mr/3/3.2/3.2.4/01

在制作局域网用户登录窗体时,窗体中要有服务器端的ID地址的名称、用户名及密码输入文本框,为了使输入的密码处于保密状态,将密码文本框中的字符用“*”来表示,如图3.25所示。

图3.25  局域网用户登录窗体

在制作登录窗体前,首先要在数据库中制作一个用户表(tb_LAN_User),该表记录了本系统的合法用户名和密码。tb_LAN_User数据表的关系图如图3.26所示。

图3.26  tb_LAN_User数据表的关系图

在第一次运行客户端“登录”窗体时,要单击“服务器地址”按钮,在弹出的“配置数据库”窗体中对服务器(服务器即可以是IP地址,也可以是服务器端计算机的名称)和数据库进行配置,单击“确定”按钮进行保存,以便下次直接进行登录。然后,在“登录”窗体中输入用户名及密码进行登录。数据库配置如图3.27所示。

图3.27  对数据库进行配置

下面就详细介绍登录窗体的制作过程。

在主窗体显示前,动态调用登录窗体,可以在主窗体的OnShow事件中动态调用。代码如下:

procedure TFrm_Main.FormShow(Sender: TObject);

begin

  Application.CreateForm(TFrm_Enter,Frm_Enter);

  Frm_Enter.ShowModal;

  Frm_Enter.Free;

end;

之所以在主窗体的OnShow事件中动态调用登录窗体,是因为在用户名和密码正确时,关闭登录窗体,可以直接进入主窗体;当直接关闭登录窗体,或按“取消”按钮时,通过Application.Terminate语句,关闭整个工程。

本方案为了能确保在第一次配置完数据库后,下次登录不必在配置,将配置后的信息保存在INI文件中。在“登录”窗体创建时,首先要在指定的路径下查找是否有conn.ini文件,如果有,则将该文件中所保存的服务器和数据库信息,通过ADOConnection1组件中的ConnectionString属性与服务器端的数据库相连接。代码如下:

procedure TFrm_Enter.FormCreate(Sender: TObject);

begin

  CollocateData;

end;

自定义过程CollocateData,用于完成在“登录”窗体创建时与服务器端数据库相连接的操作。之所以将操作过程封装到CollocateData过程中,是为了在“配置数据库”窗体中配置完数据库后,使数据源直接与数据库相连接,否则,必需退出本系统后重新登录。该过程代码如下:

procedure TFrm_Enter.CollocateData;

begin

  IDName := '';

  DateName := '';

  GetSystemDirectory(Dir, MAX_PATH);

  with TIniFile.Create(Dir + '/conn.ini') do

  begin

    if FileExists(Dir + '/conn.ini') then

      begin

        IDName := ReadString('DataSource', 'TEXT1', '');

        DateName := ReadString('DataSource', 'TEXT2', '');

      end;

    free;

  end;

  if (Length(IDName) <> 0) and (Length(DateName) <> 0) then

  begin

    DataModule1.ADOConnection1.Connected := False;

    DataModule1.ADOConnection1.ConnectionString := 'Provider=SQLOLEDB.1;Password

= ''''' +

      ';Persist Security Info=True;User ID= sa;' +

      'Initial Catalog=' + DateName + ';Data Source=' + IDName;

    try

      DataModule1.ADOConnection1.Open;

    except

    end;

  end

  else

    showmessage('数据库没有连接成功,请连接数据库。');

end;

在窗体显示时,首先要判断全局变量DateName中是否记录了数据库名,如果有,则将服务器端的IP地址显示在“登录”窗口的指定文本框中,否则,文本框将为空,表示必需在配置数据库后,方可登录。代码如下:

procedure TFrm_Enter.FormShow(Sender: TObject);

begin

  Edit1.Clear;

  Edit2.Clear;

  Edit3.Clear;

  if DateName<>'' then

  begin

    Edit3.Text := IDName;

    Edit1.SetFocus;

  end

  else

    Edit3.SetFocus;end;

如果没有配置服务器地址,单击“登录”窗体中的“服务器地址”按钮,调用“配置数据库”窗体,代码如下:

procedure TFrm_Enter.SpeedButton1Click(Sender: TObject);

begin

  Application.CreateForm(TFrm_Collocate,Frm_Collocate);

  Frm_Collocate.ShowModal;

  Frm_Collocate.Free;

end;

在“配置数据库”窗体显示时,要在该窗体的OnShow事件中设置服务器和数据库的默认信息。代码如下:

procedure TFrm_Collocate.FormShow(Sender: TObject);

begin

  Edit1.Text := '127.0.0.1';  //IP地址为本地计算机

  Edit2.Text := 'MR_Distribution';  //默认的数据库名称

  Edit1.SetFocus;  //设置焦点

end;

在配置数据库时,为了可以完全用键盘操作,可以在文本框中输入完数据后,按“回车”键,将焦点移动到指定的文本框中,直至单击“确定”按钮。可以在各文本框中的OnKeyPress事件中进行焦点移动操作。代码如下:

procedure TFrm_Collocate.Edit1KeyPress(Sender: TObject; var Key: Char);

begin

  if Key = #13 then  //判断是否按“回车”键

    Edit2.SetFocus;  //要移动到的焦点位置

end;

在输入完服务器地址和数据库信息后,单击“确定”按钮,将信息保存在系统盘的C:/WINDOWS/system32目录下的conn.ini文件中,并用“登录”窗体(Frm_Enter)的公有过程CollocateData将数据库与数据源相连接,以便返回登录窗体时,直接登录。代码如下:

procedure TFrm_Collocate.Button1Click(Sender: TObject);

var

  txtfile: TIniFile;

  Dir: array[0..MAX_PATH] of Char;

begin

  if Length(Edit1.Text) = 0 then  //判断服务器是否为空

    begin

      ShowMessage('服务器不能为空');

      Edit1.SetFocus;

      exit;

    end;

  if Length(Edit2.Text) = 0 then  //判断数据库名是否为空

    begin

      ShowMessage('数据库不能为空');

      Edit2.SetFocus;

      Abort;

    end;

  GetSystemDirectory(Dir, MAX_PATH);

  txtfile := TIniFile.Create(Dir + '/conn.ini');  //创建INI文件

  //向INI文件中写入数据

  txtfile.WriteString('DataSource', 'TEXT1', Trim(Edit1.Text));

  txtfile.WriteString('DataSource', 'TEXT2', Trim(Edit2.Text));

  txtfile.Free;

  Frm_Enter.CollocateData;  //连接数据源

  Frm_Enter.Edit3.Text := Edit2.Text;

  Close;  //关闭当前窗体

end;

在单击“配置数据库”窗体的“确定”按钮后,将关闭该窗体,重新进入“登录”窗体,在该窗体中输入用户名和密码后,单击“确定”按钮,可直接进行登录。代码如下:

procedure TFrm_Enter.BitBtn1Click(Sender: TObject);

begin

  if ((Edit1.Text<>'')and(Edit2.Text<>'')) then

  begin

    with DataModule1.ADO_User do

    begin

      Close;

      SQL.Clear;

      SQl.Add('select * from tb_LAN_User where User_Name='+''''+Trim(Edit1.Text)+'''');

      Open;

      if RecordCount>0 then

      begin

        if DataModule1.ADO_User.FieldByName('User_Pass').AsString=

Trim(Edit2.Text) then

        begin

          IsClose := 1;  //标识,用于判断以什么方式关闭窗体

          self.Close;

        end

        else

        begin

          showmessage('密码错误,请重新输入。');

          Edit2.Clear;

          Edit2.SetFocus;

        end;

      end

      else

      begin

        showmessage('用户名不存在');

        Edit2.Clear;

        Edit1.Clear;

        Edit1.SetFocus;

      end;

    end;

  end

  else

  begin

    showmessage('用户名和密码不能为空。');

    Edit1.SetFocus;

  end;

end;

在用户名和密码正确时,单击“确定”按钮,关闭的是“登录”窗体,当单击“取消”按钮时,关闭的是整个工程,可以用全局变量IsClose在该窗体的OnClose事件中进行判断,当IsClose变量不为0时,关闭当前窗体,否则,关闭整个工程。代码如下:

procedure TFrm_Enter.FormClose(Sender: TObject; var Action: TCloseAction);

begin

  if IsClose=0 then

    Application.Terminate;

end;

以上就完成了局域网用户登录窗体的制作过程。

3.补充说明

在保存INI文件时,为了可以让操作员便于找到INI文件,或是在INI文件中直接对数据信息进行修改,可以将INI文件保存在工程所在文件中。

Var

  txtfile: TIniFile;

  Dir : String;

begin

  Dir := ExtractfilePath(Application.ExeName);

  txtfile := TIniFile.Create(Dir + '/conn.ini');

  //向INI文件中写入数据

  txtfile.Free;

end;

3.2.5  角色用户登录

角色用户登录实际上就是将用户分成不同的角色进地登录,它不同于部门用户登录,部门用户登录是以各部门的应用权限来指定用户,而角色可以将各部门的应用权限以指定的用户进行操作。本节将主要介绍角色用户登录窗体的制作过程。

1.方案分析

本方案是一个局域网的角色用户登录程序,主要是利用用户设置的图片,如登录界面,按钮等,对登录界面进行设置,使登录界面不但具有动态效果,而且更加美观。在程序运行后,通过对服务器端的连接,将数据库中的角色用户名添加到图片与组件组合成的用户下拉列表中,以便选择相应的用户进行登录。下面给出角色用户登录的流程图,如图3.28所示。

图3.28  角色用户登录的流程图

在制作角色用户登录方案时,主要有以下几个难点:

(1)合理设置登录窗体的布局;

(2)如何使图片制作的按钮在单击时,具有动态效果;

(3)如何自制下拉列表;

(4)连接服务器端(也就是3.2.4节中的难点)。

2.实施过程

在制作一些应用程序时,为了使界面更加美观,可以用TImage组件以图片的形式,拼成一个登录窗体(也可以是其它样式的窗体)。下面以一个进销存管理系统为例,介绍“角色用户登录”窗体的制作过程。

*    实例位置:光盘/mr/3/3.2/3.2.5/01

本实例实现的“角色用户登录”窗体的效果如图3.29所示。

图3.29  角色用户登录

在制作登录窗体前,首先要在Mr_Distribution数据库中创建tb_Part_Table(角色名称数据表)和tb_Part_User(用户名数据表)数据表。

tb_Part_Table数据表用来存储所创建的角色名称,其关系图如图3.30所示。

图3.30  tb_Part_Table数据表的关系图

tb_Part_User数据表用来存储所创建的用户信息,其中要包含角色编号字段,便于角色与用户名建立连接。其关系图如图3.31所示。

图3.31  tb_Part_Table数据表的关系图

下面对“角色用户登录”窗体的制作进行详细的讲解。

首先对登录窗体中主要组件的相关设置进行一下说明,如表3.10所示。

表3.10                               各窗体的相关组件

对象名

对象类型

属性

描述

Image1

TImage

AutoSize

False

用于在登录窗体中显示登录界面的背景图

Picture

登录背景图片

Label1

TLabel

AutoSize

False

用于显示服务器IP地址

Edit1

TEdit

BorderStyle

bsNone

用于显示以选择的用户名称

ReadOnly

True

Edit3

BorderStyle

bsNone

显示无边框的密码文本框

Image2

TImage

AutoSize

False

设置用户下拉列表框的下拉按钮

Picture

下拉按钮图片

ListBox1

TListBox1

Ctl3D

False

用来实现下拉列表框

Panel1

TPanel

BevelOuter

bvNone

用来显示密码修改的相关组件

*   交叉链接:连接服务器的相关操作及代码,可参见3.2.4节,在这里不作详解。

在登录窗体显示时,首先在窗体的OnShow事件中设置窗体的大小,向自制的下拉列表框中添加数据表中的用户名。代码如下:

procedure TFrm_Logon.FormShow(Sender: TObject);

begin

  self.Height := 281;  //设置窗体的高度

  MyListBox := TListBox.Create(Self);  //创建一个TlistBox组件,用于记录用户编号

  MyListBox.Parent := Frm_Logon;

  MyListBox.Visible := False;

  CollocateData;

  ListBox1.Visible := False;  //隐藏用户下拉列表框

  Label1.Caption := 'IP:  '+IDName;  //显示服务器的IP地址

  Edit1.Clear;

  Edit2.Clear;

  Edit3.Clear;

end;

自定义函数CollocateData,通过“连接服务器端”按钮所生成的INI文件DataJoin,与服务器端的数据库相连接,并将数据库中的tb_Part_User表(用户表)中的用户名与用户编号以相同的顺序分别存入到ListBox1和MyListBox(动态生成的组件)组件中,并按用户的多少动态扩展下拉列表框。如图3.32所示。

图3.32  “角色用户登录”窗体的部分效果图

实现代码如下:

procedure TFrm_Logon.CollocateData;

var

  i,j : Integer;

begin

  j := 0;

  IDName := '';

  DateName := '';

  GetSystemDirectory(Dir, MAX_PATH);

  //查找已有的INI文件,并通过IP地址和数据库名称,与服务器中的数据库相连接

  with TIniFile.Create(Dir + '/DataJoin.ini') do

  begin

    if FileExists(Dir + '/DataJoin.ini') then

      begin

        IDName := ReadString('DataSource', 'TEXT1', '');

        DateName := ReadString('DataSource', 'TEXT2', '');

      end;

    free;

  end;

  if (Length(IDName) <> 0) and (Length(DateName) <> 0) then

  begin

    DataModule1.ADOConnection1.Connected := False;

    DataModule1.ADOConnection1.ConnectionString := 'Provider=SQLOLEDB.1;

Password= ''''' +      ';Persist Security Info=True;User ID= sa;' +

'Initial Catalog=' + DateName + ';Data Source=' + IDName;

    try

      DataModule1.ADOConnection1.Open;

      with DataModule1.ADOQuery1 do  //打开数据库中的tb_Part_User数据表

      begin

        Close;

        SQL.Clear;

        SQL.Add('select * from tb_Part_User');

        Open;

      end;

      ListBox1.Clear;

      MyListBox.Clear;

      //将用户名和用户编号分别存入ListBox1组件和动态生成的MyListBox组件中

      if DataModule1.ADOQuery1.RecordCount>0 then

      begin

        for i:=0 to DataModule1.ADOQuery1.RecordCount-1 do

        begin

          if DataModule1.ADOQuery1.FieldByName('Title').AsBoolean=False then

          begin

            ListBox1.Items.Add(DataModule1.ADOQuery1.FieldByName('User_Name')

.AsString);

            MyListBox.Items.Add(DataModule1.ADOQuery1.FieldByName

('Part_ID').AsString);

            j := j+1;

          end;

          DataModule1.ADOQuery1.Next;

          if ListBox1.Height>=60 then  //使下拉列表框根据记录的多少进行扩展

            ListBox1.Height := 65

          else

            ListBox1.Height := (j)*20;

        end;

      end;

    except

    end;

  end

  else

    showmessage('数据库没有连接成功,请连接数据库。');

end;

在窗体显示之后,可以单击用户下拉列表框的下拉按钮,来显示下拉列表框,并选择要登录的用户,该按钮是用Image2组件制作的,可以在该组件的OnMouseDown事件中完成下拉列表框的显示和隐藏的操作。代码如下:

procedure TFrm_Logon.Image2MouseDown(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

begin

  if ListBox1.Visible=True then

    ListBox1.Visible := False

  else

    ListBox1.Visible := True;

end;

当下拉列表框显示后,为了能实现光标在下拉列表框中进行移动时,焦点也随之移动的效果,可以在下拉列表框的OnMouseMove事件中完成其相关操作。代码如下:

procedure TFrm_Logon.ListBox1MouseMove(Sender: TObject; Shift: TShiftState;

  X, Y: Integer);

var

  Point : TPoint;

  Index : integer;

begin

  point.X := X;  //记录当前光标的位置

  point.Y := y;

  Index := listbox1.ItemAtPos(Point,True);  //获取当前光标所在记录的索引号

  if Index <> -1 then

    ListBox1.Selected[index] := True;  //使记录获得焦点

end;

在下拉列表框中单击要登录的用户名后,所选中用户名将在用户名文本框中进行显示,同时,将用户名所在的角色名显示在角色文本框中。以上操作将在下拉列表的OnClick事件中完成。代码如下:

procedure TFrm_Logon.ListBox1Click(Sender: TObject);

var

  S : String;

begin

  if ListBox1.Selected[ListBox1.ItemIndex] then

  begin

    Edit1.Text := ListBox1.Items[ListBox1.ItemIndex];

    ListBox1.Visible := False;

    with DataModule1.ADOQuery4 do  //查找用户所对应的角色名称

    begin

      Close;

      SQL.Clear;

      S := MyListBox.Items[ListBox1.ItemIndex];  //获取用户名编号

      SQL.Add('select Part_Name from tb_Part_Table where Part_ID='+QuotedStr(Trim(S)));

      Open;

      Frm_Main.PartID := Trim(S);

    end;

    if DataModule1.ADOQuery4.RecordCount>0 then  //在文本框中显示角色的名称

      Edit2.Text := DataModule1.ADOQuery4.FieldByName('Part_Name').AsString

  end;

end;

在密码框中输入正确的密码后,便可以通过单击“登录”按钮进行登录,该“登录”按钮是用Image5组件来制作的,当鼠标在该组件上按下时,该组件将改变按钮的效果,当鼠标松开时,将对用户名和密码进行判断,如果正确则进入主窗体,否则重新登录。以上操作主要是在Image5组件的OnMouseDown和OnMouseUp事件中实现的。代码如下:

procedure TFrm_Logon.Image5MouseDown(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

Begin  //动态改变按钮的效果

  Image5.Picture.LoadFromFile(SDirIma+'8.bmp');

end;

procedure TFrm_Logon.Image5MouseUp(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

Begin  //判断用户名及密码,进行登录

  ListBox1.Visible := False;

  if ((Edit1.Text<>'')and(Edit3.Text<>'')) then

  begin

    with DataModule1.ADOQuery1 do  //在tb_Part_User表中查找指定的用户名和密码

    begin

      Close;

      SQL.Clear;

      SQl.Add('select * from tb_Part_User where User_Name='+''''+Trim(Edit1.Text)+''''

+' and User_Pass='+''''+Trim(Edit3.Text)+'''');

      Open;

      if RecordCount>0 then  //如果记录存在,则进入主窗体

      begin

        IsClose := 1;

        Frm_Main.Name := Trim(Edit1.Text);

        self.Close;

      end

      else

      begin

        showmessage('密码错误,请重新输入。');

        Edit3.Clear;

        Edit3.SetFocus;

      end;

    end;

  end

  else

  begin

    showmessage('用户名和密码不能为空。');

    Edit1.SetFocus;

  end;

end;

  注意:本方案中的所有按钮,全是用TImage组件来制作的,其中该组件的OnMouseDown事件只是重新加载组件中的图片,以实现按钮的单击效果,以下按钮将不对OnMouseDown事件进行说明,只对OnMouseUp事件进行讲解。

在Image6组件的OnMouseUp事件中完成登录窗体的关闭操作。代码如下:

procedure TFrm_Logon.Image6MouseUp(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

begin

  IsClose := 0;

  Close;

end;

为了能够让登录用户更快速的修改用户密码,本方案在登录窗体上添加了一个“修改”按钮,用于在窗体的下面弹出一个修改密码的文本框。如图3.33所示。

图3.33  弹出修改密码文本框

以上操作在Image4组件的OnMouseUp事件中完成。代码如下:

procedure TFrm_Logon.Image4MouseUp(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

begin

  if Panel1.Visible then

  begin

    self.Height := 281;

    Panel1.Visible := False;

  end

  else

  begin

    self.ClientHeight := 354;

    Panel1.Visible := True;

  end;

end;

当显示修改密码文本框后,便可以在修改密码和确认密码文本框中输入要修改的密码,单击“修改”按钮进行修改。“修改”按钮的操作过程在Image7组件的OnMouseUp事件中完成。代码如下:

procedure TFrm_Logon.Image7MouseUp(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

begin

  if (Edit1.Text='') and (Edit3.Text='') then

  begin

    showmessage('请选择用户名及正确的密码。');

    Exit;

  end;

  if (Edit4.Text='') and (Edit5.Text='') then

  begin

    showmessage('请输入要修改的密码。');

    Exit;

  end;

  if (Edit4.Text<>Edit5.Text) then

  begin

    showmessage('修改密码与确认密码不同。');

    Exit;

  end;

  with DataModule1.ADOQuery2 do

  begin

    Close;

    SQL.Clear;

    SQL.Add('Select * from tb_Part_User where User_Name='+''''+Trim(Edit1.Text)+

''''+' and User_Pass='+''''+Trim(Edit3.Text)+'''');

    Open;

    if RecordCount>0 then

    begin

      Edit;

      FieldByName('User_Pass').AsString := Edit4.Text;

      Post;

    end

    else

      showmessage('原密码错误。');

  end;

end;

在修改完密码后,可以单击修改文本框中的按钮,使文本框隐藏,该按钮(Image8组件)的操作过程可以用“登录”按钮(Image4组件)的操作过程来实现,在这里不作讲解。

3.补充说明

在本方案中的所有按钮都是用TImage组件来制作的,为了使按钮更具有动态效果,当鼠标在按钮上进行移动时,可以用OnMouseMove事件改变TImage组件中的图片样式,同时设置一个标记,用于记录当前操作的是哪个按钮,当鼠标移出时,可以根据标记,在自定义过程(该过程能通过标记和Case语句,将所有按钮的图片恢复为默认状态,)中将TImage组件中的图片恢复为默认状态。

原创粉丝点击