基于Qt的桌面镜面翻转程序

windows桌面可以横向、纵向翻转显示桌面,但是不能对屏幕进行镜像翻转,当然基本上也不会有人有这种奇怪的需求。UltraMon可以实现这个功能,在扩展屏上镜像覆盖主屏幕,此外,这个软件本身也有很多很强大的功能。但是在主屏幕缩放比例超过100%时会无法正确显示,每次使用的时候都重新设置一下分辨率和缩放比例显得还是有些奇怪了。 于是自己写了一个基于Qt的镜像翻转桌面的小程序,基本的原理就是捕获主屏幕的画面,将图像镜像翻转后显示在窗口内。 如果想直接下载使用可以参考github页面下载链接。

看看效果先: 扩展模式的双屏幕示例,右下为主屏幕,左上为扩展屏幕

捕获窗口

QPixmap QScreen::grabWindow(WId window = 0, int x = 0, int y = 0, int width = -1, int height = -1)可以实现指定句柄的窗口捕获,但是美中不足的是没有办法捕获到鼠标。 函数grW(HWND winId, int x, int y, int w, int h)参考附录1,实现了捕获桌面的同时也捕获鼠标,在使用时需要在Qt的设置中添加winextras组件。 winId是窗口句柄,获取主桌面的句柄可以借助以下语句实现:

	screen = QGuiApplication::primaryScreen();

获取窗口后,将图像进行镜面翻转后再嵌入窗口中,这个功能可能借助Qt自带的QImage QImage::mirrored(bool horizontal = false, bool vertical = true)函数实现,两个参数分别为水平方向和垂直方向的翻转与否。

定时触发

搞定了桌面和鼠标捕获,其实基本上就完成了主要工作,接下来只要设置一个定时器实时触发桌面捕获和显示的槽函数就可以了。

	connect(timer, SIGNAL(timeout()), this, SLOT(timeoutSlot()));
	timer->start(2);

定时器的触发间隔看需求了,虽然代码里设置了2毫秒,实际上也达不到这么快的速度,考虑到只在本地执行,也没有加上缓存区存储图像。

全屏切换

毕竟是用窗口覆盖了桌面,在显示的时候还是全屏遮盖掉其他应用和任务栏比较好,重构一下鼠标双击事件:

void screenRelayer::mouseDoubleClickEvent(QMouseEvent* mouseEvent)
{
	//showFlag为标志位
	if (showFlag) {
		this->showFullScreen();
		showFlag = false;
	}
	else {
		this->showNormal();
		showFlag = true;
	}
}

这样就可以在窗口内通过双击鼠标切换全屏和窗口了。

附录

  1. 窗口捕获函数实现1

     QPixmap screenRelayer::grW(HWND winId, int x, int y, int w, int h)
     {
    
         RECT r;
         GetClientRect(winId, &r);
    
         if (w < 0) w = r.right - r.left;
         if (h < 0) h = r.bottom - r.top;
    
         HDC display_dc = GetDC(winId);
         HDC bitmap_dc = CreateCompatibleDC(display_dc);
         HBITMAP bitmap = CreateCompatibleBitmap(display_dc, w, h);
         HGDIOBJ null_bitmap = SelectObject(bitmap_dc, bitmap);
    
         BitBlt(bitmap_dc, 0, 0, w, h, display_dc, x, y, SRCCOPY | CAPTUREBLT);
    
         CURSORINFO ci;
         ci.cbSize = sizeof(CURSORINFO);
         GetCursorInfo(&ci);
         if ((ci.ptScreenPos.x > x) && (ci.ptScreenPos.y > y) && (ci.ptScreenPos.x < (x + w)) && (ci.ptScreenPos.y < (y + h)))
             DrawIcon(bitmap_dc, ci.ptScreenPos.x - x, ci.ptScreenPos.y - y, ci.hCursor);
    
         // clean up all but bitmap
         ReleaseDC(winId, display_dc);
         SelectObject(bitmap_dc, null_bitmap);
         DeleteDC(bitmap_dc);
    
         QPixmap pixmap = QtWin::fromHBITMAP(bitmap);
    
         DeleteObject(bitmap);
    
         return pixmap;
     }
    
  2. 链接: https://github.com/Braised-Lamb/screenRelayer 软件下载

    参考


「访客留言」:

本站总访问量次 本文总阅读量