1. 程式人生 > >不改動duilib原始碼的情況下,實現tab鍵切換登入介面EDIT控制元件功能

不改動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鍵切換帳號密碼框的功能了。