
// Copyright (C) Recursion Company. All rights reserved.

#ifndef __MFC_UI_BASE_H__
#define __MFC_UI_BASE_H__

#define _VOL_MFC_UI

//----------------------------------------------------------------------  火山窗口组件本地类的创建参数

class CVolNativeWndCreateParam
{
public:
    CVolNativeWndCreateParam (CWnd* pParentWnd, const INT nLeft, const INT nTop, const INT nWidth, const INT nHeight, INT nID, INT nGroupNumber = -1);

    inline_ CVolNativeWndCreateParam (const CVolNativeWndCreateParam* pCopyParam)
    {
        ASSERT (pCopyParam != NULL);
        COPY_MEM (this, pCopyParam, sizeof (CVolNativeWndCreateParam));
    }

public:
    void CheckBorderStyle (CWnd* pWnd) const;

public:
    CWnd* m_pParentWnd;  // 父窗口对象,为NULL表示无.
    CVolObject* m_pParentWndObject;  // 父窗口火山对象,为NULL表示无.
    INT m_nLeft, m_nTop, m_nWidth, m_nHeight;  // 位置矩形的左上角坐标和宽度及高度
    UINT m_nID;  // 在父窗口中的ID值
    INT m_nGroupNumber;  // 所属的设计时分组编号

    DWORD m_dwStyle;  // 窗口风格
    DWORD m_dwExStyle;  // 窗口扩展风格
    const TCHAR* m_szCaption;  // 窗口标题

    // 以下成员仅在创建非子组件窗口时被使用
    CRefVolMenu* m_pVolMenu;  // 所使用的菜单,为NULL表示无.
    BOOL m_blModalDialog;  // 指定所创建窗口是否为模态对话框状态
    BOOL m_blForceUseDialogStyle;  // 本成员仅当m_blModalDialog为真时有效,用作记录是否强制使用所指定的对话框风格.
    INT m_nDialogResult;  // 本成员仅当m_blModalDialog为真时有效,用作记录当以对话框方式显示所创建窗口时,用户程序调用EndDialog时所返回的值.

    // 以下成员正常情况下创建时不用处理:
    HFONT m_hFont;  // 所使用的字体句柄,调用CreateControl时必定不为NULL.
};

//----------------------------------------------------------------------  相关宏定义

// 内部宏
#define _BASE_DECLARE_VOL_NATIVE_WND_CLASS(base_class_name, event_listener_interface, skip_focus_msg, msg_filter_code)  \
    public:                                                                                    \
        event_listener_interface* m_pEventListener;                                            \
        INT m_nGroupNumber;                                                                    \
        DWORD m_dwControlState;                                                                \
        CVolWindowProcFilters m_filters;                                                       \
        BOOL CreateControl (CVolNativeWndCreateParam* pCreateParam);                           \
        virtual LRESULT WindowProc (UINT message, WPARAM wParam, LPARAM lParam) override       \
        {                                                                                      \
            msg_filter_code                                                                    \
            LRESULT lResultProcessed = 0;                                                      \
            if (ProcessVolSysMessage (m_hWnd, message, wParam, lParam, lResultProcessed, &m_nGroupNumber, &m_dwControlState, m_filters) == FALSE)  \
            {                                                                                  \
                if (ProcessNativeMessage (m_hWnd, message, wParam, lParam, skip_focus_msg, m_pEventListener))  \
                    return 0;                                                                  \
                lResultProcessed = base_class_name::WindowProc (message, wParam, lParam);      \
            }                                                                                  \
            return lResultProcessed;                                                           \
        }

// 火山本地窗口类声明宏
//   class_name: 当前窗口类名
//   base_class_name: 其基础类名
//   event_listener_interface: 其事件监听接口类名,必须直接或间接继承了IBaseEventListener.
//   skip_focus_msg: 是否跳过 WM_SETFOCUS 和 WM_KILLFOCUS 消息,此时改由本地窗口类本身来手动发送(因为某些组件譬如编辑框有自己的通知EN_SETFOCUS/EN_KILLFOCUS).
//   msg_filter_code: 用作加入消息的过滤处理代码.
// 用户必须实现OnConstruct方法和CreateControl方法:
// OnConstruct方法:
//     用作在类构造时进行相关初始化
//     注意: 不要在此方法中初始化GUI资源(可以放到CreateControl方法中),因为本组件的
//   实例对象有可能伴随启动类的实例对象创建而创建,而此时MFC尚未初始化.
// CreateControl方法: 用作创建所对应的窗口本地组件对象,返回是否成功.
//   原型为: BOOL CreateControl (CVolNativeWndCreateParam* pCreateParam)
//   pCreateParam: 具体创建参数,其中的内容可以被修改.
#define DECLARE_VOL_NATIVE_WND_CLASS2(class_name, base_class_name, event_listener_interface, skip_focus_msg, msg_filter_code)  \
        _BASE_DECLARE_VOL_NATIVE_WND_CLASS (base_class_name, event_listener_interface, skip_focus_msg, msg_filter_code)  \
        private:                          \
            void OnConstruct ();          \
        public:                           \
            inline_ class_name ()         \
            {                             \
                m_pEventListener = NULL;  \
                m_nGroupNumber = -1;      \
                m_dwControlState = 0;     \
                OnConstruct ();           \
            }                             \

// 同 DECLARE_VOL_NATIVE_WND_CLASS2 宏,唯一的区别是不需要实现OnConstruct方法
#define DECLARE_VOL_NATIVE_WND_CLASS_WITHOUT_CONSTRUCT2(class_name, base_class_name, event_listener_interface, skip_focus_msg, msg_filter_code)  \
        _BASE_DECLARE_VOL_NATIVE_WND_CLASS (base_class_name, event_listener_interface, skip_focus_msg, msg_filter_code)  \
        public:                           \
            inline_ class_name ()         \
            {                             \
                m_pEventListener = NULL;  \
                m_nGroupNumber = -1;      \
                m_dwControlState = 0;     \
            }

