SOUI入门

环境:win7_64旗舰版,VS2013

发现了一个比较好用的DirectUI库——SOUI,但是写一个窗口程序不是很方便,程序初始化的地方稍显繁琐,这里稍微封装一下。

大概包含6个文件:

SouiConfig.h:负责SOUI的配置,包括导入动态库,定义SOUI系统资源名称等。

#ifndef _SOUI_CONFIG_
#define _SOUI_CONFIG_

#ifdef _DEBUG
#define SYS_NAMED_RESOURCE _T("soui-sys-resourced.dll")
#pragma comment(lib, "souid.lib")
#pragma comment(lib, "utilitiesd.lib")
#else
#define SYS_NAMED_RESOURCE _T("soui-sys-resource.dll")
#pragma comment(lib, "soui.lib")
#pragma comment(lib, "utilities.lib")
#endif // _DEBUG

#define DLL_SOUI

#endif
View Code

SouiInclude.h:负责包含SOUI的头文件。

#ifndef _SOUI_INCLUDE_H_
#define _SOUI_INCLUDE_H_

#include "SouiConfig.h"
#include "souistd.h"
#include "core/SHostDialog.h"
#include "control/SMessageBox.h"
#include "control/souictrls.h"
#include "com-cfg.h"

using namespace SOUI;

#endif
View Code

SouiApp类:负责SOUI应用程序初始化,包括设置资源路径,初始化渲染引擎,初始化OLE和消息循环。

SouiApp.h

#ifndef _SOUI_APP_H_
#define _SOUI_APP_H_

#include <string>
#include "SouiInclude.h"

class SouiApp {
public:
    SouiApp() : m_initOle(false), m_app(NULL) {
    }
    ~SouiApp();

public:
    // 初始化OLE
    void initOle();
    // 初始化应用程序
    void initApp(HINSTANCE hInstance);
    // 消息循环
    void run(SHostWnd& mainWnd) { m_app->Run(mainWnd.m_hWnd); }

public: // 属性设置
    // 获取当前应用程序路径
    std::wstring getAppPath() const;
    // 设置资源路径
    void setResPath(const std::wstring& path);

private:
    // 初始化渲染工厂
    CAutoRefPtr<SOUI::IRenderFactory> initRenderFactory();
    // 初始化语言翻译管理器
    CAutoRefPtr<SOUI::ITranslatorMgr> initTranslator(const std::wstring& path);
    // 初始化自定义资源
    CAutoRefPtr<IResProvider> initResProvider(HINSTANCE hInstance, const std::wstring& path);
    // 初始化系统资源
    CAutoRefPtr<IResProvider> initSysResource();

private:
    bool            m_initOle;    // 初始化OLE
    std::wstring    m_resPath;    // 资源路径

    SComMgr            m_comMgr;    // SOUI组件配置
    SApplication*    m_app;        // SOUI应用程序类
};

#endif
View Code

SouiApp.cpp

#include <windows.h>
#include "SouiApp.h"

SouiApp::~SouiApp()
{
    delete m_app;
    m_app = NULL;

    if (m_initOle) {
        ::OleUninitialize();
    }
}

void SouiApp::initOle()
{
    SASSERT(!m_initOle);
    HRESULT hRes = ::OleInitialize(NULL);
    SASSERT(SUCCEEDED(hRes));
    m_initOle = true;
}

