• 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。

  • 相关阅读:
    LeetCode Missing Number (简单题)
    LeetCode Valid Anagram (简单题)
    LeetCode Single Number III (xor)
    LeetCode Best Time to Buy and Sell Stock II (简单题)
    LeetCode Move Zeroes (简单题)
    LeetCode Add Digits (规律题)
    DependencyProperty深入浅出
    SQL Server存储机制二
    WPF自定义RoutedEvent事件示例代码
    ViewModel命令ICommand对象定义
  • 原文地址:https://www.cnblogs.com/dongc/p/5225063.html
Copyright © 2020-2023  润新知