最新消息:想得多,做的少。一天到晚瞎鸡巴搞。

duilib源码剖析 day5 按键消息处理过程

曲径通幽 阿虚 318浏览 0评论

.      上面讲完了WinMain()中的pFrame->Create()函数。接下来就是设置窗体居中pFrame->CenterWindow();和显示窗体pFrame->ShowWindow(true);都是调用的常规的API函数,最后一行执行消息循环CPaintManagerUI::MessageLoop();。

.     下面是消息循环代码,只比win32sdk的消息循环多了一层CPaintManagerUI::TranslateMessage(&msg)。

MSG msg = { 0 };
while( ::GetMessage(&msg, NULL, 0, 0) ) 
{
    if( !CPaintManagerUI::TranslateMessage(&msg) ) 
    {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg); 
    }
}

键盘消息处理

.      所有键盘消息处理都在CPaintManagerUI::TranslateMessage(&msg)中,函数按键处理分为两部分。子窗口按键消息处理和非子窗口消息处理。

//得到当前窗体风格
UINT uStyle = GetWindowStyle(pMsg->hwnd);
//是否包含"子窗体"风格
UINT uChildRes = uStyle & WS_CHILD;	
LRESULT lRes = 0;
if (uChildRes != 0)
{ 
    //进入条件则当前窗体是子窗体。
}
else
{ 
    //当前窗体不是子窗体
}

子窗体按键消息处理

//得到当前窗体的父窗体
HWND hWndParent = ::GetParent(pMsg->hwnd); 
//循环所有按键消息过滤ary
for( int i = m_aPreMessages.GetSize() - 1; i >= 0 ; --i ) 
{
    CPaintManagerUI* pT = static_cast<CPaintManagerUI*>(m_aPreMessages[i]);       
    HWND hTempParent = hWndParent;
    while(hTempParent)
    {  
        //判断是否是父窗口消息
        if(pMsg->hwnd == pT->GetPaintWindow() 
          || hTempParent == pT->GetPaintWindow())
        {
            //先处理加速键
            if (pT->TranslateAccelerator(pMsg))
                return true;

            //在处理按键消息
            pT->PreMessageHandler(pMsg->message, pMsg->wParam, pMsg->lParam, lRes); 
        }

        //继续获取父窗体的父窗体......
        hTempParent = GetParent(hTempParent);
    } 
}

非子窗体按键消息处理

//以下不是子窗口按键消息处理。
for( int i = 0; i < m_aPreMessages.GetSize(); i++ ) 
{
    int size = m_aPreMessages.GetSize();
    CPaintManagerUI* pT = static_cast<CPaintManagerUI*>(m_aPreMessages[i]);
    //判断消息是否是当前窗体的消息
    if(pMsg->hwnd == pT->GetPaintWindow())
    {
        //处理加速键
        if (pT->TranslateAccelerator(pMsg))
            return true;

        //处理按键消息
        if( pT->PreMessageHandler(pMsg->message, pMsg->wParam, pMsg->lParam, lRes) ) 
            return true;

        return false;
    }
}

.      不管是否处理的是子窗口还是非子窗口负责TranslateAccelerator()处理加速键的函数,PreMessageHandler()处理按键消息函数。

加速键处理

.      想要处理加速键需要继承ITranslateAccelerator类,它只有一个接口函数就是需要实现TranslateAccelerator();即可。

.      所有加速键的回调全部存储在CPaintManagerUI::m_aTranslateAccelerator中。CPaintManagerUI::TranslateAccelerator()函数就是遍历m_aTranslateAccelerator保存的数据强转成ITranslateAccelerator调用TranslateAccelerator接口。

除了继承ITranslateAccelerator接口还需调用AddTranslateAccelerator()将自己添加到m_aTranslateAccelerator中。

bool CPaintManagerUI::TranslateAccelerator(LPMSG pMsg)
{
    for (int i = 0; i < m_aTranslateAccelerator.GetSize(); i++)
    {
        LRESULT lResult = static_cast<ITranslateAccelerator *>(
            m_aTranslateAccelerator[i])->TranslateAccelerator(pMsg);
        if( lResult == S_OK ) 
            return true;
    }
    return false;
}

按键消息处理

.      按键消息处理在CPaintManagerUI::PreMessageHandler()。按键消息处理会先提供一个按键预处理回调函数。按键预处理存储在CPaintManagerUI::m_aPreMessageFilters。如果需要预先处理按键消息那么需要继承IMessageFilterUI并且实现MessageHandler接口。并且调用CPaintManagerUI::AddPreMessageFilter()来将自己添加到CPaintManagerUI::m_aPreMessageFilters中。

for( int i = 0; i < m_aPreMessageFilters.GetSize(); i++ ) 
{
    bool bHandled = false;
    LRESULT lResult = static_cast<IMessageFilterUI*>(
    m_aPreMessageFilters[i])->MessageHandler(uMsg, wParam, lParam, bHandled);
    if( bHandled ) 
    {
        return true;
    }
}

.      如果有没做预处理那么CPaintManagerUI::PreMessageHandler()将会处理WM_KEYDOWN(键盘按下)、WM_SYSCHAR(atl + 按键)、WM_SYSKEYDOWN(atl)

转载请注明:虚无 » duilib源码剖析 day5 按键消息处理过程

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址