Как убрать системное меню из приложения свёрнутого в иконку

Существуют два метода, которые позволяют убрать системное меню, которое появляется при клике пользователем по приложению, свёрнутому в иконку:

  1. Переопределить функцию основного фрейма окна PreCreateWindow, чтобы удалить WS_SYSMENU из оконных стилей. Однако, данный метод убирает системное меню когда приложение находится в нормальном состоянии.

  2. Переопределить метод основного фрейма окна OnSize и включить или исключить стиль WS_SYSMENU окна основного фрейма в зависимости от действий пользователя. Данный способ позволяет убрать системное меню когда приложение свёрнуто в иконку и добавить системное меню, когда приложение восстановлено.

Первый метод

Чтобы полностью убрать системное меню из приложения, переопределяем метод основного фрейма окна PreCreateWindow как показано ниже:

   BOOL CMainFrame::PreCreateWindow(CREATESTRUCT & cs)
{
// Вызываем PreCreateWindow из базового класса, и в следующей
// строке заменяем CMDIFrameWnd на CFrameWnd для SDI приложения

if (!CMDIFrameWnd::PreCreateWindow(cs))
return FALSE;

// Убираем бит стиля системного меню из окна

cs.style &= ~WS_SYSMENU;
return TRUE;
}

Второй метод

Следующие шаги и фрагменты кода показывают, как убрать системное меню когда приложение свёрнуто в иконку и вернуть системное меню, когда приложение восстановлено.

  1. В объявлении класса CMainFrame объявляем public переменную типа BOOLEAN. Эта переменная определяет, разрешено системное меню или нет:
          // В SDI приложении CMainFrame наследуется от CFrameWnd

    class CMainFrame : public CMDIFrameWnd
    {
    public:
    BOOL sys_menu_enabled;
    .
    . // Остальные объявления класса
    .
    }
  2. Изменяем конструктор CMainFrame, чтобы инициализировать переменную sys_menu_enabled в TRUE:
          CMainFrame::CMainFrame()
    {
    //поумолчанию системное меню разрешено
    sys_menu_enabled = TRUE;
    .
    . // обычный код конструктора, если он есть
    .
    }
  3. Воспользуемся визардом (Class Wizard), чтобы создать обработчик сообщения WM_SIZE для класса CMainFrame и добавим следующий код в обработчик сообщения CMainFrame::OnSize:
          void CMainFrame::OnSize(UINT nType, int cx, int cy)
    {
    // объявляем локальную переменную для хранения стиля окна

    long window_style;

    //вызываем функцию OnSize базового класса,
    //если SDI приложение вызывает CFrameWnd::OnSize()

    CMDIFrameWnd::OnSize(nType, cx, cy);

    //если пользователь минимизирует приложение

    if (nType == SIZE_MINIMIZED)
    {
    // Получаем стиль основного фрейма окна
    window_style = GetWindowLong(m_hWnd, GWL_STYLE);

    //Убираем системное меню из оконного стиля
    window_style &= ~WS_SYSMENU;

    //переключаем булевую переменную, чтобы запретить системное меню
    sys_menu_enabled = FALSE;

    //Устанавливаем атрибуты стиля для основного фрейма окна
    SetWindowLong(m_hWnd, GWL_STYLE, window_style);
    }
    else
    {
    //если пользователь восстанавливает приложение
    //и его системное меню запрещено,
    if ((nType == SIZE_RESTORED) || nType == SIZE_MAXIMIZED) &&
    (!sys_menu_enabled))
    {
    window_style = GetWindowLong(m_hWnd, GWL_STYLE);

    //Добавляем системное меню к стилю окна
    window_style |= WS_SYSMENU;

    //переключаем булевую переменную, чтобы разрешить системное меню
    sys_menu_enabled = TRUE;

    SetWindowLong(m_hWnd, GWL_STYLE, window_style);
    SendMessage(WM_NCACTIVATE,TRUE);
    }
    }
    }