Панели приложений и "Показать рабочий стол"
Вопрос
У меня есть приложение для Windows, которое использует API AppBar для установки в качестве панели приложений в верхней части экрана (аналогично самой панели задач Windows).Это отлично работает, и размер рабочего стола соответствующим образом корректируется, так что мое приложение всегда видно.
Однако, если пользователь выберет "Показать рабочий стол" (Windows + D), мое приложение будет скрыто.Кто-нибудь знает способ перехватить "Показать рабочий стол", чтобы я мог убедиться, что мое приложение остается видимым (я предполагаю, что Windows перечисляет все окна верхнего уровня и скрывает их с помощью ShowWindow (SW_HIDE).
Решение
Используйте следующий код и передайте дескриптор окна функции во время загрузки формы.Надеюсь, это решит вашу проблему.
public void SetFormOnDesktop(IntPtr hwnd)
{
IntPtr hwndf = hwnd;
IntPtr hwndParent = FindWindow("ProgMan", null);
SetParent(hwndf, hwndParent);
}
Другие советы
У меня сложилось впечатление, что установка окна в качестве самого верхнего окна (через SetWindowPos Установить windowpos и флаг HWND_TOPMOST) не позволял рабочему столу закрывать его.Windows + D выполняет сворачивание всех окон, а затем закрывает те, которые невозможно свернуть, поднимая рабочий стол в порядке z (ну, это было сделано на во всяком случае , одно очко).Я верю, что вы можете сделать окно неминимизируемым, не передавая WS_MINIMIZEBOX в CreateWindowEx или используя WS_EX_TOOLWINDOW, хотя я не уверен на 100% в этой части.
Гораздо более сложным подходом было бы подключить глобальную клавиатуру с помощью SetWindowsHookEx и KeyboardProc.Это окажет пагубное влияние на пользовательский интерфейс.
Я пошел и закодировал действительно простой пример того, о чем я говорю.Следующий код создает окно, которое не сворачивается и не закрывается пользователем, нажимающим Windows + D.Обратите внимание, что в Windows 7 гаджеты на рабочем столе по-прежнему можно перенести поверх него;что я действительно не могу объяснить.
#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;
}
В уведомлении ABN_FULLSCREENAPP вам необходимо определить, является ли окно, занимающее рабочую область, рабочим столом, и если да, проигнорируйте сообщение ABN_FULLSCREENAPP.
P.S.В качестве альтернативной реализации рассмотрим коммерческий Панель ШеллаПпбАра компонент.
В дополнение к ответ JKS, вот рабочий код для VB.NET , предполагая, что вы уже преобразовали свою форму в панель приложений.Вам нужно p / вызвать функции FindWindow
и 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