void SouiApp::initApp(HINSTANCE hInstance)
{
    try
    {
        SASSERT(!m_app);
        // 初始化渲染工厂
        CAutoRefPtr<SOUI::IRenderFactory> renderFactory = initRenderFactory();
        if (!renderFactory) {
            throw std::runtime_error("init render factory faild!");
        }
        m_app = new SApplication(renderFactory, hInstance);

        // 初始化语言翻译管理器
        CAutoRefPtr<SOUI::ITranslatorMgr> trans = initTranslator(m_resPath + L"\translator\lang_cn.xml");
        if (!trans) {
            throw std::runtime_error("init translator faild!");
        }
        m_app->SetTranslator(trans);

        // 初始化自定义资源
        CAutoRefPtr<IResProvider> resProvider = initResProvider(hInstance, m_resPath);
        if (!resProvider) {
            throw std::runtime_error("init resource faild!");
        }
        m_app->AddResProvider(resProvider);

        // 初始化系统资源
        CAutoRefPtr<IResProvider> sysResProvider = initSysResource();
        if (!sysResProvider) {
            throw std::runtime_error("init system resource faild!");
        }
        m_app->LoadSystemNamedResource(sysResProvider);

        m_app->Init(L"XML_INIT");
    }
    catch (std::runtime_error&)
    {
    }
}

std::wstring SouiApp::getAppPath() const
{
    std::wstring path(MAX_PATH, L'');
    DWORD dw = ::GetModuleFileName(NULL, &path[0], path.length());
    path.resize(dw);

    path = path.substr(0, path.rfind(L"\"));
    return path;
}

void SouiApp::setResPath(const std::wstring& path)
{
    m_resPath = path;
    ::SetCurrentDirectory(m_resPath.c_str());
}

CAutoRefPtr<SOUI::IRenderFactory> SouiApp::initRenderFactory()
{
    CAutoRefPtr<SOUI::IRenderFactory> renderFactory;
    CAutoRefPtr<SOUI::IImgDecoderFactory> imgDecoderFactory;
    if (m_comMgr.CreateRender_GDI((IObjRef**)&renderFactory)
        && m_comMgr.CreateImgDecoder((IObjRef**)&imgDecoderFactory)) {
        renderFactory->SetImgDecoderFactory(imgDecoderFactory);
    }
    return renderFactory;
}

CAutoRefPtr<SOUI::ITranslatorMgr> SouiApp::initTranslator(const std::wstring& path)
{
    CAutoRefPtr<SOUI::ITranslatorMgr> trans;
    if (m_comMgr.CreateTranslator((IObjRef**)&trans)) {
        pugi::xml_document xmlLang;
        if (xmlLang.load_file(path.c_str())) {
            CAutoRefPtr<ITranslator> langCN;
            trans->CreateTranslator(&langCN);
            langCN->Load(&xmlLang.child(L"language"), 1);
            trans->InstallTranslator(langCN);
        }
    }
    return trans;
}

CAutoRefPtr<IResProvider> SouiApp::initResProvider(HINSTANCE hInstance, const std::wstring& path)
{
    const BUILTIN_RESTYPE res = RES_FILE;
    CAutoRefPtr<IResProvider> resProvider;
    CreateResProvider(res, (IObjRef**)&resProvider);
    if (res == RES_FILE) {
        if (!resProvider->Init((LPARAM)path.c_str(), 0))  {
            SASSERT(false);
        }
    }
    else if (res == RES_PE) {
        if (!resProvider->Init((WPARAM)hInstance, 0)) {
            SASSERT(false);
        }
    }
    return resProvider;
}

CAutoRefPtr<IResProvider> SouiApp::initSysResource()
{
    CAutoRefPtr<IResProvider> sysResProvider;
    HMODULE hSysResource = LoadLibrary(SYS_NAMED_RESOURCE);
    if (hSysResource) {
        CreateResProvider(RES_PE, (IObjRef**)&sysResProvider);
        sysResProvider->Init((WPARAM)hSysResource, 0);
    }
    return sysResProvider;
}
View Code

SouiWindow类:负责SOUI窗口。

SouiWindow.h

#ifndef _SOUI_WINDOW_H_
#define _SOUI_WINDOW_H_

#include "SouiInclude.h"

class SouiWindow : public SHostWnd {
public:
    SouiWindow(LPCTSTR pszResName) : SHostWnd(pszResName), m_bLayoutInited(false) {}
    virtual ~SouiWindow() {}

    // 创建
    void create(SouiWindow* window = NULL);
    // 居中显示
    void centerShow();
    // 显示
    void show();

protected:
    void OnClose() { DestroyWindow(); }
    void OnMaximize() { SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE); }
    void OnRestore() { SendMessage(WM_SYSCOMMAND, SC_RESTORE); }
    void OnMinimize() { SendMessage(WM_SYSCOMMAND, SC_MINIMIZE); }

    int OnCreate(LPCREATESTRUCT lpCreateStruct);
    void OnSize(UINT nType, CSize size);
    BOOL OnInitDialog(HWND hWnd, LPARAM lParam);

protected:
    EVENT_MAP_BEGIN()
        EVENT_NAME_COMMAND(L"btn_close", OnClose)
        EVENT_NAME_COMMAND(L"btn_min", OnMinimize)
        EVENT_NAME_COMMAND(L"btn_max", OnMaximize)
        EVENT_NAME_COMMAND(L"btn_restore", OnRestore)
    EVENT_MAP_END()

    BEGIN_MSG_MAP_EX(SouiWindow)
        MSG_WM_CREATE(OnCreate)
        MSG_WM_INITDIALOG(OnInitDialog)
        MSG_WM_CLOSE(OnClose)
        MSG_WM_SIZE(OnSize)
        CHAIN_MSG_MAP(SHostWnd)
        REFLECT_NOTIFICATIONS_EX()
    END_MSG_MAP()

private:
    bool            m_bLayoutInited;
};

#endif
View Code

SouiWindow.cpp

#include "SouiWindow.h"

void SouiWindow::create(SouiWindow* window /*= NULL*/)
{
    HWND parent = window ? window->m_hWnd : NULL;
    SHostWnd::Create(parent, 0, 0);
    SHostWnd::SendMessage(WM_INITDIALOG);
}

void SouiWindow::centerShow()
{
    SHostWnd::CenterWindow(m_hWnd);
    show();
}

void SouiWindow::show()
{
    SHostWnd::ShowWindow(SW_SHOW);
}

int SouiWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    SetMsgHandled(FALSE);
    return 0;
}

