不改動duilib原始碼的情況下,實現tab鍵切換登入介面EDIT控制元件功能
由於duilib是開源無專人管理的介面庫,導致網上流傳了各式各樣的版本。今天某某修復了這個bug上傳一版,明天某某修復另一個bug上傳別的版本,太過雜亂。而且之所以寫這篇文章,是因為公司用的duilib庫,存在EDIT控制元件對table鍵支援的bug。即焦點混亂。花了近一天時間研究了PaintManager.cpp,Edit.cpp,EditWnd.cpp三個檔案的原始碼,發現邏輯上不存在問題。試了csdn多個博主提供的方法改動皆無成效的情況下,決定採用無腦的方法實現帳號密碼框table鍵的切換。
接下來闡述本人使用的方法,希望有小夥伴遇到類似情況看了此文章能有所幫助。在我自己的專案中,登入介面是一個子視窗它有自身的控制代碼,只要有控制代碼,我們就可以使用鉤(Hook)這個視窗,拿到我們想要的資訊。
我們不妨腦補下登入介面的流程。以僅有帳號框,密碼框,登入按鈕的登入介面為例,大致分為兩種情況:
1. 滑鼠點選帳號框,table鍵按下情況下切換到密碼框,再按下切回帳號框。
2. 滑鼠點選密碼框,table鍵按下情況下切換到帳號框,再按下切回密碼框。
最後點選登入按鈕執行登入操作。所以我們只需要鉤鍵盤訊息即可。在duilib中,HandWindow函式功能豐富,滑鼠按下的訊息可以直接在裡面進行捕獲和實現可以。
以下貼上功能實現的程式碼部分。CPP實現開頭加上如下鍵盤訊息回撥程式碼。其中WM_TAB_KEY_PRESS是自定義的table鍵訊息
#define WM_TAB_KEY_PRESS WM_USER+100
HWND g_hHwndMain = NULL;
HHOOK g_hKeyBoardHook = NULL;
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (0 == nCode)
{
//lParam的最高位為1代表按鍵正在被釋放操作,0代表按鍵正在被按下操作
//代表正在按下Tab鍵
if ((((lParam >> 31) & 1) == 0) && (wParam == VK_TAB))
::PostMessage(g_hHwndMain, WM_TAB_KEY_PRESS, 0, 0);
}
return CallNextHookEx(g_hKeyBoardHook, nCode, wParam, lParam);
}
在建立登入視窗的函式中,呼叫HookLoginWindows()函式,鉤住鍵盤訊息。回撥函式為KeyboardProc。其中g_hHwndMain和g_hKeyBoardHook是全域性控制代碼變數
void CLoginWnd::HookLoginWindows()
{
g_hHwndMain = m_hWnd;
g_hKeyBoardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, GetCurrentThreadId());
}
接下來只要在登入視窗類中過載HandleMessage方法。處理此自定義訊息即可。
LRESULT CLoginWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_TAB_KEY_PRESS:
HandleTableMessage();
break;
default:
break;
}
return __super::HandleMessage(uMsg, wParam, lParam);
}
HandleTableMessage方法中處理的形式就多種多樣了。先說下我對table切換帳號密碼的處理方式:
定義一個變數記錄滑鼠點選在了帳號框,還是密碼框。如果點選在帳號框,table鍵切換後,給密碼框傳送一個滑鼠點選訊息。
::SendMessage(m_hWnd, WM_LBUTTONDOWN, NULL, MAKELONG(rect.left, rect.top))
rect是控制元件的座標。通過GetPos方法獲得。反之則給帳號框傳送點選訊息。這樣就實現了tab鍵切換帳號密碼框的功能了。