这次遇到的问题是这样的,我们使用C++(QT) 做的客户端,里面是嵌入CEF的界面(web页面)。也就是外层是C++界面,里面是cef界面。在外层有使用C++做的搜索框,输入搜索内容,会自动将搜索结果实时的以类似弹窗的方式展示出来。类似下面的功能:
关于这个弹出的结果框,如何消失出现了问题。就是鼠标点击了一下其他C++界面,这个弹窗失去了焦点,就会自动收回。
========================================================================
如果鼠标点击了cef界面,这时候cef的web页面获取了焦点,但是这时候C++并不知道自己已经失去了焦点,在搜索框内的鼠标还在闪烁,同时,搜索结果框也并没有消失。
造成这个问题的原因就是C++不知道cef界面已经获取了焦点,所以自己并没有释放焦点,弹窗也并没有消失。
…
那么解决方法就是当cef的web页面获取了焦点,就要通知c++界面,让c++知道自己已经失去了焦点,并且做失去焦点之后该做的事(比如收起弹窗,清除搜索框的焦点等)。
…
知道了我们应该去做什么,但是怎么去做呢?还得从cef的handler入手,仔细查找cef常用的handler,发现了cef关于焦点处理的handler: CefFocusHandler 我们查看一些他们提供的API,其中都是关于焦点的接口,一共三个:
///
// Called when the browser component is about to loose focus. For instance, if
// focus was on the last HTML element and the user pressed the TAB key. |next|
// will be true if the browser is giving focus to the next component and false
// if the browser is giving focus to the previous component.
///
/*--cef()--*/
virtual void OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) {}
///
// Called when the browser component is requesting focus. |source| indicates
// where the focus request is originating from. Return false to allow the
// focus to be set or true to cancel setting the focus.
///
/*--cef()--*/
virtual bool OnSetFocus(CefRefPtr<CefBrowser> browser, FocusSource source) {
return false;
}
///
// Called when the browser component has received focus.
///
/*--cef()--*/
virtual void OnGotFocus(CefRefPtr<CefBrowser> browser) {}
其中 我们来逐个分析一下
- OnTaskeFocus : 在浏览器组件将要失去焦点的时候调用。
- OnSetFocus : 在浏览器组件请求焦点的时候调用。
- OnGotFocus : 在浏览器组件得到了焦点的时候调用。
CEF提供的这三个关于焦点的处理函数,分别是失去焦点的时候、请求焦点与得到了焦点时候调用。那么很显然,我们是需要使用最后一个函数OnGotFocus的时候需要通知C++,而不是使用OnsetFocus的时候,为什么呢?因为万一浏览器请求焦点的时候失败了呢(虽然这种概率很小)?这时候焦点还是不在浏览器上。
那么具体做法是:
- 我们自己的handler继承CefFocusHandler
class SimpleHandler : public CefClient,
public CefFocusHandler
- 重写OnGotFocus方法
//CefFocusHandler
/**
* @brief OnGotFocus CEF界面得到焦点后执行
* @param browser
*/
virtual void OnGotFocus(CefRefPtr<CefBrowser> browser) OVERRIDE;
- 在OnGotFocus方法中,将浏览器得到了焦点的消息通知出去。
将浏览器得到焦点的消息通知给C++的 方法有很多种比如使用PostMessage/SendMessage/回调函数/信号槽等。
在C++界面的接收函数里进行失去焦点的处理:比如收起搜索结果框体,收起其他的弹出框,清除搜索框的焦点等等。