ResizableLib

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

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

/////
//  CResizableDialog

inline 
void  CResizableDialog::PrivateConstruct()
{
    m_bEnableSaveRestore 
= FALSE;
    m_dwGripTempState 
= 1;
}


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


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


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


CResizableDialog::
~ CResizableDialog()
{
}



BEGIN_MESSAGE_MAP(CResizableDialog, CCmdUIDialog)
    
// {{AFX_MSG_MAP(CResizableDialog)
    ON_WM_GETMINMAXINFO()
    ON_WM_SIZE()
    ON_WM_DESTROY()
    ON_WM_CREATE()
    ON_WM_ERASEBKGND()
    
// }}AFX_MSG_MAP
END_MESSAGE_MAP()


/////
//  CResizableDialog message handlers

int  CResizableDialog::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
    
if (__super::OnCreate(lpCreateStruct) == -1)
        
return -1;

    
// child dialogs don't want resizable border or size grip,
    
// nor they can handle the min/max size constraints
    BOOL bChild = GetStyle() & WS_CHILD;

    
if (!bChild)
    
{
        
// keep client area
        CRect rect;
        GetClientRect(
&rect);
        
// set resizable style
        ModifyStyle(DS_MODALFRAME, WS_POPUP | WS_THICKFRAME);
        
// adjust size to reflect new style
        ::AdjustWindowRectEx(&rect, GetStyle(),
            ::IsMenu(GetMenu()
->GetSafeHmenu()), GetExStyle());
        SetWindowPos(NULL, 
00, rect.Width(), rect.Height(), SWP_FRAMECHANGED|
            SWP_NOMOVE
|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREPOSITION);

        
// set the initial size as the min track size
        SetMinTrackSize(rect.Size());
    }


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

    
return 0;
}


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

    
// remove child windows
    RemoveAllAnchors();

    __super::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 (nType == SIZE_MAXIMIZED)
        HideSizeGrip(
&m_dwGripTempState);
    
else
        ShowSizeGrip(
&m_dwGripTempState);

    
// update grip and layout
    UpdateSizeGrip();
    ArrangeLayout();
}


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)
{
    m_sSection 
= pszSection;

    m_bEnableSaveRestore 
= TRUE;
    m_bRectOnly 
= bRectOnly;

    
// restore immediately
    LoadWindowRect(pszSection, bRectOnly);
}



BOOL CResizableDialog::OnEraseBkgnd(CDC
*  pDC) 
{
    
// Windows XP doesn't like clipping regions ...try this!
    EraseBackground(pDC);
    
return TRUE;

/*    ClipChildren(pDC);    // old-method (for safety)

    return CDialog::OnEraseBkgnd(pDC);
*/

}

#if  !defined(AFX_RESIZABLEGRIP_H__INCLUDED_)
#define  AFX_RESIZABLEGRIP_H__INCLUDED_

#if  _MSC_VER > 1000
#pragma  once
#endif   //  _MSC_VER > 1000

class  CResizableGrip  
{
private:
    
class CSizeGrip : public CScrollBar
    
{
    
public:
        CSizeGrip()
        
{
            m_bTransparent 
= FALSE;
            m_bTriangular 
= FALSE;
            m_size.cx 
= 0;
            m_size.cy 
= 0;
        }


        
void SetTriangularShape(BOOL bEnable);
        
void SetTransparency(BOOL bActivate);

        BOOL IsRTL();            
// right-to-left layout support

        
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);

        SIZE m_size;            
// holds grip size

    
protected:
        
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

        BOOL m_bTriangular;        
// triangular shape active
        BOOL m_bTransparent;    // transparency active

        
// memory DCs and bitmaps for transparent grip
        CDC m_dcGrip, m_dcMask;
        CBitmap m_bmGrip, m_bmMask;
    }
;

    CSizeGrip m_wndGrip;        
// grip control
    int m_nShowCount;            // support for hiding the grip

protected:
    
// create a size grip, with options
    BOOL CreateSizeGrip(BOOL bVisible = TRUE,
        BOOL bTriangular 
= TRUE, BOOL bTransparent = FALSE);

    BOOL IsSizeGripVisible();    
// TRUE if grip is set to be visible
    void SetSizeGripVisibility(BOOL bVisible);    // set default visibility
    void UpdateSizeGrip();        // update the grip's visibility and position
    void ShowSizeGrip(DWORD* pStatus, DWORD dwMask = 1);    // temp show the size grip
    void HideSizeGrip(DWORD* pStatus, DWORD dwMask = 1);    // temp hide the size grip
    BOOL SetSizeGripBkMode(int nBkMode);        // like CDC::SetBkMode
    void SetSizeGripShape(BOOL bTriangular);

    
virtual CWnd* GetResizableWnd() = 0;

public:
    CResizableGrip();
    
virtual ~CResizableGrip();
}
;

#endif   //  !defined(AFX_RESIZABLEGRIP_H__INCLUDED_)
#include  " stdafx.h "
#include 
" ResizableGrip.h "

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

//
//  Construction/Destruction
//

CResizableGrip::CResizableGrip()
{
    m_nShowCount 
= 0;
}


CResizableGrip::
~ CResizableGrip()
{

}


void  CResizableGrip::UpdateSizeGrip()
{
    ASSERT(::IsWindow(m_wndGrip.m_hWnd));

    
// size-grip goes bottom right in the client area
    
// (any right-to-left adjustment should go here)

    RECT rect;
    GetResizableWnd()
->GetClientRect(&rect);

    rect.left 
= rect.right - m_wndGrip.m_size.cx;
    rect.top 
= rect.bottom - m_wndGrip.m_size.cy;

    
// must stay below other children
    m_wndGrip.SetWindowPos(&CWnd::wndBottom, rect.left, rect.top, 00,
        SWP_NOSIZE 
| SWP_NOACTIVATE | SWP_NOREPOSITION
        
| (IsSizeGripVisible() ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
}


//  pbStatus points to a variable, maintained by the caller, that
//  holds its visibility status. Initialize the variable with 1
//  to allow to temporarily hide the grip, 0 to allow to
//  temporarily show the grip (with respect to the dwMask bit).

//  NB: visibility is effective only after an update

void  CResizableGrip::ShowSizeGrip(DWORD *  pStatus, DWORD dwMask  /*= 1*/ )
{
    ASSERT(pStatus 
!= NULL);

    
if (!(*pStatus & dwMask))
    
{
        m_nShowCount
++;
        (
*pStatus) |= dwMask;
    }

}


void  CResizableGrip::HideSizeGrip(DWORD *  pStatus, DWORD dwMask  /*= 1*/ )
{
    ASSERT(pStatus 
!= NULL);

    
if (*pStatus & dwMask)
    
{
        m_nShowCount
--;
        (
*pStatus) &= ~dwMask;
    }

}


BOOL CResizableGrip::IsSizeGripVisible()
{
    
// NB: visibility is effective only after an update
    return (m_nShowCount > 0);
}


void  CResizableGrip::SetSizeGripVisibility(BOOL bVisible)
{
    
if (bVisible)
        m_nShowCount 
= 1;
    
else
        m_nShowCount 
= 0;
}


BOOL CResizableGrip::SetSizeGripBkMode(
int  nBkMode)
{
    
if (::IsWindow(m_wndGrip.m_hWnd))
    
{
        
if (nBkMode == OPAQUE)
            m_wndGrip.SetTransparency(FALSE);
        
else if (nBkMode == TRANSPARENT)
            m_wndGrip.SetTransparency(TRUE);
        
else
            
return FALSE;
        
return TRUE;
    }

    
return FALSE;
}


void  CResizableGrip::SetSizeGripShape(BOOL bTriangular)
{
    m_wndGrip.SetTriangularShape(bTriangular);
}


BOOL CResizableGrip::CreateSizeGrip(BOOL bVisible 
/*= TRUE*/ ,
        BOOL bTriangular 
/*= TRUE*/ , BOOL bTransparent  /*= FALSE*/ )
{
    
// create grip
    CRect rect(0 , 0, m_wndGrip.m_size.cx, m_wndGrip.m_size.cy);
    BOOL bRet 
= m_wndGrip.Create(WS_CHILD | WS_CLIPSIBLINGS
        
| SBS_SIZEGRIP, rect, GetResizableWnd(), 0);

    
if (bRet)
    
{
        
// set options
        m_wndGrip.SetTriangularShape(bTriangular);
        m_wndGrip.SetTransparency(bTransparent);
        SetSizeGripVisibility(bVisible);
    
        
// update position
        UpdateSizeGrip();
    }


    
return bRet;
}


/////
//  CSizeGrip implementation

BOOL CResizableGrip::CSizeGrip::IsRTL()
{
    
return GetExStyle() & 0x00400000L/*WS_EX_LAYOUTRTL*/;
}


BOOL CResizableGrip::CSizeGrip::PreCreateWindow(CREATESTRUCT
&  cs) 
{
    
// set window size
    m_size.cx = GetSystemMetrics(SM_CXVSCROLL);
    m_size.cy 
= GetSystemMetrics(SM_CYHSCROLL);

    cs.cx 
= m_size.cx;
    cs.cy 
= m_size.cy;
    
    
return CScrollBar::PreCreateWindow(cs);
}


LRESULT CResizableGrip::CSizeGrip::WindowProc(UINT message,
                                              WPARAM wParam, LPARAM lParam)
{
    
switch (message)
    
{
    
case WM_GETDLGCODE:
        
// fix to prevent the control to gain focus, using arrow keys
        
// (standard grip returns DLGC_WANTARROWS, like any standard scrollbar)
        return DLGC_STATIC;

    
case WM_NCHITTEST:
        
// choose proper cursor shape
        if (IsRTL())
            
return HTBOTTOMLEFT;
        
else
            
return HTBOTTOMRIGHT;
        
break;

    
case WM_SETTINGCHANGE:
        
{
            
// update grip's size
            CSize sizeOld = m_size;
            m_size.cx 
= GetSystemMetrics(SM_CXVSCROLL);
            m_size.cy 
= GetSystemMetrics(SM_CYHSCROLL);

            
// resize transparency bitmaps
            if (m_bTransparent)
            
{
                CClientDC dc(
this);

                
// destroy bitmaps
                m_bmGrip.DeleteObject();
                m_bmMask.DeleteObject();

                
// re-create bitmaps
                m_bmGrip.CreateCompatibleBitmap(&dc, m_size.cx, m_size.cy);
                m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 
11, NULL);
            }


            
// re-calc shape
            if (m_bTriangular)
                SetTriangularShape(m_bTriangular);

            
// reposition the grip
            CRect rect;
            GetWindowRect(rect);
            rect.InflateRect(m_size.cx 
- sizeOld.cx, m_size.cy - sizeOld.cy, 00);
            ::MapWindowPoints(NULL, GetParent()
->GetSafeHwnd(), (LPPOINT)&rect, 2);
            MoveWindow(rect, TRUE);
        }

        
break;

    
case WM_DESTROY:
        
// perform clean up
        if (m_bTransparent)
            SetTransparency(FALSE);
        
break;

    
case WM_PAINT:
        
if (m_bTransparent)
        
{
            CPaintDC dc(
this);

            
// select bitmaps
            CBitmap *pOldGrip, *pOldMask;

            pOldGrip 
= m_dcGrip.SelectObject(&m_bmGrip);
            pOldMask 
= m_dcMask.SelectObject(&m_bmMask);

            
// obtain original grip bitmap, make the mask and prepare masked bitmap
            CScrollBar::WindowProc(WM_PAINT, (WPARAM)m_dcGrip.GetSafeHdc(), lParam);
            m_dcGrip.SetBkColor(m_dcGrip.GetPixel(
00));
            m_dcMask.BitBlt(
00, m_size.cx, m_size.cy, &m_dcGrip, 00, SRCCOPY);
            m_dcGrip.BitBlt(
00, m_size.cx, m_size.cy, &m_dcMask, 000x00220326);
            
            
// draw transparently
            dc.BitBlt(00, m_size.cx, m_size.cy, &m_dcMask, 00, SRCAND);
            dc.BitBlt(
00, m_size.cx, m_size.cy, &m_dcGrip, 00, SRCPAINT);

            
// unselect bitmaps
            m_dcGrip.SelectObject(pOldGrip);
            m_dcMask.SelectObject(pOldMask);

            
return 0;
        }

        
break;
    }


    
return CScrollBar::WindowProc(message, wParam, lParam);
}


void  CResizableGrip::CSizeGrip::SetTransparency(BOOL bActivate)
{
    
// creates or deletes DCs and Bitmaps used for
    
// implementing a transparent size grip

    
if (bActivate && !m_bTransparent)
    
{
        m_bTransparent 
= TRUE;

        CClientDC dc(
this);

        
// create memory DCs and bitmaps
        m_dcGrip.CreateCompatibleDC(&dc);
        m_bmGrip.CreateCompatibleBitmap(
&dc, m_size.cx, m_size.cy);

        m_dcMask.CreateCompatibleDC(
&dc);
        m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 
11, NULL);
    }

    
else if (!bActivate && m_bTransparent)
    
{
        m_bTransparent 
= FALSE;

        
// destroy memory DCs and bitmaps
        m_dcGrip.DeleteDC();
        m_bmGrip.DeleteObject();

        m_dcMask.DeleteDC();
        m_bmMask.DeleteObject();
    }

}


