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

#include "stdafx.h"
#include "vol_user_app_info.h"

CVolNativeWndCreateParam::CVolNativeWndCreateParam (HWND hParentWnd, const INT nLeft, const INT nTop, const INT nWidth, const INT nHeight, INT nID, INT nGroupNumber) :
        m_hParentWnd (hParentWnd),
        m_nLeft (nLeft),
        m_nTop (nTop),
        m_nWidth (nWidth),
        m_nHeight (nHeight),
        m_nID (nID),
        m_nGroupNumber (nGroupNumber)
{
	m_pParentWndObject = NULL;
    m_dwStyle = m_dwExStyle = 0;
    m_szCaption = _T ("");
    m_pVolMenu = NULL;
    m_blModalDialog = FALSE;
    m_nDialogResult = 0;
    m_hFont = NULL;
}

// 检查处理参数中没有设置 WS_BORDER 风格而创建后自动增加的情况
void CVolNativeWndCreateParam::CheckBorderStyle (CWindow* pWnd) const
{
    ASSERT (pWnd != NULL);

    if ((m_dwStyle & WS_BORDER) == 0 && (pWnd->GetStyle () & WS_BORDER) != 0)
        pWnd->ModifyStyle (WS_BORDER, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_DRAWFRAME);
}

HFONT CWtlWndObject::CheckGetFont ()
{
    if (m_hFont == NULL)
    {
        LOGFONT infFont;
        GetDefaultFontInfo (&infFont);  // 使用默认字体的信息进行初始化
        m_hFont = ::CreateFontIndirect (&infFont);
    }

    return m_hFont;
}

#define _VOL_WND_CS_VISIBLE  (1 << 0)  // 用作同步记录窗口组件的可视状态

BOOL_P ProcessVolSysMessage (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, void* pWndObject,
        const TCHAR* szClassName, INT* pnGroupNumber, DWORD* pdwControlState, CVolWindowProcFilters& filters)
{
    ASSERT (pWndObject != NULL && IsEmptyStr (szClassName) == FALSE && pnGroupNumber != NULL && pdwControlState != NULL);

    if (lParam == _VOL_MSG_ACK)
    {
        switch (uMsg)
        {
        case MWM_SET_WND_GROUP_NUMBER:
            *pnGroupNumber = (INT)wParam;
            lResult = _VOL_MSG_ACK;
            return TRUE;

        case MWM_RECORD_WND_VISIBLE_STATE:
            if ((BOOL_P)wParam)
                *pdwControlState |= _VOL_WND_CS_VISIBLE;
            else
                *pdwControlState &= ~_VOL_WND_CS_VISIBLE;
            lResult = _VOL_MSG_ACK;
            return TRUE;
        }

        if (wParam != NULL)
        {
            // 获取窗口所对应的对象指针
            switch (uMsg)
            {
            case MWM_GET_WND_RECORDED_VISIBLE_STATE:
                *(BOOL*)wParam = ((*pdwControlState & _VOL_WND_CS_VISIBLE) != 0);
                lResult = _VOL_MSG_ACK;
                return TRUE;

            case MWM_GET_WND_OBJECT:  {
                _VOL_GET_WND_OBJECT_PARAM* pParam = (_VOL_GET_WND_OBJECT_PARAM*)wParam;
                ASSERT (IsEmptyStr (pParam->m_szFindClassName) == FALSE);

                if (_tcscmp (pParam->m_szFindClassName, szClassName) == 0)
                {
                    pParam->m_pWndObject = pWndObject;
                    lResult = _VOL_MSG_ACK;
                    return TRUE;
                }
                break;  }
        
            case MWM_GET_WND_GROUP_NUMBER:
                *(INT*)wParam = *pnGroupNumber;
                lResult = _VOL_MSG_ACK;
                return TRUE;

            case MWM_REGISTER_WINDOW_PROC_FILTER:
                filters.RegisterFilter ((IVolWindowProcFilter*)wParam);
                lResult = _VOL_MSG_ACK;
                return TRUE;

            case MWM_UNREGISTER_WINDOW_PROC_FILTER:
                filters.UnregisterFilter ((IVolWindowProcFilter*)wParam);
                lResult = _VOL_MSG_ACK;
                return TRUE;
            }
        }
    }

    const BOOL_P blpProcessed = filters.CallFilterBeforeDefProc (hWnd, uMsg, wParam, lParam, lResult);

    if (uMsg == WM_NCDESTROY)
        filters.Cleanup ();

    return blpProcessed;
}

