背景
最近在做一个软件,需要截图功能,遇到一个问题。由于windows系统缩放问题,比如在125%的缩放下,程序渲染的分辨率会比实际显示器分辨率低。
// 这里通过获取整个屏幕,并将屏幕保存为一个pixmap
void CaptureScreen::loadBackgroundPixmap() {
QScreen *screen = QGuiApplication::primaryScreen();
if (const QWindow *window = windowHandle())
screen = window->screen();
m_loadPixmap = screen->grabWindow(0);
m_screenwidth = m_loadPixmap.width();
m_screenheight = m_loadPixmap.height();
qDebug() << "screen_w:" << m_screenwidth << " " << "screen_h:" << m_screenheight;
}
// 这里绘制截图界面
void CaptureScreen::paintEvent(QPaintEvent *event) {
m_painter.begin(this); //进行重绘;
QColor shadowColor = QColor(0, 0, 0, 100); //阴影颜色设置;
m_painter.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap)); //设置画笔;
m_painter.drawPixmap(0, 0, m_loadPixmap); //将背景图片画到窗体上;
m_painter.fillRect(m_loadPixmap.rect(), shadowColor); //画影罩效果;
if (m_isMousePress) {
QRect selectedRect = getRect(m_beginPoint, m_endPoint);
m_capturePixmap = m_loadPixmap.copy(selectedRect);
m_painter.drawPixmap(selectedRect.topLeft(), m_capturePixmap);
m_painter.drawRect(selectedRect);
qDebug() << "selectedRect:" << selectedRect;
}
qDebug() << "m_loadPixmap.rect()" << m_loadPixmap.rect() << " : " << this->size();
}
实现效果如下:
可以发现截取区域显示已经错位了,
其中
qDebug() << "m_loadPixmap.rect()" << m_loadPixmap.rect() << " : " << this->size();
打印出来的结果是
可以看到,通过截取屏幕获得的大小,为2560x1440,这是我屏幕分辨率,也是系统桌面渲染分辨率,而2048x1152 则是 CaptureScreen这个QDialog的实际显示大小,注意,CaptureScreen为全屏显示。
处理方法
那应该怎么做?由于截图软件需要有线保障截图的清晰度,所以建议,将控件坐标映射到屏幕分辨率。
增加两个映射函数
QPoint CaptureScreen::to_screen_point(QPoint p) {
int x = (p.x() * 1.0 / this->size().width()) * m_screenwidth;
int y = (p.y() * 1.0 / this->size().height()) * m_screenheight;
return QPoint(x, y);
}
QSize CaptureScreen::to_screen_size(QSize s) {
int w = (s.width() * 1.0 / this->size().width()) * m_screenwidth;
int h = (s.height() * 1.0 / this->size().height()) * m_screenheight;
return QSize(w, h);
}
绘画处改成这样:
if (m_isMousePress) {
QRect selectedRect = getRect(m_beginPoint, m_endPoint);
auto pix_rel_topleft = to_screen_point(selectedRect.topLeft());
auto pix_rel_size = to_screen_size(selectedRect.size());
QRect pix_rel_rect(pix_rel_topleft, pix_rel_size);
qDebug() << "selectedRect" << selectedRect << " to pix_rel_rect" << pix_rel_rect;
m_capturePixmap = m_loadPixmap.copy(pix_rel_rect);
m_painter.drawPixmap(selectedRect.topLeft(), m_capturePixmap);
m_painter.drawRect(selectedRect);
}
效果如图:
总结
如果能后很好的区分不同层级的渲染分辨率,这个问题还是很好解决的。