You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Win11下NIN_POPUPOPEN的坐标是否变更?技术求助

Windows 11下NIN_POPUPOPEN回调坐标异常问题

问题描述

我有一个使用任务栏系统托盘的C++应用,处理NIN_POPUPOPEN回调。Windows 10下运行正常,但Windows 11中,WPARAM封装的X、Y值表现异常:

  • Windows 10中,坐标是绝对坐标(多显示器系统下以主显示器左上角为原点)
  • Windows 11中,Y坐标变为相对于任务栏顶部的相对坐标,X坐标时而为绝对位置,时而偏差极大

应用使用的是NOTIFYICON_VERSION_4版本,处理代码如下:

LRESULT MySystemTray::OnTrayNotification(WPARAM uID, LPARAM lEvent)
{
    int ID = HIWORD(lEvent);
    int notif = LOWORD(lEvent);
    int x = GET_X_LPARAM(uID);
    int y = GET_Y_LPARAM(uID);
    if ( ID == m_tnd.uID )
    {
        switch (notif)
        {
        case NIN_POPUPOPEN:
            TRACE("Received tray notification, x: %d, y: %d, ID: %04x, notif: %04x\n", x, y, ID, notif);
            ShowPopUp(x, y);
            break;
        case NIN_POPUPCLOSE:
            HidePopUp();
            break;
        default:
            return CSystemTray::OnTrayNotification(uID, lEvent);
        }
    }
    return 0;
}

ShowPopUp会根据弹出窗口高度调整Y值,直接使用X值后调用SetWindowPos()。

请问相关的更新文档是什么?


问题原因与解决方案

Windows 11对任务栏和通知区域的交互逻辑做了调整,NIN_POPUPOPEN回调传递的坐标规则发生变化,这是微软在Windows 11版本迭代中对通知区域行为的隐性调整,目前官方文档未单独针对NOTIFYICON_VERSION_4做坐标变更的专项说明,但可通过以下逻辑适配:

核心调整点

  • Windows 11的任务栏支持居中对齐、小尺寸等布局,导致通知区域的坐标参考系不再固定为主显示器原点
  • NIN_POPUPOPEN触发时,WPARAM的Y坐标默认是任务栏顶部的相对偏移,X坐标会因任务栏对齐方式(左/中/右)出现偏移

适配方案

要获取正确的绝对坐标,需通过任务栏的窗口信息转换坐标:

  1. 获取任务栏窗口句柄:使用FindWindowW(L"Shell_TrayWnd", nullptr)获取任务栏主窗口
  2. 获取任务栏绝对矩形:调用GetWindowRect获取任务栏的屏幕坐标矩形
  3. 转换相对坐标为绝对坐标:结合任务栏停靠方向(通过SHAppBarMessage获取APPBARDATA)调整X、Y值

调整后的代码示例:

case NIN_POPUPOPEN:
{
    int x = GET_X_LPARAM(uID);
    int y = GET_Y_LPARAM(uID);

    // 获取任务栏窗口与矩形
    HWND hTray = FindWindowW(L"Shell_TrayWnd", nullptr);
    RECT trayRect;
    GetWindowRect(hTray, &trayRect);

    // 转换Y坐标为绝对坐标
    int absoluteY = trayRect.top + y;

    // 处理X坐标:根据任务栏停靠方向调整
    APPBARDATA abd = {0};
    abd.cbSize = sizeof(APPBARDATA);
    if (SHAppBarMessage(ABM_GETTASKBARPOS, &abd))
    {
        if (abd.uEdge == ABE_TOP || abd.uEdge == ABE_BOTTOM)
        {
            // 水平任务栏,X为任务栏左边界+相对偏移
            int absoluteX = abd.rc.left + x;
            ShowPopUp(absoluteX, absoluteY);
        }
        else
        {
            // 垂直任务栏(左/右),按实际场景调整X逻辑
            ShowPopUp(x, absoluteY);
        }
    }
    else
    {
        // 降级到原逻辑
        ShowPopUp(x, absoluteY);
    }
    break;
}

官方参考方向

微软在Windows 11任务栏开发文档中明确,通知区域交互的适配原则是不要依赖固定坐标参考系,需通过任务栏动态位置信息计算绝对坐标,相关API的详细说明可查看Windows SDK文档中的SHAppBarMessage、FindWindow章节。


内容的提问来源于stack exchange,提问作者J. Hyslop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 07:31:11