Win32:全屏和隐藏任务栏

问题描述 投票:26回答:5

我有一个窗口,我SetWindowPos(window, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);

它覆盖了整个屏幕,确定,但是还需要一段时间(0.5秒)才能覆盖任务栏。

是否有一种方法可以立即通过任务栏?我发现设置HWND_TOPMOST可以立即执行此操作,但是即使我切换了该应用程序,它仍然位于所有其他窗口之上-这是我不想要的。另外,如果我先隐藏窗口然后再显示它,它将以某种方式迫使窗口重新绘制并立即覆盖任务栏,但它会闪烁(由于隐藏)。还有其他方法吗?

winapi fullscreen taskbar
5个回答
39
投票

Edit 2。还有一种更好的方法来进行全屏显示,铬的方式,取自这里:

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);
  }
}

编辑

。最好创建一个全屏窗口,因为BrendanMcK在对此答案的评论中指出了这一点,请参见以下链接:http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx(“如何用全屏窗口覆盖任务栏?”)

使用上面的链接的新代码将是:

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);
}

下面的旧答案-请勿使用,仅记录如何不执行此操作。

您必须隐藏任务栏和菜单栏才能立即查看全屏。

这里是代码(使用WTL),调用SetFullScreen(true)进入全屏模式:

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);
        }       
    }
};

您还必须在WM_CLOSE消息中添加一些代码:

case WM_CLOSE:
    ShowTaskBar(true);

此解决方案有一个警告,如果您的应用程序崩溃或通过任务管理器被杀死,那么用户将永久失去其系统上的任务栏! (除非他再次运行您的应用程序,进入全屏并退出,然后他将再次看到任务栏)。

在我的回答中,我之前指向“ atlwince.h”,但该功能仅在Windows CE上有效,我上面粘贴的功能在XP,Vista和7上都可以正常工作。


14
投票

是,HWND_TOPMOST为我做了。这是一段代码,可以让我全屏(并且快速)工作:


7
投票

[Raymond Chen在他的博客中描述了执行此操作的“正确”方法:


1
投票

[我相信任务栏在其外壳挂钩告诉它“粗鲁的应用程序”时会避开它,这可能需要一些时间。


-4
投票
  1. 右键单击任务栏
© www.soinside.com 2019 - 2024. All rights reserved.