【问题标题】:Application terminates for no apparent reason应用程序无故终止
【发布时间】:2015-04-11 08:42:37
【问题描述】:

我已经使用可用表单 (Form4) 和 MainForm 设置了我的登录程序。 在可用的表格 (form4) 上,我有:

var
  Form4: TForm4;
  procedure Login;
implementation
.....

“登录”过程如下:

procedure Login;
begin
  with TForm4.Create(nil) do
  try
    Application.MainForm.Hide;
    if ShowModal = mrOK then
      Application.MainForm.Show
    else
      Application.Terminate;
  finally
    Free;
  end;
end;

然后在同一个表单上我有一个登录按钮:

procedure TForm4.AdvGlowButton1Click(Sender: TObject);  //the buton's property is ModalResult=mrOK
begin
DataModule2.LOGIN_QUERY.Active:=false;
DataModule2.LOGIN_QUERY.SQL.Clear;
DataModule2.LOGIN_QUERY.SQL.Add('select user,passsword from users where user='+QuotedStr(cxlookupcombobox1.text)+' and password='+QuotedStr(cxTextEdit1.Text));
DataModule2.LOGIN_QUERY.Open;
if DataModule2.LOGIN_QUERY.FieldByName('password').AsString<>''
then   ModalResult := mrOK  else
ModalResult := mrNone;
end;

项目源码如下:

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := False;
  Application.CreateForm(TDataModule2, DataModule2);
  Application.CreateForm(TMainForm, MainForm);
  Application.CreateForm(TForm7, Form7);
  Application.CreateForm(TARCHIVE, ARHCIVE);
  Application.CreateForm(TForm10, Form10);
  Application.CreateForm(TForm1, Form1);
  Application.CreateForm(TForm6, Form6);
  Application.CreateForm(TForm5, Form5);
  Application.CreateForm(TForm9, Form9);
  Application.CreateForm(TForm12, Form12);
  Application.CreateForm(TForm12, Form12);
  Application.CreateForm(TAboutBox, AboutBox);
  Login;
  Application.Run;
end.

然而,当单击 Form4 上的登录按钮时,应用程序时不时地 无故终止。为什么会这样? 应该

Application.MainFormOnTaskbar := False;

也许设置为真?

编辑:

我在创建事件时编辑了项目文件和form4:

procedure TForm4.FormCreate(Sender: TObject);
begin
AdvGlowButton1.ModalResult := mrOK;
end;

并更改了项目来源:

{$R *.res}
 var
  MainForm: TMainForm;

begin
  Application.Initialize;
  Application.CreateForm(TMainForm, MainForm);
  Application.MainFormOnTaskbar := False;
  Application.CreateForm(TDataModule2, DataModule2);
  Application.CreateForm(TForm7, Form7);
  Application.CreateForm(TARCHIVE, ARCHIVE);
  Application.CreateForm(TForm10, Form10);
  Application.CreateForm(TForm1, Form1);
  Application.CreateForm(TForm6, Form6);
  Application.CreateForm(TForm5, Form5);
  Application.CreateForm(TForm9, Form9);
  Application.CreateForm(TForm12, Form12);
  Application.CreateForm(TForm12, Form12);
  Application.CreateForm(TAboutBox, AboutBox);
  Login;
  Application.Run;
end.

而且我似乎没有关闭应用程序....(它仍然可以,呃...)

编辑2:

试过这种方式。我将 AdvGlowButton1 设置为 ModalResult=mrNone 并将 Form 样式设置为 fsdialog:

procedure TForm4.AdvGlowButton1Click(Sender: TObject);  //the buton's property is ModalResult=mrOK
begin
DataModule2.LOGIN_QUERY.Active:=false;
DataModule2.LOGIN_QUERY.SQL.Clear;
DataModule2.LOGIN_QUERY.SQL.Add('select user,passsword from users where user='+QuotedStr(cxlookupcombobox1.text)+' and password='+QuotedStr(cxTextEdit1.Text));
DataModule2.LOGIN_QUERY.Open;
if DataModule2.LOGIN_QUERY.FieldByName('password').AsString<>''
then   ModalResult := mrOK  else
dxStatusBar1.Panels[1].Text :='Wrong password !';
end;

这在大多数情况下都有效,但有时当我启动应用程序并点击 AdvGlowButton1 按钮(登录按钮)时它会关闭。我想出的另一件事是丢失,您如何提示关闭此登录表单上的应用程序,因为它只需要模态结果?