BOOL_P ProcessNativeMessage (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult,
        const BOOL_P blpSkipFocusMessage, IBaseEventListener* pEventListener)
{
    if (uMsg == WM_DESTROY && hWnd == _Module.m_hMainWnd)
        PostQuitMessage (0);

    return SendNativeMessage (hWnd, uMsg, wParam, lParam, pEventListener, blpSkipFocusMessage);
}

BOOL_P SendNativeMessage (MSG* pMsg, IBaseEventListener* pEventListener)
{
    ASSERT (pMsg != NULL);

    if (pEventListener == NULL)
        return FALSE;

    // pMsg->hwnd可能会在处理OnNativeWndMsg的过程中被MFC修改
    const HWND hWnd = pMsg->hwnd;
    ASSERT (hWnd != NULL && ::IsWindow (hWnd));
    return (pEventListener->OnNativeWndMsg (pMsg) || hWnd != pMsg->hwnd || ::IsWindow (hWnd) == FALSE);
}

BOOL_P SendNativeMessage (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, IBaseEventListener* pEventListener)
{
    ASSERT (hWnd != NULL);

    if (pEventListener == NULL)
        return FALSE;

    MSG msg;
    ZERO_MEM (&msg, sizeof (msg));
    msg.hwnd = hWnd;
    msg.message = message;
    msg.wParam = wParam;
    msg.lParam = lParam;

    return SendNativeMessage (&msg, pEventListener);
}

BOOL_P SendNativeMessage (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, IBaseEventListener* pEventListener, const BOOL_P blpSkipFocusMessage)
{
    if (pEventListener == NULL ||
            (blpSkipFocusMessage && (message == WM_SETFOCUS || message == WM_KILLFOCUS)))
    {
        return FALSE;
    }

    return SendNativeMessage (hWnd, message, wParam, lParam, pEventListener);
}

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

#ifdef _VOL_FOR_UI_DESIGNER  // 为编译布局设计器专用版本?

void CVolDummyWnd::OnPaint (HDC hNotUsed)
{
    CPaintDC dc (m_hWnd);

    CRect rtClipBox;
    dc.GetClipBox (&rtClipBox);
    if (rtClipBox.IsRectEmpty ())
        return;

    CBrush brh;
    brh.CreateSolidBrush (::GetSysColor (COLOR_BTNFACE));
    HBRUSH hOldBrush = dc.SelectBrush (brh);
    dc.PatBlt (rtClipBox.left, rtClipBox.top, rtClipBox.Width (), rtClipBox.Height (), PATCOPY);
    dc.SelectBrush (hOldBrush);

    CRect rtClient;
    GetClientRect (&rtClient);

    CBitmap bmp;
    if (m_uIDMarkBitmap == 0 || bmp.LoadBitmap (m_uIDMarkBitmap) == FALSE)
        return;

    BITMAP infBitmap;
    bmp.GetBitmap (&infBitmap);

    CDC dcBitmap;
    dcBitmap.CreateCompatibleDC (dc);
    const HBITMAP hOldBmp = dcBitmap.SelectBitmap (bmp);

    dc.BitBlt (MAX (0, (rtClient.Width () - infBitmap.bmWidth) / 2),
            MAX (0, (rtClient.Height () - infBitmap.bmHeight) / 2),
            infBitmap.bmWidth, infBitmap.bmHeight, dcBitmap, 0, 0, SRCCOPY);

    dcBitmap.SelectBitmap (hOldBmp);
}

#endif

BOOL CVolDummyWnd::CreateDummyControl (CVolNativeWndCreateParam* pCreateParam)
{
#ifdef _VOL_FOR_UI_DESIGNER  // 为编译布局设计器专用版本?
    pCreateParam->m_dwStyle |= WS_BORDER;
#else
    pCreateParam->m_dwStyle &= ~WS_VISIBLE;
#endif

    return (_CREATE_WND_BY_PARAM (pCreateParam) != NULL);
}
