【问题标题】:Pin window to desktop / Glue window to desktop / "Always-on-bottom" window将窗口固定到桌面/将窗口粘贴到桌面/“始终在底部”窗口
【发布时间】:2021-03-09 16:52:33
【问题描述】:

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

我现在的目标是创建一个基本的“便签”应用程序,该应用程序将固定/粘贴到桌面,即始终位于桌面前面,但始终位于任何其他应用程序的后面。 那里真的是一个个人项目,只是为了对抗我糟糕的记忆力,让我的任务/笔记总是在桌面上可见,这样我在启动计算机时就不会错过它们等等。

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

我从Get Started with Win32 and C++ docs 开始使用sample code 来进行最基本的Win32 最小窗口设置。

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

  1. 在处理 WM_SETFOCUS 事件时,我通过在窗口过程 (WindowProc) 中调用 SetWindowPos 设法将窗口保持在所有其他应用程序的底部和桌面前面将事件 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;

但并不理想,因为我真的希望我的应用始终保持在桌面前并“生存”到 Show Desktop 操作。

我尝试了什么:

我查看了这些答案,但不知道如何实现我想要的。

  1. How to make 'always-on-bottom'-window
  2. Window “on desktop” :请注意这一点,我在wWinMain 中尝试了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 我尝试了这些来“拦截” Show Desktop 事件,但似乎该事件不会被 Show Desktop 操作触发。

我错过了什么吗?

【问题讨论】:

  • 您在处理WM_WINDOWPOSCHANGING 消息吗?
  • WM_WINDOWPOSCHANGING 可能是您想要使用的。设置 SWP_NOZORDER 标志以阻止您的 z 顺序被更改。 Show Desktop 似乎是通过将屏幕外的窗口移至 -32000,-32000 来实现的,因此您应该能够检查并设置 SWP_NOMOVE 以防止它。
  • 感谢您的回答,我尝试使用以下代码处理WM_WINDOWPOSCHANGINGcpp case WM_WINDOWPOSCHANGING: SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER); return 0; (似乎我无法在此评论中正确格式化,抱歉????)但是行为还是一样的;当点击Windows + D 或单击桌面按钮时,窗口被隐藏:/ 我错过了什么吗?
  • 不,您不会致电 SetWindowPos 来响应该消息。您修改它传递给您的WINDOWPOS 结构的参数。请参阅documentation
  • 好吧,@JonathanPotter 你是对的,不知道我到底搞砸了什么,但我回到了文档中的原始代码,重新创建了一个计时器来调试记录窗口的位置,它确实被移动了到 -32 000, -32 000 在点击 Windows + D 时。所以最后我只处理了事件WM_SIZEWM_SETFOCUS 以及WM_WINDOWPOSCHANGING 并设置标志SWP_NOMOVESWP_NOSIZE 如果窗口位置 x 为 -32000。再次感谢 !准备写最终答案

标签: c++ windows winapi desktop-application


【解决方案1】:

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

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

为防止这种移动,只需在lParam 中传递的WINDOWPOS 结构上设置标志SWP_NOMOVESWP_NOSIZE

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

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

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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    相关资源
    最近更新 更多