注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

写着玩

Bob

 
 
 

日志

 
 
 
 

chrome UI 学习笔记2  

2009-12-01 16:12:23|  分类: Chrome |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

基本控件

前面提到过,chrome的基础控件在目录“ src/chrome/views/controls”目录下。

下面是chrome自带的控件一览

 

//按钮

D:\chrometrunk\chrometrunk\src\chrome\views\controls\button>ls

button.cc custom_button.cc native_button.cc radio_button.h

button.h custom_button.h native_button.h text_button.cc

button_dropdown.cc image_button.cc native_button_win.cc text_button.h

button_dropdown.h image_button.h native_button_win.h

checkbox.cc menu_button.cc native_button_wrapper.h

checkbox.h menu_button.h radio_button.cc


//菜单

D:\chrometrunk\chrometrunk\src\chrome\views\controls\menu>ls

chrome_menu.cc controller.h menu.h

chrome_menu.h menu.cc view_menu_delegate.h


//滑动条

D:\chrometrunk\chrometrunk\src\chrome\views\controls\scrollbar>ls

bitmap_scroll_bar.cc native_scroll_bar.cc scroll_bar.cc

bitmap_scroll_bar.h native_scroll_bar.h scroll_bar.h


//表格

D:\chrometrunk\chrometrunk\src\chrome\views\controls\table>ls

group_table_view.cc table_view.cc table_view_unittest.cc

group_table_view.h table_view.h


//

D:\chrometrunk\chrometrunk\src\chrome\views\controls\tree>ls

tree_model.h tree_node_iterator_unittest.cc tree_view.cc

tree_node_iterator.h tree_node_model.h tree_view.h


//其他控件

D:\chrometrunk\chrometrunk\src\chrome\views\controls>ls

button label_unittest.cc native_control_win.h tabbed_pane.h

combo_box.cc link.cc scroll_view.cc table

combo_box.h link.h scroll_view.h text_field.cc

hwnd_view.cc menu scrollbar text_field.h

hwnd_view.h message_box_view.cc separator.cc throbber.cc

image_view.cc message_box_view.h separator.h throbber.h

image_view.h native_control.cc single_split_view.cc tree

label.cc native_control.h single_split_view.h

label.h native_control_win.cc tabbed_pane.cc


   尽管chrome提供丰富的控件,但是如果打算使用chrome这一套UI框架开发自己的程序,这些远远不够用,幸运的是基于chrome开发自定义控件相当的方便。

       接着上面的例子,下面的程序在客户区添加一个ButtonLabel。当点击按钮后,Label显示“点击了“。下面是源码:



DE<//test.h

#include "chrome/views/view.h"
#include "chrome/views/window/window_delegate.h"
#include "chrome/views/controls/button/button.h"

namespace views{
    class Label;
    class TextButton;
}
class ChromeCanvas;


class TestWindow :
    public views::View,
    public views::WindowDelegate,
    public views::ButtonListener{
public:

    TestWindow();

    virtual View* GetContentsView() {
        return this;
    }

    virtual gfx::Size GetPreferredSize(){
        return gfx::Size(400,300);
    }

    virtual void Layout();
    virtual void Paint(ChromeCanvas* canvas);
    virtual void ButtonPressed(views::Button* sender);

    static void CreateTestWindow();

private:

    views::Label * lable_;
    views::TextButton * button_;

};

//test.cpp

#include "test.h"
#include "chrome/views/window/window.h"
#include "chrome/views/controls/button/text_button.h"
#include "chrome/views/controls/label.h"
#include "chrome/common/gfx/chrome_canvas.h"

TestWindow::TestWindow(){
    this->lable_ = new views::Label(L"");
    this->button_ = new views::TextButton(this,L"点击");
    AddChildView(this->lable_);
    AddChildView(this->button_);
}

void TestWindow::Layout(){
    this->lable_->SetBounds(10,10,50,30);
    this->button_->SetBounds(10,50,60,30);
}


void TestWindow::Paint(ChromeCanvas* canvas){
    canvas->FillRectInt(SK_ColorWHITE, 0, 0, width(), height());
}

void TestWindow::ButtonPressed(views::Button* sender){
    if(sender == this->button_){
        this->lable_->SetText(L"点击了");
    }
}

void TestWindow::CreateTestWindow(){
    views::Window::CreateChromeWindow(NULL,gfx::Rect(),new TestWindow)->Show();
}
DE<


结果如下:


chrome UI 学习笔记2 - yolcy - 写着玩

源码解析

  1. 包含相关的控件views::Label * lable_ views::TextButton * button_;

  2. 通过实现 views::ButtonListener接口来处理button_的点击事件

  3. 使用 AddChildView 将两个控件添加为子控件。

  4. buttonPressed函数中添加事件处理的代码。

  5. Paint 函数将整个客户区画成白色

  6. Layout函数设置子控件的位置。


