GetLastInputInfo

GetLastInputInfo是一種函式,功能是獲取上次輸入操作的時間。。

原型

BOOL WINAPI GetLastInputInfo( __out PLASTINPUTINFO plii);

參數

[out] 類型:PLASTINPUTINFO結構

一個指向接收到最後一個輸入事件時間的LASTINPUTINFO結構指針。

返回值

類型:BOOL

如果調用函式成功,返回值為非零。

如果調用函式失敗,返回值為零。

備註

此函式用來檢測系統的輸入空閒時間,然而GetLastInputInfo不提供全系統所有正在運行的會話用戶輸入信息。相反,GetLastInputInfo 僅提供調用的會話功能會話特定的用戶輸入的信息。

示例

GetLastInputInfo是Windows中獲取鍵盤和滑鼠空閒時間的API

1.調用函式GetLastInputInfo()以後, 結構成員lpi.dwTime 中的值並非上次輸入事件發生以後的毫秒數。而是上次輸入事件發生時的系統運行時間。相當於上次輸入事件發生時執行了lpi.dwTime=::GetTickCount()。::GetTickCount()-lpi.dwTime才是上次輸入事件發生以後的毫秒數。

2.如原文中所說windows2000以上系統才支持函式GetLastInputInfo()因此有可能需要在StdAfx.h中加上如下語句:

#ifdef _WIN32_WINNT

#undef _WIN32_WINNT

#endif

#define _WIN32_WINNT 0x0500

原文:

在編寫程式的過程中,我遇到了這樣的需求:在基於Windows® 9x 或Windows NT4.0

的程式中,要求確定鍵盤、滑鼠處於空閒狀態的時間。

查詢了有關資料文檔以後,發現Windows 9x和Windows NT4.0沒有提供API或系統調用來實現這樣的功能。但是,在Windows 2000中提供了一個新的函式:GetLastInputInfo(),這個函式使用結構 LASTINPUTINFO 作為參數:

LASTINPUTINFO lpi;

lpi.cbSize = sizeof(lpi);

GetLastInputInfo(&lpi);

調用函式GetLastInputInfo()以後, 結構成員lpi.dwTime 中的值便是自上次輸入事件發生以後的毫秒數。這個值也就是鍵盤、滑鼠處於空閒狀態的時間。

可惜的是這個函式只能在Windows 2000中使用,Windows 9x 或Windows NT4.0不提供此API函式。

那么,如何在Windows 9x 或Windows NT4.0中實現GetLastInputInfo()的功能呢?

筆者的方法是利用系統鉤子對鍵盤、滑鼠進行監控。

Windows中的鉤子實際上是一個回調函式,當用戶有輸入動作的時候,Windows要調用這個函式。比較典型的系統鉤子套用就是鍵盤鉤子和滑鼠鉤子,

HHOOK g_hHookKbd = NULL;

HHOOK g_hHookMouse = NULL;

在Windows中,一個系統(相對於一個特定進程而言)鉤子必須用一個動態程式庫(DLL)來實現。不妨將這個動態程式庫命名為IdleUI.dll。 這個動態程式庫在Windows 9x和Windows NT4.0中實現了GetLastInputInfo()的功能。IdleUI.dll中有三個函式:

BOOL IdleUIInit()

void IdleUITerm();

DWORD IdleUIGetLastInputTime();

IdleUIInit()是環境初始化函式,IdleUITerm()是環境清理函式,分別在MFC應用程式的InitInstance() 和 ExitInstance()中調用它們。當用IdleUIInit()做完初始化後,就可以調用第三個函式IdleUIGetLastInputTime()來獲取最後一次輸入事件後的時鐘。從而實現與GetLastInputInfo()一樣的功能。

程式TestIdleUI.exe是用來測試IdleUI動態庫的,程式中調用了IdleUIInit 和 IdleUITerm,同時在程式的客戶區中間顯示鍵盤、滑鼠空閒的秒數。

void CMainFrame::OnPaint()

{

CPaintDC dc(this);

CString s;

DWORD nsec = (GetTickCount() - IdleUIGetLastInputTime())/1000;

s.Format( "滑鼠或鍵盤空閒 %d 秒。",nsec);

CRect rc;

GetClientRect(&rc);

dc.DrawText(s, &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE);

}

圖一顯示了TestIdleUI運行時的情形。

圖一

為了連續的顯示,TestIdleUI設定刷新定時器間隔為一秒。

void CMainFrame::OnTimer(UINT)

{

Invalidate();

UpdateWindow();

}

運行TestIdleUI,當鍵盤和滑鼠什麼也不做時,可以看到計時器跳動,當移動滑鼠或按鍵時,計時器又恢復到零,這樣就實現了對輸入設備空閒狀態的監控。實現細節請看下面對IdleUI.dll工作原理的描述:

首先調用IdleUIInit ()進行初始化,安裝兩個鉤子:一個用於監控滑鼠輸入,一個用於監控鍵盤輸入。

HHOOK g_hHookKbd;

HHOOK g_hHookMouse;

g_hHookKbd = SetWindowsHookEx(WH_KEYBOARD,

MyKbdHook,

hInst, 0);

g_hHookMouse = SetWindowsHookEx(WH_MOUSE,

MyMouseHook,

hInst, 0);

當用戶移動滑鼠或按下鍵盤鍵時,Windows調用其中的一個鉤子並且鉤子函式開始記錄時間:

LRESULT CALLBACK MyMouseHook(int code,

WPARAM wp,

LPARAM lp)

{

if (code==HC_ACTION) {

// note the tick count

g_dwLastInputTick = GetTickCount();

}

return ::CallNextHookEx(g_hHookMouse,

code, wp, lp);

}

如法炮製MyKbdHook。IdleUIGetLastInputTime 返回結果g_dwLastInputTick, 並且IdleUITerm 卸載兩個鉤子。

這個程式中有一個細節使用了一些技巧:通常,建立一個動態程式庫時,連結器將靜態數據標記為非共享,也就是說,每一個調用DLL的進程都獲得自己的數據拷貝------在本程式中是g_hHookKbd、g_hHookMouse和g_dwLastInputTick。當在整個進程空間中需要且只需要一個這些數據的實例時,這樣的靜態數據標記就不適合了,為了解決這個問題,必須實現數據共享。為此得把數據放入一個特定的段地址中,然後將它們標記為共享。實現代碼如下:

#pragma data_seg (".IdleUI") // 可以取任何別的名字

HHOOK g_hHookKbd = NULL;

HHOOK g_hHookMouse = NULL;

DWORD g_dwLastInputTick = 0;

#pragma data_seg ()

這段代碼告訴連結器將三個變數放到叫“.IdleUI”的數據段中。然後在模組定義檔案.DEF中加入下面的代碼來共享這個數據段:

SECTIONS .IdleUI READ WRITE SHARED // in IdleUI.def

Requirements

Minimum supported clientWindows 2000 Professional [desktop apps only]
Minimum supported serverWindows 2000 Server [desktop apps only]
HeaderWinuser.h (include Windows.h)
LibraryUser32.lib
DLLUser32.dll

相關詞條

相關搜尋

熱門詞條

聯絡我們