C : как центрировать MessageBox?

#c #windows #mfc #center #messagebox

#c #Windows #mfc #центрировать #messagebox

Вопрос:

Использование Visual Studio C с MFC. Как мне центрировать MessageBox в его родительском окне? В настоящее время он центрируется на рабочем столе.

Комментарии:

1. Используйте postMessage() перед вызовом MessageBox. В вашем обработчике сообщений используйте EnumWindows, чтобы найти окно сообщения обратно и переместить Windows туда, куда вы хотите.

2. Окно сообщения имеет класс # 32770, который должен помочь вам его найти

3. Есть способ изменить местоположение, но он слишком сложен для такой небольшой задачи. Просто создайте свой собственный CDialog.

Ответ №1:

Вам необходимо установить перехват и изменить положение диалогового окна при создании.

 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, amp;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;
}
  

Ответ №2:

:: Для меня AfxMessageBox () отображается в центре мэйнфрейма. По сути, это вызов ::MessageBox() с дескриптором мэйнфрейма в качестве первого параметра. Разве у тебя это не работает?

Комментарии:

1. У меня это не работает. Возможно, он может быть привязан к «мэйнфрейму» приложения, но мне нужно, чтобы он был привязан к моему диалоговому окну, производному от CDialog (именно оттуда я вызываю MessageBox / AfxMessageBox).

Ответ №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,amp;R1); GetWindowRect(X,amp;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… Вы можете установить положение по своему усмотрению, в этом случае оно просто располагается по центру главного окна программы. Это будет сделано для любого messagebox или диалогового окна открытия / сохранения файла и, вероятно, некоторых других встроенных элементов управления. Я не уверен, но я думаю, что вам, возможно, потребуется включить COMMCTRL или COMMDLG, чтобы использовать это, по крайней мере, вы это сделаете, если хотите открыть / сохранить диалоги.

Я поэкспериментировал с кодами уведомлений и HWNDF из NMHDR, затем решил, что это так же эффективно и намного проще не делать. Если вы действительно хотите быть очень конкретным, скажите FindWindow, чтобы он искал уникальную подпись (title), которую вы даете окну, которое вы хотите, чтобы оно нашло.

Это срабатывает перед отображением messagebox на экране, поэтому, если вы установите глобальный флаг, указывающий, когда действие выполняется вашим кодом, и ищите уникальную подпись, вы можете быть уверены, что выполняемые вами действия будут выполняться только один раз (скорее всего, будет несколько уведомителей). Я не изучал это подробно, но мне удалось получить CreateWindow, чтобы поместить окно редактирования в диалоговое окно messagebox. Это выглядело так же неуместно, как крысиное ухо, пересаженное на позвоночник клонированной свиньи, но это работает. Делать все таким образом может быть намного проще, чем создавать свой собственный.

Ворон.

РЕДАКТИРОВАТЬ: Небольшое исправление для решения проблемы, поднятой Рэймондом Ченом. Убедитесь, что родительские дескрипторы согласованы во всем, и это должно работать нормально. Для меня это работает, даже с двумя экземплярами одной и той же программы…

Комментарии:

1. Обратите внимание, что при этом будет найдено окно сообщения, не обязательно ваше окно сообщения.

2. Не проблема… Замените if(X) на if(GetParent(X)==H_frame) , и файловые диалоговые окна и ящики сообщений в программе также будут родительскими с помощью H_frame или любого другого имени дескриптора, значение которого будет уникальным, так что даже несколько экземпляров одной и той же программы будут безопасно сосуществовать.