void  CResizableGrip::CSizeGrip::SetTriangularShape(BOOL bEnable)
{
    m_bTriangular 
= bEnable;

    
if (bEnable)
    
{
        
// set a triangular window region
        CRect rect;
        GetWindowRect(rect);
        rect.OffsetRect(
-rect.TopLeft());
        POINT arrPoints[] 
=
        
{
            
{ rect.left, rect.bottom },
            
{ rect.right, rect.bottom },
            
{ rect.right, rect.top }
        }
;
        CRgn rgnGrip;
        rgnGrip.CreatePolygonRgn(arrPoints, 
3, WINDING);
        SetWindowRgn((HRGN)rgnGrip.Detach(), IsWindowVisible());
    }

    
else
    
{
        SetWindowRgn((HRGN)NULL, IsWindowVisible());
    }

}

#if  !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_)
#define  AFX_RESIZABLELAYOUT_H__INCLUDED_

#include 
< afxtempl.h >
#include 
" ResizableMsgSupport.h "

#if  _MSC_VER > 1000
#pragma  once
#endif   //  _MSC_VER > 1000

//  useful compatibility constants (the only one required is NOANCHOR)

const  CSize NOANCHOR( - 1 , - 1 ),
    TOP_LEFT(
0 , 0 ), TOP_CENTER( 50 , 0 ), TOP_RIGHT( 100 , 0 ),
    MIDDLE_LEFT(
0 , 50 ), MIDDLE_CENTER( 50 , 50 ), MIDDLE_RIGHT( 100 , 50 ),
    BOTTOM_LEFT(
0 , 100 ), BOTTOM_CENTER( 50 , 100 ), BOTTOM_RIGHT( 100 , 100 );


class  CResizableLayout
{
protected:
    
class LayoutInfo
    
{
    
public:
        HWND hWnd;
        UINT nCallbackID;

        CString sWndClass;

        
// upper-left corner
        SIZE sizeTypeTL;
        SIZE sizeMarginTL;
        
        
// bottom-right corner
        SIZE sizeTypeBR;
        SIZE sizeMarginBR;

        
// custom window support
        BOOL bMsgSupport;
        RESIZEPROPERTIES properties;
    
    
public:
        LayoutInfo() : hWnd(NULL), nCallbackID(
0), bMsgSupport(FALSE)
        

            sizeTypeTL.cx 
= 0;
            sizeTypeTL.cy 
= 0;
            sizeMarginTL.cx 
= 0;
            sizeMarginTL.cy 
= 0;
            sizeTypeBR.cx 
= 0;
            sizeTypeBR.cy 
= 0;
            sizeMarginBR.cx 
= 0;
            sizeMarginBR.cy 
= 0;
            memset(
&properties, 0sizeof properties);
        }


        LayoutInfo(HWND hwnd, SIZE tl_t, SIZE tl_m, 
            SIZE br_t, SIZE br_m, CString classname)
            : hWnd(hwnd), nCallbackID(
0),
            sWndClass(classname), bMsgSupport(FALSE),
            sizeTypeTL(tl_t), sizeMarginTL(tl_m),
            sizeTypeBR(br_t), sizeMarginBR(br_m)
        

            memset(
&properties, 0sizeof properties);
        }

    }
;

private:
    
// list of repositionable controls
    CMap<HWND, HWND, POSITION, POSITION> m_mapLayout;
    CList
<LayoutInfo, LayoutInfo&> m_listLayout;
    CList
<LayoutInfo, LayoutInfo&> m_listLayoutCB;

    
void ClipChildWindow(const CResizableLayout::LayoutInfo &layout, CRgn* pRegion);

    
void CalcNewChildPosition(const CResizableLayout::LayoutInfo &layout,
        
const CRect &rectParent, CRect &rectChild, UINT& uFlags);

protected:
    
// override to initialize resize properties (clipping, refresh)
    virtual void InitResizeProperties(CResizableLayout::LayoutInfo& layout);

    
// override to specify clipping for unsupported windows
    virtual BOOL LikesClipping(const CResizableLayout::LayoutInfo &layout);

    
// override to specify refresh for unsupported windows
    virtual BOOL NeedsRefresh(const CResizableLayout::LayoutInfo &layout,
        
const CRect &rectOld, const CRect &rectNew);

    
// paint the background on the given DC (for XP theme's compatibility)
    void EraseBackground(CDC* pDC);

    
// clip out child windows from the given DC (support old code)
    void ClipChildren(CDC* pDC);

    
// get the clipping region (without clipped child windows)
    void GetClippingRegion(CRgn* pRegion);
    
    
// override for scrollable or expanding parent windows
    virtual void GetTotalClientRect(LPRECT lpRect);

    
// add anchors to a control, given its HWND
    void AddAnchor(HWND hWnd, CSize sizeTypeTL, CSize sizeTypeBR = NOANCHOR);

    
// add anchors to a control, given its ID
    void AddAnchor(UINT nID, CSize sizeTypeTL, CSize sizeTypeBR = NOANCHOR)
    
{
        AddAnchor(::GetDlgItem(GetResizableWnd()
->GetSafeHwnd(), nID),
            sizeTypeTL, sizeTypeBR);
    }


    
// add a callback (control ID or HWND is unknown or may change)
    void AddAnchorCallback(UINT nCallbackID);

    
