簡體   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