【问题讨论】:

  • 我冒险猜测 ShowModal 不是 mrOk。
  • 很难看到过去的Application.Terminate。我也想知道为什么你不给你的表格名字。以及为什么在启动时创建它们。我猜ide是为你做的。但这是一个糟糕的指南。它认为你是 20 世纪后期的 VB 程序员。
  • BTW 在这一切都修好之后,您的下一个任务(在您在应用程序中执行任何其他操作之前)是摆脱数据库中的纯文本密码,并将它们替换为 (SHA1) 哈希.这是互联网/数据库安全规则 #1,你不能尽快开始这样做
  • Buttons 属性已设置:ModalResult=mrOK
  • 完全同意密码哈希,但也不要忘记公然的 SQL 注入!

标签: delphi delphi-xe7


【解决方案1】:

就像@SertacAkyuz 暗示的那样,一种选择是 ShowModal 不返回 mrOK。检查此按钮的 ModalResult 值和/或此按钮的 OnClick 的事件处理程序,以查看 mrOK 是否是在这些情况下返回的 ModalResult...

如果您单击一个按钮,则会触发 OnClick 事件,如果该按钮的 ModalResult 设置为任何值,则表单的 ModalResult 将设置为该值。当事件(如 OnClick 事件)结束时,表单会检查其 ModalResult 值,如果将其设置为 0(零)以外的任何值,则表单将关闭,并将值作为 ShowModal 函数的结果返回。

因此,根据您提供的信息,这似乎是一种可能的情况 - 表单的 ModalResult 设置为某个不是 mrOK 的值。然后表单关闭,然后您的 IF ShowModal 测试终止应用程序(因为它没有返回 mrOK)。

【讨论】:

  • 所以我应该尝试设置表单的创建:ModalResult := mrOK;?
  • 仅当您希望它立即关闭且 ShowModal 返回 mrOK。
  • 那么我该如何解决这个问题?
  • 首先,您要弄清楚 ShowModal 函数的返回值究竟是什么(将其保存在局部变量中并在调试输出中或在 Application.Terminate 之前使用 ShowMessage 显示)。然后你会弄清楚如何返回该特定值。
  • 在我看来,点击按钮会改变表单模式结果。因此,将其声明为模式表单 oncreate 毫无意义,因为按钮总是会改变它。
【解决方案2】:

基于您的代码输入错误的密码也会导致您的应用程序终止,因为在这种情况下,返回的模式结果将为 mrNone,您只希望 mrOK 继续您的应用程序。

所以我建议下一个更改:

首先删除按钮的模态结果属性。按钮模态结果属性主要仅用作在单击哪个特定按钮导致模态表单关闭时转发信息的一种方式。

然后更改您的按钮事件代码,使其仅在代码正确时设置表单模式结果,否则应显示输入密码不正确的消息。像这样:

procedure TForm4.AdvGlowButton1Click(Sender: TObject);  //the buton's property is ModalResult=mrOK
begin
  DataModule2.LOGIN_QUERY.Active:=false;
  DataModule2.LOGIN_QUERY.SQL.Clear;
  DataModule2.LOGIN_QUERY.SQL.Add('select user,passsword from users where user='+QuotedStr(cxlookupcombobox1.text)+' and password='+QuotedStr(cxTextEdit1.Text));
  DataModule2.LOGIN_QUERY.Open;
  if DataModule2.LOGIN_QUERY.FieldByName('password').AsString<>'' then
    //Close the modal form with returning of mrOK as modal result
    ModalResult := mrOK  
  else
  begin
    //No modal result should be set here or it would lead to closure of login form
    MessageDlg('Entered password is incorect!',mtError, mbOKCancel, 0);
  end;
end;

这是针对您的特定问题的直接解决方案。但我建议您认真重新考虑您对整个登录系统的设计。为什么?

在您当前的设计中,您在应用程序开始时创建所有表单。现在,虽然您确实从隐藏主表单开始,但这并不意味着您的用户无法访问它。

使用特殊的软件用户可以找到主窗体窗口的句柄并显示它,而无需通过您的登录过程。

因此,避免这种情况的正确方法是首先创建登录表单,然后仅在成功登录时创建其余表单。但这意味着您的登录表单实际上将成为您应用程序的主要表单,因此您应该非常小心不要关闭它,因为它会导致您的整个应用程序关闭。

您可以在我对另一个问题的回答中查看如何实施这种方法的示例:

Delphi Change main form while application is running

【讨论】:

  • 如果按钮返回mrNone,错误的护照如何终止申请?
  • 我的表单样式 (form4) 设置为 bsdialog。默认是不是mrOK的对话框形式?
  • @user763539 这是因为在您的登录方法中,您正在检查模态结果,如果是 mrOK,您会显示主表单,但在所有其他情况下(也包括 mrNone)声明您调用 Application.Terminate。
  • 我已经从上面尝试了您的建议,但当我点击登录按钮时,应用程序有时仍会终止。
  • 您能否编辑问题以包含最新代码,以便我查看您到目前为止所做的更改并发现可能的问题。
猜你喜欢
  • 1970-01-01
  • 2014-10-03
  • 2019-03-31
  • 2015-11-05
  • 2015-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多