// get rect of an anchored window, given the parent's client area
    BOOL GetAnchorPosition(HWND hWnd, const CRect &rectParent,
        CRect 
&rectChild, UINT* lpFlags = NULL)
    
{
        POSITION pos;
        
if (!m_mapLayout.Lookup(hWnd, pos))
            
return FALSE;

        UINT uTmpFlags;
        CalcNewChildPosition(m_listLayout.GetAt(pos), rectParent, rectChild,
            (lpFlags 
!= NULL) ? (*lpFlags) : uTmpFlags);
        
return TRUE;
    }


    
// get rect of an anchored window, given the parent's client area
    BOOL GetAnchorPosition(UINT nID, const CRect &rectParent,
        CRect 
&rectChild, UINT* lpFlags = NULL)
    
{
        
return GetAnchorPosition(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID),
            rectParent, rectChild, lpFlags);
    }


    
// remove an anchored control from the layout, given its HWND
    BOOL RemoveAnchor(HWND hWnd)
    
{
        POSITION pos;
        
if (!m_mapLayout.Lookup(hWnd, pos))
            
return FALSE;

        m_listLayout.RemoveAt(pos);
        
return m_mapLayout.RemoveKey(hWnd);
    }


    
// remove an anchored control from the layout, given its HWND
    BOOL RemoveAnchor(UINT nID)
    
{
        
return RemoveAnchor(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID));
    }


    
// reset layout content
    void RemoveAllAnchors()
    
{
        m_mapLayout.RemoveAll();
        m_listLayout.RemoveAll();
        m_listLayoutCB.RemoveAll();
    }


    
// adjust children's layout, when parent's size changes
    void ArrangeLayout();

    
// override to provide dynamic control's layout info
    virtual BOOL ArrangeLayoutCallback(CResizableLayout::LayoutInfo& layout);

    
// override to provide the parent window
    virtual CWnd* GetResizableWnd() = 0;

public:
    CResizableLayout() 
{ }

    
virtual ~CResizableLayout()
    
{
        
// just for safety
        RemoveAllAnchors();
    }

}
;

#endif   //  !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_)
#include  " stdafx.h "
#include 
" commctrl.h "
#include 
" ResizableLayout.h "
#include 
" ResizableMsgSupport.inl "

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

//
//  Construction/Destruction
//

//  In August 2002 Platform SDK, some guy at MS thought it was time to
//  add the missing symbol BS_TYPEMASK, but forgot its original meaning
//  and so now he's telling us not to use that symbol because its
//  value is likely to change in the future SDK releases, including all
//  the BS_* style bits in the mask, not just the button's type as the
//  symbol's name suggests. So now we're forced to use another symbol!
#define  _BS_TYPEMASK 0x0000000FL

void  CResizableLayout::AddAnchor(HWND hWnd, CSize sizeTypeTL, CSize sizeTypeBR)
{
    CWnd
* pParent = GetResizableWnd();

    
// child window must be valid
    ASSERT(::IsWindow(hWnd));
    
// must be child of parent window
//    ASSERT(::IsChild(pParent->GetSafeHwnd(), hWnd));
    
// top-left anchor must be valid
    ASSERT(sizeTypeTL != NOANCHOR);

    
// get control's window class
    CString sClassName;
    GetClassName(hWnd, sClassName.GetBufferSetLength(MAX_PATH), MAX_PATH);
    sClassName.ReleaseBuffer();

    
// get parent window's rect
    CRect rectParent;
    GetTotalClientRect(
&rectParent);
    
// and child control's rect
    CRect rectChild;
    ::GetWindowRect(hWnd, 
&rectChild);
    ::MapWindowPoints(NULL, pParent
->m_hWnd, (LPPOINT)&rectChild, 2);

    
// adjust position, if client area has been scrolled
    rectChild.OffsetRect(-rectParent.TopLeft());

    
// go calculate margins
    CSize sizeMarginTL, sizeMarginBR;

    
if (sizeTypeBR == NOANCHOR)
        sizeTypeBR 
= sizeTypeTL;
    
    
// calculate margin for the top-left corner

    sizeMarginTL.cx 
= rectChild.left - rectParent.Width() * sizeTypeTL.cx / 100;
    sizeMarginTL.cy 
= rectChild.top - rectParent.Height() * sizeTypeTL.cy / 100;
    
    
// calculate margin for the bottom-right corner

    sizeMarginBR.cx 
= rectChild.right - rectParent.Width() * sizeTypeBR.cx / 100;
    sizeMarginBR.cy 
= rectChild.bottom - rectParent.Height() * sizeTypeBR.cy / 100;

    
// prepare the structure
    LayoutInfo layout(hWnd, sizeTypeTL, sizeMarginTL,
        sizeTypeBR, sizeMarginBR, sClassName);

    
// initialize resize properties (overridable)
    InitResizeProperties(layout);

    
// must not be already there!
    
// (this is probably due to a duplicate call to AddAnchor)
    POSITION pos;
    ASSERT(
!m_mapLayout.Lookup(hWnd, pos));

    
// add to the list and the map
    pos = m_listLayout.AddTail(layout);
    m_mapLayout.SetAt(hWnd, pos);
}


void  CResizableLayout::AddAnchorCallback(UINT nCallbackID)
{
    
// one callback control cannot rely upon another callback control's
    
// size and/or position (they're updated all together at the end)
    
// it can however use a non-callback control, which is updated before

    
// add to the list
    LayoutInfo layout;
    layout.nCallbackID 
= nCallbackID;
    m_listLayoutCB.AddTail(layout);
}


BOOL CResizableLayout::ArrangeLayoutCallback(CResizableLayout::LayoutInfo
&   /*layout*/ )
{
    ASSERT(FALSE);
    
// must be overridden, if callback is used
    
    
return FALSE;    // no output data
}


void  CResizableLayout::ArrangeLayout()
{
    
// common vars
    UINT uFlags;
    LayoutInfo layout;
    CRect rectParent, rectChild;
    GetTotalClientRect(
&rectParent); // get parent window's rect
    int count = m_listLayout.GetCount();
    
int countCB = m_listLayoutCB.GetCount();

    
// reposition child windows
    HDWP hdwp = ::BeginDeferWindowPos(count + countCB);
    
    POSITION pos 
= m_listLayout.GetHeadPosition();
    
while (pos != NULL)
    
{
        
// get layout info
        layout = m_listLayout.GetNext(pos);
        
        
// calculate new child's position, size and flags for SetWindowPos
        CalcNewChildPosition(layout, rectParent, rectChild, uFlags);

        
// only if size or position changed
        if ((uFlags & (SWP_NOMOVE|SWP_NOSIZE)) != (SWP_NOMOVE|SWP_NOSIZE))
        
{
            hdwp 
= ::DeferWindowPos(hdwp, layout.hWnd, NULL, rectChild.left,
                rectChild.top, rectChild.Width(), rectChild.Height(), uFlags);
        }

    }


    
// for callback items you may use GetAnchorPosition to know the
    
// new position and size of a non-callback item after resizing

    pos 
= m_listLayoutCB.GetHeadPosition();
    
while (pos != NULL)
    
{
        
// get layout info
        layout = m_listLayoutCB.GetNext(pos);
        
// request layout data
        if (!ArrangeLayoutCallback(layout))
            
continue;

        
// calculate new child's position, size and flags for SetWindowPos
        CalcNewChildPosition(layout, rectParent, rectChild, uFlags);

        
// only if size or position changed
        if ((uFlags & (SWP_NOMOVE|SWP_NOSIZE)) != (SWP_NOMOVE|SWP_NOSIZE))
        
{
            hdwp 
= ::DeferWindowPos(hdwp, layout.hWnd, NULL, rectChild.left,
                rectChild.top, rectChild.Width(), rectChild.Height(), uFlags);
        }

    }


    
// finally move all the windows at once
    ::EndDeferWindowPos(hdwp);
}


void  CResizableLayout::ClipChildWindow( const  CResizableLayout::LayoutInfo &  layout,
                                       CRgn
*  pRegion)
{
    
// obtain window position
    CRect rect;
    ::GetWindowRect(layout.hWnd, 
&rect);
    ::MapWindowPoints(NULL, GetResizableWnd()
->m_hWnd, (LPPOINT)&rect, 2);

    
// use window region if any
    CRgn rgn;
    rgn.CreateRectRgn(
0,0,0,0);
    
switch (::GetWindowRgn(layout.hWnd, rgn))
    
{
    
case COMPLEXREGION:
    
case SIMPLEREGION:
        rgn.OffsetRgn(rect.TopLeft());
        
break;

    
default:
        rgn.SetRectRgn(
&rect);
    }


    
// get the clipping property
    BOOL bClipping = layout.properties.bAskClipping ?
        LikesClipping(layout) : layout.properties.bCachedLikesClipping;

    
// modify region accordingly
    if (bClipping)
        pRegion
->CombineRgn(pRegion, &rgn, RGN_DIFF);
    
else
        pRegion
->CombineRgn(pRegion, &rgn, RGN_OR);
}


