Win32:全屏和隐藏任务栏

发布于 2024-08-24 15:49:48 字数 347 浏览 14 评论 0原文

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

它覆盖了整个屏幕,好吧,但需要一段时间(0.5 秒)也覆盖任务栏。

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

I have a window, which I SetWindowPos(window, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);

It covers the whole screen, ok, but it takes a while (0.5 sec) to cover the taskbar as well.

Is there a way to come over the taskbar immediately? I found that setting HWND_TOPMOST does it immediately, but it stays above all the other windows, even if I switch the app - this is something I don't want. Also, if I first hide the window and then show it, it somehow forces the window to redraw and covers the taskbar immediately, but it flickers (because of the hiding). Is there another way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦幻的味道 2024-08-31 15:49:48

编辑2。甚至还有一种更好的全屏方式,即 chromium 方式,来源取自此处:

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

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。

Edit 2. There is even a better way for doing fullscreen, the chromium way, source taken from here:

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

Edit.
It is probably better to create a fullscreen window as BrendanMcK pointed it out in a comment to this answer, see this link: http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx ("How do I cover the taskbar with a fullscreen window?")

The new code using the link above would be:

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

Old answer below - do not use it, stays only for the record on how NOT to do this.

You have to hide taskbar and menubar to see fullscreen immediately.

Here is the code (uses WTL), call SetFullScreen(true) to go into full screen mode:

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

You also have to add some code to WM_CLOSE message:

case WM_CLOSE:
    ShowTaskBar(true);

There is one caveat with this solution, if your application crashes or is killed through task manager, then user losses taskbar on his system permanently! (unless he runs your application again, goes into fullscreen and exits, then he will see the taskbar again).

Earlier in my answer I pointed to "atlwince.h" but that function worked only on Windows CE, the one I pasted above works fine with XP, Vista and 7.

没企图 2024-08-31 15:49:48

是的,HWND_TOPMOST 为我做到了。
这是一段使全屏对我来说运行良好(且快速)的代码:


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

请注意,如果您告诉它错误的设置,这将更改分辨率。这是我通常想要的,但如果您不喜欢这样,您可以使用 (其中 mainWindow 是从 CreateWindow()CreateWindowEx()):


windowHDC = GetDC(mainWindow);
fullscreenWidth  = GetDeviceCaps(windowHDC, DESKTOPHORZRES);
fullscreenHeight = GetDeviceCaps(windowHDC, DESKTOPVERTRES);
colourBits       = GetDeviceCaps(windowHDC, BITSPIXEL);
refreshRate      = GetDeviceCaps(windowHDC, VREFRESH);

当您想退出全屏时,您可以执行以下操作:


bool exitFullscreen(HWND hwnd, int windowX, 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;
}

我将代码设置为使用热键在全屏和窗口模式之间切换,并保持窗口模式模式变量为全局变量,因此当更改为窗口模式时,它保持不变。

这段代码还有一个优点是可以在相当于“独占模式”的情况下运行(我使用的是 XP,还没有在较新版本的 Windows 上尝试过),这意味着它会快得多。如果我在压缩代码(来自我更大的代码)时犯了任何错误,请告诉我。

Yup, HWND_TOPMOST does it for me.
Here is a section of code that makes full-screen work well (and quick) for me:


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

Note that this will change the resolution if you tell it the wrong settings. This is what I usually want, but if you don't like that, you can find out your resolution by using (where mainWindow is returned from something like CreateWindow() or CreateWindowEx()):


windowHDC = GetDC(mainWindow);
fullscreenWidth  = GetDeviceCaps(windowHDC, DESKTOPHORZRES);
fullscreenHeight = GetDeviceCaps(windowHDC, DESKTOPVERTRES);
colourBits       = GetDeviceCaps(windowHDC, BITSPIXEL);
refreshRate      = GetDeviceCaps(windowHDC, VREFRESH);

When you want to get out of full-screen you do something like this:


bool exitFullscreen(HWND hwnd, int windowX, 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;
}

I set my code to change between full-screen and windowed mode using a hotkey, and I keep the windowed mode variables as global, so that when changing to windowed mode, it stays put.

This code also has the advantage of running in the equivalent of "exclusive mode" (I'm using XP, and haven't tried it on the newer versions of windows), which means it'll be much, much faster. Let me know if I've made any mistakes from condensing the code (from my much bigger code).

绮筵 2024-08-31 15:49:48

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

https: //devblogs.microsoft.com/oldnewthing/20100412-00/?p=14353

明确摆弄任务栏窗口是推荐的行为。

Raymond Chen describes the "correct" way to do this at his blog:

https://devblogs.microsoft.com/oldnewthing/20100412-00/?p=14353

Fiddling with the task bar window explicitly is not recommended behaviour.

沉默的熊 2024-08-31 15:49:48

这是最新完整链接Raymond Chen 回答。

由于 MSDN/Microsoft 不断破坏链接,我将在下面粘贴以供后代使用:


出于某种原因, 人们想得太难了。如果您想创建一个覆盖任务栏的全屏窗口,只需创建一个全屏窗口,任务栏就会自动消失。不要到处寻找任务栏并戳它;让它做它该做的事。

与往常一样,从临时程序开始并添加如下所示:

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

void OnChar(HWND hwnd, TCHAR ch, int cRepeat)
{
 if (ch == TEXT(' ')) {
  CreateFullscreenWindow(hwnd);
 }
}

HANDLE_MSG(hwnd, WM_CHAR, OnChar);

