不改动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键切换帐号密码框的功能了。

猜你喜欢

转载自blog.csdn.net/hdy_ylmb/article/details/79174614