Centering MessageBox
<< Back
It all stemmed from this
post.
The good thing is that there is
an article
on CodeProject shows you how to do that. The following code is basically a bit updated code that has the following improvements
- It's in C++. No need for .NET runtime libraries
- Take Multiple Monitor into consideration.
- You can leave the hook up there instead of hooking/unhooking before calling MessageBox.
- Take Workarea into consideration so that the message box doesn't show up behind the taskbar.
#include <windows.h>
HHOOK ghHook;
void CenterMessageBox(HWND hOwner, HWND hMsgBox)
{
RECT rOwner, rMsgBox;
MONITORINFO mi;
GetWindowRect(hOwner, &rOwner);
HMONITOR hMon = MonitorFromWindow(hOwner, MONITOR_DEFAULTTONEAREST);
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMon, &mi);
GetWindowRect(hMsgBox, &rMsgBox);
int iWidth = rMsgBox.right - rMsgBox.left;
int iHeight = rMsgBox.bottom - rMsgBox.top;
int ix = ((rOwner.right - rOwner.left) - iWidth) / 2;
int iy = ((rOwner.bottom - rOwner.top) - iHeight) / 2;
int iLeft = rOwner.left + ix;
int iTop = rOwner.top + iy;
int iRight = iLeft + iWidth;
int iBottom = iTop + iHeight;
if (iRight >= mi.rcWork.right) iLeft = mi.rcWork.right - iWidth;
if (iBottom >= mi.rcWork.bottom) iTop = mi.rcWork.bottom - iHeight;
if (iLeft < mi.rcWork.left) iLeft = mi.rcWork.left;
if (iTop < mi.rcWork.top) iTop = mi.rcWork.top;
SetWindowPos(hMsgBox, NULL, iLeft, iTop, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
}
LRESULT CALLBACK HookProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
TCHAR szClass[8];
HWND hMsgBox;
LRESULT lResult = CallNextHookEx(ghHook, nCode, wParam, lParam);
if (nCode == HCBT_ACTIVATE)
{
hMsgBox = reinterpret_cast<HWND>(wParam);
if (!IsWindowVisible(hMsgBox))
{
if (GetClassName(hMsgBox, szClass, 8))
{
if (lstrcmp(szClass, TEXT("#32770")) == 0) // You can do more checks to see if it is really a message box.
{
HWND hOwner = GetWindow(hMsgBox, GW_OWNER);
if (hOwner)
CenterMessageBox(hOwner, hMsgBox);
}
}
}
}
return lResult;
}
ghHook = SetWindowsHookEx(WH_CBT, HookProc, NULL, GetCurrentThreadId());