void  CResizableLayout::GetClippingRegion(CRgn *  pRegion)
{
    CWnd
* pWnd = GetResizableWnd();

    
// System's default clipping area is screen's size,
    
// not enough for max track size, for example:
    
// if screen is 1024 x 768 and resizing border is 4 pixels,
    
// maximized size is 1024+4*2=1032 x 768+4*2=776,
    
// but max track size is 4 pixels bigger 1036 x 780 (don't ask me why!)
    
// So, if you resize the window to maximum size, the last 4 pixels
    
// are clipped out by the default clipping region, that gets created
    
// as soon as you call clipping functions (my guess).

    
// reset clipping region to the whole client area
    CRect rect;
    pWnd
->GetClientRect(&rect);
    pRegion
->CreateRectRgnIndirect(&rect);

    
// clip only anchored controls
    LayoutInfo layout;
    POSITION pos 
= m_listLayout.GetHeadPosition();
    
while (pos != NULL)
    
{
        
// get layout info
        layout = m_listLayout.GetNext(pos);
        
        
if (::IsWindowVisible(layout.hWnd))
            ClipChildWindow(layout, pRegion);
    }

    pos 
= m_listLayoutCB.GetHeadPosition();
    
while (pos != NULL)
    
{
        
// get layout info
        layout = m_listLayoutCB.GetNext(pos);
        
// request data
        if (!ArrangeLayoutCallback(layout))
            
continue;

        
if (::IsWindowVisible(layout.hWnd))
            ClipChildWindow(layout, pRegion);
    }


    
// fix for RTL layouts (1 pixel of horz offset)
    if (pWnd->GetExStyle() & 0x00400000L/*WS_EX_LAYOUTRTL*/)
        pRegion
->OffsetRgn(-1,0);
}


void  CResizableLayout::EraseBackground(CDC *  pDC)
{
    HWND hWnd 
= GetResizableWnd()->GetSafeHwnd();

    
// retrieve the background brush
    HBRUSH hBrush = NULL;

    
// is this a dialog box?
    
// (using class atom is quickier than using the class name)
    ATOM atomWndClass = (ATOM)::GetClassLong(hWnd, GCW_ATOM);
    
if (atomWndClass == (ATOM)0x8002)
    
{
        
// send a message to the dialog box
        hBrush = (HBRUSH)::SendMessage(hWnd, WM_CTLCOLORDLG,
            (WPARAM)pDC
->GetSafeHdc(), (LPARAM)hWnd);
    }

    
else
    
{
        
// take the background brush from the window's class
        hBrush = (HBRUSH)::GetClassLongPtr(hWnd, GCL_HBRBACKGROUND);
    }


    
// fill the clipped background
    CRgn rgn;
    GetClippingRegion(
&rgn);

    ::FillRgn(pDC
->GetSafeHdc(), rgn, hBrush);
}


//  support legacy code (will disappear in future versions)
void  CResizableLayout::ClipChildren(CDC *  pDC)
{
    CRgn rgn;
    GetClippingRegion(
&rgn);
    
// the clipping region is in device units
    rgn.OffsetRgn(-pDC->GetWindowOrg());
    pDC
->SelectClipRgn(&rgn);
}


void  CResizableLayout::GetTotalClientRect(LPRECT lpRect)
{
    GetResizableWnd()
->GetClientRect(lpRect);
}


