我有一个Windows应用程序,它使用AppBar API作为应用程序栏安装在屏幕顶部(类似于Windows任务栏本身)。 这很好,桌面大小相应地调整,所以我的应用程序始终可见。
但是,如果用户select“显示桌面”(Windows + D),我的应用程序被隐藏。 有谁知道一种方法来捕获“显示桌面”,所以我可以确保我的应用程序保持可见(我假定Windows枚举所有顶级窗口,并隐藏它们与ShowWindow(SW_HIDE)。
使用下面的代码并在窗体加载时将窗口句柄传递给函数。 希望这可以解决您的问题。
public void SetFormOnDesktop(IntPtr hwnd) { IntPtr hwndf = hwnd; IntPtr hwndParent = FindWindow("ProgMan", null); SetParent(hwndf, hwndParent); }
我的印象是,将窗口设置为最上面的窗口(通过SetWindowPos和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消息。
PS作为替代实现,请考虑商业ShellAppBar组件。
除了JKS的答案之外,这里是VB.NET的工作代码,假设你已经将表单转换为一个appbar。 你需要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