QCefView icon indicating copy to clipboard operation
QCefView copied to clipboard

高dpi下cefveiw显示问题

Open WilliamZhangZhe opened this issue 7 years ago • 18 comments

您好,我这边有在高dpi下(dpi = 126 等等)使用cefview显示网页,显示的网页的窗口大小与实际窗口大小不符,会出现3/4的区域为空白或者透明,请问是什么问题呢?我已启用qt的高dpi显示设置(Application::setAttribute(Qt::AA_EnableHighDpiScaling);) image

WilliamZhangZhe avatar Jan 22 '18 13:01 WilliamZhangZhe

@WilliamZhangZhe QCefView主要解决的一个问题是native的CEF窗口和Qt窗口的融合问题,关键部件是QCefWindow

融合的方法并不是简单的把CEF的native窗口作为child添加到QCefWindow,虽然他们具有父子关系,但是CEF的native窗口的绘制并没有交给QCefWindow去管理,QCefWindow只负责把CEF的native窗口实时的移动到QCefWindows的client区域(大小,位置等)。这个过程是获取到QCefWindow的size,然后利用MoveWindow去设置CEF的native窗口。

我还没有去重现这个问题,但是我猜想应该是,Qt启用了DPI缩放,但是通过size函数获取到的QCefWindow的宽和高的数值仍然是没有经过缩放因子处理的数值。

解决这个问题的思路: 1.获取当前Qt窗口的缩放因子scale

然后有两种处理方法: 1.获取QCefWindow的size数值然后 newHeight = height * scale,newWidth = width * scale, 然后用这个newHeight和newWidth去调整CEF的natvice窗口的大小。 这种方法有个问题,Qt窗口显示的内容是经过缩放的,可是CEF的内容是没有缩放的,两部分比例不一致,会不会怪怪的?

  1. 直接对CEF的native窗口应用缩放因子scale,这里通过Windows API 或者 CEF 提供的API ?

希望对你有帮助,我有空的时候会尝试调试下

tishion avatar Jan 23 '18 05:01 tishion

hi,非常感谢您的回复,我这边测试情况是cef在默认情况下是应用缩放的,如果想要关闭可以添加“--high-dpi-support=1 --force-device-scale-factor=1”运行参数,(亦可通过CefEnableHighDPISupport启用),您回复的关于navie窗口适应dpi缩放的qt窗口的方案一正是我所遇到问题的解决方案,非常感谢!!

WilliamZhangZhe avatar Jan 23 '18 06:01 WilliamZhangZhe

我也遇到同样问题,能否分享下解决代码;另我想升级到CEF 3.3239 X64,部分接口已过时,API找到有替代方法不大会用,惭愧。。

liulinhere avatar Jan 25 '18 05:01 liulinhere

你按照tishion所提及的解决办法修改即可,(1.获取QCefWindow的size数值然后 newHeight = height * scale,newWidth = width * scale, 然后用这个newHeight和newWidth去调整CEF的natvice窗口的大小)这个是我应用的方案,在CCefwindow.cpp 中依据当前系统的dpi scale value 修改updateCefBrowserWindow内的窗口大小设置即可

WilliamZhangZhe avatar Jan 25 '18 05:01 WilliamZhangZhe

感谢,我按您的方法尝试下。在VS2015里,CCefwindow.cpp没包含在include的头文件项目里,把它忽略了;

liulinhere avatar Jan 25 '18 07:01 liulinhere

demo 设置放大比例好,出现了一些新的情况,1. 当鼠标移入网页区域,会出现一个小网页;2. 当窗口缩很小后,大的区域不见了,只有很小的网页区。

liulinhere avatar Jan 25 '18 09:01 liulinhere

@liulinhere 把你修改的代码贴出来一下

tishion avatar Jan 25 '18 10:01 tishion

@liulinhere , 你得qcefwing的编译清单文件选项上添加上“高dpi支持”

WilliamZhangZhe avatar Jan 25 '18 10:01 WilliamZhangZhe

