我有一个窗口,我SetWindowPos(window, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);
它覆盖了整个屏幕,确定,但是也需要一段时间(0.5秒)来覆盖任务栏。
有没有办法立刻过来任务栏?我发现设置HWND_TOPMOST
会立即执行,但它会保持在所有其他窗口之上,即使我切换应用程序 - 这是我不想要的。此外,如果我首先隐藏窗口然后显示它,它会以某种方式强制窗口重绘并立即覆盖任务栏,但它会闪烁(因为隐藏)。还有另一种方式吗?
答案 0 :(得分:37)
编辑2 。甚至还有一种更好的方法来做全屏,铬方式,来自这里的来源:
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。
答案 1 :(得分:14)
是的,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()
返回)找出您的解决方案:< / p>
windowHDC = GetDC(mainWindow);
fullscreenWidth = GetDeviceCaps(windowHDC, HORZRES);
fullscreenHeight = GetDeviceCaps(windowHDC, VERTRES);
colourBits = GetDeviceCaps(windowHDC, BITSPIXEL);
refreshRate = GetDeviceCaps(windowHDC, VREFRESH);
如果你想要退出全屏,你可以这样做:
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;
}
我设置我的代码使用热键在全屏和窗口模式之间切换,并且我将窗口模式变量保持为全局,以便在更改为窗口模式时,它保持不变。
这段代码还具有运行相当于“独占模式”的优势(我使用的是XP,并没有在新版本的Windows上试过它),这意味着它会更快,更快。如果我在编写代码时出错(请使用我更大的代码),请告诉我。
答案 2 :(得分:7)
Raymond Chen在他的博客中描述了“正确”的方法:
http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx
明确地摆弄任务栏窗口不推荐行为。
答案 3 :(得分:1)
我相信当shell挂钩告诉它关于“粗鲁的应用程序”时,任务栏会不会受到影响,这可能需要一段时间。
如果你开始使用HWND_TOPMOST窗口并在1秒后使其不是最顶端怎么办?
答案 4 :(得分:1)
这是latest unbroken link至Raymond Chen的答案。
由于MSDN / Microsoft不断断开链接,因此我将在后继粘贴以下内容:
由于某些原因,people think too hard。如果要创建一个覆盖任务栏的全屏窗口,只需创建一个全屏窗口,任务栏将自动退出。不要四处寻找任务栏并戳戳它。让它做自己的事。
与往常一样,从the scratch program开始并添加以下内容:
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函数。
我们使用the MonitorFromWindow function来确定应全屏显示的显示器。请注意,在多监视器系统中,该监视器可能与任务栏所在的监视器不同。幸运的是,我们不必为此担心。任务栏可以解决问题。
我已经看到人们搜寻任务栏窗口,然后在其上执行ShowWindow(hwndTaskbar,SW_HIDE)。出于很多原因,这很疯狂。
首先,这是一种智力锻炼,在评估如下技巧时应始终使用:“如果两个程序尝试了该技巧怎么办?”现在,您有两个程序,它们都认为它们负责隐藏和显示任务栏,而这两个程序都不相互协调。结果是一团糟。一个程序隐藏任务栏,然后另一个隐藏,然后第一个决定完成,因此取消隐藏任务栏,但是第二个程序尚未完成,并在认为应该隐藏时获得可见的任务栏。事情只能从那里下坡。
第二,如果您的程序在有机会取消隐藏任务栏之前崩溃了,该怎么办?现在,任务栏已永久隐藏,用户必须注销然后再登录才能恢复其任务栏。那不是很好。
第三,如果根本没有任务栏怎么办?在run programs by themselves without Explorer(archived)中,在终端服务器方案中很常见。在此配置中,没有资源管理器,也没有任务栏。也许您正在运行的Windows未来版本没有任务栏,但已被其他某种机制取代。您的程序现在将做什么?
不要在任务栏上进行任何此类混乱。只需创建您的全屏窗口,然后让任务栏自动执行操作即可。
答案 5 :(得分:-4)
任务栏属于用户,当应用程序全屏显示时,由他们关心让自动隐藏需要1/2秒。如果他们想要改变那种行为,那么他们就可以改变它。
如果您在嵌入式系统中工作,那么您可能有合理的理由隐藏任务栏。但在这种情况下,没有理由不简单地将任务栏配置为不总是在顶部。如果您想在代码中更改其中一些设置,也可以查看SystemParametersInfo
。