web-dev-qa-db-fra.com

Win32: plein écran et masquage de la barre des tâches

J'ai une fenêtre que je SetWindowPos(window, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);

Cela couvre tout l'écran, ok, mais cela prend un certain temps (0,5 sec) pour couvrir également la barre des tâches.

Existe-t-il un moyen d'accéder immédiatement à la barre des tâches? J'ai trouvé que le paramètre HWND_TOPMOST le fait immédiatement, mais il reste au-dessus de toutes les autres fenêtres, même si je change d'application - c'est quelque chose que je ne veux pas. De plus, si je masque d'abord la fenêtre et que je la montre, cela force en quelque sorte la fenêtre à se redessiner et couvre immédiatement la barre des tâches, mais elle scintille (à cause de la dissimulation). Y a-t-il un autre moyen?

26
Lars Kanto

Éditez 2 . Il y a même une meilleure façon de faire du plein écran, à la manière du chrome, source prise ici:

http://src.chromium.org/viewvc/chrome/trunk/src/ui/views/win/fullscreen_handler.cc?revision=HEAD&view=markup

void FullscreenHandler::SetFullscreenImpl(bool fullscreen, bool for_metro) {
  ScopedFullscreenVisibility visibility(hwnd_);

  // Save current window state if not already fullscreen.
  if (!fullscreen_) {
    // Save current window information.  We force the window into restored mode
    // before going fullscreen because Windows doesn't seem to hide the
    // taskbar if the window is in the maximized state.
    saved_window_info_.maximized = !!::IsZoomed(hwnd_);
    if (saved_window_info_.maximized)
      ::SendMessage(hwnd_, WM_SYSCOMMAND, SC_RESTORE, 0);
    saved_window_info_.style = GetWindowLong(hwnd_, GWL_STYLE);
    saved_window_info_.ex_style = GetWindowLong(hwnd_, GWL_EXSTYLE);
    GetWindowRect(hwnd_, &saved_window_info_.window_rect);
  }

  fullscreen_ = fullscreen;

  if (fullscreen_) {
    // Set new window style and size.
    SetWindowLong(hwnd_, GWL_STYLE,
                  saved_window_info_.style & ~(WS_CAPTION | WS_THICKFRAME));
    SetWindowLong(hwnd_, GWL_EXSTYLE,
                  saved_window_info_.ex_style & ~(WS_EX_DLGMODALFRAME |
                  WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));

    // On expand, if we're given a window_rect, grow to it, otherwise do
    // not resize.
    if (!for_metro) {
      MONITORINFO monitor_info;
      monitor_info.cbSize = sizeof(monitor_info);
      GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST),
                     &monitor_info);
      gfx::Rect window_rect(monitor_info.rcMonitor);
      SetWindowPos(hwnd_, NULL, window_rect.x(), window_rect.y(),
                   window_rect.width(), window_rect.height(),
                   SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
    }
  } else {
    // Reset original window style and size.  The multiple window size/moves
    // here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be
    // repainted.  Better-looking methods welcome.
    SetWindowLong(hwnd_, GWL_STYLE, saved_window_info_.style);
    SetWindowLong(hwnd_, GWL_EXSTYLE, saved_window_info_.ex_style);

    if (!for_metro) {
      // On restore, resize to the previous saved rect size.
      gfx::Rect new_rect(saved_window_info_.window_rect);
      SetWindowPos(hwnd_, NULL, new_rect.x(), new_rect.y(),
                   new_rect.width(), new_rect.height(),
                   SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
    }
    if (saved_window_info_.maximized)
      ::SendMessage(hwnd_, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
  }
}

Modifier . Il est probablement préférable de créer une fenêtre plein écran comme l'a souligné BrendanMcK dans un commentaire à cette réponse, voir ce lien: http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05 /414910.aspx ("Comment puis-je couvrir la barre des tâches avec une fenêtre plein écran?")

Le nouveau code utilisant le lien ci-dessus serait:

HWND CreateFullscreenWindow(HWND hwnd)
{
 HMONITOR hmon = MonitorFromWindow(hwnd,
                                   MONITOR_DEFAULTTONEAREST);
 MONITORINFO mi = { sizeof(mi) };
 if (!GetMonitorInfo(hmon, &mi)) return NULL;
 return CreateWindow(TEXT("static"),
       TEXT("something interesting might go here"),
       WS_POPUP | WS_VISIBLE,
       mi.rcMonitor.left,
       mi.rcMonitor.top,
       mi.rcMonitor.right - mi.rcMonitor.left,
       mi.rcMonitor.bottom - mi.rcMonitor.top,
       hwnd, NULL, g_hinst, 0);
}

Ancienne réponse ci-dessous - ne l'utilisez pas, ne reste que pour mémoire sur la façon de NE PAS le faire.

Vous devez masquer la barre des tâches et la barre de menus pour afficher immédiatement le plein écran.

Voici le code (utilise WTL), appelez SetFullScreen (true) pour passer en mode plein écran:

template <class T, bool t_bHasSip = true>
class CFullScreenFrame
{
public:
    bool m_fullscreen;
    LONG m_windowstyles;
    WINDOWPLACEMENT m_windowplacement;

    CFullScreenFrame() 
        :
        m_fullscreen(false),
        m_windowstyles(0)
    { }

    void SetFullScreen(bool fullscreen)
    {
        ShowTaskBar(!fullscreen);

        T* pT = static_cast<T*>(this);

        if (fullscreen) {
            if (!m_fullscreen) {
                m_windowstyles = pT->GetWindowLongW(GWL_STYLE);
                pT->GetWindowPlacement(&m_windowplacement);
            }

        }

        // SM_CXSCREEN gives primary monitor, for multiple monitors use SM_CXVIRTUALSCREEN.
        RECT fullrect = { 0 };              
        SetRect(&fullrect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));

        WINDOWPLACEMENT newplacement = m_windowplacement;
        newplacement.showCmd = SW_SHOWNORMAL;
        newplacement.rcNormalPosition = fullrect;

        if (fullscreen) {
            pT->SetWindowPlacement(&newplacement);
            pT->SetWindowLongW(GWL_STYLE,  WS_VISIBLE);
            pT->UpdateWindow();
        } else {
            if (m_fullscreen) {
                pT->SetWindowPlacement(&m_windowplacement);
                pT->SetWindowLongW(GWL_STYLE, m_windowstyles);
                pT->UpdateWindow();
            }
        }

        m_fullscreen = fullscreen;
    }

    void ShowTaskBar(bool show)
    {
        HWND taskbar = FindWindow(_T("Shell_TrayWnd"), NULL);
        HWND start = FindWindow(_T("Button"), NULL);

        if (taskbar != NULL) {
            ShowWindow(taskbar, show ? SW_SHOW : SW_HIDE);
            UpdateWindow(taskbar);
        }
        if (start != NULL) { 
            // Vista
            ShowWindow(start, show ? SW_SHOW : SW_HIDE);
            UpdateWindow(start);
        }       
    }
};

