記一次 Windows 系統焦點游標的監控嘗試

2021-09-11 08:14:25 字數 2466 閱讀 8133

研究這個主要是為了進一步完善當前的自用軟體 alterful 的啟用流程,實現「無熱鍵」鍵盤增強。

雖然最終沒能得到接近完美的解決辦法,不過也在這個嘗試的過程中取得了一些進展,故簡單地記錄一下。

**猴開發部落格:記一次 windows 系統焦點游標的監控嘗試

其實所研究這個問題的本質就是希望能夠實時監測系統當中是否有輸入焦點,也就是在文字框中輸入內容時一閃一閃的游標,更準確地說應該是叫輸入焦點,或者說「插入符」。

歸納了一下,主要有兩種辦法可以基本實現這一點。

作為處於待輸入狀態的控制項,其父視窗一般來講是當前時刻的頂級視窗,因此考慮通過函式 getguithreadinfo 來獲得頂層視窗的相關資訊,進而判斷頂層視窗是否含有輸入焦點來確定系統全域性是否含有輸入焦點。

下面是 c++ 中 getguithreadinfo 的函式原型:

bool getguithreadinfo(

dword idthread,

pguithreadinfo pgui

);

其中引數 idthread 是欲取得資訊的gui執行緒id,如果是要獲取乙個指定視窗的info的話,那麼可以通過 getwindowthreadprocessid 來得到其 idthread 值,其函式原型如下:

dword getwindowthreadprocessid(

hwnd hwnd,

lpdword lpdwprocessid

);

不過我們只是要取的頂級視窗的資訊,幸運的是 idthread 接受 null,並且當傳入 null 時將預設認為目標視窗就是頂級視窗,因此此處直接傳null即可,還是很方便的。

第二個引數 pgui 是乙個 pguithreadinfo 型別的結構體指標,在微軟官方文件當中給出的定義如下:

typedef struct tagguithreadinfo  guithreadinfo, *pguithreadinfo, *lpguithreadinfo;
其中對此處比較有用的就是 flags、hwndfocus 以及 hwndcaret 這三個資料成員,其中 hwndfocus 表示具有鍵盤焦點的視窗的控制代碼,hwndcaret 表示顯示插入符的視窗的控制代碼,而 flags 表徵的是執行緒的狀態。flag 一共有 5 個可取值,具體見下圖:

當 flags == 1 時,說明當前視窗中有閃爍的插入符,也就說明當前系統具有輸入焦點,處於可輸入狀態。

相應的,此時就可以通過 hwndcaret 來知道具體的焦點控制項控制代碼。(不過針對此處需要,這些資訊都不用管,不過對大多數其它情況和需求而言,這些資料都是有意義的,所以還是提一下)

getcaretpos 函式其實是用來獲取當前的游標位置的,不過從其函式原型:

bool getcaretpos(

lppoint lppoint

);

可以看到返回值是布林型,因此也可以用來判斷是否存在輸入游標。

很明顯 getcaretpos 函式相比 getguithreadinfo 而言要簡潔得多,這也是由函式的使命所決定的。

從 getcaretpos 你只能得到 「是否有游標?」 以及 「游標座標是什麼?」 這兩個問題的答案,而 getguithreadinfo 可以得到的資訊要豐富得多。

函式 getcaretpos 不需要任何有意義的輸入引數,只需要乙個 lppoint 指標用於接受游標的客戶座標。

如果當前螢幕有游標,那麼函式返回 true,如果螢幕沒有游標,那麼函式返回 flase,並且可以通過 getlasterror 來取得錯誤資訊。

測試效果在概述當中已經說了,不盡理想。在目前已經試過的所有原生視窗(如記事本、資源管理器等)當中可以正常得到游標資訊,

但是在大部分基於atl或wtl開發的directui視窗(如qq、wps、迅雷)和幾乎所有的瀏覽器當中,getcaretpos 始終返回 true,lpdwprocessid 的 flags 始終為 0,也就是說都無法得到游標資訊。

在網上找了一天也沒能找到這個問題的原因,雖然有一些相關的提問,但是都沒有結帖,並且都是10年前左右的問題,年代久遠,也就是目前為止都沒有找到有效的解決辦法。這一問題只能暫時告一段落了,如果以後有閒情繼續研究,會嘗試鑽研一些開源輸入法游標跟蹤原理,若取得進展,再回到本篇繼續更新。

下面是對有效情況的測試圖:

記一次linux系統中毒

在公司的linux伺服器裡面發現cpu的負載偏高用top看到異常的程序 ijcfwyjoqk 父程序為init 執行 ps l 10854 顯示cmd列為uptime 執行 whereis ijcfwyjoqk 顯示在 usr bin下而且還發現在 etc init.d和 etc rc.d rc3....

記一次系統效能優化

用thinkphp3.2.3做了自己的畢業設計,上線使用後發現,響應時間比較長,經過檢測後發現是sql的查詢時間太長。這裡要感謝系統效能監控平台聽雲,他們的官網是 它能檢測到不正常的web請求 不正常的sql查詢 接著就是對mysql資料庫進行查詢的調優,筆者這裡採用建立索引的方法。什麼是索引以及索...

記一次除錯

這是我最近幾個月來遇到的最棘手的乙個問題 昨天花了4個小時找出第一層次的原因 這個糾結啊,本來和老婆說好準時下班回家吃飯的,結果被這個問題拖了老久。這是乙個gradle的plugin,用來resolve公司內部的dependency的,弄完了跑測試專案的,拋乙個npe,而且npe還不在自己的 裡面。...