编程与调试 C++ -- Qt 动态加载图片资源文件(资源文件与源代码分离)

Qt QResource 配合 rcc 命令,资源文件与源码分离,可以挂载多个资源,存在优先级,先加进去 de 先检索到。

使用 rcc 命令将 resource.qrc 生成 .rcc 二进制文件。

rcc --binary resource.qrc -o skin.rcc # Windows
rcc -binary resource.qrc -o skin.rcc # Linux
QResource::registerResource(qApp->applicationDirPath() + "/skin/skin.rcc");
QFile file(":/qss/stylesheet");
if (file.open(QFile::ReadOnly))
{
    QString strStyleSheet = file.readAll();
    file.close();
    qApp->setStyleSheet(strStyleSheet);
}

QResource::unregisterResource();
bool QResource::registerResource(const QString& rccFilename, const QString& resourceRoot)
{
    QString r = qt_resource_fixResourceRoot(resourceRoot);
    if (!r.isEmpty() && r[0] != QLatin1Char('/'))
    {
        qWarning("QDir::registerResource: Registering a resource [%s] must be rooted in an absolute path (start  with /) [%s]",
            rccFilename.toLocal8Bit().data(), resourceRoot.toLocal8Bit().data());
        return false;
    }

    QDynamicFileResourceRoot* root = new QDynamicFileResourceRoot(r);
    if (root->registerSelf(rccFilename))
    {
        root->ref.ref();
        QMutexLocker lock(resourceMutex());
        resourceList()->append(root);
        return true;
    }
    delete root;
    return false;
}

bool QResource::unregisterResource(const QString& rccFilename, const QString& resourceRoot)
{
    QString r = qt_resource_fixResourceRoot(resourceRoot);

    QMutexLocker lock(resourceMutex());
    ResourceList* list = resourceList();
    for (int i = 0; i < list->size(); ++i)
    {
        QResourceRoot* res = list->at(i);
        if (res->type() == QResourceRoot::Resource_File)
        {
            QDynamicFileResourceRoot* root = reinterpret_cast<QDynamicFileResourceRoot*>(res);
            if (root->mappingFile() == rccFilename && root->mappingRoot() == r)
            {
                resourceList()->removeAt(i);
                if (!root->ref.deref())
                {
                    delete root;
                    return true;
                }
                return false;
            }
        }
    }
    return false;
}

dll 模块资源文件

编译成静态 lib,就需要自己调用一下;编译成动态 dll,就自动被调用了。

fastvceng::initResources(bDebug);
fastvcwidget::initResources(bDebug);
#pragma once

#include <QtCore/qglobal.h>

#ifndef FASTVCWIDGET_STATIC
# if defined(FASTVCWIDGET_LIB)
#  define FASTVCWIDGET_EXPORT Q_DECL_EXPORT
# else
#  define FASTVCWIDGET_EXPORT Q_DECL_IMPORT
# endif
#else
# define FASTVCWIDGET_EXPORT
#endif
#pragma once

#include "fastvcwidget_global.h"

class FASTVCWIDGET_EXPORT fastvcwidget
{
public:
    fastvcwidget();

    static void initResources(bool debug);

    static bool isDebug() { return m_debug; }

private:
    static bool m_debug;
};
#include "fastvcwidget.h"

fastvcwidget::fastvcwidget()
{
}

bool fastvcwidget::m_debug = false;

void fastvcwidget::initResources(bool debug) {
    m_debug = debug;
    Q_INIT_RESOURCE(fastvcwidget);
}

namespace {
    struct ResourceLoader {
    public:
        ResourceLoader() { fastvcwidget::initResources(
#ifdef _DEBUG
            1
#else
            0
#endif
        ); }
    } fastvcwidget_ResourceLoader;
}

直接 exe 构建的情况

#include "qtest.h"

qtest::qtest(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    // 都包含 ":/qtest/image.png"
    Q_CLEANUP_RESOURCE(qtest_default);
    Q_CLEANUP_RESOURCE(qtest_usen);
    Q_CLEANUP_RESOURCE(qtest_zhcn);

    // 多个图片素材包,先放进去的先检索到。
    //Q_INIT_RESOURCE(qtest_zhcn); // 柠檬
    Q_INIT_RESOURCE(qtest_usen); // 石头
    Q_INIT_RESOURCE(qtest_default); // 橙子

    QImage myImage;
    bool temp = myImage.load(":/qtest/image.png");
    ui.imageLabel->setPixmap(QPixmap::fromImage(myImage));
}

工程默认配置多个 qrc: resource.qrc,resource_usen.qrc,resource_zhcn.qrc。 根据国内版还是国外版,合理安排它们的顺序,就可以保证同样的路径,检索到不同的图片文件。

会生成多个源文件: rcc/qrc_resource.cpp、rcc/qrc_resource_usen.cpp、rcc/qrc_resource_zhcn.cpp。

void QMainClient::InitEnvironment() {

    // 资源文件国际化
    Q_CLEANUP_RESOURCE(resource);
    Q_CLEANUP_RESOURCE(resource_usen);
    Q_CLEANUP_RESOURCE(resource_zhcn);
    // 多个图片素材包,先放进去的先检索到。
    if (IsInternationEdition()) {
        Q_INIT_RESOURCE(resource_usen);
        Q_INIT_RESOURCE(resource);
    } else {
        Q_INIT_RESOURCE(resource_zhcn);
        Q_INIT_RESOURCE(resource);
    }
}

Qt 资源解析

from

qrc_resource.cpp

qt_resource_data qt_resource_name qt_resource_struct

逆向破解分析 Hacking Tools 搜罗大集合(上) Hacking Tools 搜罗大集合(下)


参考资料快照
参考资料快照

本文短链接:
If you have any questions or feedback, please reach out .