请注意,该示例程序并不担心会破坏该全屏窗口或阻止用户创建多个全屏窗口。这只是一个样本。重点是看CreateFullScreenWindow函数是怎么写的。

我们使用 MonitorFromWindow 函数来确定我们应该使用哪个监视器进入全屏模式。请注意,在多显示器系统中,这可能与任务栏所在的显示器不同。幸运的是,我们不必担心这一点;任务栏可以解决这个问题。

我见过人们寻找任务栏窗口,然后在其上执行 ShowWindow(hwndTaskbar, SW_HIDE) 。出于多种原因,这很疯狂。

首先是在评估这样的技巧时应该始终使用的心理练习:“如果两个程序都尝试了这个技巧怎么办?”现在您有两个程序,它们都认为自己负责隐藏和显示任务栏,但两者都不相互协调。结果一团糟。一个程序隐藏任务栏,然后另一个程序隐藏任务栏,然后第一个程序决定它已完成,因此它取消隐藏任务栏,但第二个程序尚未完成,并在它认为应该隐藏时获得可见的任务栏。事情只会从那里开始走下坡路。

其次,如果您的程序在有机会取消隐藏任务栏之前崩溃了怎么办?任务栏现在永久隐藏,用户必须注销并重新登录才能恢复任务栏。这不太好。

第三,如果根本没有任务栏怎么办?在终端服务器方案中,通常 无需资源管理器即可自行运行程序 (已存档)。在此配置中,没有资源管理器,没有任务栏。或者,也许您运行的 Windows 的未来版本没有任务栏,它已被其他某种机制取代。你的程序现在要做什么?

不要对任务栏做任何这种混乱的事情。只需创建全屏窗口并让任务栏自动执行其操作即可。

Here's the latest unbroken link to Raymond Chen answer.

Since MSDN/Microsoft keeps breaking links I'll paste below for posterity:


For some reason, people think too hard. If you want to create a fullscreen window that covers the taskbar, just create a fullscreen window and the taskbar will automatically get out of the way. Don't go around hunting for the taskbar and poking it; let it do its thing.

As always, start with the scratch program and add the following:

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

void OnChar(HWND hwnd, TCHAR ch, int cRepeat)
{
 if (ch == TEXT(' ')) {
  CreateFullscreenWindow(hwnd);
 }
}

HANDLE_MSG(hwnd, WM_CHAR, OnChar);

Note that this sample program doesn't worry about destroying that fullscreen window or preventing the user from creating more than one. It's just a sample. The point is seeing how the CreateFullScreenWindow function is written.

We use the MonitorFromWindow function to figure out which monitor we should go fullscreen to. Note that in a multiple monitor system, this might not be the same monitor that the taskbar is on. Fortunately, we don't have to worry about that; the taskbar figures it out.

I've seen people hunt for the taskbar window and then do a ShowWindow(hwndTaskbar, SW_HIDE) on it. This is nuts for many reasons.

First is a mental exercise you should always use when evaluating tricks like this: "What if two programs tried this trick?" Now you have two programs both of which think they are in charge of hiding and showing the taskbar, neither of which is coordinating with the other. The result is a mess. One program hides the taskbar, then the other does, then the first decides it's finished so it unhides the taskbar, but the second program wasn't finished yet and gets a visible taskbar when it thought it should be hidden. Things only go downhill from there.

Second, what if your program crashes before it gets a chance to unhide the taskbar? The taskbar is now permanently hidden and the user has to log off and back on to get their taskbar back. That's not very nice.

Third, what if there is no taskbar at all? It is common in Terminal Server scenarios to run programs by themselves without Explorer (archived). In this configuration, there is no Explorer, no taskbar. Or maybe you're running on a future version of Windows that doesn't have a taskbar, it having been replaced by some other mechanism. What will your program do now?

Don't do any of this messing with the taskbar. Just create your fullscreen window and let the taskbar do its thing automatically.

痴意少年 2024-08-31 15:49:48

我相信当它的 shell 钩子告诉它一个“粗鲁的应用程序”时,任务栏会摆脱困境,这可能需要一段时间。

如果您从窗口 HWND_TOPMOST 开始并使其在 1 秒后不再位于最顶层怎么办?

I believe the taskbar will get out of the way when its shell hook tells it about a "rude app", this might take a little while.

What if you start out with the window HWND_TOPMOST and make it not top most after 1 second?

煞人兵器 2024-08-31 15:49:48
  1. 右键单击任务栏,
  2. 选择“属性”,
  3. 取消选中“将任务栏保留在其他窗口之上”复选框。

任务栏属于用户,他们需要关心当您的应用程序全屏显示时是否需要 1/2 秒自动隐藏。如果他们想改变这种行为,那么他们就可以改变它。

如果您在嵌入式系统中工作,那么您可能有合理的理由隐藏任务栏。但在这种情况下,没有理由不简单地将任务栏配置为不始终位于顶部。如果您想更改代码中的某些设置,您还可以查看SystemParametersInfo

  1. Right click on the taskbar
  2. choose Properties
  3. uncheck the checkbox that says "Keep the taskbar on top of other windows".

The taskbar belongs to the user, It's up to them to care about having it take 1/2 second to auto-hide when you app goes full screen. If they want to change that behavior then they can change it.

If you are working in an embedded system, then you may have a legitimate reason to hide the taskbar. But in that case, there's no reason not to simply configure the taskbar to not always be on top. You could also have a look at SystemParametersInfo if you want to change some of these settings in your code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文