Как раскрыть окно во весь экран?

Автор: Павел Блудов

Версия текста: 1.0

Демонстрационное приложение FullscreenView (30kb)


Приложение FullscreenView

Многие программы умеют изменять свои размеры так, чтобы максимально увеличить размер рабочей области за счет меню, заголовка, панелей управления и строки состояния. Как правило, этот режим включается через меню View->Full Screen.

Причем разные программы делают это по-разному: Developer Studio и Internet Explorer, например, закрывают панель задач, в то время как программы пакета Microsoft Office 2000 оставляют ее на экране. Кроме того, одни MDI-программы увеличивают также и окно активного документа, другие оставляют его как есть.

Самый простой способ заключается в том, чтобы спрятать все панели управления и и изменить размеры окна таким образом, чтобы размеры рабочей области приложения совпали с размерами рабочего стола. Так устроен полноэкранный режим в Developer Studio. К сожалению, в системах с несколькими мониторами это недостаточно. Заголовок, меню и рамка окна вылезут на соседние мониторы и будут торчать там перекрывая нужную информацию.

Решение должно быть более комплексным:

Пример - приложение FullscreenView (MFC MDI) реализует все эти действия.

Реализация

Запоминаем положение и размеры окна, панелей инструментов и строки состояния:

    // Hide the toolbar and the statusbar
    if (m_bToolBarWasVisible = m_wndToolBar.IsWindowVisible())
        ShowControlBar(&m_wndToolBar, FALSE, FALSE); 
    if (m_bStatusBarWasVisible = m_wndStatusBar.IsWindowVisible())
        ShowControlBar(&m_wndStatusBar, FALSE, FALSE);
    
    // Save the old position and the old size of the main window
    GetWindowRect(&m_mainRect);
    
    // Save all styles affected by fullscreenview
    m_dwSavedStyles = GetStyle() & (FS_AFFECTED_STYLES | WS_MAXIMIZE);

Убираем меню, заголовок и рамку окна:

    // Save the Original Menu and set menu to NULL
    ASSERT(m_OrgMenu.GetSafeHmenu() == NULL);
    CMenu* pOldMenu = GetMenu();
    m_OrgMenu.Attach(pOldMenu->Detach());
    SetMenu((CMenu*)NULL);

    // remove the caption and the frame of the main window
    ModifyStyle(FS_AFFECTED_STYLES, 0);

    // maximize the main window if need
    if (0 == (WS_MAXIMIZE & m_dwSavedStyles))
        ShowWindow(SW_MAXIMIZE);

Если хочется занять пространство, зарезервированное за панелью задач, следует немного подвинуть наше максимизированное окошко:

    int screenx, screeny, screencx, screency;
    screenx = screeny = 0;
    screencx = ::GetSystemMetrics(SM_CXSCREEN);
    screency = ::GetSystemMetrics(SM_CYSCREEN);
    MoveWindow(screenx, screeny, screencx, screency);

К сожалению, в системах с несколькими мониторами мы переместим окно на основной экран, придется добавить немного кода на такой случай:

    int screenx, screeny, screencx, screency;

#if(WINVER >= 0x0500)

    if (::GetSystemMetrics(SM_CMONITORS) > 0)
    {
        typedef HMONITOR (WINAPI * FPMONITORFROMWINDOW)( HWND hwnd, DWORD dwFlags);
        typedef BOOL (WINAPI * FPGETMONITORINFO)(HMONITOR hMonitor, LPMONITORINFO lpmi);

        MONITORINFO mi;
        HMONITOR hm;
        FPMONITORFROMWINDOW fpMonitorFromWindow;
        FPGETMONITORINFO fpGetMonitorInfo;

        HINSTANCE h = ::GetModuleHandle(_T("user32.dll"));
        ASSERT(NULL != h);

        fpMonitorFromWindow = (FPMONITORFROMWINDOW)GetProcAddress(h, "MonitorFromWindow");
#ifdef _UNICODE
        fpGetMonitorInfo = (FPGETMONITORINFO)GetProcAddress(h, "GetMonitorInfoW");
#else
        fpGetMonitorInfo = (FPGETMONITORINFO)GetProcAddress(h, "GetMonitorInfoA");
#endif
        ASSERT(NULL != fpMonitorFromWindow && NULL != fpGetMonitorInfo);

        mi.cbSize = sizeof(MONITORINFO);
        hm = fpMonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
        fpGetMonitorInfo(hm, &mi);
        screenx = mi.rcMonitor.left;
        screeny = mi.rcMonitor.top;
        screencx = mi.rcMonitor.right - screenx;
        screency = mi.rcMonitor.bottom - screeny;
    }
    else

