Barras de aplicação e 'Show Desktop'
Pergunta
Eu tenho um aplicativo do Windows que utiliza a API AppBar instalar como uma barra de aplicação, na parte superior da tela (similar à própria barra de tarefas do Windows). Isso funciona muito bem e o tamanho do desktop é ajustado em conformidade, de modo a minha candidatura é sempre visível.
No entanto, se o usuário escolher 'Show Desktop' (Windows + D), minha aplicação está escondido. Alguém sabe de uma maneira de armadilha 'Show Desktop' para que eu possa garantir minhas estadias de aplicação visível (presumo que o Windows enumera todas as janelas de nível superior e esconde-los com ShowWindow (SW_HIDE).
Solução
Use o seguinte código e passar o identificador de janela para a função enquanto a carga formulário. Esperemos que isso resolve o seu problema.
public void SetFormOnDesktop(IntPtr hwnd)
{
IntPtr hwndf = hwnd;
IntPtr hwndParent = FindWindow("ProgMan", null);
SetParent(hwndf, hwndParent);
}
Outras dicas
Eu estava sob a impressão de que a configuração da janela como uma janela de nível superior (via SetWindowPos ea bandeira HWND_TOPMOST) impediu a área de trabalho de cobri-la. Windows + D passa por minimizar todas as janelas, e em seguida, cobrindo-se aqueles que não podem ser minimizados através do aumento da área de trabalho na ordem z (bem, ele fez a um ponto de qualquer maneira ). Eu acredito que você pode fazer uma janela unminimizable por não passar WS_MINIMIZEBOX para CreateWindowEx, ou usando WS_EX_TOOLWINDOW embora eu não estou 100% sobre a parte.
A abordagem muito mais pesado handed seria para ligar o teclado mundial usando SetWindowsHookEx e uma KeyboardProc. Isto terá um efeito deletério sobre a experiência do usuário.
Eu fui e codificado um exemplo muito simples do que estou falando. O código a seguir faz com que uma janela que não está minimizada ou coberta por um usuário bater Windows + D. Note que no Windows 7, gadgets no desktop pode ainda ser trazido acima dela; que eu realmente não posso 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;
}
Na sua notificação ABN_FULLSCREENAPP, você precisa determinar se a janela ocupando a área de trabalho é a área de trabalho e se assim for, ignore a mensagem ABN_FULLSCREENAPP.
P.S. Como uma implementação alternativa, considere o componente comercial ShellAppBar .
Além da resposta de JKS , aqui está o código de trabalho para VB.NET, assumindo que você já convertido o seu formulário a um appbar. Você precisa p / invocar as funções FindWindow
e 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