Skip to content

SOUI控件注册机制

Warning

The current page still doesn't have a translation for this language.

You can read it through google translate.

本文详细介绍SOUI框架中的控件注册机制,包括控件的注册方式、内存管理及扩展方法。

控件注册概述

控件注册是SOUI系统中一个重要的机制,它使得: - 系统能够通过XML描述创建控件 - 保证控件内存的正确分配和释放 - 支持控件的扩展和自定义

注册控件

1. 基本注册方法

// 注册窗口控件
theApp->RegisterWndFactory(TplSWindowFactory<SMyWindow>());

// 注册皮肤对象
theApp->RegisterSkinFactory(TplSkinFactory<SMySkin>());

2. 注册示例

// 注册各种控件
void RegisterControls()
{
    // 注册GIF播放器
    theApp->RegisterWndFactory(TplSWindowFactory<SGifPlayer>());

    // 注册IP地址控件
    theApp->RegisterWndFactory(TplSWindowFactory<SIPAddressCtrl>());

    // 注册属性表控件
    theApp->RegisterWndFactory(TplSWindowFactory<SPropertyGrid>());

    // 注册动画控件(条件注册)
    if(SUCCEEDED(CUiAnimation::Init()))
    {
        theApp->RegisterWndFactory(TplSWindowFactory<SUiAnimationWnd>());
    }
}

工厂模式实现

1. 窗口工厂基类

class SWindowFactory
{
public:
    virtual ~SWindowFactory() {}
    virtual SWindow* NewWindow() = 0;
    virtual LPCWSTR SWindowBaseName() = 0;
    virtual const SStringW & getWindowType() = 0;
    virtual SWindowFactory* Clone() const = 0;
};

2. 模板工厂实现

template <typename T>
class TplSWindowFactory : public SWindowFactory
{
public:
    TplSWindowFactory()
        : m_strTypeName(T::GetClassName())
    {
    }

    // 获取基类名称
    LPCWSTR SWindowBaseName() 
    { 
        return T::BaseClassName(); 
    }

    // 创建新窗口
    virtual SWindow* NewWindow()
    {
        return new T;
    }

    // 获取窗口类型
    virtual const SStringW & getWindowType()
    {
        return m_strTypeName;
    }

    // 克隆工厂对象
    virtual SWindowFactory* Clone() const 
    {
        return new TplSWindowFactory();
    }

protected:
    SStringW m_strTypeName;
};

内存管理机制

1. 引用计数基类

template<class T>
class TObjRefImpl : public T
{
public:
    TObjRefImpl() : m_cRef(1) {}

    // 增加引用计数
    virtual void AddRef()
    {
        InterlockedIncrement(&m_cRef);
    }

    // 释放引用
    virtual void Release()
    {
        InterlockedDecrement(&m_cRef);
        if(m_cRef == 0)
        {
            OnFinalRelease();
        }
    }

    // 最终释放
    virtual void OnFinalRelease()
    {
        delete this;
    }

protected:
    volatile LONG m_cRef;
};

2. 双继承引用计数实现

template<class T, class T2>
class TObjRefImpl2 : public TObjRefImpl<T>
{
public:
    virtual void OnFinalRelease()
    {
        delete static_cast<T2*>(this);
    }
};

自定义控件实现

1. 标准实现方式

// 定义控件类
class SMyControl : public SWindow
{
    SOUI_CLASS_NAME(SMyControl, L"mycontrol")
public:
    SMyControl() {}
    ~SMyControl() {}

protected:
    // 控件实现
};

// 注册控件
theApp->RegisterWndFactory(TplSWindowFactory<SMyControl>());

2. 自管理内存方式

class SCustomControl : public SWindow
{
public:
    // 重写OnFinalRelease实现自己的内存管理
    virtual void OnFinalRelease()
    {
        delete this;
    }
};

// 直接创建控件
SCustomControl* pCtrl = new SCustomControl();

最佳实践

1. 控件注册规范

class MyApp
{
public:
    bool InitControls()
    {
        // 1. 基础控件注册
        RegisterBasicControls();

        // 2. 条件控件注册
        if(CheckDependency())
        {
            RegisterOptionalControls();
        }

        // 3. 自定义控件注册
        RegisterCustomControls();

        return true;
    }
};

2. 内存管理

class SMyControl : public SWindow
{
    SOUI_CLASS_NAME(SMyControl, L"mycontrol")
public:
    SMyControl()
    {
        // 资源初始化
    }

    ~SMyControl()
    {
        // 资源清理
    }

protected:
    // 使用智能指针管理资源
    CAutoRefPtr<IResource> m_pResource;
};

3. 扩展性设计

// 基础接口
struct IMyControlCallback
{
    virtual void OnCustomEvent() = 0;
};

// 控件实现
class SMyControl : public SWindow
{
public:
    void SetCallback(IMyControlCallback* pCallback)
    {
        m_pCallback = pCallback;
    }

protected:
    IMyControlCallback* m_pCallback;
};

调试技巧

1. 控件注册验证

void VerifyControlRegistration()
{
    // 验证控件是否注册成功
    SWindow *pWnd = SApplication::getSingleton()
        .CreateWindowByName(L"mycontrol");
    SASSERT(pWnd);
}

2. 内存泄漏检测

void CheckMemoryLeak()
{
    #ifdef _DEBUG
    // 创建控件
    SWindow *pWnd = new SMyControl();

    // 检查引用计数
    SASSERT(pWnd->GetRef() == 1);

    // 释放控件
    pWnd->Release();
    #endif
}

注意事项

  1. 内存管理
  2. 正确使用引用计数
  3. 避免循环引用
  4. 及时释放资源

  5. 控件注册

  6. 在应用初始化时注册
  7. 确保注册顺序正确
  8. 处理依赖关系

  9. 扩展开发

  10. 遵循SOUI设计规范
  11. 合理使用内存管理机制
  12. 注意模块间的内存分配