[x]秒后关闭Delphi对话框

[x]秒后关闭Delphi对话框,delphi,dialog,timeout,Delphi,Dialog,Timeout,是否可以让Delphi在一定时间后关闭ShowMessage或MessageDlg对话框 我想在应用程序关闭时向用户显示一条消息,但不想阻止应用程序关闭超过10秒 我可以让默认对话框在定义的时间后关闭,还是需要编写自己的表单?我考虑使用一个单独的线程,但它可能会让您陷入许多不必要的代码等。Windows对话框根本不是为这件事而设计的 你应该做你自己的表格。好的一面是,您可以像定时对话框一样使用带有倒计时功能的自定义代码/UI。确定。您有两种选择: 1-您可以创建自己的MessageDialog表

是否可以让Delphi在一定时间后关闭ShowMessage或MessageDlg对话框

我想在应用程序关闭时向用户显示一条消息,但不想阻止应用程序关闭超过10秒


我可以让默认对话框在定义的时间后关闭,还是需要编写自己的表单?

我考虑使用一个单独的线程,但它可能会让您陷入许多不必要的代码等。Windows对话框根本不是为这件事而设计的


你应该做你自己的表格。好的一面是,您可以像定时对话框一样使用带有倒计时功能的自定义代码/UI。

确定。您有两种选择:

1-您可以创建自己的MessageDialog表单。然后,您可以使用它并添加一个TTimer,在需要时关闭表单

2-您可以继续使用showmessage并创建一个线程,该线程将使用FindWindow(查找messadialog窗口),然后关闭它


我建议您使用您自己的带有计时器的表单。它更干净更容易

否。ShowMessage和MessageDlg都是模式窗口,这意味着您的应用程序在显示时基本上处于挂起状态

您可以设计自己的带有计时器的替换对话框。在FormShow事件中,启用计时器,在FormClose事件中禁用它。在OnTimer事件中,禁用计时器,然后关闭窗体本身。

尝试以下操作:

function MessageBoxTimeOut(hWnd: HWND; lpText: PChar; lpCaption: PChar;
  uType: UINT; wLanguageId: WORD; dwMilliseconds: DWORD): integer;
  stdcall; external user32 name 'MessageBoxTimeoutA';

我已经用了很长时间了;这是一种享受。

您可以尝试使用标准的消息对话框。使用CreateMessageDialog过程从Dialogs创建对话框,然后添加所需的控件

在带有TButton的表单中,使用以下命令定义onClick:

procedure TForm1.Button1Click(Sender: TObject);
var
  tim:TTimer;
begin
  // create the message
  AMsgDialog := CreateMessageDialog('This is a test message.',mtWarning, [mbYes, mbNo]) ;
  lbl := TLabel.Create(AMsgDialog) ;
  tim := TTimer.Create(AMsgDialog);
  counter := 0;

  // Define and adding components
  with AMsgDialog do
   try
    Caption := 'Dialog Title' ;
    Height := 169;

    // Label
    lbl.Parent := AMsgDialog;
    lbl.Caption := 'Counting...';
    lbl.Top := 121;
    lbl.Left := 8;

    // Timer
    tim.Interval := 400;
    tim.OnTimer := myOnTimer;
    tim.Enabled := true;

    // result of Dialog
    if (ShowModal = ID_YES) then begin
      Button1.Caption := 'Press YES';
    end
    else begin
      Button1.Caption := 'Press NO';
    end;
   finally
    Free;
   end;
end;
类似以下内容的OnTimer属性:

procedure TForm1.MyOnTimer(Sender: TObject);
begin

  inc(counter);
  lbl.Caption := 'Counting: ' + IntToStr(counter);
  if (counter >= 5) then begin
    AMsgDialog.Close;
  end;
end;
定义变量和程序:

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    AMsgDialog: TForm;
    lbl:TLabel;
    counter:integer;
    procedure MyOnTimer(Sender: TObject);
  end;
并对其进行测试。
计时器结束倒计时时,窗体将自动关闭。与此类似,您可以添加其他类型的组件

问候。

您可以用手机来完成这项工作


您可以在中找到,也可以自己调用。

当模式对话框或系统消息框或类似对话框处于活动状态时(或当菜单打开时),您的应用程序实际上仍在工作,这只是一个辅助消息循环正在运行,它处理所有消息-发送或发布到它的所有消息,并且它将合成(并处理)
WM_定时器
WM_绘制
必要时的信息

因此,无需创建线程或跳过任何其他环,只需安排关闭消息框的代码在10秒后运行。一种简单的方法是调用时不使用目标
HWND
,而是使用回调函数:

procedure CloseMessageBox(AWnd: HWND; AMsg: UINT; AIDEvent: UINT_PTR;
  ATicks: DWORD); stdcall;
var
  Wnd: HWND;
begin
  KillTimer(AWnd, AIDEvent);
  // active window of the calling thread should be the message box
  Wnd := GetActiveWindow;
  if IsWindow(Wnd) then
    PostMessage(Wnd, WM_CLOSE, 0, 0);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TimerId: UINT_PTR;
begin
  TimerId := SetTimer(0, 0, 10 * 1000, @CloseMessageBox);
  Application.MessageBox('Will auto-close after 10 seconds...', nil);
  // prevent timer callback if user already closed the message box
  KillTimer(0, TimerId);
end;

