MFC中應用duilib的相關兼容性問題處理

本文致力於解決在MFC中應用duilib的相關兼容性問題。

 

duilib非常強大,目前已經被各大公司廣泛應用,但基本都是基於win32的;一份與MFC混合使用的DEMO,使得我們這些在老的MFC項目下久經UI之苦的看到了希望。

 

然而,就在我對這個MFCDEMO進行測試時,在基本功能正常的情況下,發現還是有少許的問題的,目前我發現的問題主要集中在鍵按鍵與鼠標按鍵方面,具體如下:

1. VK_TAB無效

2. 如果窗口中內嵌了WebBrowser,瀏覽器的CTRL+CV無效,DEL無效  

3. 如果窗口中內嵌了WebBrowser,則其他部分的滾動條將失效 

 

由於我對duilib還不熟悉,當碰到這幾個問題時,一下子沒了主意,只好請教於羣內的各路大神,可更多的得到的答覆是:爲什麼要與MFC混用?

 

我想大家可能更多的是考慮一個項目新建立,能直接使用duilib框架,還用什麼MFC,而且MFC似乎本來就不怎麼受人待見;但這裏我想說的是,對於若干MFC的老項目,想切換UIduilib上,難道說完全重寫過麼? 而且我已經做過遷移測試,將MFC項目的UI切換到duilib,可以比較簡單的在duilibUI與舊的MFC窗口的邏輯中間加一層代理轉發,這樣的工作量還是可以控制的。

 

扯遠了,最終經過多次詢問,還是在羣裏碰到了有相關處理經驗的朋友,經過他們的指點,總算對這種兼容處理有了一些思路,下面就將我目前的處理方案貼出來:

 

1. VK_TAB無效

這個需要在MFC的窗口類中處理 PreTranslateMessage ,將對於VK_TAB的處理強制交給duilib的 CPaintManagerUI::TranslateMessage 來處理 

 

2. 如果窗口中內嵌了WebBrowser,瀏覽器的CTRL+CV無效,DEL無效 

這個與第一點類似,將給duilib來處理即可 

 

12點代碼如下:

BOOL CMFCTestDlg::PreTranslateMessage( MSG* pMsg )
{
if( pMsg->message == WM_KEYDOWN)
{
{
if (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN || pMsg->wParam == VK_TAB || pMsg->wParam == VK_DELETE)
{
if(m_dlgWnd.TranslateMessage(pMsg))
return TRUE;
}
else if (pMsg->wParam == 'C' || pMsg->wParam == 'V')
{
if( (GetKeyState(VK_CONTROL) & 0x8000))
{
m_dlgWnd.TranslateMessage(pMsg);
}
}
}
}
return CDialog::PreTranslateMessage(pMsg);
 
 
//TranslateMessage方法僅是轉而調用CPaintManagerUI::TranslateMessage 
bool MainFrame::TranslateMessage( MSG* pMsg )
{
return m_PaintManager.TranslateMessage(pMsg);
}

這裏其實根本原因,原理我還沒搞清楚,請知道的補充一下。

 

3. 如果窗口中內嵌了WebBrowser,則其他部分的滾動條將失效

這個問題以前就發現了,但在昨天才發現,如果將內嵌的瀏覽器拿掉的話,滾動條又正常了,進行了跟蹤,發現是由於當窗口中未選中任何的Edit或其他可操作的控件時,默認的焦點是在這個 WebBrowser [原因不詳],這樣鼠標中鍵滾輪滾動時,WM_MOUSEWHEEL消息會被路由到 LRESULT CActiveXWnd::HandleMessage,而此處對於消息 WM_MOUSEWHEEL是直接丟棄,導致了滾動條消息丟失了,按如下處理可以解決這個問題:

將WM_MOUSEWHEEL消息發給主窗口進行處理:


LRESULT CActiveXWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT lRes=0;
    BOOL bHandled = TRUE;
    switch( uMsg ) {
    case WM_PAINT:         lRes = OnPaint(uMsg, wParam, lParam, bHandled); break;
    case WM_SETFOCUS:      lRes = OnSetFocus(uMsg, wParam, lParam, bHandled); break;
    case WM_KILLFOCUS:     lRes = OnKillFocus(uMsg, wParam, lParam, bHandled); break;
    case WM_ERASEBKGND:    lRes = OnEraseBkgnd(uMsg, wParam, lParam, bHandled); break;
    case WM_MOUSEACTIVATE: lRes = OnMouseActivate(uMsg, wParam, lParam, bHandled); break;
case WM_MOUSEWHEEL: 
{
::PostMessage(::GetParent(GetHWND()), uMsg, wParam, lParam);
return 0;
}
break;
    default:
        bHandled = FALSE;
 
    }
    if( !bHandled ) return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
    return lRes;
}

按上述處理,目前這幾個問題基本得到了處理,我也敢在項目中應用了,但其實這裏還是有細節問題的,比如:

1. 按TAB鍵後,如果沒有WebBrowser,則按到最後,TAB就沒辦法切換有焦點的控件了,一直出現叮叮的系統聲音[不可操作]

2. 按TAB鍵,如果有WebBrowser,則最終焦點進入WebBrowser後,不能切換出來了,只能通過鼠標來調整焦點;另外如果當前窗口沒選中任何控件,默認焦點在 WebBrowser 中,按TAB鍵則直接進入了WebBrowser 中。

3. 另外還有一個問題duilib的問題,我這邊暫時簡單處理了一下

所有的button[button,check,option]均會響應TABSTOP,這個可以在XML文件中通過keyboard屬性來設置,但庫中的CTreeViewUI中創建節點中會自動添加按鈕,這種需要手動將其設置爲不響應TABSTOP

pFolderButton->SetKeyboardEnabled(false);
pDottedLine->SetKeyboardEnabled(false);
pCheckBox->SetKeyboardEnabled(false);
pItemButton->SetKeyboardEnabled(false);


我目前直接將所有按鈕的默認接受屬性設置成了false,需要的時候針對需要的按鈕設置 keyboard屬性。 

 

4. 其他未知問題,歡迎補充

 

注:

我的測試基於duilib svn 中的 MFCdemo 改編而來,目前已經是在自己的項目中來做實測,這個代碼暫時不便上傳 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章