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

Windows系统启动时如何准确检测屏幕解锁状态?求优化方案

优化Windows锁屏状态检测逻辑

问题分析

你当前使用SwitchDesktop判断锁屏状态的逻辑,在Windows 10启动初期(密码输入界面未完全加载时)会失效,原因是此时Default桌面仍处于可切换状态,SwitchDesktop调用成功,导致误判为未锁屏。

优化方案:使用系统级会话状态检测(推荐)

微软提供了WTSQuerySessionInformation API,其中WTSIsLocked信息类可直接获取当前会话的锁定状态,不受界面加载进度影响,是更可靠的检测方式。

代码示例

#include <windows.h>
#include <wtsapi32.h>

bool IsScreenLocked()
{
    bool isLocked = false;
    HMODULE hWtsApi = LoadLibrary(_T("wtsapi32.dll"));
    
    if (hWtsApi)
    {
        // 动态加载WTS相关函数
        typedef BOOL(WINAPI *PFNWTSQUERYSESSIONINFO)(HANDLE, DWORD, WTS_INFO_CLASS, LPSTR*, DWORD*);
        typedef VOID(WINAPI *PFNWTSFREEMEM)(PVOID);

        PFNWTSQUERYSESSIONINFO pWtsQuery = reinterpret_cast<PFNWTSQUERYSESSIONINFO>(
            GetProcAddress(hWtsApi, "WTSQuerySessionInformationW")
        );
        PFNWTSFREEMEM pWtsFree = reinterpret_cast<PFNWTSFREEMEM>(
            GetProcAddress(hWtsApi, "WTSFreeMemory")
        );

        if (pWtsQuery && pWtsFree)
        {
            LPWSTR buffer = nullptr;
            DWORD bytesReturned = 0;
            // 查询当前会话的锁定状态
            if (pWtsQuery(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSIsLocked, reinterpret_cast<LPSTR*>(&buffer), &bytesReturned))
            {
                isLocked = *reinterpret_cast<BOOL*>(buffer);
                pWtsFree(buffer);
            }
        }
        FreeLibrary(hWtsApi);
    }
    return isLocked;
}

说明

  • 该方法直接读取系统会话的锁定标记,无需依赖桌面切换操作,完全避免了界面加载阶段的误判。
  • 一般交互式程序默认具备访问会话信息的权限,无需额外配置。

兼容性补充方案:结合窗口类检测

如果需要兼容更旧的Windows系统,可在WTS方法失效时,检测前台窗口是否为锁屏相关窗口:

#include <windows.h>
#include <string>

bool IsScreenLocked()
{
    // 优先使用WTS方法
    bool isLocked = false;
    HMODULE hWtsApi = LoadLibrary(_T("wtsapi32.dll"));
    if (hWtsApi)
    {
        typedef BOOL(WINAPI *PFNWTSQUERYSESSIONINFO)(HANDLE, DWORD, WTS_INFO_CLASS, LPSTR*, DWORD*);
        typedef VOID(WINAPI *PFNWTSFREEMEM)(PVOID);

        PFNWTSQUERYSESSIONINFO pWtsQuery = reinterpret_cast<PFNWTSQUERYSESSIONINFO>(
            GetProcAddress(hWtsApi, "WTSQuerySessionInformationW")
        );
        PFNWTSFREEMEM pWtsFree = reinterpret_cast<PFNWTSFREEMEM>(
            GetProcAddress(hWtsApi, "WTSFreeMemory")
        );

        if (pWtsQuery && pWtsFree)
        {
            LPWSTR buffer = nullptr;
            DWORD bytesReturned = 0;
            if (pWtsQuery(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSIsLocked, reinterpret_cast<LPSTR*>(&buffer), &bytesReturned))
            {
                isLocked = *reinterpret_cast<BOOL*>(buffer);
                pWtsFree(buffer);
            }
        }
        FreeLibrary(hWtsApi);
        if (isLocked) return true;
    }

    // 备用:检测锁屏相关窗口
    HWND foregroundWnd = GetForegroundWindow();
    if (foregroundWnd)
    {
        WCHAR className[256] = {0};
        GetClassNameW(foregroundWnd, className, sizeof(className)/sizeof(WCHAR));
        std::wstring clsName(className);
        
        // Windows 10+ 锁屏窗口类名
        if (clsName == L"Windows.UI.Core.CoreWindow" || clsName == L"Credential Dialog Xaml Host")
        {
            return true;
        }
    }

    // 最后回退到原方法
    static HMODULE hUser32 = LoadLibrary(_T("user32.dll"));
    if (hUser32)
    {
        typedef HDESK(WINAPI *PFNOPENDESKTOP)(LPSTR, DWORD, BOOL, ACCESS_MASK);
        typedef BOOL(WINAPI *PFNCLOSEDESKTOP)(HDESK);
        typedef BOOL(WINAPI *PFNSWITCHDESKTOP)(HDESK); 

        static PFNOPENDESKTOP fnOpenDesktop = reinterpret_cast<PFNOPENDESKTOP>(GetProcAddress(hUser32, "OpenDesktopA")); 
        static PFNCLOSEDESKTOP fnCloseDesktop = reinterpret_cast<PFNCLOSEDESKTOP>(GetProcAddress(hUser32, "CloseDesktop")); 
        static PFNSWITCHDESKTOP fnSwitchDesktop = reinterpret_cast<PFNSWITCHDESKTOP>(GetProcAddress(hUser32, "SwitchDesktop")); 

        if (fnOpenDesktop && fnCloseDesktop && fnSwitchDesktop) 
        { 
            HDESK hDesk = fnOpenDesktop("Default", 0, FALSE, DESKTOP_SWITCHDESKTOP); 
            if (hDesk) 
            {  
                isLocked = !fnSwitchDesktop(hDesk); 
                fnCloseDesktop(hDesk); 
            }  
        }
    }
    return isLocked;
}

说明

  • 该方案通过多层检测保证兼容性:优先用最可靠的WTS方法,再检测锁屏窗口,最后回退到原逻辑。
  • 窗口类名可能随Windows版本略有变化,需根据目标系统调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 08:38:12