QMLアプリケーションにおけるWindowsシステム情報取得手法

QMLアプリケーション開発時に、システムのカラー情報やアイコンを取得する必要がある場合、Win32 APIを活用することで効率的に実装できます。

プロジェクト設定ファイルに必要なライブラリを追加します。

QT += svg gui

# Windows API設定
win32:LIBS += -lUser32 -lgdi32

# OpenCV設定
win32:CONFIG(release, debug|release): {
    LIBS += -L$$PWD/opencv/lib -lopencv_core451
    INCLUDEPATH += $$PWD/opencv/include
}
win32:CONFIG(debug, debug|release): {
    LIBS += -L$$PWD/opencv/lib -lopencv_core451d
    INCLUDEPATH += $$PWD/opencv/include
}

ヘルパークラスのインターフェース定義:

#ifndef SYSTEM_UTILITY_H
#define SYSTEM_UTILITY_H

#include <QObject>
#include <QColor>
#include <QPoint>
#include <QSize>

class SystemUtility : public QObject
{
    Q_OBJECT
public:
    explicit SystemUtility(QObject* parent = nullptr);

    Q_INVOKABLE QPoint getMousePosition() const;
    Q_INVOKABLE QColor getScreenColor(int x, int y) const;
    Q_INVOKABLE void saveCursorIcon(const QString& path, 
                                  const QSize& size = QSize(32, 32)) const;
};

#endif // SYSTEM_UTILITY_H

実装クラス:

#include "systemutility.h"
#include <windows.h>
#include <QSvgGenerator>
#include <QPainter>
#include <QPixmap>

SystemUtility::SystemUtility(QObject* parent) : QObject(parent) {}

QPoint SystemUtility::getMousePosition() const
{
    POINT cursorPos;
    GetCursorPos(&cursorPos);
    return QPoint(cursorPos.x, cursorPos.y);
}

QColor SystemUtility::getScreenColor(int x, int y) const
{
    HDC dc = GetDC(nullptr);
    COLORREF color = GetPixel(dc, x, y);
    ReleaseDC(nullptr, dc);
    return QColor(GetRValue(color), GetGValue(color), GetBValue(color));
}

void SystemUtility::saveCursorIcon(const QString& path, const QSize& size) const
{
    const int width = size.width();
    const int height = size.height();
    
    HDC screenDC = GetDC(nullptr);
    HDC memDC = CreateCompatibleDC(screenDC);
    HBITMAP bitmap = CreateCompatibleBitmap(screenDC, width, height);
    HBITMAP oldBitmap = static_cast<HBITMAP>(SelectObject(memDC, bitmap));
    
    POINT cursorPos;
    GetCursorPos(&cursorPos);
    BitBlt(memDC, 0, 0, width, height, screenDC, 
          cursorPos.x - width/2, cursorPos.y - height/2, SRCCOPY);
    
    QImage image(width, height, QImage::Format_ARGB32);
    BITMAPINFO bmi = {0};
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = -height;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;
    
    GetDIBits(memDC, bitmap, 0, height, 
             image.bits(), &bmi, DIB_RGB_COLORS);
    
    SelectObject(memDC, oldBitmap);
    DeleteObject(bitmap);
    DeleteDC(memDC);
    ReleaseDC(nullptr, screenDC);
    
    QSvgGenerator svg;
    svg.setFileName(path);
    svg.setSize(size);
    svg.setViewBox(QRect(0, 0, width, height));
    
    QPainter painter;
    painter.begin(&svg);
    painter.drawImage(0, 0, image);
    painter.end();
}

QMLからは以下のように利用できます:

SystemUtility {
    id: systemUtil
}

// マウス位置取得
var pos = systemUtil.getMousePosition();

// 画面色取得
var color = systemUtil.getScreenColor(100, 200);

// アイコン保存
systemUtil.saveCursorIcon("icon.svg");

タグ: QML win32 OpenCV SVG Qt

7月5日 00:17 投稿