处理ommitted时出错,但这应该可以让您开始。

如果您想要连接计时器关闭感兴趣的窗体,可以连接Screen.OnActiveFormChange事件并使用Screen.ActiveCustomForm

{code}
procedure abz.ActiveFormChange(Sender: TObject);
var
   Timer: TTimer;
begin
  if (Screen.ActiveCutomForm <> nil) and //valid form
     (Screen.ActiveCutomForm.Tag = 0) and //not attached a timer yet
     (Screen.ActiveCutomForm.ClassName = 'TMessageForm') //any interested form type check
    then 
  begin
    Timer := TTimer.Create(Screen.ActiveCutomForm); // let the form owned so it will be freed
    Timer.Enabled := False;
    Timer.Tag := Integer(Screen.ActiveCutomForm); // keep track to be used in timer event
    .... setup any timer interval + event
    Screen.ActiveCutomForm.Tag := Integer(Timer);
    Timer.Enabled := True; 
  end;
end;
{code}
{code}
程序abz.ActiveFormChange(发送方:ToObject);
变量
定时器:TTimer;
开始
if(Screen.ActiveCutomForm nil)和//有效形式
(Screen.ActiveCutomForm.Tag=0)和//尚未连接计时器
(Screen.ActiveCutomForm.ClassName='TMessageForm')//任何感兴趣的表单类型检查
然后
开始
计时器:=TTimer.Create(Screen.ActiveCutomForm);//让窗体拥有它,以便将其释放
Timer.Enabled:=False;
Timer.Tag:=整数(Screen.ActiveCutomForm);//跟踪要在计时器事件中使用的内容
.... 设置任何计时器间隔+事件
Screen.ActiveCutomForm.Tag:=整数(计时器);
Timer.Enabled:=True;
结束;
结束;
{code}

享受

这在windows 98和新版本中运行良好

我不使用“MessageBoxTimeOut”,因为旧的Windows98,我,没有它

这个新功能就像一个“魔咒”

//添加此过程

procedure DialogBoxAutoClose(const ACaption, APrompt: string; DuracaoEmSegundos: Integer);
var
  Form: TForm;
  Prompt: TLabel;
  DialogUnits: TPoint;
  ButtonTop, ButtonWidth, ButtonHeight: Integer;
  nX, Lines: Integer;

  function GetAveCharSize(Canvas: TCanvas): TPoint;
    var
      I: Integer;
      Buffer: array[0..51] of Char;
    begin
      for I := 0 to 25 do Buffer[I]          := Chr(I + Ord('A'));
      for I := 0 to 25 do Buffer[I + 26]    := Chr(I + Ord('a'));
      GetTextExtentPoint(Canvas.Handle, Buffer, 52, TSize(Result));
      Result.X := Result.X div 52;
    end;

begin
  Form       := TForm.Create(Application);
  Lines   := 0;

  For nX := 1 to Length(APrompt) do
     if APrompt[nX]=#13 then Inc(Lines);

  with Form do
    try
      Font.Name:='Arial';     //mcg
      Font.Size:=10;          //mcg
      Font.Style:=[fsBold];
      Canvas.Font    := Font;
      DialogUnits    := GetAveCharSize(Canvas);
      //BorderStyle    := bsDialog;
      BorderStyle    := bsToolWindow;
      FormStyle         := fsStayOnTop;
      BorderIcons      := [];
      Caption          := ACaption;
      ClientWidth    := MulDiv(Screen.Width div 4, DialogUnits.X, 4);
      ClientHeight    := MulDiv(23 + (Lines*10), DialogUnits.Y, 8);
      Position          := poScreenCenter;

      Prompt             := TLabel.Create(Form);
      with Prompt do
      begin
        Parent          := Form;
        AutoSize       := True;
        Left             := MulDiv(8, DialogUnits.X, 4);
        Top             := MulDiv(8, DialogUnits.Y, 8);
        Caption       := APrompt;
      end;

      Form.Width:=Prompt.Width+Prompt.Left+50;  //mcg fix

      Show;
      Application.ProcessMessages;
    finally
       Sleep(DuracaoEmSegundos*1000);
      Form.Free;
    end;
end;
////////////////////////////这叫什么//////////////////

DialogBoxAutoClose('警报','此消息将在10秒内关闭',10)


/////////////////////////////////////////////////////////

MessageBox在内部调用此函数,并将0xFFFFFF作为超时参数传递,因此删除它的概率最小(多亏了Maurizio)

最好的方法是使用StationTop窗体,并使用窗体的Alpha blend属性管理计数器以使其消失,在计数结束时,只需关闭窗体,但
控件将在显示表单之前传递到所需的活动控件,这样,用户将收到一条消息,该消息将自动消失,并且不会阻止使用下一个功能,这对我来说非常酷。

谢谢,这就是我所想的,在表单上添加计时器是我应该采取的方式-我只是想检查一下defaults:)请参阅我的答案以获得(简单的)第三种选择。操作系统提供的消息框比VCL消息对话框(外观)有优势.Hm…Raymond Chen不喜欢开发人员使用Windows API的未记录功能。所以我不得不对这一点投反对票。没关系;当它可供Microsoft使用时,我也使用它。对每个人来说都是他们自己的。我不知道你所说的“应用程序被暂停”到底是什么意思“,但这是错误的,-1。当模式窗口处于活动状态时,完全有可能执行代码。和