15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Как создать приложение MFC, которое не имеет строки меню

Для большинства приложений Windows, меню является частью пользовательского интерфейса. Меню играет важную роль в управлении программой. Однако, необязательно, чтобы каждое приложение Windows содержало строку меню. В этой статье как раз и описывается, как создать MFC приложение без меню.

В приложениях, сгенерированных визардом, ресурс IDR_MAINFRAME это стандартный ресурс меню как для приложений SDI так и для MDI. В приложении SDI ресурс меню только один. MDI приложения содержать дополнительные меню для дочерних окон. Такие ресурсы меню обычно называются IDR_xxxTYPE, где xxx связан с типом соответствующего документа. Таким образом, создание MDI приложения без меню не такая уж простая задача в отличие от SDI приложения. В основном, Вам прийдётся изменять все функции, связанные с загрузкой и переключением менюшек.

Шаги по созданию SDI приложения не имеющего меню

  1. При помощи визарда сгенерируйте SDI приложение. Не удаляйте ресурс меню IDR_MAINFRAME. Если же у Вас приложение сгенерированное без участия визарда то, соответственно не удаляйте основной ресурс, отвечающий за меню. Оставить ресурс меню необходимо чтобы избежать ошибок в коде MFC.

  2. Чтобы основное окно приложения не имело полоски, необходимо удалить уже загруженное меню и установить в функции CFrameWnd::PreCreateWindow() поле hMenu структуры CREATESTRUCT в NULL:
          BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
          {
             if(cs.hMenu!=NULL)
             {
                 ::DestroyMenu(cs.hMenu);      // удаляем меню, если загружено
                 cs.hMenu = NULL;              // для этого окна меню нет
             }
    
             return CFrameWnd::PreCreateWindow(cs);
          } 



Шаги по созданию MDI приложения не имеющего меню

  1. При помощи визарда сгенерируйте MDI приложение. Не удаляйте ресурс меню IDR_MAINFRAME. Если же у Вас приложение сгенерированное без участия визарда то, соответственно не удаляйте основной ресурс, отвечающий за меню. Оставить ресурс меню необходимо чтобы избежать ошибок в коде MFC.

  2. Удалите ресурсы меню, связанные с дочерними окнами MDI (IDR_xxxTYPE). Они не будут использоваться. Таким образом мы избежим утечки памяти.

  3. В классе CMainFrame переопределите функцию PreCreateWindow():
          BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
          {
             if(cs.hMenu!=NULL)
             {
                 ::DestroyMenu(cs.hMenu);      // удаляем меню, если загружено
                 cs.hMenu = NULL;              // для этого окна меню нет
             }
    
             return CMDIFrameWnd::PreCreateWindow(cs);
          } 



  4. Измените код, отвечающий за переключение меню путём переопределения методов LoadFrame() и OnCreateClient() класса CMainFrame. Это необходимо, так как MFC уже загрузило менюшки автоматически. Следующий код показывает как это сделать:
          // Переопределённые объявления методов для CMainFrame
    
          BOOL LoadFrame( UINT nIDResource,
                 DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,
                 CWnd* pParentWnd = NULL, CCreateContext* pContext = NULL );
          BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs,
                 CCreateContext* /*pContext*/);
    
          // Переопределённые объявления методов для CMainFrame
    
          BOOL CMainFrame::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
                 CWnd* pParentWnd, CCreateContext* pContext)
          {
              return CFrameWnd::LoadFrame(nIDResource,dwDefaultStyle,
                  pParentWnd,pContext);
          }
    
          BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs,
                  CCreateContext* /*pContext*/)
          {
              return CreateClient(lpcs,NULL);
          } 



 

ОБРАТИТЕ ВНИМАНИЕ: Вместо вызова базового класса (CMDIFrameWnd) в переопределённой LoadFrame, мы вызываем  CFrameWnd, тем самым избегая кода, который работает с менюшками в MDI приложении.