Duilib自定義控件


新版博客已經搭建好了,有問題請訪問 htt://www.crazydebug.com

在公司二期項目中為了將谷歌內核嵌入到duilib中,采用了自定義duilib控件的方法,由於也是第一次用duilib,邊學邊用,所有網上的資料給了我很大的幫助,尤其Redrain兄弟的文章給我啟發很大,再次感謝互聯網具有開源精神的程序員。

今天簡單總結下duilib的自定義控件,要實現自定義控件需要做兩件事情

      1、繼承現有的控件類創建新的控件類
      2、讓程序識別新的控件並可以在xml中使用
第一步繼承我就不多說了,直接看代碼吧
class CBrowserUI :public CControlUI
{
public:
    CBrowserUI();
    ~CBrowserUI();
    virtual LPCTSTR GetClass() const;
    virtual LPVOID GetInterface(LPCTSTR pstrName);
    //這個一定要設置,不然控件無法顯示
    virtual void SetPos(RECT rc, bool bNeedInvalidate = true);

    
    CefRefPtr<CefBrowser> GetBrowser()
    {
        return m_Browser->GetBrowser();
    }

    CefRefPtr<CefFrame> GetMainFrame()
    {
        return m_Browser->GetMainFrame();
    }

    void CloseAllBrowser(); 
    bool CreateBrowser(const CefString & szHomePage, CHaoMainFrame  * pWnd);
    void LoadUrl(const CefString & url);

protected:
    CefRefPtr<CHaoBrowserHandler> m_Browser; 
};

下面是實現文件

CBrowserUI::CBrowserUI() :m_Browser(NULL)// m_Browser(NULL) 
{
    
}


CBrowserUI::~CBrowserUI()
{
}


LPCTSTR CBrowserUI::GetClass() const
{
    return _T("BrowserUI");
}

LPVOID CBrowserUI::GetInterface(LPCTSTR pstrName)
{
    if (_tcsicmp(pstrName, _T("Browser")) == 0)
    {
        return static_cast<CBrowserUI*>(this);
    }
    return CControlUI::GetInterface(pstrName);
}

void CBrowserUI::SetPos(RECT rc, bool bNeedInvalidate /* = true */)
{
    CControlUI::SetPos(rc, bNeedInvalidate);
    if (m_Browser.get())
    {
        CefRefPtr<CefBrowser> browser = m_Browser->GetBrowser();
        DuiLib::CDuiRect rc = GetPos(); 
        if (browser && !rc.IsNull())
        {
            ::SetWindowPos(browser->GetHost()->GetWindowHandle(),
                NULL, rc.left, rc.top, rc.GetWidth(), rc.GetHeight(), SWP_NOZORDER | SWP_NOACTIVATE); 
        }
    }
}

void CBrowserUI::CloseAllBrowser()
{
    if (m_Browser.get())
    {
        m_Browser->CloseAllBrowsers(true);
    }
}

bool CBrowserUI::CreateBrowser(const CefString & szHomePage, CHaoMainFrame  * pWnd)
{
    CefWindowInfo info; 
    if (m_Browser == NULL)
    {
        m_Browser = new CHaoBrowserHandler(pWnd);
    }
    m_Browser->SetHomePage(szHomePage);
    if (m_Browser != NULL)
    {
        info.SetAsChild(GetManager()->GetPaintWindow(), GetPos());
        CefBrowserSettings browserSettings; 
        return CefBrowserHost::CreateBrowser(info, m_Browser.get(), szHomePage,browserSettings,NULL);
    }

    return false;
}

void CBrowserUI::LoadUrl(const CefString & url)
{
    if (m_Browser.get())
    {
        CefRefPtr<CefFrame> mainframe = m_Browser->GetMainFrame();
        if (mainframe)
            mainframe->LoadURL(url);
    }
}

建立新控件后,最先應該重寫的兩個函數是GetClass和GetInterface。他們后用來區分控件的類型的虛函數,用於動態識別控件類型和做控件的類型轉換。

從Duilib的自帶控件上可以看出,比如當前的自定義控件類名為CBrowserUI,那么GetClass函數返回的字符串BrowserUI。而GetInterface函數是根據傳入的參數是否與自身的字符串匹配,來決定能否把自己轉換為需要的控件類型。GetInterface中用來匹配的字符串,應該與xml中的對應的控件的標簽名稱一直,這里應該是Browser。

ButtonUI類,GetClass對應ButtonUI,GetInterface對應Button。這不是強制的,但是保持這個風格很重要

 

好了控件類的定義實現都有了,那么如何讓xml可以識別我們定義的控件?這才是最重要的問題

為了讓xml布局識別我們的新控件,我們需要完成Duilib的IDialogBuilderCallback接口,重寫這個接口中的CreateControl函數。

通常情況下,可以讓窗體類繼承IDialogBuilderCallback接口並且重寫CreateControl(DuiLib自帶的WindowImplBase窗體類已經繼承了這個接口,如果是繼承WindowImplBase的話就直接重寫CreateControl就可以了)。函數處理方法是比較傳入的字符串,根據字符串來決定返回什么控件的指針,這個傳入的字符串就是xml文件中控件的標簽,比如<Button />中的字符串Button

CControlUI * CHaoMainFrame::CreateControl(LPCTSTR pstrClass)
{
    CControlUI * pUI = NULL;
    if (_tcsicmp(pstrClass, _T("MyBrowser")) == 0)
    {
        pUI = m_browser = new CBrowserUI;
    }
    return pUI;
}

這樣一個自定義控件就搞完了,而且我用着也是很不錯的,上個圖吧,無圖無真相

 


免責聲明!

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



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