Skip to content

Instantly share code, notes, and snippets.

@haseeb-heaven
Last active May 7, 2021 03:25
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haseeb-heaven/a97ea40c4ca3b6ba6d5a1b8348bd0585 to your computer and use it in GitHub Desktop.
Save haseeb-heaven/a97ea40c4ca3b6ba6d5a1b8348bd0585 to your computer and use it in GitHub Desktop.
/* AutoCloseMessageBox - C++ Implementation of original code of C# from CodeProject https://www.codeproject.com/Articles/7968/MessageBox-with-a-timeout-for-NET
By Artic Coder.
*/
#undef UNICODE
#include <iostream>
#include <Windows.h>
using std::string;
//Pointer to Hook functions.
typedef intptr_t(*HookProc)(int nCode, intptr_t wParam, intptr_t lParam);
typedef void(*TimerProc)(intptr_t hWnd, uint32_t uMsg, uintptr_t nIDEvent, uint32_t dwTime);
//Global vars.
const int timerID = 42;
HookProc hookProc;
TimerProc hookTimer;
uint32_t hookTimeout;
string hookCaption;
HHOOK hHook;
int captionLen;
class AutoCloseMessageBox {
private:
static void MessageBoxHook(string caption, uint32_t uTimeout)
{
if (hHook != NULL)
throw new std::runtime_error("multiple calls are not supported");
hookTimeout = uTimeout;
hookCaption = !caption.empty() ? caption : "";
hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)hookProc, 0, GetCurrentThreadId());
}
static intptr_t MessageBoxHookProc(int nCode, intptr_t wParam, intptr_t lParam)
{
if (nCode < 0)
return CallNextHookEx(hHook, nCode, wParam, lParam);
auto msg = reinterpret_cast<CWPRETSTRUCT*>(lParam);
auto hook = hHook;
//Hook Messagebox on Initialization.
if (!hookCaption.empty() && msg->message == WM_INITDIALOG)
{
int nLength = GetWindowTextLength(msg->hwnd);
char* text = new char[captionLen + 1];
GetWindowText(msg->hwnd, text, captionLen + 1);
//If Capttion window found Unhook it.
if (hookCaption == text)
{
hookCaption = string("");
SetTimer(msg->hwnd, (uintptr_t)timerID, hookTimeout, (TIMERPROC)hookTimer);
UnhookWindowsHookEx(hHook);
hHook = 0;
}
}
return CallNextHookEx(hook, nCode, wParam, lParam);
}
static void MessageBoxTimerProc(HWND hWnd, uint32_t uMsg, uintptr_t nIDEvent, uint32_t dwTime)
{
if (nIDEvent == (uintptr_t)timerID)
{
short dw = (short)SendMessage(hWnd, DM_GETDEFID, 0, 0);
EndDialog(hWnd, (intptr_t)dw);
}
}
public:
AutoCloseMessageBox() {
hookProc = HookProc(MessageBoxHookProc);
hookTimer = TimerProc(MessageBoxTimerProc);
hookTimeout = 0;
hookCaption = string("");
hHook = 0;
}
//Different overloaded methods for Showing message.
static int Show(string message) {
string caption = " ";
captionLen = caption.length();
MessageBoxHook(caption, 1000);
return MessageBox((HWND)NULL,message.c_str(), caption.c_str(),0);
}
static int Show(string message,uint32_t uTimeout) {
string caption = " ";
captionLen = caption.length();
MessageBoxHook(caption, uTimeout);
return MessageBox((HWND)NULL, message.c_str(),caption.c_str(), 0);
}
static int Show(string message, string caption, uint32_t uTimeout) {
captionLen = caption.length();
MessageBoxHook(caption, uTimeout);
return MessageBox((HWND)NULL, message.c_str(), caption.c_str(), 0);
}
static int Show(string message, string caption, uint32_t uTimeout,uint32_t iconType) {
captionLen = caption.length();
MessageBoxHook(caption, uTimeout);
caption = !caption.empty() ? caption : "";
return MessageBox((HWND)0, message.c_str(),caption.c_str(),iconType);
}
};
//Main methods with examples.
int main()
{
AutoCloseMessageBox().Show("Hello AutoCloseMsgBox");//Message with default timeout.
AutoCloseMessageBox().Show("Hello AutoCloseMsgBox",2500);//Message with 2.5 Seconds timeout.
AutoCloseMessageBox().Show("Hello AutoCloseMsgBox","Error",1000); //Message with 1 Seconds timeout with Caption.
AutoCloseMessageBox().Show("Hello AutoCloseMsgBox","Confirmation Dialog",1000,MB_YESNOCANCEL); //Message with 1 Seconds timeout with Caption and MessageButton.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment