自动消失的自定义消息框

Posted

技术标签:

【中文标题】自动消失的自定义消息框【英文标题】:Custom message box that automatically disappears 【发布时间】:2018-08-23 12:29:39 【问题描述】:

我需要向现有的 MFC 应用程序添加一个自定义消息框,如果用户没有按“确定”,该消息框将在几秒钟后消失。

怎么做?

我对 MFC 基本熟悉,但对 c++ 也很熟悉。

【问题讨论】:

使用无模式对话框。 正如@seccpur 所说,只是添加让无模式对话框自己发布一条 WM_TImer 消息,收到后它可以自行关闭。 您不需要无模式对话框来设置计时器,其处理程序会关闭对话框。此方法适用于 any 对话框。 使用MessageBoxTimeoutW @RbMm:这个问题被标记为winapi。根据定义,未记录的函数不是已记录的 API 表面的一部分。 【参考方案1】:

无需使用TaskDialogIndirect() 编写自定义对话框即可完成此操作。

基本步骤

    TASKDIALOGCONFIG::dwFlags 中设置TDF_CALLBACK_TIMER 位。这将大约每 200 毫秒调用一次回调(如果指定)。 将callback function 分配给TASKDIALOGCONFIG::pfCallback。 当使用TDN_TIMER 通知代码调用回调时,将通过wParam 传递给回调的经过时间与您想要的超时值进行比较。要关闭对话框,请发送TDM_CLICK_BUTTON 消息。

您可以花哨地显示进度条 (TDF_SHOW_PROGRESS_BAR),或者只显示您在计时器回调中更新的倒计时文本。见Task Dialog Messages。

示例

这是一个使用普通 Windows API 的示例。 MFC 有CTaskDialog 类,但我认为如果它不太依赖MFC,这个答案会更有用。对于非 MFC 用户,只需更改对 tc.hInstancetc.hwndParent 的分配。

TASKDIALOGCONFIG tc sizeof(tc) ;
tc.hInstance = AfxGetInstanceHandle();
tc.hwndParent = GetSafeHwnd();  // assuming you call this from a dialog member function
tc.dwFlags = TDF_CALLBACK_TIMER | TDF_SIZE_TO_CONTENT;
tc.dwCommonButtons = TDCBF_OK_BUTTON;
tc.pszWindowTitle = L"Task dialog with timeout";
tc.pszContent = L"This dialog will close after 5 seconds!";

DWORD timeout = 5000;  // milliseconds
tc.lpCallbackData = reinterpret_cast<LONG_PTR>( &timeout );

// Assign a lambda function as callback.
tc.pfCallback = []( HWND hwnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData )

    if( uNotification == TDN_TIMER )
    
        DWORD* pTimeout = reinterpret_cast<DWORD*>( dwRefData );  // = tc.lpCallbackData
        DWORD timeElapsed = static_cast<DWORD>( wParam );
        if( *pTimeout && timeElapsed >= *pTimeout )
        
            *pTimeout = 0; // Make sure we don't send the button message multiple times.
            SendMessage( hwnd, TDM_CLICK_BUTTON, IDOK, 0 );
        
    
    return S_OK;
;

::TaskDialogIndirect( &tc, nullptr, nullptr, nullptr );

【讨论】:

为什么不直接打电话给MessageBoxTimeoutW @RbMm 未记录和过时的 API。 你在 outdated 下是什么意思?它存在于所有windows版本中,从win2000到最新的win10最低多少 @RbMm 由于它没有记录,因此可以在将来的任何时间删除。过时了,因为任务对话框 API 更强大。 我不认为与过时的绑定有多强大。存在不同的 api,其中存在更强大的版本,但这并不意味着这个 api 已经过时了【参考方案2】:

最简单的方法,如果您只想要超时的消息框,请使用 user32.dll 中的下一个未记录的 api:

extern "C"
WINUSERAPI int WINAPI MessageBoxTimeoutW(IN HWND hWnd, 
                            IN PCWSTR lpText, IN PCWSTR lpCaption, 
                            IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds);

所有我们需要的 - 将此声明添加到 c++ 代码并与 user32.lib 链接,但我们通常默认这样做。在此之后像往常一样简单地调用它 MessageBoxW 并带有 2 个附加参数。最后一个如何简单地查看 - 以毫秒为单位的 tiemout。

例如:

MessageBoxTimeoutW(HWND_DESKTOP, L"Text", 
    L"Caption", MB_ICONINFORMATION|MB_YESNO, 0, 4000);

注意MessageBoxW 只需调用MessageBoxTimeoutW

int MessageBoxW(
  HWND    hWnd,
  LPCTSTR lpText,
  LPCTSTR lpCaption,
  UINT    uType
)

    return MessageBoxTimeoutW(hWnd, lpText, lpCaption, uType, 0, INFINITE);

所以前 4 个参数和返回值类似于 MessageBoxW api。如果消息框因超时关闭 - IDTIMEOUT 返回(在 winuser.h 中声明),但 MB_OK 使用(单个 OK 按钮) - 在这种情况下总是 @987654330 @返回。

【讨论】:

以上是关于自动消失的自定义消息框的主要内容,如果未能解决你的问题,请参考以下文章

MFC自定义消息的方法?

[Android]自定义定时消失PopupWindow

MFC的自定义消息的定义与使用

自定义 MFC 控件包含另一个控件 - 消息未通过

禁用 MFMessageComposeViewController 的自定义外观

Mongoose 的自定义错误消息