有些浏览器会有一些底部工具条,如360的浏览器,它的底部工具条样例如下:
模仿360,本文介绍如何修改chromium代码,在chromium的底部也加上一个工具条。
首先浏览器的整个窗口的实现类是BrowserView,先在browser_view中加入相应的代码
src\chrome\browser\ui\views\frame\browser_view.h scoped_ptr<BottomBarView> bottombar_; src\chrome\browser\ui\views\frame\browser_view.cc void BrowserView::InitViews() { …… bottombar_.reset(new BottomBarView(browser_.get())); AddChildView(bottombar_.get()); bottombar_->Init(); …… }
在往BrowserView中增加bottombar_后,需要为bottombar_设置它的布局,也就是bottombar_的显示位置。BrowserView的布局由BrowserViewLayout负责,需要修改这个类。
src\chrome\browser\ui\views\frame\browser_view_layout.h class BrowserViewLayout : public views::LayoutManager { …… BottomBarView *bottombar_; …… } src\chrome\browser\ui\views\frame\ browser_view_layout.cc void BrowserViewLayout::Layout(views::View* browser_view) { …… int bottom = LayoutBottombar(browser_view->height()); bottom = LayoutDownloadShelf(bottom); //int bottom = LayoutDownloadShelf(browser_view->height()); …… }
bottombar_会在视图的最底端显示,而这个位置原来是下载栏的位置,修改一下这段代码,把下载栏放在底部工具栏之上。实现LayoutBottombar函数:
src\chrome\browser\ui\views\frame\ browser_view_layout.cc int BrowserViewLayout::LayoutBottombar(int bottom) { int browser_view_width = vertical_layout_rect_.width(); int height = bottombar_->GetPreferredSize().height(); if (!delegate_->IsTabStripVisible()) { bottombar_->SetVisible(false); bottombar_->SetBounds(0, bottom, browser_view_width, 0); return bottom; } bottombar_->SetVisible(true); bottombar_->SetBounds(vertical_layout_rect_.x(), bottom - height, browser_view_width, height); return bottom - height; }
SetBounds函数就是设置bottombar_的绘制位置,它的参数分别是x、y、width、height。在chromium中,这四个参数的含义如下。
在按F11显示全屏时标签栏是不显示的,底部工具栏和标签栏一样在全屏模式下不进行显示,所以增加IsTabStripVisible的判定。
接下来,我们来实现类BottomBarView,在src\chrome\browser\ui\views\目录下增加目录bottombar,在该目录下增加文件bottombar_view.h以及bottombar_view.cc。底部工具栏我是根据ToolbarView改的,所以一开始,我直接先从src\chrome\browser\ui\views\toolbar把toolbar_view.h和toolbar_view.cc拷贝过来,然后在这基础上进行修改。
增加代码需要更改src/chrome/chrome_browser_ui.gypi文件, 找到browser_view的位置,增加bottombar的文件路径
...... 'browser/ui/views/frame/browser_view.cc', 'browser/ui/views/frame/browser_view.h', 'browser/ui/views/bottombar/bottombar_view.h', 'browser/ui/views/bottombar/bottombar_view.cc', ......
修改的办法就是保留back_按扭,把所有其它如下所示所有不相关的按钮和元素相关的代码通通注释掉。
ToolbarButton*forward_;
ReloadButton*reload_;
HomeButton*home_;
LocationBarView*location_bar_;
BrowserActionsContainer*browser_actions_;
WrenchToolbarButton*app_menu_;
接下来开始修改back按钮,把它修改成查看历史记录的按扭。
src\chrome\browser\ui\views\bottombar\bottombar_view.h BackButton* history_;
在Init()函数中,把back_相应的代码段改为
src\chrome\browser\ui\views\bottombar\bottombar_view.cc void BottomBarView::Init() { …… history_ = new BackButton(this, NULL); history_->set_triggerable_event_flags( ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON); history_->set_tag(IDC_SHOW_HISTORY); history_->SetTooltipText(l10n_util::GetStringUTF16(IDS_SHOW_HISTORY)); history_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_SHOW_HISTORY)); history_->set_id(VIEW_ID_HISTORY_BUTTON_BOTTOMBAR); history_->Init(); AddChildView(history_); …… }
IDC_SHOW_HISTORY会弹出查看历史记录的页面。history_按钮需要一个id,这个id在src\chrome\browser\ui\view_ids.h中定义一个即可,在该文件后边添加了如下的内容,这些id可以自由定义。
VIEW_ID_BOTTOM_BAR = 2000, VIEW_ID_BACK_BUTTON_BOTTOMBAR, VIEW_ID_PRINT_BUTTON_BOTTOMBAR, VIEW_ID_DOWNLOAD_BUTTON_BOTTOMBAR, VIEW_ID_HISTORY_BUTTON_BOTTOMBAR,
IDS_SHOW_HISTORY是src\chrome\app\generated_resources.grd中定义的字符串,我暂时用了chromium下拉菜单的“历史记录”文字来代替。
Init()函数最后还会调用LoadImages函数,这个函数用于设置按钮图片,对该函数进行如下修改。
void BottomBarView::LoadImages() { ui::ThemeProvider* tp = GetThemeProvider(); history_->SetImage(views::Button::STATE_NORMAL, *(tp->GetImageSkiaNamed(IDR_HISTORY_BOTTOMBAR))); }
IDR_HISTORY_BOTTOMBAR是在src\chrome\app\theme\theme_resources.grd文件下增加一行设置,并在src\chrome\app\theme\default_100_percent\common增加一个按钮图标history.png。
<structure type="chrome_scaled_image"name="IDR_HISTORY_BOTTOMBAR"file="common/history.png" />
该图标的大小我按照back_按扭的大小改的,是一张29*29的图标。
最后,需要将按钮设置成enable,这个在函数EnabledStateChangedForCommand中可以设置
void BottomBarView::EnabledStateChangedForCommand(int id, bool enabled) { views::Button* button = NULL; switch (id) { case IDC_SHOW_HISTORY: button = history_; break; } if (button) button->SetEnabled(enabled); }
按钮的初始化工作完成,接下来,需要修改按钮的布局,首先,底部工具栏的大小由GetPreferredSize()设置。
宽度和高度都可以自由设置,但是通常高度以按钮高度为主,宽度足够排满按钮就可以了。
gfx::Size BottomBarView::GetPreferredSize() const { gfx::Size size(history_->GetPreferredSize()); if (is_display_mode_normal()) { int content_width = kLeftEdgeSpacing + kStandardSpacing + kRightEdgeSpacing + search_->GetPreferredSize().width() + download_->GetPreferredSize().width(); size.Enlarge(content_width, 0); } size.Enlarge(0, kTopSeperatorHeight); return SizeForContentSize(size); }
按钮的布局在Layout函数中实现,把它改写成如下代码,available_width记录当前按钮的排布x坐标,child_y希望把按钮放在底部工具栏的中间,通过SetBounds设置按钮的位置和大小。
void BottomBarView::Layout() { if (print_ == NULL) return; int child_height = std::min(history_->GetPreferredSize().height(), height()); int seperator_y = (height() - child_height + 1) / 2; int child_y = seperator_y + kTopSeperatorHeight; bool maximized = browser_->window() && browser_->window()->IsMaximized(); int history_width = history_->GetPreferredSize().width(); int available_width = std::max(0, width() - kRightEdgeSpacing - history_width); history_->SetBounds(available_width, child_y, history_width, child_height); ...... }
完成上述工作后,会发现底部工具栏的背景为黑色的,需要为底部工具栏绘制背景,底部工具栏的背景在src\chrome\browser\ui\views\frame\opaque_browser_frame_view.cc进绘制。加入下列代码绘制底部工具栏背景。
void OpaqueBrowserFrameView::OnPaint(gfx::Canvas* canvas) { …… PaintBottombarBackground(canvas); } void OpaqueBrowserFrameView::PaintBottombarBackground(gfx::Canvas* canvas) { gfx::Rect bottombar_bounds(browser_view()->GetBottombarBounds()); if (bottombar_bounds.IsEmpty()) return; gfx::Point toolbar_origin(bottombar_bounds.origin()); ConvertPointToTarget(browser_view(), this, &toolbar_origin); bottombar_bounds.set_origin(toolbar_origin); int x = bottombar_bounds.x(); int w = bottombar_bounds.width(); int y = bottombar_bounds.y(); int h = bottombar_bounds.height(); ui::ThemeProvider* tp = GetThemeProvider(); canvas->FillRect(gfx::Rect(x, y, w, h), tp->GetColor(ThemeProperties::COLOR_TOOLBAR)); gfx::ImageSkia* theme_toolbar = tp->GetImageSkiaNamed(IDR_THEME_TOOLBAR); canvas->TileImageInt(*theme_toolbar, x, y, w, h); canvas->FillRect(gfx::Rect(x,y,w,kClientEdgeThickness), ThemeProperties::GetDefaultColor( ThemeProperties::COLOR_TOOLBAR_SEPARATOR)); }
原文:http://blog.csdn.net/ljm198745/article/details/44648993