Paint&&Layout

          Chrome使用Skia作为二位绘图引擎,而绘图体现在每一个ViewPaint函数中,views::ViewPaint函数屁事都不干,所以在第一个程序中可以看到客户区将背景图片和默认的黑色显示出来,而第二个函数,我们覆盖默认的Paint函数并且将整个View TestWindow)的区间绘成白色。

         每一个ViewLayout函数用于定位它所有的子View。当因为某些原因整个窗口需要重构时,根View调用Layout函数,然后递归调用每一个子ViewLayout函数。关于ChromeLayoutchrome还提供一个GridLayout(src\chrome\views\grid_layout.h)和FillLayout(src\chrome\views\fill_layout.h)。具体的用法可以参考chrome中的源码。


事件处理

          chrome控件通常的事件处理方式是通过声明一个接口,然后将该接口指针作为一个成员变量来使用实现。例如按钮事件的接口声明如下:


DE<// An interface implemented by an object to let it know that a button was

// pressed.

class ButtonListener {
 public:
  virtual void ButtonPressed(Button* sender) = 0;
};
DE<

    一般情况下,控件的父View会继承子控件依赖的借口并实现相关的函数,然后将自己作为参数传递给这些控件实现完整的事件处理。一个父View可能包含好几个同类的控件,所以这些接口一般会包含一个sender以便区分不同的控件发送者。

          其他控件的使用,可以参考源码中的代码,这里不多叙述。




原生控件

         一般来说,如果有设计良好,使用方便的控件可用就完全不必自己从轮子造起,chrome就是这样。chrome提供的很多控件并不是自己从零绘制的,而是基于原生的操作系统控件,最典型的是TextField(src\chrome\views\controls\text_field.h)。该控件底层的实现完全使用WTL提供的richedit(http://msdn.microsoft.com/en-us/library/bb787873%28VS.85%29.aspx#_win32_Rich_Edit_Version_2.0)。当然为了方便扩展,chrome也提供相关的类方便用户封装其他的原生控件。

        下面以封装IE浏览器说明问题,当用户需要在UI中嵌入浏览器,可以将下面的View像上面的代码中Button那样使用。

        首先获得WTLIE的封装(实际上是一个com),相关源码可参考下面的代码(http://devel.openocr.org/svn/openocr/trunk/cuneiform/interface/icrashreport/wtl/samples/tabbrowser/browserview.h )。

接着新建一个View,并封装该原生控件,具体的源码可参考:



DE<// ie_view.h BrowserView.h 是原生控件的封装头文件

#include "BrowserView.h"
#include "string"
#include "chrome/views/view.h"
#include "base/scoped_ptr.h"

namespace views{
    class HWNDView;
}

class IEView :
    public views::View{

public:

    explicit IEView(const std::wstring & url);
    virtual ~IEView();

    virtual void Layout();
    virtual void ViewHierarchyChanged(bool is_add,
        views::View* parent,
        views::View* child);

private:

    void initChildViews();

    scoped_ptr<CBrowserView> iebrowser_;
    views::HWNDView * iebrowser_view_;

    std::wstring url_;

protected:

    DISALLOW_COPY_AND_ASSIGN(IEView);
};

// ie_view.cpp

#include "ie_view.h"
#include "base/logging.h"
#include "chrome/views/controls/hwnd_view.h"
#include "chrome/views/widget/widget.h"

IEView::IEView(const std::wstring & url) :
        url_(url) {
}

IEView::~IEView() {
}

void IEView::Layout() {
    this->iebrowser_view_->SetBounds(0,0,width(),height());
}



void IEView::initChildViews() {

    iebrowser_.reset( new CBrowserView );
    HWND hwnd = GetWidget()->GetNativeView();

    RECT rc = {0,0,100,100};
    HWND hwnd_ie = iebrowser_->Create( hwnd, 0, url_.c_str(), WS_CHILD|WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL);
    DWORD errcode = GetLastError();
    DCHECK(iebrowser_->IsWindow());

    iebrowser_view_ = new views::HWNDView;
    DCHECK(iebrowser_view_) << "LocationBarView::Init - OOM!";
    AddChildView(iebrowser_view_);
    iebrowser_view_->SetAssociatedFocusView(this);
    iebrowser_view_->Attach(iebrowser_->m_hWnd);

}


void IEView::ViewHierarchyChanged(bool is_add,
                                  views::View* parent,
                                  views::View* child) {
    if (is_add && child == this ) {
        this->initChildViews();
    }
}
DE<


   这个过程中,最关键的View就是 views::HWNDView。该View提供一个机制将原生控件和Chrome View进行绑定,以便用户能够像View一样操作原生控件。

     ViewHierarchyChanged函数在它所述的Viewaddremove时被调用。上面源码的意思是当 IEView被父View调用AddChildView函数将其加为子View时被调用。之所以不放在构造函数内是因为有些控件的初始化依赖一个窗口句柄,而在构造函数结束之前,这个句柄很可能还没有初始化。

 

 

  评论这张
 
阅读(1423)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017