// ResizableDialog.cpp : implementation file
//
/////////////////////////////////////////////////////////////////////////////
//
// This file is part of ResizableLib
// http://sourceforge.net/projects/resizablelib
//
// Copyright (C) 2000-2004 by Paolo Messina
// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com
//
// The contents of this file are subject to the Artistic License (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
// http://www.opensource.org/licenses/artistic-license.html
//
// If you find this code useful, credits would be nice!
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ResizableDialog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CResizableDialog

IMPLEMENT_DYNAMIC(CResizableDialog, CDialog)

BOOL CResizableDialog::IsDwmCompositionEnabled(void)
{
    HIGHCONTRAST hc = { sizeof(HIGHCONTRAST) };
    SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST), &hc, FALSE);
    BOOL bEnabled = FALSE;
    return (((hc.dwFlags & HCF_HIGHCONTRASTON) == 0) && SUCCEEDED(DwmIsCompositionEnabled(&bEnabled)) && bEnabled);
}

inline void CResizableDialog::PrivateConstruct()
{
    m_bEnableSaveRestore = FALSE;
    m_dwGripTempState = 1;
    m_bShowGrip = !IsDwmCompositionEnabled();
    m_bRectOnly = FALSE;
}

CResizableDialog::CResizableDialog()
{
    PrivateConstruct();
}

CResizableDialog::CResizableDialog(UINT nIDTemplate, CWnd* pParentWnd)
    : CDialog(nIDTemplate, pParentWnd)
{
    PrivateConstruct();
}

CResizableDialog::CResizableDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
    : CDialog(lpszTemplateName, pParentWnd)
{
    PrivateConstruct();
}

CResizableDialog::~CResizableDialog()
{
}


BEGIN_MESSAGE_MAP(CResizableDialog, CDialog)
    //{{AFX_MSG_MAP(CResizableDialog)
    ON_WM_GETMINMAXINFO()
    ON_WM_SIZE()
    ON_WM_DESTROY()
    ON_WM_ERASEBKGND()
    ON_WM_NCCREATE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CResizableDialog message handlers

BOOL CResizableDialog::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (!CDialog::OnNcCreate(lpCreateStruct))
        return FALSE;

    // child dialogs don't want resizable border or size grip,
    // nor they can handle the min/max size constraints
    BOOL bChild = lpCreateStruct->style & WS_CHILD;

    // create and init the size-grip
    if (!CreateSizeGrip(!bChild))
        return FALSE;

    if (!bChild)
    {
        // set the initial size as the min track size
        SetMinTrackSize(CSize(lpCreateStruct->cx, lpCreateStruct->cy));
    }

    MakeResizable(lpCreateStruct);

    return TRUE;
}

void CResizableDialog::OnDestroy()
{
    if (m_bEnableSaveRestore)
        SaveWindowRect(m_sSection, m_bRectOnly);

    // remove child windows
    RemoveAllAnchors();

    CDialog::OnDestroy();
}

void CResizableDialog::OnSize(UINT nType, int cx, int cy)
{
    CWnd::OnSize(nType, cx, cy);

    if (nType == SIZE_MAXHIDE || nType == SIZE_MAXSHOW)
        return;     // arrangement not needed

    if ((m_bShowGrip)||(!IsDwmCompositionEnabled()))
    {
        if (nType == SIZE_MAXIMIZED)
            HideSizeGrip(&m_dwGripTempState);
        else
            ShowSizeGrip(&m_dwGripTempState);
        // update grip and layout
        UpdateSizeGrip();
    }
    if (IsDwmCompositionEnabled())
        HideGrip();

    ArrangeLayout();
    // on Vista, the redrawing doesn't work right, so we have to work
    // around this by invalidating the whole dialog so the DWM recognizes
    // that it has to update the application window.
        Invalidate();
}

void CResizableDialog::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
    MinMaxInfo(lpMMI);
}

// NOTE: this must be called after setting the layout
//       to have the dialog and its controls displayed properly
void CResizableDialog::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly, BOOL bHorzResize, BOOL bVertResize)
{
    m_sSection = pszSection;

    m_bEnableSaveRestore = TRUE;
    m_bRectOnly = bRectOnly;

    // restore immediately
    LoadWindowRect(pszSection, bRectOnly, bHorzResize, bVertResize);

    CMenu* pMenu = GetMenu();
    if ( pMenu )
        DrawMenuBar();
}

BOOL CResizableDialog::OnEraseBkgnd(CDC* pDC)
{
    ClipChildren(pDC, FALSE);

    BOOL bRet = CDialog::OnEraseBkgnd(pDC);

    ClipChildren(pDC, TRUE);

    return bRet;
}

LRESULT CResizableDialog::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message != WM_NCCALCSIZE || wParam == 0 || m_noNcCalcSizeAdjustments)
        return CDialog::WindowProc(message, wParam, lParam);

    LRESULT lResult = 0;
    HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult);
    lResult = CDialog::WindowProc(message, wParam, lParam);
    HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult);
    return lResult;
}