void SouiWindow::OnSize(UINT nType, CSize size)
{
    SetMsgHandled(FALSE);
    if (!m_bLayoutInited) return;
    if (nType == SIZE_MAXIMIZED)
    {
        FindChildByName(L"btn_restore")->SetVisible(TRUE);
        FindChildByName(L"btn_max")->SetVisible(FALSE);
    }
    else if (nType == SIZE_RESTORED)
    {
        FindChildByName(L"btn_restore")->SetVisible(FALSE);
        FindChildByName(L"btn_max")->SetVisible(TRUE);
    }
}

BOOL SouiWindow::OnInitDialog(HWND hWnd, LPARAM lParam)
{
    m_bLayoutInited = true;
    return 0;
}
View Code

接下来就是如何使用了,首先编写窗口XML布局文件,这里是MainWnd.xml,具体的内容这里不再详述。

SouiApp app;
// 资源路径一般为当前程序运行目录下面的res文件下
app.setResPath(app.getAppPath() + L"\res");
app.initApp(hInstance);

// 必须在uires.idx文件中,必须编写窗口资源名称和窗口XML布局文件路径,例如'<file name="XML_MAINWND" path="MainWnd.xml" />'
SouiWindow mainWnd(L"LAYOUT:XML_MAINWND");
mainWnd.create();
mainWnd.centerShow();

// 消息循环
app.run(mainWnd);
View Code

最后的界面显示为:

这里有一个小技巧,如何让窗体四周没有圆角矩形呢?

我们可以在root节点中使用属性skin="skin.border",它是一个半透明的png图片,定义为<imgframe name="skin.border"  src="PNG:ID_SHADOW" left="5" top="3" right="5" bottom="7"/>,只显示窗口边框的阴影部分;

然后在window节点中使用一张背景图片,就可以到的上图的效果,具体可参考SOUI中的"360"deom。

原文地址:https://www.cnblogs.com/dongc/p/5225063.html