BOOL CResizableLayout::NeedsRefresh(
const  CResizableLayout::LayoutInfo &  layout,
                                    
const  CRect &  rectOld,  const  CRect &  rectNew)
{
    
if (layout.bMsgSupport)
    
{
        REFRESHPROPERTY refresh;
        refresh.rcOld 
= rectOld;
        refresh.rcNew 
= rectNew;
        
if (Send_NeedsRefresh(layout.hWnd, &refresh))
            
return refresh.bNeedsRefresh;
    }


    
int nDiffWidth = (rectNew.Width() - rectOld.Width());
    
int nDiffHeight = (rectNew.Height() - rectOld.Height());

    
// is the same size?
    if (nDiffWidth == 0 && nDiffHeight == 0)
        
return FALSE;

    
// optimistic, no need to refresh
    BOOL bRefresh = FALSE;

    
// window classes that need refresh when resized
    if (layout.sWndClass == WC_STATIC)
    
{
        DWORD style 
= ::GetWindowLong(layout.hWnd, GWL_STYLE);

        
switch (style & SS_TYPEMASK)
        
{
        
case SS_LEFT:
        
case SS_CENTER:
        
case SS_RIGHT:
            
// word-wrapped text
            bRefresh = bRefresh || (nDiffWidth != 0);
            
// vertically centered text
            if (style & SS_CENTERIMAGE)
                bRefresh 
= bRefresh || (nDiffHeight != 0);
            
break;

        
case SS_LEFTNOWORDWRAP:
            
// text with ellipsis
            if (style & SS_ELLIPSISMASK)
                bRefresh 
= bRefresh || (nDiffWidth != 0);
            
// vertically centered text
            if (style & SS_CENTERIMAGE)
                bRefresh 
= bRefresh || (nDiffHeight != 0);
            
break;

        
case SS_ENHMETAFILE:
        
case SS_BITMAP:
        
case SS_ICON:
            
// images
        case SS_BLACKFRAME:
        
case SS_GRAYFRAME:
        
case SS_WHITEFRAME:
        
case SS_ETCHEDFRAME:
            
// and frames
            bRefresh = TRUE;
            
break;
        }

    }


    
// window classes that don't redraw client area correctly
    
// when the hor scroll pos changes due to a resizing
    BOOL bHScroll = FALSE;
    
if (layout.sWndClass == WC_LISTBOX)
        bHScroll 
= TRUE;

    
// fix for horizontally scrollable windows
    if (bHScroll && (nDiffWidth > 0))
    
{
        
// get max scroll position
        SCROLLINFO info;
        info.cbSize 
= sizeof(SCROLLINFO);
        info.fMask 
= SIF_PAGE | SIF_POS | SIF_RANGE;
        
if (::GetScrollInfo(layout.hWnd, SB_HORZ, &info))
        
{
            
// subtract the page size
            info.nMax -= __max(info.nPage-1,0);
        }


        
// resizing will cause the text to scroll on the right
        
// because the scrollbar is going beyond the right limit
        if ((info.nMax > 0&& (info.nPos + nDiffWidth > info.nMax))
        
{
            
// needs repainting, due to horiz scrolling
            bRefresh = TRUE;
        }

    }


    
return bRefresh;
}


BOOL CResizableLayout::LikesClipping(
const  CResizableLayout::LayoutInfo &  layout)
{
    
if (layout.bMsgSupport)
    
{
        CLIPPINGPROPERTY clipping;
        
if (Send_LikesClipping(layout.hWnd, &clipping))
            
return clipping.bLikesClipping;
    }


    DWORD style 
= ::GetWindowLong(layout.hWnd, GWL_STYLE);

    
// skip windows that wants background repainted
    if (layout.sWndClass == TOOLBARCLASSNAME && (style & TBSTYLE_TRANSPARENT))
        
return FALSE;
    
else if (layout.sWndClass == WC_BUTTON)
    
{
        CRect rect;
        
switch (style & _BS_TYPEMASK)
        
{
        
case BS_GROUPBOX:
            
return FALSE;

        
case BS_OWNERDRAW:
            
// ownerdraw buttons must return correct hittest code
            
// to notify their transparency to the system and this library
            ::GetWindowRect(layout.hWnd, &rect);
            
if ( HTTRANSPARENT == ::SendMessage(layout.hWnd,
                WM_NCHITTEST, 
0, MAKELPARAM(rect.left, rect.top)) )
                
return FALSE;
            
break;
        }

        
return TRUE;
    }

    
else if (layout.sWndClass == WC_STATIC)
    
{
        
switch (style & SS_TYPEMASK)
        
{
        
case SS_LEFT:
        
case SS_CENTER:
        
case SS_RIGHT:
        
case SS_SIMPLE:
        
case SS_LEFTNOWORDWRAP:
            
// text
        case SS_BLACKRECT:
        
case SS_GRAYRECT:
        
case SS_WHITERECT:
            
// filled rects
        case SS_ETCHEDHORZ:
        
case SS_ETCHEDVERT:
            
// etched lines
        case SS_BITMAP:
            
// bitmaps
            return TRUE;
            
break;

        
case SS_ICON:
        
case SS_ENHMETAFILE:
            
if (style & SS_CENTERIMAGE)
                
return FALSE;
            
return TRUE;
            
break;

        
default:
            
return FALSE;
        }

    }


    
// assume the others like clipping
    return TRUE;
}


void  CResizableLayout::CalcNewChildPosition( const  CResizableLayout::LayoutInfo &  layout,
                                
const  CRect  & rectParent, CRect  & rectChild, UINT &  uFlags)
{
    CWnd
* pParent = GetResizableWnd();

    ::GetWindowRect(layout.hWnd, 
&rectChild);
    ::MapWindowPoints(NULL, pParent
->m_hWnd, (LPPOINT)&rectChild, 2);
    
    CRect rectNew;

    
// calculate new top-left corner
    rectNew.left = layout.sizeMarginTL.cx + rectParent.Width() * layout.sizeTypeTL.cx / 100;
    rectNew.top 
= layout.sizeMarginTL.cy + rectParent.Height() * layout.sizeTypeTL.cy / 100;
    
    
// calculate new bottom-right corner
    rectNew.right = layout.sizeMarginBR.cx + rectParent.Width() * layout.sizeTypeBR.cx / 100;
    rectNew.bottom 
= layout.sizeMarginBR.cy + rectParent.Height() * layout.sizeTypeBR.cy / 100;

    
// adjust position, if client area has been scrolled
    rectNew.OffsetRect(rectParent.TopLeft());

    
// get the refresh property
    BOOL bRefresh = layout.properties.bAskRefresh ?
        NeedsRefresh(layout, rectChild, rectNew) : layout.properties.bCachedNeedsRefresh;

    
// set flags 
    uFlags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION;
    
if (bRefresh)
        uFlags 
|= SWP_NOCOPYBITS;
    
if (rectNew.TopLeft() == rectChild.TopLeft())
        uFlags 
|= SWP_NOMOVE;
    
if (rectNew.Size() == rectChild.Size())
        uFlags 
|= SWP_NOSIZE;

    
// update rect
    rectChild = rectNew;
}


void  CResizableLayout::InitResizeProperties(CResizableLayout::LayoutInfo  & layout)
{
    
// check if custom window supports this library
    
// (properties must be correctly set by the window)
    layout.bMsgSupport = Send_QueryProperties(layout.hWnd, &layout.properties);

    
// default properties
    if (!layout.bMsgSupport)
    
{
        
// clipping property is assumed as static
        layout.properties.bAskClipping = FALSE;
        layout.properties.bCachedLikesClipping 
= LikesClipping(layout);
        
// refresh property is assumed as dynamic
        layout.properties.bAskRefresh = TRUE;
    }

}

#if  !defined(AFX_RESIZABLEMINMAX_H__INCLUDED_)
#define  AFX_RESIZABLEMINMAX_H__INCLUDED_

#if  _MSC_VER > 1000
#pragma  once
#endif   //  _MSC_VER > 1000

class  CResizableMinMax  
{
// Attributes
private:
    
// flags
    BOOL m_bUseMaxTrack;
    BOOL m_bUseMinTrack;
    BOOL m_bUseMaxRect;

    POINT m_ptMinTrackSize;        
// min tracking size
    POINT m_ptMaxTrackSize;        // max tracking size
    POINT m_ptMaxPos;            // maximized position
    POINT m_ptMaxSize;            // maximized size

public:
    CResizableMinMax();
    
virtual ~CResizableMinMax();

protected:
    
void MinMaxInfo(LPMINMAXINFO lpMMI);

    
void SetMaximizedRect(const CRect& rc);        // set window rect when maximized
    void ResetMaximizedRect();                    // reset to default maximized rect
    void SetMinTrackSize(const CSize& size);    // set minimum tracking size
    void ResetMinTrackSize();                    // reset to default minimum tracking size
    void SetMaxTrackSize(const CSize& size);    // set maximum tracking size
    void ResetMaxTrackSize();                    // reset to default maximum tracking size
}
;

#endif   //  !defined(AFX_RESIZABLEMINMAX_H__INCLUDED_)
#include  " stdafx.h "
#include 
" ResizableMinMax.h "

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

//
//  Construction/Destruction
//

CResizableMinMax::CResizableMinMax()
{
    m_bUseMinTrack 
= FALSE;
    m_bUseMaxTrack 
= FALSE;
    m_bUseMaxRect 
= FALSE;
}


CResizableMinMax::
~ CResizableMinMax()
{

}


void  CResizableMinMax::MinMaxInfo(LPMINMAXINFO lpMMI)
{
    
if (m_bUseMinTrack)
        lpMMI
->ptMinTrackSize = m_ptMinTrackSize;

    
if (m_bUseMaxTrack)
        lpMMI
->ptMaxTrackSize = m_ptMaxTrackSize;

    
if (m_bUseMaxRect)
    
{
        lpMMI
->ptMaxPosition = m_ptMaxPos;
        lpMMI
->ptMaxSize = m_ptMaxSize;
    }

}


void  CResizableMinMax::SetMaximizedRect( const  CRect &  rc)
{
    m_bUseMaxRect 
= TRUE;

    m_ptMaxPos 
= rc.TopLeft();
    m_ptMaxSize.x 
= rc.Width();
    m_ptMaxSize.y 
= rc.Height();
}


void  CResizableMinMax::ResetMaximizedRect()
{
    m_bUseMaxRect 
= FALSE;
}


void  CResizableMinMax::SetMinTrackSize( const  CSize &  size)
{
    m_bUseMinTrack 
= TRUE;

    m_ptMinTrackSize.x 
= size.cx;
    m_ptMinTrackSize.y 
= size.cy;
}


void  CResizableMinMax::ResetMinTrackSize()
{
    m_bUseMinTrack 
= FALSE;
}


void  CResizableMinMax::SetMaxTrackSize( const  CSize &  size)
{
    m_bUseMaxTrack 
= TRUE;

    m_ptMaxTrackSize.x 
= size.cx;
    m_ptMaxTrackSize.y 
= size.cy;
}


void  CResizableMinMax::ResetMaxTrackSize()
{
    m_bUseMaxTrack 
= FALSE;
}

#if  !defined(AFX_RESIZABLEMSGSUPPORT_H__INCLUDED_)
#define  AFX_RESIZABLEMSGSUPPORT_H__INCLUDED_

#if  _MSC_VER > 1000
#pragma  once
#endif   //  _MSC_VER > 1000

typedef 
struct  tagRESIZEPROPERTIES
{
    
// wether to ask for resizing properties every time
    BOOL bAskClipping;
    BOOL bAskRefresh;
    
// otherwise, use the cached properties
    BOOL bCachedLikesClipping;
    BOOL bCachedNeedsRefresh;

    
// initialize with valid data
    tagRESIZEPROPERTIES() : bAskClipping(TRUE), bAskRefresh(TRUE) {}

}
 RESIZEPROPERTIES,  * PRESIZEPROPERTIES,  * LPRESIZEPROPERTIES;


typedef 
struct  tagCLIPPINGPROPERTY
{
    BOOL bLikesClipping;

    
// initialize with valid data
    tagCLIPPINGPROPERTY() : bLikesClipping(FALSE) {}

}
 CLIPPINGPROPERTY,  * PCLIPPINGPROPERTY,  * LPCLIPPINGPROPERTY;


typedef 
struct  tagREFRESHPROPERTY
{
    BOOL bNeedsRefresh;
    RECT rcOld;
    RECT rcNew;

    
// initialize with valid data
    tagREFRESHPROPERTY() : bNeedsRefresh(TRUE) {}

}
 REFRESHPROPERTY,  * PREFRESHPROPERTY,  * LPREFRESHPROPERTY;


#endif   //  !defined(AFX_RESIZABLEMSGSUPPORT_H__INCLUDED_)
#if  !defined(AFX_RESIZABLEMSGSUPPORT_H__INCLUDED_)
#define  AFX_RESIZABLEMSGSUPPORT_H__INCLUDED_

#if  _MSC_VER > 1000
#pragma  once
#endif   //  _MSC_VER > 1000

typedef 
struct  tagRESIZEPROPERTIES
{
    
// wether to ask for resizing properties every time
    BOOL bAskClipping;
    BOOL bAskRefresh;
    
// otherwise, use the cached properties
    BOOL bCachedLikesClipping;
    BOOL bCachedNeedsRefresh;

    
// initialize with valid data
    tagRESIZEPROPERTIES() : bAskClipping(TRUE), bAskRefresh(TRUE) {}

}
 RESIZEPROPERTIES,  * PRESIZEPROPERTIES,  * LPRESIZEPROPERTIES;


typedef 
struct  tagCLIPPINGPROPERTY
{
    BOOL bLikesClipping;

    
// initialize with valid data
    tagCLIPPINGPROPERTY() : bLikesClipping(FALSE) {}

}
 CLIPPINGPROPERTY,  * PCLIPPINGPROPERTY,  * LPCLIPPINGPROPERTY;


typedef 
struct  tagREFRESHPROPERTY
{
    BOOL bNeedsRefresh;
    RECT rcOld;
    RECT rcNew;

    
// initialize with valid data
    tagREFRESHPROPERTY() : bNeedsRefresh(TRUE) {}

}
 REFRESHPROPERTY,  * PREFRESHPROPERTY,  * LPREFRESHPROPERTY;


#endif   //  !defined(AFX_RESIZABLEMSGSUPPORT_H__INCLUDED_)
//  registered message to communicate with the library
//  (defined so that in the same executable it is initialized only once)
const  UINT WMU_RESIZESUPPORT  =  ::RegisterWindowMessage(_T( " WMU_RESIZESUPPORT " ));

//  if the message is implemented the returned value must be non-zero
//  the default window procedure returns zero for unhandled messages

//  wParam is one of the following RSZSUP_* values, lParam as specified

#define  RSZSUP_QUERYPROPERTIES    101     //  lParam = LPRESIZEPROPERTIES

#define  RSZSUP_LIKESCLIPPING    102     //  lParam = LPCLIPPINGPROPERTY

#define  RSZSUP_NEEDSREFRESH        103     //  lParam = LPREFRESHPROPERTY


/////
//  utility functions

inline BOOL Send_QueryProperties(HWND hWnd, LPRESIZEPROPERTIES pResizeProperties)
{
    ASSERT(::IsWindow(hWnd));
    
return (0 != SendMessage(hWnd, WMU_RESIZESUPPORT,
        RSZSUP_QUERYPROPERTIES, (LPARAM)pResizeProperties));
}


inline BOOL Send_LikesClipping(HWND hWnd, LPCLIPPINGPROPERTY pClippingProperty)
{
    ASSERT(::IsWindow(hWnd));
    
return (0 != SendMessage(hWnd, WMU_RESIZESUPPORT,
        RSZSUP_LIKESCLIPPING, (LPARAM)pClippingProperty));
}


inline BOOL Send_NeedsRefresh(HWND hWnd, LPREFRESHPROPERTY pRefreshProperty)
{
    ASSERT(::IsWindow(hWnd));
    
return (0 != SendMessage(hWnd, WMU_RESIZESUPPORT,
        RSZSUP_NEEDSREFRESH, (LPARAM)pRefreshProperty));
}

#include  " ResizableLayout.h "


/////
//  CResizablePage window

class  CResizablePage :  public  CPropertyPage,  public  CResizableLayout
{
    DECLARE_DYNCREATE(CResizablePage)

// Construction
public:
    CResizablePage();
    CResizablePage(UINT nIDTemplate, UINT nIDCaption 
= 0);
    CResizablePage(LPCTSTR lpszTemplateName, UINT nIDCaption 
= 0);

// Attributes
public:

// Operations
public:

// Overrides
    
// ClassWizard generated virtual function overrides
    
//{{AFX_VIRTUAL(CResizablePage)
    
//}}AFX_VIRTUAL

// Implementation
public:
    
virtual ~CResizablePage();

// callable from derived classes
protected:

    
virtual CWnd* GetResizableWnd()
    
{
        
// make the layout know its parent window
        return this;
    }
;

// Generated message map functions
protected:
    
//{{AFX_MSG(CResizablePage)
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg BOOL OnEraseBkgnd(CDC
* pDC);
    
//}}AFX_MSG
    DECLARE_MESSAGE_MAP()
}
;

/////

// {{AFX_INSERT_LOCATION}}
//  Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif   //  !defined(AFX_RESIZABLEPAGE_H__INCLUDED_)
#include  " stdafx.h "
#include 
" ResizablePage.h "

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

/////
//  CResizablePage

IMPLEMENT_DYNCREATE(CResizablePage, CPropertyPage)

CResizablePage::CResizablePage()
{
}


CResizablePage::CResizablePage(UINT nIDTemplate, UINT nIDCaption)
    : CPropertyPage(nIDTemplate, nIDCaption)
{
}


CResizablePage::CResizablePage(LPCTSTR lpszTemplateName, UINT nIDCaption)
    : CPropertyPage(lpszTemplateName, nIDCaption)
{
}


CResizablePage::
~ CResizablePage()
{
}



BEGIN_MESSAGE_MAP(CResizablePage, CPropertyPage)
    
// {{AFX_MSG_MAP(CResizablePage)
    ON_WM_SIZE()
    ON_WM_ERASEBKGND()
    
// }}AFX_MSG_MAP
END_MESSAGE_MAP()


/////
//  CResizablePage message handlers

void  CResizablePage::OnSize(UINT nType,  int  cx,  int  cy) 
{
    CWnd::OnSize(nType, cx, cy);
    
    ArrangeLayout();
}


BOOL CResizablePage::OnEraseBkgnd(CDC
*  pDC) 
{
    
// Windows XP doesn't like clipping regions ...try this!
    EraseBackground(pDC);
    
return TRUE;

/*    ClipChildren(pDC);    // old-method (for safety)
    
    return CPropertyPage::OnEraseBkgnd(pDC);
*/

}

#include  " ResizableLayout.h "
#include 
" ResizableGrip.h "
#include 
" ResizableMinMax.h "
#include 
" ResizableState.h "

/////
//  ResizableSheet.h : header file
//

class  CResizableSheet :  public  CPropertySheet,  public  CResizableLayout,
                        
public  CResizableGrip,  public  CResizableMinMax,
                        
public  CResizableState
{
    DECLARE_DYNAMIC(CResizableSheet)

// Construction
public:
    CResizableSheet();
    CResizableSheet(UINT nIDCaption, CWnd 
*pParentWnd = NULL, UINT iSelectPage = 0);
    CResizableSheet(LPCTSTR pszCaption, CWnd 
*pParentWnd = NULL, UINT iSelectPage = 0);

// Attributes
private:
    
// support for temporarily hiding the grip
    DWORD m_dwGripTempState;

    
// flags
    BOOL m_bEnableSaveRestore;
    BOOL m_bRectOnly;
    BOOL m_bSavePage;

    
// layout vars
    CSize m_sizePageTL, m_sizePageBR;

    
// internal status
    CString m_sSection;            // section name (identifies a parent window)

// Operations
public:

// Overrides
    
// ClassWizard generated virtual function overrides
    
//{{AFX_VIRTUAL(CResizableSheet)
    public:
    
virtual BOOL OnInitDialog();
    
//}}AFX_VIRTUAL
    protected:

// Implementation
public:
    
void RefreshLayout();
    
virtual ~CResizableSheet();

// used internally
private:
    
void PresetLayout();
    
void PrivateConstruct();
    
void SavePage();
    
void LoadPage();

    BOOL IsWizard() 
return (m_psh.dwFlags & PSH_WIZARD); }

// callable from derived classes
protected:
    
// section to use in app's profile
    void EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE,
        BOOL bWithPage 
= FALSE);
    
