使用Libcef+Duilib创建自己的Chrome内核浏览器

来源:互联网 发布:罗素兰挂号 知乎 编辑:程序博客网 时间:2024/04/30 09:21

前言:

编译Chrome开源代码是一件很恐怖的事情,代码庞大,还需要各种工具配合。在windows上快速开发chrome内核网页程序,Libcef是一个很好的选择。最近趁空闲时间,写了一个简单的浏览器,很多功能都没有完善,不知道以后还会不会继续写了,PC端确实是萎了。

1、Libcef 的使用

在前面的几篇文章中大概介绍了下Libcef的使用,很多时候我们都会遇到各种问题,建议去看看它的接口函数声明,里面的注释写的非常清楚。

libCEF中C++与JavaScript的交互调

Windows上使用CEF嵌入基于chrome内核浏览器小例

2、大概的要点

程序运行截图



首先需要解决的是浏览器的Tab控件,扩展Duilib控件,每一个Tab控件就是一个容器里面存放着一系列Item,根据Item的个数和Tab的尺寸来计算每一个Item 节点的宽度。

对于单个节点Item控件,里面又有一个子Button控件,也就是关闭按钮。对于这个Item的消息进行处理,包括选中、双击、关闭,把这些消息都转发到父控件Tab中去处理。Tab控件同一管理这些控件的哪一个是选中状态。

然后是Libcef控件的创建,Tab中点击Add按钮后,需要创建网页控件并加载到当前窗口中去。整个父窗口在大小发生变化时,又要通知里面所有的Libcef子窗口随之变化。

然后就是关闭时,要让所有的Libcef子进程都能正常退出,就必须按照Libef文档说的那样,在退出时调用CefQuitMessageLoop()。

3、部分源代码

Duilib扩展Tab控件

#pragma once#include "ScrollTabUI.h"class CScrollOptionUI :public CContainerUI{public:CScrollOptionUI(void);~CScrollOptionUI(void);voidSetParent(CScrollTabUI* pTab){ m_pParent = pTab; }protected:virtual void Init();virtual void PaintText(HDC hDC);virtual void SetPos(RECT rc);virtual void DoEvent(TEventUI& event);boolOnBtnClose(void* pParam);private:CButtonUI*m_pBtnExit;CScrollTabUI*m_pParent;};

#include "StdAfx.h"#include "ScrollOptionUI.h"#define BTN_CLOSE_WIDTH14#define BTN_CLOSE_HEIGHT14CScrollOptionUI::CScrollOptionUI(void): m_pBtnExit(NULL), m_pParent(NULL){}CScrollOptionUI::~CScrollOptionUI(void){}void CScrollOptionUI::Init(){m_pBtnExit = new CButtonUI;CDuiString strAttr;strAttr.Format(L"float=\"true\" pos=\"%d,%d,%d,%d\" normalimage=\"close_nor.png\" hotimage=\"close_hot.png\" pushedimage=\"close_push.png\"",m_cxyFixed.cx-BTN_CLOSE_WIDTH, 0, m_cxyFixed.cx, BTN_CLOSE_HEIGHT);m_pBtnExit->ApplyAttributeList(strAttr);Add(m_pBtnExit);m_pBtnExit->OnNotify += MakeDelegate(this, &CScrollOptionUI::OnBtnClose);}void CScrollOptionUI::PaintText( HDC hDC ){RECT rc = m_rcItem;rc.left += 4;rc.right-= 10;CRenderEngine::DrawText(hDC, m_pManager, rc, m_sText, 0xFF666666, 0,  DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);}void CScrollOptionUI::SetPos( RECT rc ){CContainerUI::SetPos(rc);RECT rcExit = {rc.right-BTN_CLOSE_WIDTH-1, rc.top+1, rc.right-1, rc.top+BTN_CLOSE_HEIGHT+1};m_pBtnExit->SetPos(rcExit);}void CScrollOptionUI::DoEvent( TEventUI& event ){if( event.Type == UIEVENT_BUTTONDOWN && m_pParent ){m_pParent->SelectItem(this);}else if ( event.Type == UIEVENT_DBLCLICK && m_pParent ){m_pParent->OnOptionDbClick(this);}CContainerUI::DoEvent(event);}bool CScrollOptionUI::OnBtnClose( void* pParam ){TNotifyUI* pNotifyUI = (TNotifyUI*)pParam;if(pNotifyUI->sType == DUI_MSGTYPE_CLICK && m_pParent ) {m_pParent->DeleteItem(this);}return true;}

