上一次說到處理
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
接口的方便性,最后還學會了使用棧對象的生命周期來方便對加鎖和解鎖的操作,以便降低代碼的出錯率。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