#define DECLARE_VOL_NATIVE_WND_CLASS(class_name, base_class_name, event_listener_interface, skip_focus_msg)  \
        DECLARE_VOL_NATIVE_WND_CLASS2 (class_name, base_class_name, event_listener_interface, skip_focus_msg, ;)

#define DECLARE_VOL_NATIVE_WND_CLASS_WITHOUT_CONSTRUCT(class_name, base_class_name, event_listener_interface, skip_focus_msg)  \
        DECLARE_VOL_NATIVE_WND_CLASS_WITHOUT_CONSTRUCT2 (class_name, base_class_name, event_listener_interface, skip_focus_msg, ;)

//----------------------------------------------------------------------  用作保存MFC窗口对象的类

class CMfcWndObject : public CRefObject
{
    DECLARE_DERIVED_CLASS (CMfcWndObject)

public:
    inline_ CMfcWndObject (CWnd* pWnd, const BOOL_P blpMfcWndWillAutoDelete) :
            m_pWnd (pWnd),
            m_blpMfcWndWillAutoDelete (blpMfcWndWillAutoDelete)
    {
        ASSERT (pWnd != NULL);

        m_dwAttrInitialStyle = (WS_VISIBLE | WS_CLIPSIBLINGS);
        m_dwAttrInitialExStyle = 0;
        m_hAttrCustomCursur = NULL;
        m_hFont = NULL;
    }

    virtual ~CMfcWndObject ()
    {
        if (m_hFont != NULL)
            ::DeleteObject (m_hFont);

        if (m_pWnd != NULL)
            delete m_pWnd;
    }

    virtual void OnBeforeDestory () override
    {
        if (m_pWnd->m_hWnd != NULL)
        {
            m_pWnd->DestroyWindow ();

            if (m_blpMfcWndWillAutoDelete)  // m_pWnd在销毁时是否将自动删除自身?
                m_pWnd = NULL;  // 取消在本对象析构函数中的删除操作,避免出错.
        }
    }

    inline_ CWnd* GetRefWndPtr () const
    {
        return m_pWnd;
    }

    inline_ CWnd* SafeGetRefWndPtrWithValidHWnd () const
    {
        return ((this == NULL || m_pWnd->m_hWnd == NULL) ? NULL : m_pWnd);
    }

    inline_ HWND SafeGetRefWndHandle () const
    {
        return (this == NULL ? NULL : m_pWnd->m_hWnd);
    }

    HFONT CheckGetFont ();  // 检查获取字体句柄值,如果当前未设置字体句柄,则返回默认GUI字体.

public:
    // 用作在本窗口组件尚未创建时记录相关支持在所处组件创建前设置的属性值:
    CVolString m_strAttrCaption;  // 组件标题
    DWORD m_dwAttrInitialStyle, m_dwAttrInitialExStyle;  // 指定相关初始风格
    HCURSOR m_hAttrCustomCursur;  // 所使用的鼠标指针句柄,为NULL表示使用标准鼠标指针.
    HFONT m_hFont;  // 所使用的字体,为NULL表示使用默认字体.

protected:
    CWnd* m_pWnd;  // 记录对应的MFC窗口对象指针,必定不为NULL.
    const BOOL_P m_blpMfcWndWillAutoDelete;  // 提供所指定的 m_pWnd MFC窗口在销毁时是否会自动删除自身(在PostNcDestroy中)
};

//----------------------------------------------------------------------  相关事件监听接口

// 所有事件监听接口的基础类
class IBaseEventListener
{
public:
    // 用作预先处理本地窗口的消息,返回真表示该消息已经被处理且不再需要继续向后传递,返回假表示该消息未被处理.
    virtual BOOL OnNativeWndMsg (MSG* pMsg) = 0;
};

// 发送本地窗口消息到IBaseEventListener的OnNativeWndMsg接口方法
//   pMsg: 所欲处理的消息,必定不为NULL.
//   pEventListener: 所欲发送到的接口对象,如无则为NULL.
// 返回真表示消息已经被成功处理且不需要后续处理
BOOL_P SendNativeMessage (MSG* pMsg, IBaseEventListener* pEventListener);
BOOL_P SendNativeMessage (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, IBaseEventListener* pEventListener);

BOOL_P ProcessVolSysMessage (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT& lResult, INT* pnGroupNumber, DWORD* pdwControlState, CVolWindowProcFilters& filters);

// blpSkipFocusMessage: 是否跳过WM_SETFOCUS和WM_KILLFOCUS消息.
BOOL_P ProcessNativeMessage (HWND hWnd, UINT message, WPARAM& wParam, LPARAM& lParam, const BOOL_P blpSkipFocusMessage, IBaseEventListener* pEventListener);

// 发送WM_SETFOCUS本地窗口消息到IBaseEventListener的OnNativeWndMsg接口方法
inline_ BOOL_P SendSetFocusNativeMessage (const HWND hThisWnd, IBaseEventListener* pEventListener)
{
    return SendNativeMessage (hThisWnd, WM_SETFOCUS, 0, 0, pEventListener);
}

// 发送WM_KILLFOCUS本地窗口消息到IBaseEventListener的OnNativeWndMsg接口方法
inline_ BOOL_P SendKillFocusNativeMessage (const HWND hThisWnd, IBaseEventListener* pEventListener)
{
    return SendNativeMessage (hThisWnd, WM_KILLFOCUS, 0, 0, pEventListener);
}

//----------------------------------------------------------------------

#include "tr_mfc_ui_res.h"
#include "mfc_ui_functions.h"

#endif