#endif (WINVER >= 0x0500)

    {
        screenx = screeny = 0;
        screencx = ::GetSystemMetrics(SM_CXSCREEN);
        screency = ::GetSystemMetrics(SM_CYSCREEN);
    }
    MoveWindow(screenx, screeny, screencx, screency);

И завершающий штрих - маленькая панель с кнопкой для отключения полноэкранного режима:

    // this will contain the full-screen off button
    // create the new toolbar
    ASSERT(!m_pwndFullScreenBar);
    m_pwndFullScreenBar = new CToolBar;
    m_pwndFullScreenBar->Create(this);
    m_pwndFullScreenBar->LoadToolBar(IDR_FULLSCREEN);
    m_pwndFullScreenBar->SetBarStyle(m_pwndFullScreenBar->GetBarStyle() |
        CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
    // to look better:
    m_pwndFullScreenBar->ModifyStyle(0, TBSTYLE_FLAT);
    m_pwndFullScreenBar->EnableDocking(0);
    // place the full-screen off button somewhere:
    CPoint pt(screenx + screencx - 64, screeny + 16);
    FloatControlBar(m_pwndFullScreenBar, pt);

Чтобы вернуть все в изначальный вид слуедует проделать эти действия в обратном порядке:

    if (m_pwndFullScreenBar)
    {
        delete m_pwndFullScreenBar;
        m_pwndFullScreenBar = NULL;
    }
    
    m_bFullScreenMode = false;

    // Restore all affected styles
    ModifyStyle(0, m_dwSavedStyles);

    // Restore the main window if need
    if (0 == (WS_MAXIMIZE & m_dwSavedStyles))
        ShowWindow(SW_RESTORE);

    MoveWindow(&m_mainRect);
    ShowControlBar(&m_wndToolBar, m_bToolBarWasVisible, FALSE);
    ShowControlBar(&m_wndStatusBar, m_bStatusBarWasVisible, FALSE);

    ASSERT(m_OrgMenu.GetSafeHmenu() != NULL);
    SetMenu(&m_OrgMenu);
    m_OrgMenu.Detach();

Для приложений MDI кроме того необходимо убирать заголовок у дочерних окон:

void CChildFrame::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd) 
{

    CMainFrame* pMainFrame=(CMainFrame*)AfxGetMainWnd();
    if(!pMainFrame->m_bFullScreenMode)
        CMDIChildWnd::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd);
    else if (!bActivate && pDeactivateWnd->GetStyle() & WS_MAXIMIZE)
    {
        pDeactivateWnd->ModifyStyle(0, WS_CAPTION);
        pActivateWnd->ModifyStyle(WS_CAPTION, 0);
    }
}

void CChildFrame::OnSize(UINT nType, int cx, int cy) 
{
    CMainFrame* pMainFrame=(CMainFrame*)AfxGetMainWnd();
    if (pMainFrame->m_bFullScreenMode)
    {
        if (SIZE_MAXIMIZED == nType)
            ModifyStyle(WS_CAPTION, 0, SWP_DRAWFRAME);
        else
            ModifyStyle(0, WS_CAPTION, SWP_DRAWFRAME);
    }
    CMDIChildWnd::OnSize(nType, cx, cy);
}

Использованные статьи и литература


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.