Vous devez également ajouter du code au message WM_CLOSE:

case WM_CLOSE:
    ShowTaskBar(true);

Il y a une mise en garde avec cette solution, si votre application se bloque ou est tuée par le gestionnaire de tâches, la perte de la barre des tâches de l'utilisateur sur son système en permanence! (à moins qu'il ne réexécute votre application, ne passe en plein écran et quitte, il verra de nouveau la barre des tâches).

Plus tôt dans ma réponse, j'ai indiqué "atlwince.h" mais cette fonction ne fonctionnait que sur Windows CE, celle que j'ai collée ci-dessus fonctionne très bien avec XP, Vista et 7.

37
Czarek Tomczak

Oui, HWND_TOPMOST Le fait pour moi. Voici une section de code qui fait que le plein écran fonctionne bien (et rapidement) pour moi:


bool enterFullscreen(HWND hwnd, int fullscreenWidth, int fullscreenHeight, int colourBits, int refreshRate) {
    DEVMODE fullscreenSettings;
    bool isChangeSuccessful;
    RECT windowBoundary;

    EnumDisplaySettings(NULL, 0, &fullscreenSettings);
    fullscreenSettings.dmPelsWidth        = fullscreenWidth;
    fullscreenSettings.dmPelsHeight       = fullscreenHeight;
    fullscreenSettings.dmBitsPerPel       = colourBits;
    fullscreenSettings.dmDisplayFrequency = refreshRate;
    fullscreenSettings.dmFields           = DM_PELSWIDTH |
                                            DM_PELSHEIGHT |
                                            DM_BITSPERPEL |
                                            DM_DISPLAYFREQUENCY;

    SetWindowLongPtr(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_TOPMOST);
    SetWindowLongPtr(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
    SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fullscreenWidth, fullscreenHeight, SWP_SHOWWINDOW);
    isChangeSuccessful = ChangeDisplaySettings(&fullscreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL;
    ShowWindow(hwnd, SW_MAXIMIZE);

    return isChangeSuccessful;
}

Notez que cela changera la résolution si vous lui indiquez les mauvais paramètres. C'est ce que je veux habituellement, mais si vous n'aimez pas cela, vous pouvez trouver votre résolution en utilisant (où mainWindow est renvoyé à partir de quelque chose comme CreateWindow() ou CreateWindowEx()):


windowHDC = GetDC(mainWindow);
fullscreenWidth  = GetDeviceCaps(windowHDC, HORZRES);
fullscreenHeight = GetDeviceCaps(windowHDC, VERTRES);
colourBits       = GetDeviceCaps(windowHDC, BITSPIXEL);
refreshRate      = GetDeviceCaps(windowHDC, VREFRESH);

Lorsque vous voulez sortir du plein écran, vous faites quelque chose comme ceci:


bool exitFullscreen(HWND hwnd, int windowW, int windowY, int windowedWidth, int windowedHeight, int windowedPaddingX, int windowedPaddingY) {
    bool isChangeSuccessful;

    SetWindowLongPtr(hwnd, GWL_EXSTYLE, WS_EX_LEFT);
    SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
    isChangeSuccessful = ChangeDisplaySettings(NULL, CDS_RESET) == DISP_CHANGE_SUCCESSFUL;
    SetWindowPos(hwnd, HWND_NOTOPMOST, windowX, windowY, windowedWidth + windowedPaddingX, windowedHeight + windowedPaddingY, SWP_SHOWWINDOW);
    ShowWindow(hwnd, SW_RESTORE);

    return isChangeSuccessful;
}

J'ai défini mon code pour basculer entre le mode plein écran et le mode fenêtré à l'aide d'un raccourci clavier, et je garde les variables du mode fenêtré comme globales, de sorte que lors du passage en mode fenêtré, il reste en place.

Ce code a également l'avantage de fonctionner dans l'équivalent du "mode exclusif" (j'utilise XP, et je ne l'ai pas essayé sur les nouvelles versions de Windows), ce qui signifie que ce sera beaucoup, Plus vite. Faites-moi savoir si j'ai fait des erreurs en condensant le code (à partir de mon code beaucoup plus gros).

14
Warpspace

Raymond Chen décrit la façon "correcte" de procéder sur son blog:

http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx

Jouer avec la fenêtre de la barre des tâches est explicitement un comportement non recommandé .

7
Malcolm

Je crois que la barre des tâches se mettra de côté lorsque son crochet Shell lui parlera d'une "application grossière", cela pourrait prendre un peu de temps.

Que se passe-t-il si vous commencez avec la fenêtre HWND_TOPMOST et que vous ne la remplissez pas au maximum après 1 seconde?

1
Anders