c++ - 将窗口固定到桌面/将窗口粘附到桌面/"Always-on-bottom"窗口

标签 c++ windows winapi desktop-application

我正在使用 C++/Win32 开发一个基本的桌面应用程序。

我现在的目标是创建一个基本的“便利贴”应用程序,它可以固定/粘贴到桌面,即始终位于桌面前面但始终位于任何其他应用程序后面。 这真的是一个个人项目,只是为了克服我的坏内存,让我的任务/笔记始终在桌面上可见,这样我就不会在启动计算机等时错过它们。

我的目标行为类似于Stardock Fences (“有点”,因为我不会在其中存储任何桌面图标,但您希望得到想法)

我从 sample codeGet Started with Win32 and C++ docs 开始,以进行最基本的 Win32 最小窗口设置。

到目前为止我得到了什么:

  1. 在处理事件时,我通过在窗口过程 (WindowProc) 中调用 SetWindowPos 设法将我的窗口保持在所有其他应用程序的底部和桌面前面WM_SETFOCUS (我首先尝试将事件 WM_WINDOWPOSCHANGING 作为 suggested in this answer,但这导致拖动窗口时出现烦人的闪烁)
case WM_SETFOCUS:
        SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
        return 0;
  1. 问题:我的窗口停留在桌面前面除非我点击“显示桌面” 任务栏中的按钮(或点击 Windows + D 快捷键)。由于我自己经常使用此快捷方式,因此我希望我的窗口无论如何都保留在桌面上。
  2. 我设法做的一个不太令人满意但仍然很令人满意的事情是,在点击 Windows + D 后点击任何其他窗口时,将我的窗口带回桌面前面(这对多个显示器,例如在第一个显示器上打开一个随机应用程序,将在另一个屏幕上的桌面前切换回我自己的应用程序)。 这次我可以使用事件 WM_SIZE 并调用 ShowWindow 然后调用 SetWindowPos,仍然在 WindowProc<
case WM_SIZE:
        ShowWindow(hwnd, SW_SHOWNORMAL);
        SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
        return 0;

虽然不理想,因为我真的希望我的应用程序始终保持在桌面前面并“存活”到“显示桌面”操作。

我尝试了什么:

我检查了这些答案,但无法弄清楚如何实现我想要的。

  1. How to make 'always-on-bottom'-window
  2. Window “on desktop” :注意这个,我在 wWinMain
  3. 中尝试了这样的 SetParent 技巧
HWND desktop = FindWindow(L"ProgMan", L"Program Manager");
if (desktop == NULL)
{
    return 0;
}

ShowWindow(hwnd, nCmdShow);
SetParent(hwnd, desktop);

但是,即使 FindWindow 没有返回 NULL 而是返回一个实际的句柄,我的应用程序再也看不到了。

  1. Make aplication always on Bottom (pinned to desktop, behind all other apps) in C++/WinAPI [duplicate]
  2. Disable Minimize, Maximize, Close buttons in Win32 我试过这些来“拦截”显示桌面事件,但似乎这个事件并没有被显示桌面操作触发。

我错过了什么吗?

最佳答案

正如@JonathanPotter 所指出的,当点击 Windows + D 或 Show Desktop 按钮时,事件 WM_WINDOWPOSCHANGING被触发,窗口移动到 -32 000, -32 000 (它的大小也改变了)

注意:没有样式 WS_MINIMIZEBOX 的窗口在点击 Windows + D 时似乎没有收到 WINDOWPOSCHANGING 事件。因此,没有 -32 000 坐标在这种情况下进行检测......在使用 ex 样式 WS_EX_TOOLWINDOW 时也注意到了同样的问题(因为这个去掉了最小化框,即使你设置了样式标志 WS_MINIMIZEBOX )。 没有找到针对这种情况的解决方案,所以我坚持使用重叠窗口。

要防止这种移动,只需在 WINDOWPOS 上设置标志 SWP_NOMOVESWP_NOSIZElParam

中传递的结构

因此,作为最终结果,要实现所需的行为(即总是在所有其他窗口后面但总是在桌面前面),唯一需要添加到 doc's sample 的代码如下,放在窗口过程WindowProc的switch语句中:

EDIT :用 HWND_BOTTOM 强制 Z 顺序从而确保窗口始终位于底部的最佳位置也在 WM_WINDOWPOSCHANGING 事件中.事实上,在拖动窗口时调用 SetWindowPos 以在 WM_SIZE 事件中强制它,就像我之前所做的那样,在调整窗口大小时会导致窗口出现一些闪烁,而不会闪烁在 WM_WINDOWPOSCHANGING 中直接设置 WINDOWPOS 结构的 hwndInsertAfter 属性时发生。

case WM_WINDOWPOSCHANGING:
{
    WINDOWPOS* pos = (WINDOWPOS*)lParam;
    // Show desktop (Windows + D) results in the window moved to -32000, -32000 and size changed
    if (pos->x == -32000) {
        // Set the flags to prevent this and "survive" to the desktop toggle
        pos->flags |= SWP_NOMOVE | SWP_NOSIZE;
    }
    // Also force the z order to ensure the window is always on bottom
    pos->hwndInsertAfter = HWND_BOTTOM;
    return 0;
}

关于c++ - 将窗口固定到桌面/将窗口粘附到桌面/"Always-on-bottom"窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65028303/

相关文章:

winapi - 为什么 DefDlgProc 不自动处理 WM_CLOSE?

c++ - 基本游戏 DrawEngine 问题

c++ - STL 映射 C++ 中的最高值?

c++ - 固定表达;运算符优先级

c++ - 有偏随机数发生器

c - GetModuleHandle 实现不起作用

c# - 刷新当前用户配置文件

c - 是否可以在 Windows 中取消分页所有内存?

c++ - c++ 将多个文件压缩成一个文件

c++ - 有没有办法让C++应用程序功能开机?