int GetMinWidth();    // minimum width to display all buttons


    
virtual CWnd* GetResizableWnd()
    
{
        
// make the layout know its parent window
        return this;
    }
;

// Generated message map functions
protected:
    
virtual BOOL ArrangeLayoutCallback(LayoutInfo& layout);
    
//{{AFX_MSG(CResizableSheet)
    afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
    afx_msg 
void OnSize(UINT nType, int cx, int cy);
    afx_msg 
void OnDestroy();
    afx_msg 
int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg BOOL OnEraseBkgnd(CDC
* pDC);
    
//}}AFX_MSG
    afx_msg BOOL OnPageChanging(NMHDR* pNotifyStruct, LRESULT* pResult);
    DECLARE_MESSAGE_MAP()
}
;

/////

#endif      //  AFX_RESIZABLESHEET_H__INCLUDED_
#include  " stdafx.h "
#include 
" ResizableSheet.h "

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

/////
//  CResizableSheet

IMPLEMENT_DYNAMIC(CResizableSheet, CPropertySheet)

inline 
void  CResizableSheet::PrivateConstruct()
{
    m_bEnableSaveRestore 
= FALSE;
    m_bSavePage 
= FALSE;
    m_dwGripTempState 
= 1;
}



CResizableSheet::CResizableSheet()
{
    PrivateConstruct();
}


CResizableSheet::CResizableSheet(UINT nIDCaption, CWnd 
* pParentWnd, UINT iSelectPage)
     : CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
    PrivateConstruct();
}


CResizableSheet::CResizableSheet(LPCTSTR pszCaption, CWnd 
* pParentWnd, UINT iSelectPage)
     : CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
    PrivateConstruct();
}


CResizableSheet::
~ CResizableSheet()
{
}


BEGIN_MESSAGE_MAP(CResizableSheet, CPropertySheet)
    
// {{AFX_MSG_MAP(CResizableSheet)
    ON_WM_GETMINMAXINFO()
    ON_WM_SIZE()
    ON_WM_DESTROY()
    ON_WM_CREATE()
    ON_WM_ERASEBKGND()
    
// }}AFX_MSG_MAP
    ON_NOTIFY_REFLECT_EX(PSN_SETACTIVE, OnPageChanging)
END_MESSAGE_MAP()

/////
//  CResizableSheet message handlers

int  CResizableSheet::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
    
if (CPropertySheet::OnCreate(lpCreateStruct) == -1)
        
return -1;
    
    
// keep client area
    CRect rect;
    GetClientRect(
&rect);
    
// set resizable style
    ModifyStyle(DS_MODALFRAME, WS_POPUP | WS_THICKFRAME);
    
// adjust size to reflect new style
    ::AdjustWindowRectEx(&rect, GetStyle(),
        ::IsMenu(GetMenu()
->GetSafeHmenu()), GetExStyle());
    SetWindowPos(NULL, 
00, rect.Width(), rect.Height(), SWP_FRAMECHANGED|
        SWP_NOMOVE
|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREPOSITION);

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

    
return 0;
}


BOOL CResizableSheet::OnInitDialog() 
{
    BOOL bResult 
= CPropertySheet::OnInitDialog();
    
    
// set the initial size as the min track size
    CRect rc;
    GetWindowRect(
&rc);
    SetMinTrackSize(rc.Size());

    
// initialize layout
    PresetLayout();

    
// prevent flickering
    GetTabControl()->ModifyStyle(0, WS_CLIPSIBLINGS);

    
return bResult;
}


void  CResizableSheet::OnDestroy() 
{
    
if (m_bEnableSaveRestore)
    
{
        SaveWindowRect(m_sSection, m_bRectOnly);
        SavePage();
    }


    RemoveAllAnchors();

    CPropertySheet::OnDestroy();
}


//  maps an index to a button ID and vice-versa
static  UINT _propButtons[]  =
{
    IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP,
    ID_WIZBACK, ID_WIZNEXT, ID_WIZFINISH
}
;
const   int  _propButtonsCount  =   sizeof (_propButtons) / sizeof (UINT);

//  horizontal line in wizard mode
#define  ID_WIZLINE    ID_WIZFINISH+1

