在使用qml照搬某些界面时,需要选取某些svg图标或者颜色,使用ps有时会因为界面问题带来不方便,因而可以使用qt qml 和win32 api编写建议的辅助类。
Project.pro里添加opencv和win32 api相应配置
...
QT += svg
...
# opencv opencv配置
win32:CONFIG(release, debug|release): LIBS += -LD:/opencv/build/x64/vc15/lib/ -lopencv_world410
else:win32:CONFIG(debug, debug|release): LIBS += -LD:/opencv/build/x64/vc15/lib/ -lopencv_world410d
else:unix: LIBS += -LD:/opencv/build/x64/vc15/lib/ -lopencv_world410
INCLUDEPATH += D:/opencv/build/include
INCLUDEPATH += D:/opencv/build/include/opencv2
DEPENDPATH += D:/opencv/build/include
unix: CONFIG += link_pkgconfig
unix: PKGCONFIG += /usr/local/lib/pkgconfig/opencv4.pc
win32:LIBS += -lUser32 -lgdi32
在win32helper.h里添加
#ifndef WIN32HELPER_H
#define WIN32HELPER_H
#include <QColor>
#include <QImage>
#include <QObject>
#include <QPainter>
#include <QPointF>
#include <QSvgRenderer>
namespace ld {
class Win32Helper : public QObject
{
Q_OBJECT
public:
explicit Win32Helper(QObject *parent = nullptr);
Q_INVOKABLE QPoint getCursorPosition(); // 获取光标位置
Q_INVOKABLE QColor getPixelColor(int x, int y); // 获取坐标(x,y)的颜色
Q_INVOKABLE void captureSvg(const QString &filePath = "output.svg", QSize size = QSize(32,32)); // 截取当前光标为中心的size为尺寸的svg图标 存为filePath文件
signals:
};
}
#endif // WIN32HELPER_H
win32helper.cpp里添加实现
#include "win32helper.h"
#include <QSvgGenerator>
#include <windows.h>
#include <opencv.hpp>
#include "ImageUtil.h"
using namespace ld;
Win32Helper::Win32Helper(QObject *parent) : QObject(parent)
{
}
QPoint ld::Win32Helper::getCursorPosition()
{
POINT point;
GetCursorPos(&point);
return QPoint(point.x, point.y);
}
QColor ld::Win32Helper::getPixelColor(int x, int y)
{
HDC hdc = GetDC(NULL);
COLORREF color = GetPixel(hdc, x, y);
ReleaseDC(NULL, hdc);
return QColor(GetRValue(color), GetGValue(color), GetBValue(color));
}
void Win32Helper::captureSvg(const QString &filePath, QSize size)
{
int width = size.width();
int height = size.height();
HDC hdcWindow = GetDC(NULL);
HDC hdcMemDC = CreateCompatibleDC(hdcWindow);
HBITMAP hBitmap = CreateCompatibleBitmap(hdcWindow, width, height);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMemDC, hBitmap);
POINT point;
GetCursorPos(&point);
int x = point.x;
int y = point.y;
BitBlt(hdcMemDC, 0, 0, width, height, hdcWindow, x - width/2, y - height/2, SRCCOPY);
QImage image = QImage(width, height, QImage::Format_ARGB32);
image.fill(Qt::transparent);
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = width;
bi.biHeight = -height; // top-down
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
GetDIBits(hdcMemDC, hBitmap, 0, height, image.bits(), (BITMAPINFO*)&bi, DIB_RGB_COLORS);
SelectObject(hdcMemDC, hOldBitmap);
DeleteObject(hBitmap);
DeleteDC(hdcMemDC);
// ReleaseDC(hwnd, hdcWindow);
// Convert QImage to QPixmap
// QPixmap pixmap = QPixmap::fromImage(image);
QPixmap pixmap;
image.convertToFormat(QImage::Format_Grayscale8);
// QImage mirroredImage = image.mirrored(false, true); // 水平翻转
// cv::Mat mat = imageToMat(image);
// cv::Canny(mat, mat, 10,20); // 需要注意cv::Canny处理的是灰度图像
// pixmap = QPixmap::fromImage(matToImage(mat));
pixmap = QPixmap::fromImage(image);
// Convert QPixmap to SVG
QSvgGenerator svgGenerator;
svgGenerator.setFileName(filePath);
svgGenerator.setSize(pixmap.size());
svgGenerator.setViewBox(pixmap.rect());
svgGenerator.setTitle("Window Capture");
svgGenerator.setDescription("Captured image from window at mouse position");
QPainter painter;
painter.begin(&svgGenerator);
painter.drawPixmap(0, 0, pixmap);
painter.end();
}
这里保存的是灰度svg, 有时由于图片格式等问题需要注意使用水平翻转获取真实图片。
在qml里使用透明的窗体和键盘事件来获取当前光标位置和颜色,以及截取附近的图标。