William 能否把你的修改提交一个pr?

Get Outlook for Androidhttps://aka.ms/ghei36


From: WilliamZhangZhe [email protected] Sent: Thursday, January 25, 2018 7:02:43 PM To: tishion/QCefView Cc: Sheen Tian; Comment Subject: Re: [tishion/QCefView] 高dpi下cefveiw显示问题 (#32)

Reopened #32https://github.com/tishion/QCefView/issues/32.

― You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/tishion/QCefView/issues/32#event-1441402481, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AFmRcmI36KxWkj1k62eXZ_8SEip7WSSFks5tOF9TgaJpZM4Rm4-Q.

tishion avatar Jan 25 '18 11:01 tishion

我的解决办法是: 步骤一:设置目标运行程序支持高dpi 方法1:vs可通过 工程右键 > 属性 > 清单工具 > 输入和输出 > DPI识别功能 > 高DPI识别 方法2:Qt可以添加环境变量qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", QByteArray("1"));实现 方法3:Qt可以通过QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);实现 注意:方法2和方法3需要在QApplication初始化前完成

步骤二:设置qcefwing工程和QCefViewTest工程支持高dpi

步骤三:添加获取系统dpi-scale 的接口代码,例如我的是 #include <Windows.h> #include <math.h> const float DEFAULT_DPI = 96.0; float windowsDpiScaleX() { HDC screen = CreateDC(L"DISPLAY", NULL, NULL, NULL);/GetDC(0)/; FLOAT dpiX = static_cast<FLOAT>(GetDeviceCaps(screen, LOGPIXELSX)); ReleaseDC(0, screen); return dpiX / DEFAULT_DPI; }

float windowsDpiScaleY() { HDC screen = CreateDC(L"DISPLAY", NULL, NULL, NULL);/GetDC(0)/; FLOAT dpiY = static_cast<FLOAT>(GetDeviceCaps(screen, LOGPIXELSY)); ReleaseDC(0, screen); return dpiY / DEFAULT_DPI; }

步骤四:修改QCefWindow.cpp下的 updateCefBrowserWindow()实现如下: void CCefWindow::updateCefBrowserWindow() { if (!hwndCefBrowser_) hwndCefBrowser_ = ::FindWindowExA((HWND)winId(), nullptr, CEF_BROWSER_WINDOW_CLASS_NAME_A, nullptr);

int dpi_x_scale = round(windowsDpiScaleX()); int dpi_y_scale = round(windowsDpiScaleY());

if (hwndCefBrowser_)
	::MoveWindow(hwndCefBrowser_, 0, 0, width() * dpi_x_scale, height() * dpi_y_scale, TRUE);

}

以上是我的具体的实现方法,希望可以帮到你 @liulinhere

WilliamZhangZhe avatar Jan 25 '18 11:01 WilliamZhangZhe

我选择round的方式是因为在windows平台下实测125%实际会按照100%的比例放大,150% 175% 200% 实际会按照200%放大,不知道其他平台是否也是这样

WilliamZhangZhe avatar Jan 25 '18 11:01 WilliamZhangZhe

是的,QT的理解是四舍五入,4K,WIN10默认是250%,QT为3。 修改的地方,直接在:CCefWindow.cpp,updateCefBrowserWindow里, `void CCefWindow::updateCefBrowserWindow() { if (!hwndCefBrowser_) hwndCefBrowser_ = ::FindWindowExA((HWND)winId(), nullptr, CEF_BROWSER_WINDOW_CLASS_NAME_A, nullptr);

if (hwndCefBrowser_) {		
	HDC hdc = GetDC(hwndCefBrowser_);
	int ppix = GetDeviceCaps(hdc, LOGPIXELSX);
	int ppiy = GetDeviceCaps(hdc, LOGPIXELSY);
	ReleaseDC(hwndCefBrowser_, hdc);

	cout << "ppix:"<< ppix<<endl;
	cout << "ppiy:" << ppiy << endl;
	
	
	float scale = roundf((float)ppix / 96);
	cout << "scale:" << scale << endl;
	
	::MoveWindow(hwndCefBrowser_, 0, 0, width()*scale, height()*scale, TRUE);		
}		

}`

liulinhere avatar Jan 25 '18 11:01 liulinhere

QCefViewTest.zip

放上 QCefViewSDK 试下,VS2015 X86+QT5.9.3

liulinhere avatar Jan 25 '18 11:01 liulinhere

33

  1. 当不启用放缩的情况下,这两个边线怎么不知道哪来的?
  2. 启用放缩后,再到控制面板改放缩比,取出来还是一样的,会撑出去;
  3. qcefwing我没改过清单文件,是不是这儿有问题?

liulinhere avatar Jan 25 '18 11:01 liulinhere

33

  1. 当不启用放缩的情况下,这两个边线怎么不知道哪来的?
  2. 启用放缩后,再到控制面板改放缩比,取出来还是一样的,会撑出去;
  3. qcefwing我没改过清单文件,是不是这儿有问题?

请问您这个问题解决了么

bairutai avatar Jan 06 '20 02:01 bairutai

我的解决办法是: 步骤一:设置目标运行程序支持高dpi 方法1:vs可通过 工程右键 > 属性 > 清单工具 > 输入和输出 > DPI识别功能 > 高DPI识别 方法2:Qt可以添加环境变量qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", QByteArray("1"));实现 方法3:Qt可以通过QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);实现 注意:方法2和方法3需要在QApplication初始化前完成

步骤二:设置qcefwing工程和QCefViewTest工程支持高dpi

步骤三:添加获取系统dpi-scale 的接口代码,例如我的是 #include <Windows.h> #include <math.h> const float DEFAULT_DPI = 96.0; float windowsDpiScaleX() { HDC screen = CreateDC(L"DISPLAY", NULL, NULL, NULL);/GetDC(0)/; FLOAT dpiX = static_cast(GetDeviceCaps(screen, LOGPIXELSX)); ReleaseDC(0, screen); return dpiX / DEFAULT_DPI; }

float windowsDpiScaleY() { HDC screen = CreateDC(L"DISPLAY", NULL, NULL, NULL);/GetDC(0)/; FLOAT dpiY = static_cast(GetDeviceCaps(screen, LOGPIXELSY)); ReleaseDC(0, screen); return dpiY / DEFAULT_DPI; }

步骤四:修改QCefWindow.cpp下的 updateCefBrowserWindow()实现如下: void CCefWindow::updateCefBrowserWindow() { if (!hwndCefBrowser_) hwndCefBrowser_ = ::FindWindowExA((HWND)winId(), nullptr, CEF_BROWSER_WINDOW_CLASS_NAME_A, nullptr);

int dpi_x_scale = round(windowsDpiScaleX()); int dpi_y_scale = round(windowsDpiScaleY());

if (hwndCefBrowser_)
	::MoveWindow(hwndCefBrowser_, 0, 0, width() * dpi_x_scale, height() * dpi_y_scale, TRUE);

}

以上是我的具体的实现方法,希望可以帮到你 @liulinhere

为什么我用这种方法做了,网页有时显示 有时不显示。。

bairutai avatar Jan 06 '20 07:01 bairutai

我选择round的方式是因为在windows平台下实测125%实际会按照100%的比例放大,150% 175% 200% 实际会按照200%放大,不知道其他平台是否也是这样

125%不缩放这个问题似乎是Chromium的BUG,详见 https://bugs.chromium.org/p/chromium/issues/detail?id=410696

phiysng avatar Oct 27 '20 11:10 phiysng

不是chrome的,是qt5.9的版本对文本缩放的支持只能是整数倍,会四舍五入,5.12后开始支持小数倍 https://bbs.huaweicloud.com/blogs/137316 官方文档也有说明,链接可以查一下

oopses avatar Oct 27 '20 14:10 oopses