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


    雖然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~
 






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM