CEF在离屏渲染模式下没有tooltips?tooltips创建之后不显示?我以为我又遇到BUG了
这次我们在CEF显示的界面里加上了tooltips,也就是html的title属性,结果发现这玩意竟然不会显示,一开始我怀疑是自己的代码问题,很快我又去cefclient这个demo里测试了一下,确认了我的怀疑,只要打开了--off-screen-rendering-enabled,就会导致tooltips无法显示。我当然认为这是一个CEF的bug,于是去反馈issue,但是我同时也做了一堆搜索,一开始看到的都是关于manifest以及InitCommonControlsEx的问题,和这个问题并没有相关性。
直到我搜到这个issue,https://bitbucket.org/chromiumembedded/cef/issues/854/cef3-title-attribute-of-tags-is-not ,CEF在OSR模式下需要开发者手动处理CefDisplayHandler::OnTooltip事件,这玩意我记得文档上也没说过,也没人说过如何处理这个事件。那我想就直接刚,手动在这里显示tooltips就行了,于是掏出以前的代码,下面是可以抄的作业。
HWND hTips = CreateWindowEx(WS_EX_TOPMOST,
TOOLTIPS_CLASS,
NULL,
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
hWnd,
NULL,
::GetModuleHandle(NULL),
NULL);
if(!hTips)
{
return NULL;
}
SetWindowPos(hTips, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
memset(&win_tooltipsinfo, 0, sizeof(TOOLINFO));
win_tooltipsinfo.cbSize = sizeof(TOOLINFO);
win_tooltipsinfo.uFlags = TTF_SUBCLASS;
win_tooltipsinfo.hwnd = hWnd;
win_tooltipsinfo.lpszText = _tcsdup(pText);
win_tooltipsinfo.uId = (UINT_PTR) hWnd;
GetClientRect(hWnd, &win_tooltipsinfo.rect);
SendMessage(hTips, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &win_tooltipsinfo);
free(win_tooltipsinfo.lpszText);
return hTips;
然后我发现这个tooltip并没有显示出来,接着又在https://docs.microsoft.com/en-us/windows/desktop/Controls/using-tooltip-contro这个页面上变着法的尝试了另外几种方法,此时我还是在怀疑创建tooltips的姿势不对。最终无果之后,我开始去测试是不是没调用InitCommonControlsEx,加上之后无果,于是接着又加上manifest,以下是作业
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
依然无果,这个时候已经一两点了,十分生气。然后我又翻了一些别的老项目代码,终于发现一个奇妙之处……结合之前在搜索结果里也看到有人提到过关于TOOLINFO结构大小不对导致SendMessage返回错误的情况,于是找到了如下代码
#if _WIN32_WINNT > 0x0500
win_tooltipsinfo.cbSize = sizeof(TOOLINFO) - sizeof(void *);
#else
win_tooltipsinfo.cbSize = sizeof(TOOLINFO);
#endif
typedef struct tagTOOLINFOA {
UINT cbSize;
UINT uFlags;
HWND hwnd;
UINT_PTR uId;
RECT rect;
HINSTANCE hinst;
LPSTR lpszText;
LPARAM lParam;
#if (NTDDI_VERSION >= NTDDI_WINXP)
void *lpReserved;
#endif
} TTTOOLINFOA, NEAR *PTOOLINFOA, *LPTTTOOLINFOA;
上面是TOOLINFO在VS2017头文件里的定义,按照常理来说我直接认为,我的SDK版本肯定是>=NTDDI_XP的,于是最后那个void *也就应该是需要算到cbSize里的。但是总之都是MS的复杂兼容性问题,或者保险起见可以直接把cbSize设置为TTTOOLINFO_V1_SIZE。现在tooltips终于正常显示了!
但是等一会!这个tooltip的样子怎么和我们平时见到的不太一致?看起来像是98时期的老古董。这个时候我的意识还算清醒,这是一个典型的exe manifest导致的问题,可是我在我的cef renderer程序的manifest里写了正确的信息呀?(参见上面的manifest),琢磨和尝试了好一会,然后我抱着试一试的心态,在我的主程序manifest也加上了这段信息……于是结果就正确了
这里我其实并没有完全理解,我的网页在cef渲染进程里显示,它是主进程的子进程,也就是说,主进程也必须要有正确的manifest才能让子进程得到正确的风格?总之新踩的坑又一次被填平了。
- [WCF REST] 解决资源并发修改的一个有效的手段:条件更新(Conditional Update)
- [WCF REST] 通过ASP.NET Output Caching实现声明式缓存
- [WCF REST] 通过ASP.NET Output Caching实现声明式缓存
- CentOS6.5下安装JDK
- 使用Maven插件构建SpringBoot项目,生成Docker镜像push到DockerHub上
- 开源API测试工具 Hitchhiker v0.8 - 自动化测试结果统计
- 腾讯AI-JavaAPI示例代码
- C++ 模板学习
- 小程序游戏上线!独家微信官方及专业核心解读!
- 零基础小白成为大数据技术专家必知的学习历程
- Wandelbots重新定义对机器人进行编程的方式
- 结构体字节对齐
- 中国IDC圈、科智咨询王若冰:从供到需——IDC产业的演进之路
- 本周网络空间态势摘要
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Mono for Android 下的 ListActivity
- 使用JavaScript Function.prototype进行代码重构的一些例子
- Activity 生命周期及其栈管理方式
- 如何操作SAP UI5应用Footer区域工具栏按钮的背景颜色
- 我的第一个 Mono for Android 应用
- 【DB笔试面试851】在Oracle中,造成“ORA-28040: No matching ...”错误的原因是什么?
- 在 Silverlight 5 项目中使用 async/await
- 开源一个 Sliverlight 导航框架
- 【DB笔试面试852】在Oracle中,什么是静默建库?
- 从 SVN 迁移到 Git
- 在 Windows 系统上配置 Apache Git 服务器
- WMCTF2020 部分Writeup&招新帖
- 【DB宝15】生产环境中,如何利用DG的备库来异机还原一个新库?
- Java命令执行学习笔记
- SAP UI5应用DatePicker控件的设计明细