自动消失的自定义消息框
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.hInstance
和 tc.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 @返回。
【讨论】:
以上是关于自动消失的自定义消息框的主要内容,如果未能解决你的问题,请参考以下文章