Barras de aplicación y 'Mostrar Escritorio'
Pregunta
Tengo una aplicación de Windows que utiliza la API AppBar de instalar como una barra de aplicaciones en la parte superior de la pantalla (similar a la barra de tareas de Windows en sí). Esto funciona muy bien y el tamaño del escritorio se ajusta en consecuencia, por lo que mi aplicación es siempre visible.
Sin embargo, si el usuario elija 'Mostrar Escritorio' (Windows + D), mi solicitud está oculto. ¿Alguien sabe de una manera de trampa 'Mostrar Escritorio', así que puede garantizar mi solicitud permanece visible (supongo que Windows enumera todas las ventanas de nivel superior y los oculta con ShowWindow (SW_HIDE).
Solución
Utilice el código siguiente y pasar el identificador de ventana a la función mientras que la carga formulario. Espero que esto resuelve el problema.
public void SetFormOnDesktop(IntPtr hwnd)
{
IntPtr hwndf = hwnd;
IntPtr hwndParent = FindWindow("ProgMan", null);
SetParent(hwndf, hwndParent);
}
Otros consejos
I tenía la impresión de que la fijación de la ventana como una ventana superior (a través de SetWindowPos y la bandera HWND_TOPMOST) impidieron el escritorio desde que lo cubre. De Windows + D pasa a través de minimizar todas las ventanas, y luego encubrir los que no puede ser minimizada mediante el aumento del escritorio en el orden z (bueno, lo hizo en un punto de todos modos ). Me creer que puede hacer una ventana unminimizable por no pasar a WS_MINIMIZEBOX CreateWindowEx, o el uso de WS_EX_TOOLWINDOW aunque no estoy 100% en esa parte.
Un enfoque mucho más pesada mano sería la de conectar el teclado global utilizando SetWindowsHookEx y una KeyboardProc. Esto tendrá un efecto perjudicial sobre la experiencia del usuario.
Fui y codificado un ejemplo muy simple de lo que estoy hablando. El siguiente código hace que una ventana que no se minimiza o cubierto por un usuario de Windows + D golpear. Tenga en cuenta que en Windows 7, gadgets en el escritorio todavía pueden ser llevados por encima de ella; que yo no puedo explicar.
#include <windows.h>
#include <tchar.h>
#define WIN_TITLE _T("Resists Win+D Window")
#define WIN_CLASS _T("Resists Win+D Class")
LRESULT CALLBACK CustomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//Special behavior goes here
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
HWND CreateMainWindow(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = CustomWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WIN_CLASS;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex))
{
exit(1);
}
HWND hWnd = CreateWindowEx(
WS_EX_TOOLWINDOW,
WIN_CLASS,
WIN_TITLE,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
100,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
exit(1);
}
return hWnd;
}
/*
Main entry point
*/
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hwnd = CreateMainWindow(hInstance);
ShowWindow(hwnd, nCmdShow);
SetWindowPos(hwnd, HWND_TOPMOST, -1, -1, -1, -1, SWP_NOMOVE | SWP_NOSIZE);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
En la página de información ABN_FULLSCREENAPP, es necesario determinar si la ventana que ocupa el área de trabajo es la de escritorio y si es así, ignora el mensaje ABN_FULLSCREENAPP.
P.S. Como una implementación alternativa, considere el comercial componente ShellAppBar .
Además de la respuesta de JKS , aquí está el código de trabajo para VB.NET, asumiendo que ya convertido su forma a un appbar. Usted necesita p / invocar las funciones FindWindow
y SetFormOnDesktop
.
'In your form
Public Sub New()
'Stuff
SetFormOnDesktop(Me.Handle)
'More stuff
End Sub
'In your form or somewhere else.
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function SetParent(_
ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
End Function
Public Sub SetFormOnDesktop(hwnd As IntPtr)
Dim hwndf As IntPtr = hwnd
Dim hwndParent As IntPtr = FindWindow("ProgMan", Nothing)
SetParent(hwndf, hwndParent)
End Sub