点击这里给我发消息 点击这里给我发消息

谷歌浏览器的源码分析(6)

添加时间:2013-12-7
    相关阅读: 模板 程序 谷歌
  上一次说到处理WM_CHAR消息,当用户每键入一个字符时,万能连接框就会去进行一次查找的过程,然后把智能提示信息显示出来。说到AutocompleteEdit::HandleKeystroke函数的操作,那么它为什么需要冻结这个函数的使用呢?现在就来分析这部份的内容。如下:ScopedFreeze freeze(this, GetTextObjectModel());在这行代码里,首先会调用函数GetTextObjectModel()来获取一个文档ITextDocument接口,然后再使用它的功能。这个函数的代码如下:
 
 #001 ITextDocument* AutocompleteEdit::GetTextObjectModel() const {

  先判断这个接口是否获取到,如果已经获取到就不再去重复获取了。
 
 #002  if (!text_object_model_) {
#003   // This is lazily initialized, instead of being initialized in the
#004   // constructor, in order to avoid hurting startup performance.

  这里使用了智能指针来获取IRichEditOle接口。
 
 #005   CComPtr<IRichEditOle> ole_interface;

  获取到的IRichEditOle接口绑定到智能指针里。
 
 #006   ole_interface.Attach(GetOleInterface());

  下面通过=操作符获取ITextDocument接口,如果你深入去分析这个赋值操作符,会看到它自动去调用IRichEditOle的接口IUnknown::QueryInterface来查询到ITextDocument接口,这个过程对于程序员来说是完全不用关心的,这就是使用mutable CComQIPtr<ITextDocument> text_object_model_定义的作用。
 
 #007   text_object_model_ = ole_interface;
#008  }
#009  return text_object_model_;
#010 }

  通过上面的分析,可见使用CComQIPtr<ITextDocument>智能指针可以省了很多COM调用的操作,这真是模板类的强大功能的使用之处。当把ITextDocument接口获取回来之后,对于RichEdit操作就可以轻松访问了,ScopedFreeze类生成一个局部对象,这个对象实现了对RichEdit自动冻结和解冻结的功能,这个过程是通过局部对象在栈里生命周期的特性应用。如下面的代码:
 
 #001 AutocompleteEdit::ScopedFreeze::ScopedFreeze(AutocompleteEdit* edit,
#002                        ITextDocument* text_object_model)
#003   : edit_(edit),
#004    text_object_model_(text_object_model) {
#005  // Freeze the screen.
#006  if (text_object_model_) {
#007   long count;
#008   text_object_model_->Freeze(&count);
#009  }
#010 }
#011 
#012 AutocompleteEdit::ScopedFreeze::~ScopedFreeze() {
#013  // Unfreeze the screen.
#014  // NOTE: If this destructor is reached while the edit is being destroyed (for
#015  // example, because we double-clicked the edit of a popup and caused it to
#016  // transform to an unconstrained window), it will no longer have an HWND, and
#017  // text_object_model_ may point to a destroyed object, so do nothing here.
#018  if (edit_->IsWindow() && text_object_model_) {
#019   long count;
#020   text_object_model_->Unfreeze(&count);
#021   if (count == 0) {

  这里需要手动地更新窗口的显示。
 
 #022    // We need to UpdateWindow() here instead of InvalidateRect() because, as
#023    // far as I can tell, the edit likes to synchronously erase its background
#024    // when unfreezing, thus requiring us to synchronously redraw if we don't
#025    // want flicker.
#026    edit_->UpdateWindow();
#027   }
#028  }
#029 }

  从上面的代码可以看到构造函数里冻结,析构造函数里解冻结,如果需要就会自动更新窗口的显示。通过上面的分析,学会使用RichEdit的冻结窗口的输入,并且解冻结和更新窗口的显示,也同时学会使用智能指针来操作COM接口的方便性,最后还学会了使用栈对象的生命周期来方便对加锁和解锁的操作,以便降低代码的出错率。
相关谷歌浏览器的源码分析(6)

咨询热线:020-85648757 85648755 85648616 0755-27912581 客服:020-85648756 0755-27912581 业务传真:020-32579052
广州市网景网络科技有限公司 Copyright◎2003-2008 Veelink.com. All Rights Reserved.
广州商务地址:广东省广州市黄埔大道中203号(海景园区)海景花园C栋501室
= 深圳商务地址:深圳市宝源路华丰宝源大厦606
研发中心:广东广州市天河软件园海景园区 粤ICP备05103322号 工商注册