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

系统 2085 0
 

上一次说到处理 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 接口的方便性,最后还学会了使用栈对象的生命周期来方便对加锁和解锁的操作,以便降低代码的出错率。

 

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


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论