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

如何在Windows 11/10中获取任务栏日期时间的HBITMAP?

获取Windows 11/10任务栏时钟的HBITMAP

一、定位时钟窗口

Windows 10/11中,任务栏时钟的窗口层级如下:

  • 任务栏主窗口:类名Shell_TrayWnd,通过FindWindow获取。
  • 通知区域容器:类名TrayNotifyWnd,作为Shell_TrayWnd的子窗口,通过FindWindowEx获取。
  • 时钟窗口:类名TrayClockWClass,是TrayNotifyWnd的子窗口,需通过EnumChildWindows枚举找到(直接FindWindowEx可能失败,因为它不是直接的顶层子窗口)。

示例代码(C++):

#include <windows.h>

BOOL CALLBACK EnumClockChild(HWND hwnd, LPARAM lParam) {
    WCHAR className[256];
    GetClassNameW(hwnd, className, ARRAYSIZE(className));
    if (wcscmp(className, L"TrayClockWClass") == 0) {
        *(HWND*)lParam = hwnd;
        return FALSE;
    }
    return TRUE;
}

HWND GetClockWindow() {
    HWND hTaskbar = FindWindowW(L"Shell_TrayWnd", nullptr);
    if (!hTaskbar) return nullptr;

    HWND hTrayNotify = FindWindowExW(hTaskbar, nullptr, L"TrayNotifyWnd", nullptr);
    if (!hTrayNotify) return nullptr;

    HWND hClock = nullptr;
    EnumChildWindows(hTrayNotify, EnumClockChild, reinterpret_cast<LPARAM>(&hClock));
    return hClock;
}

如果上述方法在Win11中无法找到窗口,可通过Spy++工具手动查看当前系统的时钟窗口类名:

  • 打开Spy++(spyxx.exe,位于VS安装目录或Windows SDK中)。
  • 点击“查找窗口”按钮,拖动瞄准器到任务栏时钟上,即可查看窗口的类名和层级。

二、生成HBITMAP

找到时钟窗口后,可通过以下两种方式生成HBITMAP:

方法1:从窗口DC复制

直接获取时钟窗口的设备上下文,将内容复制到兼容的HBITMAP中:

HBITMAP GetClockBitmap(HWND hClockWnd) {
    if (!hClockWnd) return nullptr;

    RECT wndRect;
    GetWindowRect(hClockWnd, &wndRect);
    int width = wndRect.right - wndRect.left;
    int height = wndRect.bottom - wndRect.top;

    HDC hdcWnd = GetDC(hClockWnd);
    HDC hdcMem = CreateCompatibleDC(hdcWnd);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdcWnd, width, height);
    HGDIOBJ hOldBmp = SelectObject(hdcMem, hBitmap);

    // 复制窗口内容到内存DC
    BitBlt(hdcMem, 0, 0, width, height, hdcWnd, 0, 0, SRCCOPY);

    // 清理资源
    SelectObject(hdcMem, hOldBmp);
    DeleteDC(hdcMem);
    ReleaseDC(hClockWnd, hdcWnd);

    return hBitmap;
}

方法2:自行绘制时钟(更稳定)

由于Windows版本更新可能改变任务栏窗口结构,自行绘制时钟到HBITMAP是更可靠的方案:

HBITMAP DrawCustomClockBitmap() {
    SYSTEMTIME st;
    GetLocalTime(&st);

    // 格式化时间字符串(可根据需求调整格式)
    WCHAR timeStr[64];
    GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, nullptr, timeStr, ARRAYSIZE(timeStr));
    WCHAR dateStr[64];
    GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, nullptr, dateStr, ARRAYSIZE(dateStr));
    WCHAR fullStr[128];
    swprintf_s(fullStr, L"%s\n%s", timeStr, dateStr);

    // 创建HBITMAP
    HDC hdcScreen = GetDC(nullptr);
    HDC hdcMem = CreateCompatibleDC(hdcScreen);
    SIZE textSize;
    GetTextExtentPoint32W(hdcMem, fullStr, wcslen(fullStr), &textSize);
    int width = textSize.cx + 10; // 增加边距
    int height = textSize.cy + 10;
    HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, width, height);
    HGDIOBJ hOldBmp = SelectObject(hdcMem, hBitmap);

    // 绘制背景和文字
    RECT rect = {0, 0, width, height};
    FillRect(hdcMem, &rect, (HBRUSH)(COLOR_WINDOW+1));
    DrawTextW(hdcMem, fullStr, -1, &rect, DT_CENTER | DT_VCENTER | DT_WORDBREAK);

    // 清理资源
    SelectObject(hdcMem, hOldBmp);
    DeleteDC(hdcMem);
    ReleaseDC(nullptr, hdcScreen);

    return hBitmap;
}

三、注意事项

  • 窗口类名可能随Windows版本更新变化,建议用Spy++确认当前系统的实际类名。
  • 若使用Win32 API无法获取UWP控件的HWND(Win11部分任务栏控件基于UWP),自行绘制是更稳妥的选择。
  • 生成的HBITMAP使用后需调用DeleteObject释放资源,避免内存泄漏。

内容的提问来源于stack exchange,提问作者vzoid00000

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:23:20