1

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

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

我可以动态地创建一个带有备忘录组件和 OK 按钮的表单并传递一些文本以显示在备忘录中吗?

我试过了,当点击确定时我遇到了访问冲突。

问题:

  • 是否需要启动线程来显示表单,因为它是无模式显示的?
  • 我应该传递什么作为构造函数参数(prent)?无,因为形式会自我毁灭?
  • 当用户单击确定时,我应该怎么称呼?关闭()或免费()?单击“确定”后,其中任何一个都会在大约 1/2 秒后出现访问冲突,但如果我在函数中什么都不做,代码运行良好(当然,内存泄漏)

谷歌并没有那么有用,因为表单应该自我毁灭,而示例却让其创建者破坏它。


主要形式:

     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
4

4 回答 4

7

要关闭表单,您可以

  • 通过在 OnClose 事件中调用Close并设置操作来关闭它caFree
  • call Release,这是 Free 的一种特殊风格,尤其适用于表单。

调用Free, 的问题是表单被立即释放,而您仍在处理关闭按钮上的单击事件。在该过程中,表单和按钮被释放,导致访问冲突。Release在内部向表单发送一条消息,导致它在处理点击关闭。

于 2012-09-18T10:45:06.667 回答
4
  1. 您不需要线程来显示表单。但是,由于表单应该保持可见,我建议您将其设置FormStylefsStayOnTop
  2. 由于您正在销毁表单,因此您可以传递nilCreate()
  3. 要销毁您的表单,请调用Close和 在您的表单OnClose事件中,设置ActioncaFree.
于 2012-09-18T10:48:26.707 回答
2

为什么不让自己轻松一点,制作一个看起来像对话框的不可见面板,当重要事件发生时变得可见,而当用户单击确定时不可见?

于 2012-09-19T12:17:40.103 回答
1

是否需要启动线程来显示表单,因为它是无模式显示的?

VCL 不是多线程的。您应该始终在主线程中运行表单。你也许可以在额外的线程中调用 Win32 API ShowMessageBox,不知道,但只针对单个消息。无法将事件累积到 TMemo 或网格中。

我应该传递什么作为构造函数参数(prent)?

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

当用户单击确定时,我应该怎么称呼?关闭()或免费()?

两者都没有,没有必要创建/删除表单。只有当您可以拥有同一类的多种形式时,它才有意义。这一次,只需让 Delphi 在程序启动/结束时自动创建和自动处理它。

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


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

或者,您可以尝试使用 Snarl 等带有消息永不过期选项的 3rd 方通知工具。

于 2012-09-18T12:04:02.553 回答