繁体   English   中英

如何创建无模式对话框并在用户单击确定时将其关闭?

[英]How to create a modeless dialog box and close it when the user clicks ok?

用户坚持在应用程序中为每个“重要事件”设置一个弹出框,而在备注或列表框中添加一行是不可接受的。

我不能使用标准模式框,因为PC经常是无用的,我的应用程序将等待用户单击“确定”后再继续。

我是否可以动态创建带有备忘录组件和“确定”按钮的表单,并传递一些文本以显示在备忘录中?

我尝试了一下,单击“确定”后出现访问冲突。

问题:

  • 因为它是无模式显示的,所以有必要启动一个线程来显示表单吗?
  • 我应该通过什么作为构造函数参数(价格)? 没有,既然形式会自我毁灭?
  • 当用户单击“确定”时,我应该怎么称呼? Close()还是Free()? 单击“确定”后,这两种方法都会导致访问冲突,但如果我在该功能中未执行任何操作,则代码会正常运行(当然会发生内存泄漏)

Google并不是那么有用,因为表单应该销毁自己,而示例中有其创建者销毁它。


主要形式:

     theDialogForm := TDialogFormForm.Create(Nil);
     theDialogForm.ShowTheForm('Database error '+#13+#10+''+#13+#10+
                E.ClassName+#13+#10+
                E.Message);

和对话框形式...

unit fDialogForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TDialogFormForm = class(TForm)
    Memo1: TMemo;
    OkButton: TButton;
    procedure OkButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
      procedure ShowTheForm(const theMessage : String);
  end;

implementation

{$R *.dfm}

// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
procedure TDialogFormForm.FormCreate(Sender: TObject);
begin
   Visible := False;
end;

// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
procedure TDialogFormForm.OkButtonClick(Sender: TObject);
begin
//   Close();
   Free();
end;

// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
procedure TDialogFormForm.ShowTheForm(const theMessage : String);
begin
   Memo1.Text := theMessage;
   Show();
end;

end.

调用堆栈

main thread ($630):
005164e3 +013 StoreRoom.exe Vcl.Controls          TControl.WMLButtonUp
00515b30 +2d4 StoreRoom.exe Vcl.Controls          TControl.WndProc
0051a47b +5b3 StoreRoom.exe Vcl.Controls          TWinControl.WndProc
00537bf0 +06c StoreRoom.exe Vcl.StdCtrls          TButtonControl.WndProc
00519ad0 +02c StoreRoom.exe Vcl.Controls          TWinControl.MainWndProc
0048dea4 +014 StoreRoom.exe System.Classes        StdWndProc
76677885 +00a USER32.dll                          DispatchMessageW
005b7c63 +0f3 StoreRoom.exe Vcl.Forms             TApplication.ProcessMessage
005b7ca6 +00a StoreRoom.exe Vcl.Forms             TApplication.HandleMessage
005b7fd9 +0c9 StoreRoom.exe Vcl.Forms             TApplication.Run
00823616 +17a StoreRoom.exe StoreRoom      56 +24 initialization
75c43398 +010 kernel32.dll                        BaseThreadInitThunk

要关闭表格,您可以

  • 通过调用Close关闭它,并在OnClose事件中将action设置为caFree
  • 调用Release ,这是Free的一种特殊风格,特别是对于表单。

调用Free的问题在于,当您仍在处理关闭按钮上的click事件时,将立即释放该窗体。 在该过程中,窗体和按钮因此被释放,从而导致访问冲突。 Release内部将消息发送到表单,导致单击处理关闭。

  1. 您不需要线程即可显示该表单。 但是,由于该表单应该保持可见,因此建议您将其FormStyle设置为fsStayOnTop
  2. 由于您要销毁表单,因此可以将nil传递给Create()
  3. 要销毁表单,请调用Close然后在表单的OnClose事件中将Action设置为caFree

您为什么不轻松自如地制作一个看起来像对话框的不可见面板,当发生重大事件时该面板变为可见,而当用户单击“确定”时该对话框不可见?

因为它是无模式显示的,所以有必要启动一个线程来显示表单吗?

VCL不是多线程的。 您应该始终在主线程中运行表单。 可能会在额外的线程dunno中调用Win32 API ShowMessageBox,但随后仅用于一条消息。 无法将事件累积到TMemo或网格中。

我应该通过什么作为构造函数参数(价格)?

我会通过应用程序,但这没什么大不了的。

当用户单击“确定”时,我应该怎么称呼? Close()还是Free()?

两者都不是创建/删除表单的依据。 只有当您可以具有许多相同类的形式时,它才有意义。 这次,只需在程序启动/结束时使Delphi自动创建并自动处理它即可。

您只应显示或隐藏它。 手动创建和处置没有意义。


现在,关于线程-为什么要完全阻止应用程序? 将该窗口设置为AlwaysOnTop,然后使用TApplication.OnActivate事件检查用户何时切换到该窗口,并将该窗口置于屏幕/主窗体的前面和中央。 这样该用户就会看到它。

或者,您可以尝试使用Snarl之类的第三方通知工具,并提供邮件永不过期的选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM