Use SetWindowsHookEx() or SetWinEventHook() with a thread-local hook to capture the MessageBox() dialog’s HWND, then you can use EnableWindow() to disable the button.
Here is how to do it using SetWindowsHookEx():
HHOOK hHook = NULL;
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if( nCode == HCBT_ACTIVATE )
    {
        HWND hDlg = (HWND) wParam;
        HWND hBtnWnd = GetDlgItem(hDlg, IDNO);
        if (hBtnWnd != NULL)
            EnableWindow(hBtnWnd, FALSE);
    }
    return CallNextHookEx(hHook, nCode, wParam, lParam);
}
{
    //...
    hHook = SetWindowsHookEx(WH_CBT, &CBTProc, NULL, GetCurrentThreadId());
    MessageBox(NULL, TEXT("Test"), TEXT("Test"), MB_YESNO);
    if (hHook != NULL)
        UnhookWindowsHookEx(hHook);
    //...
}
Here is how to do it using SetWinEventHook():
void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
    if( event == EVENT_SYSTEM_DIALOGSTART )
    {
        HWND hBtnWnd = GetDlgItem(hwnd, IDNO);
        if (hBtnWnd != NULL)
            EnableWindow(hBtnWnd, FALSE);
    }
}
{
    //...
    HRESULT hRes = CoInitialize(NULL);
    HWINEVENTHOOK hHook = SetWinEventHook(EVENT_SYSTEM_DIALOGSTART, EVENT_SYSTEM_DIALOGSTART, NULL, &WinEventProc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_OUTOFCONTEXT);
    MessageBox(NULL, TEXT("Test"), TEXT("Test"), MB_YESNO);
    if (hHook != NULL)
        UnhookWinEvent(hHook);
    if (SUCCEEDED(hRes))
        CoUninitialize();
    //...
}
13
solved Show Yes/No messagebox where No is grayed out win32api C++ [closed]