您的位置:首页 > 产品设计 > UI/UE

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

2015-09-20 12:43 901 查看

前言:

编译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);
void	SetParent(CScrollTabUI* pTab)	{ m_pParent = pTab; }
protected:
virtual void Init();
virtual void PaintText(HDC hDC);
virtual void SetPos(RECT rc);
virtual void DoEvent(TEventUI& event);
bool	OnBtnClose(void* pParam);
private:
CButtonUI*		m_pBtnExit;
CScrollTabUI*	m_pParent;
};


#include "StdAfx.h"
#include "ScrollOptionUI.h"

#define BTN_CLOSE_WIDTH		14
#define BTN_CLOSE_HEIGHT	14

CScrollOptionUI::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 once

class CScrollTabUI;
class CScrollTabCallback
{
public:
virtual void	OnScrollTabCloseItem(CScrollTabUI* pTab, const int nDelIndex, const int nSelIndex) = 0;
virtual void	OnScrollTabSelectChange(CScrollTabUI* pTab, const int nUnSelIndex, const int nSelIndex) = 0;
virtual void	OnScrollTabAddItem(CScrollTabUI* pTab) = 0;
virtual void	OnScrollTabDbClick(CScrollTabUI* pTab, const int nIndex) = 0;
};

class CScrollTabUI
: public CContainerUI
{
public:
CScrollTabUI(void);
~CScrollTabUI(void);
CControlUI*	AddTabItem(LPCTSTR lpText, bool bReset=false);
void	SelectItem(CControlUI* pItem);
void	DeleteItem(CControlUI* pItem);
void	DeleteItem(const int nIndex);
void	SetItemText(const int nIndex, LPCTSTR lpText);
int		GetItemCount()const								{ return m_pTabItems.size();	}
void	SetCallback(CScrollTabCallback* pCallback)		{ m_pCallback = pCallback;		}
void	OnOptionDbClick(CControlUI* pOption);
protected:
virtual void	SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
virtual void	Init();
virtual void	SetPos(RECT rc);
void	ResetTabPos();
int		GetTabItemIndex(CControlUI* pItem);
bool	OnBtnClickAdd(void* pParam);
private:
int		m_nNorWidth;
int		m_nMinWidth;
int		m_nCurWidth;
int		m_nSelIndex;
DWORD	m_dwTabSelColor;
DWORD	m_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();
}
else
m_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;
else
m_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);
else
pItem->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、未完成的

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

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

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

菜单项,各种设置。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: