duilib入門簡明教程 -- 結合win32和MFC (16)

語言: CN / TW / HK
雖然duilib自帶在MFC中使用duilib的Demo,但只是MFC視窗和duilib視窗不重疊的情況。 如果要在MFC視窗中嵌入duilib控制元件,或者在duilib控制元件中嵌入MFC的控制元件的話,就沒有Demo可以看了,其實Alberl開始也不知道怎麼辦,看了下ActiveXUI控制元件,這個就是結合HWND的,但是由於接觸duilib不久,所以一時無法看懂ActiveXUI到底是怎麼將win32的HWND畫上去的,只好在群裡問啦,多謝鉛筆群的Troy大神指導:

圖片當時解決完之後上傳了程式碼,不過還是有網友看不懂,於是昨晚要求Alberl先寫duilib結合MFC的教程,當然啦,這個教程本來就在Alberl的計劃之類,所以就折中一下啦,上一篇教程只寫了一半,等寫完這個教程再去補充,如果小夥伴們還有其他要求,也可以提哦,如果在Alberl的計劃內,Alberl會盡量滿足小夥伴們的要求的~O(∩_∩)O~    一、在MFC中使用duilib只需要將前面教程的CDuiFrameWnd的父視窗指定為MFC的視窗就好啦,將CDuiFrameWnd m_duiFrame; 定義為MFC的成員變數,在MFC的初始化函式OnInitDialog裡面建立duilib的視窗,程式碼如下:圖片

  // TODO: 在此新增額外的初始化程式碼    CPaintManagerUI::SetInstance(AfxGetInstanceHandle());                    // 指定duilib的例項    CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());    // 指定duilib資源的路徑,這裡指定為和exe同目錄    ::CoInitialize(NULL);  // 記得釋放::CoUninitialize();     m_duiFrame.Create(*this, _T("DUIWnd"), UI_WNDSTYLE_CHILD, 0, 0, 0, 800, 600);     m_duiFrame.ShowWindow(TRUE);     return TRUE;  // 除非將焦點設定到控制元件,否則返回 TRUE

圖片    這裡只是將duilib嵌入到MFC的主視窗,如果想要將duilib嵌入到MFC的某個控制元件,也是很簡單的,因為只需要一個HWND控制代碼就行了,就不贅述了~    不過可以發現以下幾個問題:1、之前ActiveXUI的那個bug不再出現了。2、所有的MFC控制元件都顯示在duilib視窗的上面,這裡和ZORD順序應該有關係。3、在duilib視窗上面的【確定】按鈕點了沒反應,【取消】按鈕只有在點選不在duilib上面的那部分才會有反應。    由於Alberl暫時只是研究介面方面,還沒研究到事件響應方面,所以不去研究細節。如果有小夥伴急用的話,可以將MFC控制元件嵌入到duilib的控制元件上,或者把MFC控制元件放到非duilib區域,這樣就可以響應了。    二、在duilib中使用MFC控制元件這裡示例將MFC按鈕放到duilib滑塊條控制元件的位置: 1、準備好一個duilib控制元件來容納MFC控制元件,程式碼如下:

// 將帶控制代碼HWND的控制元件顯示到CControlUI上面class CWndUI: public CControlUI{public:    CWndUI(): m_hWnd(NULL){}     virtual void SetInternVisible(bool bVisible = true){        __super::SetInternVisible(bVisible);        ::ShowWindow(m_hWnd, bVisible);    }     virtual void SetPos(RECT rc){        __super::SetPos(rc);        ::SetWindowPos(m_hWnd, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE);    }     BOOL Attach(HWND hWndNew){        if (! ::IsWindow(hWndNew))        {            return FALSE;        }         m_hWnd = hWndNew;        return TRUE;    }     HWND Detach(){        HWND hWnd = m_hWnd;        m_hWnd = NULL;        return hWnd;    } protected:    HWND m_hWnd;};

2、將XML中Slider節點換成Wnd,並且只保留位置資訊,XML如下:
 <Wnd float="true" pos="30,77,0,0" width="139" height="18" />

3、建立Wnd控制元件:由於Slider是duilib內建的控制元件,所以duilib會根據XML資訊自動建立Slider控制元件,而CWndUI是我們自定義的控制元件,所以需要自己建立,只需要響應CreateControl函式(如果duilib發現自定義控制元件,會自動呼叫此函式來獲取控制元件),在CDuiFrameWnd加上如下函式:

virtual CControlUI* CreateControl(LPCTSTR pstrClassName){        if (_tcsicmp(pstrClassName, _T("Wnd")) == 0)        {            CWndUI  *pUI  = new CWndUI;                        HWND    hWnd  = CreateWindow(_T("BUTTON"), _T("win32"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 0, 0, 0, 0, m_PaintManager.GetPaintWindow(), NULL, NULL, NULL);            pUI->Attach(hWnd);               //// 上面用的是win32的按鈕,下面這段用MFC的按鈕            //CButton *pBtn = new CButton;    // 記得釋放記憶體            //pBtn->Create(_T("MFC"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, CRect(0, 0, 0, 0), CWnd::FromHandle(m_PaintManager.GetPaintWindow()), 0);            //pUI->Attach(*pBtn);                        return pUI;        }         return NULL;    }
     上面的程式碼用了win32的按鈕,其中註釋部分是MFC按鈕,親們可以都試下效果:
     圖片      到現在為止,我們既可以在duilib中新增MFC控制元件,也可以在原有的MFC專案中新增duilib控制元件,就不用再擔心不能使用以前的控制元件啦~O(∩_∩)O~


圖片