winapi - sacar - ocultar barra de tareas windows 10 en pantalla completa
Win32: barra de tareas de pantalla completa y oculta (5)
- Haga clic derecho en la barra de tareas
- elige Propiedades
- desmarque la casilla de verificación que dice "Mantener la barra de tareas encima de otras ventanas".
La barra de tareas pertenece al usuario . Depende de ellos preocuparse de que tarden 1/2 segundo en ocultarse automáticamente cuando la aplicación se muestre en pantalla completa. Si quieren cambiar ese comportamiento, entonces pueden cambiarlo.
Si trabaja en un sistema integrado, puede tener una razón legítima para ocultar la barra de tareas. Pero en ese caso, no hay razón para no configurar simplemente la barra de tareas para que no siempre esté en la parte superior. También puede echar un vistazo a SystemParametersInfo
si desea cambiar algunas de estas configuraciones en su código.
Tengo una ventana, que I SetWindowPos(window, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);
Cubre toda la pantalla, vale, pero lleva un tiempo (0,5 segundos) cubrir la barra de tareas también.
¿Hay alguna forma de pasar por la barra de tareas de inmediato? Descubrí que configurar HWND_TOPMOST
hace de inmediato, pero se mantiene por encima de todas las otras ventanas, incluso si cambio la aplicación; esto es algo que no quiero. Además, si primero oculto la ventana y luego la muestro, de alguna manera fuerza a la ventana a volver a dibujar y cubre la barra de tareas inmediatamente, pero parpadea (debido a la ocultación). ¿Hay otra manera?
Creo que la barra de tareas saldrá del camino cuando su shell hook dice sobre una "aplicación grosera", esto podría tomar un poco de tiempo.
¿Qué pasa si comienzas con la ventana HWND_TOPMOST y la haces no más alta después de 1 segundo?
Raymond Chen describe la forma "correcta" de hacer esto en su blog:
http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx
Jugar con la ventana de la barra de tareas explícitamente no es un comportamiento recomendado.
Sí, HWND_TOPMOST
hace por mí. Aquí hay una sección de código que hace que el trabajo de pantalla completa sea bueno (y rápido) para mí:
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;
}
Tenga en cuenta que esto cambiará la resolución si le dice la configuración incorrecta. Esto es lo que generalmente quiero, pero si no te gusta, puedes averiguar tu resolución usando (donde mainWindow
se devuelve de algo como CreateWindow()
o CreateWindowEx()
):
windowHDC = GetDC(mainWindow);
fullscreenWidth = GetDeviceCaps(windowHDC, HORZRES);
fullscreenHeight = GetDeviceCaps(windowHDC, VERTRES);
colourBits = GetDeviceCaps(windowHDC, BITSPIXEL);
refreshRate = GetDeviceCaps(windowHDC, VREFRESH);
Cuando quiera salir de la pantalla completa, haga algo como esto:
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;
}
Establecí mi código para cambiar entre pantalla completa y modo ventana usando una tecla de acceso rápido, y mantengo las variables de modo con ventana como globales, de modo que cuando se cambia al modo de ventana, permanece en blanco.
Este código también tiene la ventaja de ejecutarse en el equivalente del "modo exclusivo" (estoy usando XP, y no lo he probado en las versiones más nuevas de Windows), lo que significa que será mucho, mucho más rápido. Avíseme si cometí algún error al condensar el código (de mi código mucho más grande).
Editar 2 . Hay incluso una mejor manera de hacer pantalla completa, la forma de cromo, fuente tomada desde aquí:
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);
}
}
Editar . Probablemente sea mejor crear una ventana de pantalla completa como lo señaló BrendanMcK en un comentario a esta respuesta, consulte este enlace: http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx ("¿Cómo cubro la barra de tareas con una ventana de pantalla completa?")
El nuevo código que utiliza el enlace de arriba sería:
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);
}
Respuesta anterior a continuación - no la use, solo se mantiene para el registro sobre cómo NO hacer esto.
Tienes que ocultar la barra de tareas y la barra de menús para ver la pantalla completa de inmediato.
Aquí está el código (usa WTL), llame a SetFullScreen (verdadero) para pasar al modo de pantalla completa:
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);
}
}
};
También debe agregar algún código al mensaje WM_CLOSE:
case WM_CLOSE:
ShowTaskBar(true);
Hay una advertencia con esta solución: si su aplicación falla o se destruye a través del administrador de tareas, ¡el usuario pierde la barra de tareas en su sistema de forma permanente! (a menos que ejecute su aplicación nuevamente, entre en pantalla completa y salga, entonces verá la barra de tareas nuevamente).
Anteriormente en mi respuesta señalé "atlwince.h" pero esa función solo funcionaba en Windows CE, la que pegué arriba funciona bien con XP, Vista y 7.