#pragma onceclass CScrollTabUI;class CScrollTabCallback{public:virtual voidOnScrollTabCloseItem(CScrollTabUI* pTab, const int nDelIndex, const int nSelIndex) = 0;virtual voidOnScrollTabSelectChange(CScrollTabUI* pTab, const int nUnSelIndex, const int nSelIndex) = 0;virtual voidOnScrollTabAddItem(CScrollTabUI* pTab) = 0;virtual voidOnScrollTabDbClick(CScrollTabUI* pTab, const int nIndex) = 0;};class CScrollTabUI: public CContainerUI{public:CScrollTabUI(void);~CScrollTabUI(void);CControlUI*AddTabItem(LPCTSTR lpText, bool bReset=false);voidSelectItem(CControlUI* pItem);voidDeleteItem(CControlUI* pItem);voidDeleteItem(const int nIndex);voidSetItemText(const int nIndex, LPCTSTR lpText);intGetItemCount()const{ return m_pTabItems.size();}voidSetCallback(CScrollTabCallback* pCallback){ m_pCallback = pCallback;}voidOnOptionDbClick(CControlUI* pOption);protected:virtual voidSetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);virtual voidInit();virtual voidSetPos(RECT rc);voidResetTabPos();intGetTabItemIndex(CControlUI* pItem);boolOnBtnClickAdd(void* pParam);private:intm_nNorWidth;intm_nMinWidth;intm_nCurWidth;intm_nSelIndex;DWORDm_dwTabSelColor;DWORDm_dwTabNorColor;CButtonUI* m_pBtnAdd;vector<CControlUI*> m_pTabItems;CScrollTabCallback*m_pCallback;};

