【问题标题】:Undeclared Identifier using listboxes使用列表框的未声明标识符
【发布时间】:2014-11-19 20:53:21
【问题描述】:

我创建了一个列表框并使用它来添加和删除/加载并将项目保存到一个文件中,这一切都很好。但是,当我尝试在另一个单元上使用列表框时,我收到一个错误:未声明的标识符

MainUnit 下面的第一个单元是我尝试使用列表框并获取错误未声明标识符的地方。在MainUnit 下方是ManageUsersUnit,这是使用和创建列表框的单位。所有代码都适用于ManageusersUnit 上的列表框,但不适用于任何其他单元。

unit MainUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Menus, ExtCtrls;

implementation

uses AddTenantUnit, HomeUnit, MainMenuUnit;

{$R *.dfm}

{ the error im getting is in this procedure}

procedure TMainForm.FormCreate(Sender: TObject);.
begin                                    
  if fileExists('Newuser.dat')
  then
    begin
      UserListBox.Items.LoadFromFile('Newuser.dat');
    end
  {endif};
end;

unit ManageUsersUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, MainUnit, StdCtrls, Menus, ComCtrls;

type
  TManageUsersForm = class(TForm)
    AddUserButton: TButton;
    RemoveUserButton: TButton;
    ChangeUsernameButton: TButton;
    ChangePasswordButton: TButton;
    HomeButton: TButton;
    UserListBox: TListBox;
    UsernameEdit: TEdit;
    SaveButton: TButton;
    PasswordEdit: TEdit;
    SubText1Label: TLabel;
    SubText2Label: TLabel;
    PassListBox: TListBox;
    Button1: TButton;

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ManageUsersForm: TManageUsersForm;

implementation

uses PassWord, AddUserUnit, HomeUnit;

{$R *.dfm}

procedure TManageUsersForm.HomeButtonClick(Sender: TObject);
begin
  HomeForm.show;
  ManageUsersForm.Close;
end;

//Add UserName
procedure TManageUsersForm.AddUserButtonClick(Sender: TObject);

var
  i : integer;
  Found : Boolean;
  AddUser : string;

begin
  {ManageUsersForm.close;
  AddUserForm.ShowModal; }

  Found := false;
  AddUser := UsernameEdit.Text;

  i := 0;
  while i < userlistbox.Items.Count do
    begin
      if (UpperCase(AddUser) = Uppercase(userlistbox.Items[i]))
      then
        Found := True;
      inc(i);
    end;
  {endhwile};

  if Found = False then
    begin
      userlistbox.Items.Add(AddUser);
      UsernameEdit.Text := '';
      showMessage(AddUser + ' added');
    end
  else
    showMessage(AddUser + ' is already present.');
  {endif};
end;

procedure TManageUsersForm.RemoveUserButtonClick(Sender: TObject);
var
  deleted : string;
begin
  with UserListBox do
    begin
      if ItemIndex = -1
      then
        showMessage('You must select a User first.')
      else
        begin
          Deleted := Items.Strings[ItemIndex];
          Items.Delete(ItemIndex);
          showMessage(Deleted + ' deleted');
        end;
      {endif};
    end;
end;

procedure TManageUsersForm.Button1Click(Sender: TObject);
var
  i : integer;
  Found : Boolean;
  check : string;
begin
  check := PasswordEdit.Text;
  Found := false;

  i := 0;
  while i < userlistbox.Items.Count do
    begin
      if (UpperCase(check) = Uppercase(userlistbox.Items[i]))
      then
        Found := True;
      inc(i);
    end;
  {endhwile};

  if Found = False
  then
    begin
      showMessage(check + ' Incorrect Username');
    end
  else
    showMessage(' well done in file :).');
  {endif};
end;

procedure TManageUsersForm.SaveButtonClick(Sender: TObject);
begin
  assignfile (userFile,'Newuser.dat');
  UserListbox.Items.SaveToFile('Newuser.dat');
  showMessage('Saved to file');
end;

procedure TManageUsersForm.FormCreate(Sender: TObject);
begin
  if fileExists('Newuser.dat')
  then
    begin
      UserListBox.Items.LoadFromFile('Newuser.dat');
    end
  {endif};
end;

procedure TManageUsersForm.TestBtnClick(Sender: TObject);
begin
    AddUserForm.ShowModal;
end;

end.

【问题讨论】:

  • 您似乎知道使用个单位。你为什么不使用“ManageUsersUnit”呢? ManageUsersUnit.ManageUsersForm.UserListBox.Items.LoadFromFile('..
  • 列表框在一个类中。你真的应该从不同单位的不同班级戳它吗?不幸的是,Delphi 引导您使用这些全局变量并使 UI 对象随处可见。

标签: delphi listbox


【解决方案1】:

您的MainUnit 需要使用ManageUsersUnit 单位。如果在该其他单元中对表单的唯一引用在 implementation 部分中,则将其添加到那里的 uses 子句中。作为一般规则,您应该只在绝对必要的情况下添加到 interface uses 子句。

unit MainUnit;

///  ...

implementation

  uses AddTenantUnit, HomeUnit, MainMenuUnit, ManageUsersUnit;

然后您的代码会直接引用UserListBox,但此引用是TManageUsersForm 类的成员变量,因此您必须先标识该类的实例,然后才能访问该实例的成员。

在这种情况下,您似乎已经有一个您可能打算使用的公共实例:ManageUsersForm

所以您将文件数据加载到列表中的代码应该是:

ManageUsersForm.UserListBox.Items.LoadFromFile('Newuser.dat');

这将解决您的直接问题。但是,这种方法有很多错误。

  1. MainUnit 假定 ManageUsersForm 是一个有效的现有表单实例。如果表单在项目中设置为 AutoCreate,那么这可能是有效的,但很危险,因为它会使您的代码 容易受到表单创建方式变化的影响。

  2. MainUnitManageUsers 表单的某些行为负有不当责任。如果 ManageUsers 表单真正管理用户,那么这应该包括用户对文件本身的持久性。

  3. MainUnit 高度依赖于 ManageUsers 表单的内部细节。我们说它是“紧耦合”的。如果 ManageUsers 表单被修改为使用例如网格到列表视图来呈现用户,则 MainUnit 代码将中断,因为它依赖于用户列表专门是一个列表框这一亲密知识。

由于 VCL 的工作方式,Delphi 中表单上的用户界面控件是可公开访问的,但您应该将它们视为 private(或者,至多 受保护)。您的 ManageUsers 表单应该为它提供给“外部世界”的功能提供一个公共接口,该功能根据用户数据进行处理。

在表单本身(或后代表单类,如果您使用表单类的 OO 层次结构)之外,不应引用表单的用户界面元素 - 包括任何事件处理程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多