C++:如何将 MessageBox 居中?

Posted

技术标签:

【中文标题】C++:如何将 MessageBox 居中?【英文标题】:C++: How to center MessageBox? 【发布时间】:2011-06-09 21:56:02 【问题描述】:

将 Visual Studio C++ 与 MFC 结合使用。如何将 MessageBox 居中到它的父窗口?目前它以桌面为中心。

【问题讨论】:

在 MessageBox 调用之前使用 PostMessage()。在您的消息处理程序中,使用 EnumWindows 找到消息框,然后将 MoveWindow 移到您想要的位置。 消息框的类 #32770 应该可以帮助您找到它 有一种方法可以改变位置,但是对于这么小的任务来说它太复杂了。只需创建您自己的 CDialog。 【参考方案1】:

::AfxMessageBox() 对我来说出现在 MainFrame 的中心。这基本上是对 ::MessageBox() 的调用,其中 MainFrame 的句柄作为第一个参数。这不适合你吗?

【讨论】:

对我不起作用。它可能以应用程序的“MainFrame”为中心,但我需要它以我的 CDialog 派生对话框为中心(我从中调用 MessageBox/AfxMessageBox)。【参考方案2】:

您需要安装一个钩子并在创建时更改对话框位置。

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

    // Center message box at its parent window
    static HHOOK hHookCBT;
    hHookCBT = SetWindowsHookEx(WH_CBT,
        [](int nCode, WPARAM wParam, LPARAM lParam) -> LRESULT
        
            if (nCode == HCBT_CREATEWND)
            
                if (((LPCBT_CREATEWND)lParam)->lpcs->lpszClass == (LPWSTR)(ATOM)32770)  // #32770 = dialog box class
                
                    RECT rcParent;
                    GetWindowRect(((LPCBT_CREATEWND)lParam)->lpcs->hwndParent, &rcParent);
                    ((LPCBT_CREATEWND)lParam)->lpcs->x = rcParent.left + ((rcParent.right - rcParent.left) - ((LPCBT_CREATEWND)lParam)->lpcs->cx) / 2;
                    ((LPCBT_CREATEWND)lParam)->lpcs->y = rcParent.top + ((rcParent.bottom - rcParent.top) - ((LPCBT_CREATEWND)lParam)->lpcs->cy) / 2;
                
            

            return CallNextHookEx(hHookCBT, nCode, wParam, lParam);
        ,
        0, GetCurrentThreadId());

    int iRet MessageBox(hWnd, lpText, lpCaption, uType) ;

    UnhookWindowsHookEx(hHookCBT);

    return iRet;

【讨论】:

【参考方案3】:

你不能。这就是为什么很多人编写自己的 MessageBox 类的原因。

【讨论】:

【参考方案4】:

谁说“不能”?

试试这个:

这是用于 Win32 API,用 C 编写的。根据需要翻译它...

case WM_NOTIFY:
  HWND X=FindWindow("#32770",NULL);
  if(GetParent(X)==H_frame)int Px,Py,Sx,Sy; RECT R1,R2;
    GetWindowRect(hwnd,&R1); GetWindowRect(X,&R2);
    Sx=R2.right-R2.left,Px=R1.left+(R1.right-R1.left)/2-Sx/2;
    Sy=R2.bottom-R2.top,Py=R1.top+(R1.bottom-R1.top)/2-Sy/2;
    MoveWindow(X,Px,Py,Sx,Sy,1);
  
 break;

将它添加到 WndProc 代码...您可以根据需要设置位置,在这种情况下,它只是位于主程序窗口的中心。它将对任何消息框或文件打开/保存对话框以及可能的其他一些本机控件执行此操作。我不确定,但我认为您可能需要包含 COMMCTRL 或 COMMDLG 才能使用它,至少,如果您想要打开/保存对话框,您会这样做。

我尝试查看 NMHDR 的通知代码和 hwndFrom,然后认为它同样有效,而且更容易,而不是。如果您真的想要非常具体,请告诉 FindWindow 查找您为希望它找到的窗口提供的唯一标题(标题)。

这会在消息框绘制到屏幕上之前触发,因此如果您设置一个全局标志来指示您的代码何时执行操作,并寻找一个唯一的标题,您可以确保您执行的操作只会发生一次(将会可能是多个通知者)。我没有对此进行详细探讨,但我设法让 CreateWindow 在消息框对话框上放置一个编辑框。它看起来就像将老鼠的耳朵移植到克隆猪的脊椎上一样不合适,但它确实有效。以这种方式做事可能比自己动手要容易得多。

乌鸦。

编辑:处理 Raymond Chen 提出的问题的小修正。确保父句柄始终一致,这应该可以正常工作。它对我有用,即使是同一个程序的两个实例......

【讨论】:

请注意,这会找到 a 消息框,不一定是 your 消息框。 没问题... 将if(X) 替换为if(GetParent(X)==H_frame) 并且程序中的文件对话框和消息框也由 H_frame 或任何句柄名称作为父级,其值将是唯一的,因此甚至是多个同一程序的实例将安全共存。

以上是关于C++:如何将 MessageBox 居中?的主要内容,如果未能解决你的问题,请参考以下文章

C++ MessageBox (Windows.h) - 它有啥作用以及如何使它不可见(或等效)?

关于MessageBox

新线程中弹出的Messagebox,不点击确定按钮,主线程暂停

python 弹窗提示和警告框MessageBox部件

在C#的运用程序中 MessageBox.Show("")的问题

MessageBox 从 TCHAR 缓冲区打印额外的 unicode 字符