void  CResizableSheet::PresetLayout()
{
    
if (IsWizard())    // wizard mode
    {
        
// hide tab control
        GetTabControl()->ShowWindow(SW_HIDE);

        AddAnchor(ID_WIZLINE, BOTTOM_LEFT, BOTTOM_RIGHT);
    }

    
else    // tab mode
    {
        AddAnchor(AFX_IDC_TAB_CONTROL, TOP_LEFT, BOTTOM_RIGHT);
    }


    
// add a callback for active page (which can change at run-time)
    AddAnchorCallback(1);

    
// use *total* parent size to have correct margins
    CRect rectPage, rectSheet;
    GetTotalClientRect(
&rectSheet);

    GetActivePage()
->GetWindowRect(&rectPage);
    ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)
&rectPage, 2);

    
// pre-calculate margins
    m_sizePageTL = rectPage.TopLeft() - rectSheet.TopLeft();
    m_sizePageBR 
= rectPage.BottomRight() - rectSheet.BottomRight();

    
// add all possible buttons, if they exist
    for (int i = 0; i < _propButtonsCount; i++)
    
{
        
if (NULL != GetDlgItem(_propButtons[i]))
            AddAnchor(_propButtons[i], BOTTOM_RIGHT);
    }

}


BOOL CResizableSheet::ArrangeLayoutCallback(LayoutInfo 
& layout)
{
    
if (layout.nCallbackID != 1)    // we only added 1 callback
        return CResizableLayout::ArrangeLayoutCallback(layout);

    
// set layout info for active page
    layout.hWnd = (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 00);
    
if (!::IsWindow(layout.hWnd))
        
return FALSE;

    
// set margins
    if (IsWizard())    // wizard mode
    {
        
// use pre-calculated margins
        layout.sizeMarginTL = m_sizePageTL;
        layout.sizeMarginBR 
= m_sizePageBR;
    }

    
else    // tab mode
    {
        CTabCtrl
* pTab = GetTabControl();
        ASSERT(pTab 
!= NULL);

        
// get tab position after resizing and calc page rect
        CRect rectPage, rectSheet;
        GetTotalClientRect(
&rectSheet);

        VERIFY(GetAnchorPosition(pTab
->m_hWnd, rectSheet, rectPage));
        pTab
->AdjustRect(FALSE, &rectPage);

        
// set margins
        layout.sizeMarginTL = rectPage.TopLeft() - rectSheet.TopLeft();
        layout.sizeMarginBR 
= rectPage.BottomRight() - rectSheet.BottomRight();
    }


    
// set anchor types
    layout.sizeTypeTL = TOP_LEFT;
    layout.sizeTypeBR 
= BOTTOM_RIGHT;

    
// use this layout info
    return TRUE;
}


void  CResizableSheet::OnSize(UINT nType,  int  cx,  int  cy) 
{
    CWnd::OnSize(nType, cx, cy);
    
    
if (nType == SIZE_MAXHIDE || nType == SIZE_MAXSHOW)
        
return;        // arrangement not needed

    
if (nType == SIZE_MAXIMIZED)
        HideSizeGrip(
&m_dwGripTempState);
    
else
        ShowSizeGrip(
&m_dwGripTempState);

    
// update grip and layout
    UpdateSizeGrip();
    ArrangeLayout();
}


BOOL CResizableSheet::OnPageChanging(NMHDR
*   /*pNotifyStruct*/ , LRESULT *   /*pResult*/ )
{
    
// update new wizard page
    
// active page changes after this notification
    PostMessage(WM_SIZE);

    
return FALSE;    // continue routing
}


BOOL CResizableSheet::OnEraseBkgnd(CDC
*  pDC) 
{
    
// Windows XP doesn't like clipping regions ...try this!
    EraseBackground(pDC);
    
return TRUE;

/*    ClipChildren(pDC);    // old-method (for safety)

    return CPropertySheet::OnEraseBkgnd(pDC);
*/

}


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


//  protected members

int  CResizableSheet::GetMinWidth()
{
    CWnd
* pWnd = NULL;
    CRect rectWnd, rectSheet;
    GetTotalClientRect(
&rectSheet);

    
int max = 0, min = rectSheet.Width();
    
// search for leftmost and rightmost button margins
    for (int i = 0; i < 7; i++)
    
{
        pWnd 
= GetDlgItem(_propButtons[i]);
        
// exclude not present or hidden buttons
        if (pWnd == NULL || !(pWnd->GetStyle() & WS_VISIBLE))
            
continue;

        
// left position is relative to the right border
        
// of the parent window (negative value)
        pWnd->GetWindowRect(&rectWnd);
        ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)
&rectWnd, 2);
        
int left = rectSheet.right - rectWnd.left;
        
int right = rectSheet.right - rectWnd.right;

        
if (left > max)
            max 
= left;
        
if (right < min)
            min 
= right;
    }


    
// sizing border width
    int border = GetSystemMetrics(SM_CXSIZEFRAME);
    
    
// compute total width
    return max + min + 2*border;
}



//  NOTE: this must be called after all the other settings
//        to have the window and its controls displayed properly
void  CResizableSheet::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly, BOOL bWithPage)
{
    m_sSection 
= pszSection;
    m_bSavePage 
= bWithPage;

    m_bEnableSaveRestore 
= TRUE;
    m_bRectOnly 
= bRectOnly;

    
// restore immediately
    LoadWindowRect(pszSection, bRectOnly);
    LoadPage();
}


//  private memebers

//  used to save/restore active page
//  either in the registry or a private .INI file
//  depending on your application settings

#define  ACTIVEPAGE     _T("ActivePage")

void  CResizableSheet::SavePage()
{
    
if (!m_bSavePage)
        
return;

    
// saves active page index, zero (the first) if problems
    
// cannot use GetActivePage, because it always fails

    CTabCtrl 
*pTab = GetTabControl();
    
int page = 0;

    
if (pTab != NULL) 
        page 
= pTab->GetCurSel();
    
if (page < 0)
        page 
= 0;

    AfxGetApp()
->WriteProfileInt(m_sSection, ACTIVEPAGE, page);
}


void  CResizableSheet::LoadPage()
{
    
// restore active page, zero (the first) if not found
    int page = AfxGetApp()->GetProfileInt(m_sSection, ACTIVEPAGE, 0);
    
    
if (m_bSavePage)
    
{
        SetActivePage(page);
        ArrangeLayout();    
// needs refresh
    }

}


void  CResizableSheet::RefreshLayout()
{
    SendMessage(WM_SIZE);
}

#if  !defined(AFX_RESIZABLESTATE_H__INCLUDED_)
#define  AFX_RESIZABLESTATE_H__INCLUDED_

#if  _MSC_VER > 1000
#pragma  once
#endif   //  _MSC_VER > 1000

class  CResizableState  
{
protected:
    
// non-zero if successful
    BOOL LoadWindowRect(LPCTSTR pszSection, BOOL bRectOnly);
    BOOL SaveWindowRect(LPCTSTR pszSection, BOOL bRectOnly);

    
virtual CWnd* GetResizableWnd() = 0;

public:
    CResizableState();
    
virtual ~CResizableState();
}
;

#endif   //  !defined(AFX_RESIZABLESTATE_H__INCLUDED_)
#include  " stdafx.h "
#include 
" ResizableState.h "

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

//
//  Construction/Destruction
//

CResizableState::CResizableState()
{

}


CResizableState::
~ CResizableState()
{

}



//  used to save/restore window's size and position
//  either in the registry or a private .INI file
//  depending on your application settings

#define  PLACEMENT_ENT    _T("WindowPlacement")
#define  PLACEMENT_FMT     _T("%d,%d,%d,%d,%d,%d")

BOOL CResizableState::SaveWindowRect(LPCTSTR pszSection, BOOL bRectOnly)
{
    CString data;
    WINDOWPLACEMENT wp;

    ZeroMemory(
&wp, sizeof(WINDOWPLACEMENT));
    wp.length 
= sizeof(WINDOWPLACEMENT);
    
if (!GetResizableWnd()->GetWindowPlacement(&wp))
        
return FALSE;
    
    RECT
& rc = wp.rcNormalPosition;    // alias

    
if (bRectOnly)    // save size/pos only (normal state)
    {
        
// use screen coordinates
        GetResizableWnd()->GetWindowRect(&rc);

        data.Format(PLACEMENT_FMT, rc.left, rc.top,
            rc.right, rc.bottom, SW_NORMAL, 
0);
    }

    
else    // save also min/max state
    {
        
// use workspace coordinates
        data.Format(PLACEMENT_FMT, rc.left, rc.top,
            rc.right, rc.bottom, wp.showCmd, wp.flags);
    }


    
return AfxGetApp()->WriteProfileString(pszSection, PLACEMENT_ENT, data);
}


BOOL CResizableState::LoadWindowRect(LPCTSTR pszSection, BOOL bRectOnly)
{
    CString data;
    WINDOWPLACEMENT wp;

    data 
= AfxGetApp()->GetProfileString(pszSection, PLACEMENT_ENT);
    
    
if (data.IsEmpty())    // never saved before
        return FALSE;
    
    ZeroMemory(
&wp, sizeof(WINDOWPLACEMENT));
    wp.length 
= sizeof(WINDOWPLACEMENT);
    
if (!GetResizableWnd()->GetWindowPlacement(&wp))
        
return FALSE;

    RECT
& rc = wp.rcNormalPosition;    // alias

    
if (_stscanf(data, PLACEMENT_FMT, &rc.left, &rc.top,
        
&rc.right, &rc.bottom, &wp.showCmd, &wp.flags) == 6)
    
{
        
if (bRectOnly)    // restore size/pos only
        {
            CRect rect(rc);
            
return GetResizableWnd()->SetWindowPos(NULL, rect.left, rect.top,
                rect.Width(), rect.Height(), SWP_NOACTIVATE 
| SWP_NOZORDER |
                SWP_NOREPOSITION);
        }

        
else    // restore also min/max state
        {
            
return GetResizableWnd()->SetWindowPlacement(&wp);
        }

    }

    
return FALSE;
}

