Windows登录、锁屏的判定以及消息捕捉

2020-06-24  本文已影响0人  googoler

1、如果窗口想获取相关消息,需要注册Session的Notification,需要Wtsapi32.dll中的两个函数:WTSRegisterSessionNotificationWTSUnRegisterSessionNotification,分别在窗口创建和销毁的时候调用。

typedef BOOL (WINAPI *WTSRegisterSessionNotification)(HWND, DWORD);
typedef BOOL (WINAPI *WTSUnRegisterSessionNotification)(HWND);

#define WTSAPI_DLL     _T("Wtsapi32.dll")

#define MY_WTS_SESSION_FUNCTION(fnType, fnName, arg)  
    BOOL bRet = FALSE; 
    HMODULE hLibrary = ::LoadLibrary(WTSAPI_DLL); 
    if (hLibrary)  
   { 
       fnType fn  
           = (fnType)::GetProcAddress(hLibrary, fnName);  
       if (fn)
       {   
           bRet = fn##arg;
       }  
       ::FreeLibrary(hLibrary);  
   }  
    return bRet;


BOOL MyWTSRegisterSessionNotification(HWND hWnd, DWORD dwFlag)
{
   MY_WTS_SESSION_FUNCTION(WTSRegisterSessionNotification,
       "WTSRegisterSessionNotification", (hWnd, dwFlag));
}

BOOL MyWTSUnRegisterSessionNotification(HWND hWnd)
{
   MY_WTS_SESSION_FUNCTION(WTSUnRegisterSessionNotification,
       "WTSUnRegisterSessionNotification", (hWnd));
}

这样,在SESSION切换的时候,窗口就可以收到一个WM_WTSSESSION_CHANGE消息。

WTSRegisterSessionNotification(m_hWnd, NOTIFY_FOR_THIS_SESSION);

WTSUnRegisterSessionNotification(m_hWnd);
 

ON_MESSAGE(WM_WTSSESSION_CHANGE, OnSessionChange)

OnSessionChange(WPARAM wParam, LPARAM lParam)
{
    switch (wParam)
    {
     case WTS_CONSOLE_CONNECT:
             break;
     case WTS_CONSOLE_DISCONNECT:
            break;
     case WTS_REMOTE_CONNECT:
            break;
     case WTS_REMOTE_DISCONNECT:
            break;
     case WTS_SESSION_LOGON:
             break;
     case WTS_SESSION_LOGOFF:
             break;
     case WTS_SESSION_LOCK: //锁住屏幕
             break;
     case WTS_SESSION_UNLOCK://解锁屏幕
            break;
     case WTS_SESSION_REMOTE_CONTROL:
             break;
      default:
              break;
      }

 return 0;
}

2、如果不依赖窗口,需要判断当前系统是否处于锁屏状态,有一段比较tricky的代码……就是试图SwitchDesktop,如果失败就认为在锁屏。

这种方法有另一个优点:可以判断ctrl+alt+delete后系统暂时“锁定”以及“解锁”的状态,而这种状态改变,窗口是没法收到WM_WTSESSIONCHANGE的。

typedef HDESK (WINAPI *PFNOPENDESKTOP)(LPSTR, DWORD, BOOL, ACCESS_MASK);
typedef BOOL (WINAPI *PFNCLOSEDESKTOP)(HDESK);
typedef BOOL (WINAPI *PFNSWITCHDESKTOP)(HDESK);

BOOL PP_IsWorkStationLocked()
{
    // note: we can't call OpenInputDesktop directly because it's not
    // available on win 9x
    BOOL bLocked = FALSE;

    // load user32.dll once only
    static HMODULE hUser32 = LoadLibrary(_T("user32.dll"));

    if (hUser32)
    {
       static PFNOPENDESKTOP fnOpenDesktop = (PFNOPENDESKTOP)GetProcAddress(hUser32, "OpenDesktopA");
       static PFNCLOSEDESKTOP fnCloseDesktop = (PFNCLOSEDESKTOP)GetProcAddress(hUser32, "CloseDesktop");
       static PFNSWITCHDESKTOP fnSwitchDesktop = (PFNSWITCHDESKTOP)GetProcAddress(hUser32, "SwitchDesktop");

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

           if (hDesk)
           {
               bLocked = !fnSwitchDesktop(hDesk);
               // cleanup
               fnCloseDesktop(hDesk);
           }
       }
    }

   return bLocked;

}

参考:

上一篇下一篇

猜你喜欢

热点阅读