Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Change MessageBox Position in C++

Tags:

c++

void _MessageBox()
{
ResultMB = MessageBox(NULL, TEXT("MB!"), TEXT("Message"), MB_OK);
    if (ResultMB == IDOK)
    {
        for (int q = 1; q < 5; q++)
         {
            ResultMB = MessageBox(NULL, TEXT("hi"), TEXT("Message"), MB_OK);
         }
    }
}

I want to make every MessageBox be somewhere else on the screen But I do not know how to change a position using C ++

like image 296
Programmer Avatar asked Oct 16 '25 15:10

Programmer


1 Answers

MessageBox() does not allow you to specify a position for its dialog window. However, you can manipulate the dialog window manually to accomplish this. It just takes a little extra work to gain access to the dialog window.

Prior to Windows Vista, you can install a thread-local hook via SetWindowsHookEx() or SetWinEventHook() before calling MessageBox(). The hook will give you access to the dialog window when it is created. You can then do whatever you want with the dialog window.

For example:

// Using SetWindowsHookEx() ...

__thread int MsgBox_X;
__thread int MsgBox_Y;
    
static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_CREATEWND)
    {
        CBT_CREATEWND *s = (CBT_CREATEWND*) lParam;
        if (s->lpcs->hwndParent == NULL)
        {
            s->lpcs->x = MsgBox_X;
            s->lpcs->y = MsgBox_Y;
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}
    
int MessageBoxPos(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, int X, int Y)
{
    HHOOK hHook = SetWindowsHookEx(WH_CBT, &CBTProc, NULL, GetCurrentThreadId());
    MsgBox_X = X;
    MsgBox_Y = Y;
    int result = MessageBox(hWnd, lpText, lpCaption, uType);
    if (hHook) UnhookWindowsHookEx(hHook);
    return result;
}
// Using SetWinEventHook() ...

__thread int MsgBox_X;
__thread int MsgBox_Y;
    
static void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
    if ((GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CHILD) == 0) 
        SetWindowPos(hwnd, NULL, MsgBox_X, MsgBox_Y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
    
int MessageBoxPos(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, int X, int Y)
{
    HWINEVENTHOOK hHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, NULL, &WinEventProc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_OUTOFCONTEXT);
    MsgBox_X = X;
    MsgBox_Y = Y;
    int result = MessageBox(hWnd, lpText, lpCaption, uType);
    if (hHook)  UnhookWinEvent(hHook);
    return result;
}

On Windows Vista and later, the above techniques will still work, but a better option would be to simply not use MessageBox() at all, use TaskDialogIndirect() instead. You can assign a callback function to it, and when the callback receives a TDN_CREATED or TDN_DIALOG_CONSTRUCTED message, it gives you access to the dialog window, which you can then manipulate however you want.

For example:

// Using TaskDialogIndirect() ...

struct TaskDialogData
{
    int X;
    int Y;
};
    
static HRESULT CALLBACK TaskDialogCallback(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData)
{
    if (msg == TDN_DIALOG_CONSTRUCTED) // or TDN_CREATED, either one works
    {
        TaskDialogData *data = (TaskDialogData*) lpRefData;
        SetWindowPos(hwnd, NULL, data->X, data->Y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
    }
    return S_OK;
}
    
int MessageBoxPos(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, int X, int Y)
{
    TaskDialogData data;
    data.X = X;
    data.Y = Y;

    TASKDIALOGCONFIG config = {};
    config.cbSize = sizeof(config);
    config.hwndParent = hWnd;
    config.pszWindowTitle = lpCaption;
    config.pszContent = lpText;
    // configure other settings as desired, based on uType...
    config.pfCallback = &TaskDialogCallback;
    config.lpCallbackData = (LONG_PTR) &data;

    int button = 0;
    TaskDialogIndirect(&config, &button, NULL, NULL);
    return button;
}

Either way, you can then call MessageBoxPos() as needed:

void _MessageBox()
{
    ResultMB = MessageBoxPos(NULL, TEXT("MB!"), TEXT("Message"), MB_OK, DesiredX, DesiredY);
    if (ResultMB == IDOK)
    {
        for (int q = 1; q < 5; q++)
        {
            ResultMB = MessageBoxPos(NULL, TEXT("hi"), TEXT("Message"), MB_OK, DesiredX, DesiredY);
        }
    }
}
like image 105
Remy Lebeau Avatar answered Oct 18 '25 09:10

Remy Lebeau



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!