#pragma  once

//  CCmdUIDialog dialog

#include 
< afxdlgs.h >

class  CCmdUIDialog :  public  CDialog
{
    DECLARE_DYNAMIC(CCmdUIDialog)

public:
    CCmdUIDialog();
    CCmdUIDialog(UINT nIDTemplate, CWnd
* pParent = NULL);
    CCmdUIDialog(LPCTSTR lpszTemplateName, CWnd
* pParent = NULL);
    
virtual ~CCmdUIDialog();

protected:
    
virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);

    DECLARE_MESSAGE_MAP()

public:
    afx_msg 
void OnKickIdle();
    afx_msg 
void OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex,BOOL bSysMenu);
}
;


//  CCmdUIPropertyPage

class  CCmdUIPropertyPage :  public  CPropertyPage
{
    DECLARE_DYNAMIC(CCmdUIPropertyPage)

public:
    CCmdUIPropertyPage(UINT nIDTemplate, UINT nIDCaption 
= 0);   // standard constructor
    virtual ~CCmdUIPropertyPage();

protected:
    
virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);

    DECLARE_MESSAGE_MAP()

public:
    afx_msg 
void OnKickIdle();
}
;
#include  " stdafx.h "
#include 
< afxpriv.h >
#include 
" CmdUI.h "

//  CCmdUIDialog dialog

IMPLEMENT_DYNAMIC(CCmdUIDialog, CDialog)

CCmdUIDialog::CCmdUIDialog()
{
}


CCmdUIDialog::CCmdUIDialog(UINT nIDTemplate, CWnd
*  pParent  /*=NULL*/ )
    : CDialog(nIDTemplate, pParent)
{
}


CCmdUIDialog::CCmdUIDialog(LPCTSTR lpszTemplateName, CWnd
*  pParentWnd)
    : CDialog(lpszTemplateName, pParentWnd)
{
}


CCmdUIDialog::
~ CCmdUIDialog()
{
}


LRESULT CCmdUIDialog::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT ret 
= __super::DefWindowProc(message, wParam, lParam);

    
if(message == WM_INITDIALOG)
    
{
        SendMessage(WM_KICKIDLE);
    }


    
return(ret);
}


BEGIN_MESSAGE_MAP(CCmdUIDialog, CDialog)
    ON_MESSAGE_VOID(WM_KICKIDLE, OnKickIdle)
    ON_WM_INITMENUPOPUP()
END_MESSAGE_MAP()


//  CCmdUIDialog message handlers

void  CCmdUIDialog::OnKickIdle()
{
    UpdateDialogControls(
thisfalse);

    
// TODO: maybe we should send this call to modeless child cdialogs too
}


//  Q242577

void  CCmdUIDialog::OnInitMenuPopup(CMenu  * pPopupMenu, UINT nIndex,BOOL bSysMenu)
{
    ASSERT(pPopupMenu 
!= NULL);
    
// Check the enabled state of various menu items.

    CCmdUI state;
    state.m_pMenu 
= pPopupMenu;
    ASSERT(state.m_pOther 
== NULL);
    ASSERT(state.m_pParentMenu 
== NULL);

    
// Determine if menu is popup in top-level menu and set m_pOther to
    
// it if so (m_pParentMenu == NULL indicates that it is secondary popup).
    HMENU hParentMenu;
    
if (AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu)
        state.m_pParentMenu 
= pPopupMenu;    // Parent == child for tracking popup.
    else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
    
{
        CWnd
* pParent = this;
           
// Child windows don't have menus--need to go to the top!
        if (pParent != NULL &&
           (hParentMenu 
= ::GetMenu(pParent->m_hWnd)) != NULL)
        
{
           
int nIndexMax = ::GetMenuItemCount(hParentMenu);
           
for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
           
{
            
if (::GetSubMenu(hParentMenu, nIndex) == pPopupMenu->m_hMenu)
            
{
                
// When popup is found, m_pParentMenu is containing menu.
                state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
                
break;
            }

           }

        }

    }


    state.m_nIndexMax 
= pPopupMenu->GetMenuItemCount();
    
for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
      state.m_nIndex
++)
    
{
        state.m_nID 
= pPopupMenu->GetMenuItemID(state.m_nIndex);
        
if (state.m_nID == 0)
           
continue// Menu separator or invalid cmd - ignore it.

        ASSERT(state.m_pOther 
== NULL);
        ASSERT(state.m_pMenu 
!= NULL);
        
if (state.m_nID == (UINT)-1)
        
{
           
// Possibly a popup menu, route to first item of that popup.
           state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex);
           
if (state.m_pSubMenu == NULL ||
            (state.m_nID 
= state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
            state.m_nID 
== (UINT)-1)
           
{
            
continue;       // First item of popup can't be routed to.
           }

           state.DoUpdate(
this, TRUE);   // Popups are never auto disabled.
        }

        
else
        
{
           
// Normal menu item.
           
// Auto enable/disable if frame window has m_bAutoMenuEnable
           
// set and command is _not_ a system command.
           state.m_pSubMenu = NULL;
           state.DoUpdate(
this, FALSE);
        }


        
// Adjust for menu deletions and additions.
        UINT nCount = pPopupMenu->GetMenuItemCount();
        
if (nCount < state.m_nIndexMax)
        
{
           state.m_nIndex 
-= (state.m_nIndexMax - nCount);
           
while (state.m_nIndex < nCount &&
            pPopupMenu
->GetMenuItemID(state.m_nIndex) == state.m_nID)
           
{
            state.m_nIndex
++;
           }

        }

        state.m_nIndexMax 
= nCount;
    }

}


//  CCmdUIPropertyPage

IMPLEMENT_DYNAMIC(CCmdUIPropertyPage, CPropertyPage)
CCmdUIPropertyPage::CCmdUIPropertyPage(UINT nIDTemplate, UINT nIDCaption)
    : CPropertyPage(nIDTemplate, nIDCaption)
{
}


CCmdUIPropertyPage::
~ CCmdUIPropertyPage()
{
}


LRESULT CCmdUIPropertyPage::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    
if(message == WM_COMMAND)
    
{
        
switch(HIWORD(wParam))
        
{
            
case BN_CLICKED: case CBN_SELCHANGE: case EN_CHANGE:
                SetModified();
            
default:;
        }

    }


    LRESULT ret 
= __super::DefWindowProc(message, wParam, lParam);

    
if(message == WM_INITDIALOG)
    
{
        SendMessage(WM_KICKIDLE);
    }


    
return(ret);
}


BEGIN_MESSAGE_MAP(CCmdUIPropertyPage, CPropertyPage)
    ON_MESSAGE_VOID(WM_KICKIDLE, OnKickIdle)
END_MESSAGE_MAP()


//  CCmdUIPropertyPage message handlers

void  CCmdUIPropertyPage::OnKickIdle()
{
    UpdateDialogControls(
thisfalse);

    
// TODO: maybe we should send this call to modeless child cPropertyPages too
}

#include  " ResizableLayout.h "
#include 
" ResizableGrip.h "
#include 
" ResizableMinMax.h "
#include 
" ResizableState.h "
#include 
" ..CmdUICmdUI.h "

/////
//  CResizableDialog window

class  CResizableDialog :  public  CCmdUIDialog,  public  CResizableLayout,
                         
public  CResizableGrip,  public  CResizableMinMax,
                         
public  CResizableState
{

// Construction
public:
    CResizableDialog();
    CResizableDialog(UINT nIDTemplate, CWnd
* pParentWnd = NULL);
    CResizableDialog(LPCTSTR lpszTemplateName, CWnd
* pParentWnd = NULL);

// Attributes
private:
    
// support for temporarily hiding the grip
    DWORD m_dwGripTempState;

    
// flags
    BOOL m_bEnableSaveRestore;
    BOOL m_bRectOnly;

    
// internal status
    CString m_sSection;            // section name (identifies a parent window)

// Operations
public:

// Overrides
    
// ClassWizard generated virtual function overrides
    
//{{AFX_VIRTUAL(CResizableDialog)
    protected:
    
//}}AFX_VIRTUAL

// Implementation
public:
    
virtual ~CResizableDialog();

// used internally
private:
    
void PrivateConstruct();

// callable from derived classes
protected:
    
// section to use in app's profile
    void EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE);

    
virtual CWnd* GetResizableWnd()
    
{
        
// make the layout know its parent window
        return this;
    }
;

// Generated message map functions
protected:
    
//{{AFX_MSG(CResizableDialog)
    afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
    afx_msg 
void OnSize(UINT nType, int cx, int cy);
    afx_msg 
void OnDestroy();
    afx_msg 
int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg BOOL OnEraseBkgnd(CDC
* pDC);
    
//}}AFX_MSG
    DECLARE_MESSAGE_MAP()
}
;

/////

// {{AFX_INSERT_LOCATION}}
//  Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif   //  !defined(AFX_RESIZABLEDIALOG_H__INCLUDED_)
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值