#include "StdAfx.h"#include "ScrollTabUI.h"#include "ScrollOptionUI.h"CScrollTabUI::CScrollTabUI(void): m_nNorWidth(100), m_nCurWidth(0), m_nMinWidth(30), m_dwTabSelColor(0xffffffff), m_dwTabNorColor(0xfff0f0f0), m_nSelIndex(-1), m_pBtnAdd(NULL), m_pCallback(NULL){}CScrollTabUI::~CScrollTabUI(void){}CControlUI* CScrollTabUI::AddTabItem( LPCTSTR lpText, bool bReset/*=false*/ ){CScrollOptionUI* pTabItem = new CScrollOptionUI;if ( NULL == pTabItem )return NULL;CDuiString strAttr;strAttr.Format(L"float=\"true\" bordercolor=\"#FF999999\" bordersize=\"1\" borderround=\"2,2\" text=\"%s\" tooltip=\"%s\"",lpText, lpText);pTabItem->ApplyAttributeList(strAttr);pTabItem->SetParent(this);if ( !Add(pTabItem) ){delete pTabItem;return NULL;}if ( m_pTabItems.empty() )m_nSelIndex = 0;m_pTabItems.push_back(pTabItem);if ( bReset )ResetTabPos();return pTabItem;}void CScrollTabUI::SelectItem( CControlUI* pItem ){if ( m_nSelIndex>=0 && m_nSelIndex<m_pTabItems.size() ){CControlUI* pCurItem = m_pTabItems[m_nSelIndex];if ( pCurItem )pCurItem->SetBkColor(m_dwTabNorColor);}pItem->SetBkColor(m_dwTabSelColor);int nUnSelIndex = m_nSelIndex;m_nSelIndex = GetTabItemIndex(pItem);if ( m_pCallback )m_pCallback->OnScrollTabSelectChange(this, nUnSelIndex, m_nSelIndex);}void CScrollTabUI::SetAttribute( LPCTSTR pstrName, LPCTSTR pstrValue ){if ( wcscmp(pstrName, L"TabWidth") == 0 ){m_nNorWidth = _ttoi(pstrValue);return ;}if ( wcscmp(pstrName, L"MinTabWidth") == 0 ){m_nMinWidth = _ttoi(pstrValue);return ; }if ( wcscmp(pstrName, L"TabSelColor") == 0 ){if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);LPTSTR pstr = NULL;m_dwTabSelColor = _tcstoul(pstrValue, &pstr, 16);return ; }if ( wcscmp(pstrName, L"TabNorColor") == 0 ){if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);LPTSTR pstr = NULL;m_dwTabNorColor = _tcstoul(pstrValue, &pstr, 16);return ; }CContainerUI::SetAttribute(pstrName, pstrValue);}void CScrollTabUI::Init(){m_pBtnAdd = new CButtonUI;CDuiString strAttr = L"float=\"true\" pos=\"0,0,0,0\" normalimage=\"file='tab_add.png' source='0,0,25,34' dest='0,0,25,30' \" \hotimage=\"file='tab_add.png' source='25,0,50,34' dest='0,0,25,30' \" pushedimage=\"file='tab_add.png' source='50,0,75,34' dest='0,0,25,30' \" \disabledimage=\"file='tab_add.png' source='75,0,100,34' dest='0,0,25,30' \" tooltip=\"新建\" ";m_pBtnAdd->ApplyAttributeList(strAttr);Add(m_pBtnAdd);m_pBtnAdd->OnNotify += MakeDelegate(this, &CScrollTabUI::OnBtnClickAdd);}void CScrollTabUI::DeleteItem( CControlUI* pItem ){int nDelIndex = GetTabItemIndex(pItem);if ( nDelIndex == -1 )return ;DeleteItem(nDelIndex);}void CScrollTabUI::DeleteItem( const int nIndex ){if ( nIndex<0 || nIndex>=m_pTabItems.size() )return ;Remove(m_pTabItems[nIndex]);m_pTabItems.erase(m_pTabItems.begin()+nIndex);int nCount = m_pTabItems.size();if ( nCount>0 ){if ( nIndex<m_nSelIndex )m_nSelIndex--;else if ( nIndex == m_nSelIndex ){m_nSelIndex = nCount-1;CControlUI* pItem = m_pTabItems[m_nSelIndex];if ( pItem )pItem->SetBkColor(m_dwTabSelColor);}ResetTabPos();}elsem_nSelIndex = -1;if ( m_pCallback )m_pCallback->OnScrollTabCloseItem(this, nIndex, m_nSelIndex);}void CScrollTabUI::ResetTabPos(){int nCount = m_pTabItems.size();if ( nCount == 0 ){RECT rcItem = {m_rcItem.left, m_rcItem.top, 25, m_rcItem.bottom};m_pBtnAdd->SetPos(rcItem);return ;}int nWidth = m_rcItem.right - m_rcItem.left-25;int nHeight= m_rcItem.bottom - m_rcItem.top;if ( nWidth/nCount < m_nMinWidth )return ;if ( nCount*m_nNorWidth <= nWidth )m_nCurWidth = m_nNorWidth;elsem_nCurWidth = nWidth/nCount;RECT rcItem;for( size_t i=0; i<m_pTabItems.size(); ++i ){rcItem.left= m_nCurWidth*i + m_rcItem.left;rcItem.top= 0 + m_rcItem.top;rcItem.right= rcItem.left + m_nCurWidth;rcItem.bottom = rcItem.top + nHeight;CControlUI* pItem = m_pTabItems[i];pItem->SetPos(rcItem);if ( m_nSelIndex == i )pItem->SetBkColor(m_dwTabSelColor);elsepItem->SetBkColor(m_dwTabNorColor);}rcItem.left = rcItem.right;rcItem.right = rcItem.left + 25;m_pBtnAdd->SetPos(rcItem);}void CScrollTabUI::SetItemText( const int nIndex, LPCTSTR lpText ){int nCount = m_pTabItems.size();if ( 0 == nCount || nCount <= nIndex )return ;CControlUI* pItem = m_pTabItems[nIndex];if ( pItem ){pItem->SetText(lpText);pItem->SetToolTip(lpText);}}int CScrollTabUI::GetTabItemIndex( CControlUI* pItem ){int nIndex = -1;for ( size_t i=0; i<m_pTabItems.size(); ++i ){if ( m_pTabItems[i] == pItem ){nIndex = i;break;}}return nIndex;}bool CScrollTabUI::OnBtnClickAdd( void* pParam ){TNotifyUI* pNotifyUI = (TNotifyUI*)pParam;if(pNotifyUI->sType != DUI_MSGTYPE_CLICK) return true;if ( m_pCallback )m_pCallback->OnScrollTabAddItem(this);return true;}void CScrollTabUI::SetPos( RECT rc ){CContainerUI::SetPos(rc);ResetTabPos();}void CScrollTabUI::OnOptionDbClick(CControlUI* pOption){if ( m_pCallback )m_pCallback->OnScrollTabDbClick(this, m_nSelIndex);}
子控件的消息都反射给父控件去处理,父控件同一管理所有子控件(计算宽度、设置选中、取消选中)。

4、未完成的

下载管理没做,应该对下载回调进行处理,用自己封装的下载库来处理进度,并加下载管理窗口;

浏览记录,对用户输入网址进行匹配;

收藏夹,导入其他浏览器的收藏夹;

菜单项,各种设置。






2 0
原创粉丝点击