123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- /////////////////////////////////////////////////////////////////////////////
- //
- // This file is part of ResizableLib
- // https://github.com/ppescher/resizablelib
- //
- // Copyright (C) 2000-2015 by Paolo Messina
- // mailto:ppescher@hotmail.com
- //
- // The contents of this file are subject to the Artistic License 2.0
- // http://opensource.org/licenses/Artistic-2.0
- //
- // If you find this code useful, credits would be nice!
- //
- /////////////////////////////////////////////////////////////////////////////
- /*!
- * @file
- * @brief Interface for the CResizableLayout class.
- */
- #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
- /*! @addtogroup CoreComponents
- * @{
- */
- //! @brief Special type for layout alignment
- /*!
- * Implements anchor points as a percentage of the parent window client area.
- * Control corners are always kept at a fixed distance from their anchor points,
- * thus allowing a control to resize proportionally as the parent window is resized.
- */
- typedef struct tagANCHOR
- {
- int cx; //!< horizontal component, in percent
- int cy; //!< vertical component, in percent
- tagANCHOR() {}
- tagANCHOR(int x, int y)
- {
- cx = x;
- cy = y;
- }
- } ANCHOR, *PANCHOR, *LPANCHOR;
- /*! @defgroup ConstAnchors Alignment Constants
- * Define common layout alignment constants for anchor points.
- * @{
- */
- //! Anchor to the top-left corner
- const ANCHOR TOP_LEFT(0, 0);
- //! Anchor to the top edge and center horizontally
- const ANCHOR TOP_CENTER(50, 0);
- //! Anchor to the top-right corner
- const ANCHOR TOP_RIGHT(100, 0);
- //! Anchor to the left edge and center vertically
- const ANCHOR MIDDLE_LEFT(0, 50);
- //! Anchor to the center
- const ANCHOR MIDDLE_CENTER(50, 50);
- //! Anchor to the right edge and center vertically
- const ANCHOR MIDDLE_RIGHT(100, 50);
- //! Anchor to the bottom-left corner
- const ANCHOR BOTTOM_LEFT(0, 100);
- //! Anchor to the bottom edge and center horizontally
- const ANCHOR BOTTOM_CENTER(50, 100);
- //! Anchor to the bottom-right corner
- const ANCHOR BOTTOM_RIGHT(100, 100);
- // @}
- //! @brief Holds a control layout settings
- /*!
- * Layout settings specify how a control must be moved and resized with respect to
- * the parent window and how it reacts to dynamic changes to its size when painting
- * its client area, with special care for flickering.
- */
- typedef struct tagLAYOUTINFO
- {
- //! Handle of the window the layout of which is being defined
- HWND hWnd;
- //! Identification number assigned to the callback slot
- UINT nCallbackID;
- //! Window class name to identify standard controls
- TCHAR sWndClass[MAX_PATH];
- //! Anchor point for the top-left corner
- ANCHOR anchorTopLeft;
- //! Fixed distance for the top-left corner
- SIZE marginTopLeft;
-
- //! Anchor point for the bottom-right corner
- ANCHOR anchorBottomRight;
- //! Fixed distance for the bottom-right corner
- SIZE marginBottomRight;
- //! Flag that enables support for custom windows
- BOOL bMsgSupport;
- //! Redraw settings for anti-flickering and proper painting
- RESIZEPROPERTIES properties;
- tagLAYOUTINFO() : hWnd(NULL), nCallbackID(0), bMsgSupport(FALSE)
- {
- sWndClass[0] = 0;
- }
- tagLAYOUTINFO(HWND hwnd, ANCHOR tl_type, SIZE tl_margin,
- ANCHOR br_type, SIZE br_margin)
- :
- hWnd(hwnd), nCallbackID(0), bMsgSupport(FALSE),
- anchorTopLeft(tl_type), marginTopLeft(tl_margin),
- anchorBottomRight(br_type), marginBottomRight(br_margin)
- {
- sWndClass[0] = 0;
- }
- } LAYOUTINFO, *PLAYOUTINFO, *LPLAYOUTINFO;
- //! @brief Layout manager implementation
- /*!
- * Derive from this class to implement resizable windows, adding the ability
- * to dinamically resize and reposition child controls.
- * Special care is taken to ensure a smooth animation during the resize
- * operations performed by the users, without annoying flickering effects.
- */
- class CResizableLayout
- {
- private:
- //@{
- //! @brief Collection of layout settings for each control
- CMap<HWND, HWND, POSITION, POSITION> m_mapLayout;
- CList<LAYOUTINFO, LAYOUTINFO&> m_listLayout;
- CList<LAYOUTINFO, LAYOUTINFO&> m_listLayoutCB;
- //@}
- //@{
- //! @brief Used for clipping implementation
- HRGN m_hOldClipRgn;
- int m_nOldClipRgn;
- //@}
- //@{
- //! @brief Used for advanced anti-flickering
- RECT m_rectClientBefore;
- BOOL m_bNoRecursion;
- //@}
- //! @brief Apply clipping settings for the specified control
- void ClipChildWindow(const LAYOUTINFO &layout, CRgn* pRegion) const;
- //! @brief Helper function to calculate new layout
- void CalcNewChildPosition(const LAYOUTINFO &layout,
- const CRect &rectParent, CRect &rectChild, UINT& uFlags) const;
- protected:
- //! @brief Override to initialize resize properties (clipping, refresh)
- virtual void InitResizeProperties(LAYOUTINFO& layout) const;
- //! @brief Override to specify clipping for unsupported windows
- virtual BOOL LikesClipping(const LAYOUTINFO &layout) const;
- //! @brief Override to specify refresh for unsupported windows
- virtual BOOL NeedsRefresh(const LAYOUTINFO &layout,
- const CRect &rectOld, const CRect &rectNew) const;
- //! @brief Clip controls in the layout out of the specified device context
- BOOL ClipChildren(CDC* pDC, BOOL bUndo);
- //! @brief Get the layout clipping region
- void GetClippingRegion(CRgn* pRegion) const;
-
- //! @brief Override for scrollable or expanding parent windows
- virtual void GetTotalClientRect(LPRECT lpRect) const;
- //@{
- //! @brief Add anchor points for the specified control to the layout
- void AddAnchor(HWND hWnd, ANCHOR anchorTopLeft, ANCHOR anchorBottomRight);
- void AddAnchor(HWND hWnd, ANCHOR anchorTopLeft)
- {
- AddAnchor(hWnd, anchorTopLeft, anchorTopLeft);
- }
- void AddAnchor(UINT nID, ANCHOR anchorTopLeft, ANCHOR anchorBottomRight)
- {
- AddAnchor(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID),
- anchorTopLeft, anchorBottomRight);
- }
- void AddAnchor(UINT nID, ANCHOR anchorTopLeft)
- {
- AddAnchor(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID),
- anchorTopLeft, anchorTopLeft);
- }
- //@}
- //@{
- //! @brief Add anchor points for all the remaining controls to the layout
- void AddAllOtherAnchors(ANCHOR anchor);
- void AddAllOtherAnchors()
- {
- AddAllOtherAnchors(TOP_LEFT);
- }
- //@}
- //! @brief Add a callback slot to the layout for dynamic controls or anchor points
- UINT AddAnchorCallback();
- //@{
- //! @brief Get position and size of a control in the layout from the parent's client area
- BOOL GetAnchorPosition(HWND hWnd, const CRect &rectParent,
- CRect &rectChild, UINT* lpFlags = NULL) const
- {
- 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;
- }
- BOOL GetAnchorPosition(UINT nID, const CRect &rectParent,
- CRect &rectChild, UINT* lpFlags = NULL) const
- {
- return GetAnchorPosition(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID),
- rectParent, rectChild, lpFlags);
- }
- //@}
- //@{
- //! @brief Get margins surrounding a control in the layout with the given size
- BOOL GetAnchorMargins(HWND hWnd, const CSize &sizeChild, CRect &rectMargins) const;
- BOOL GetAnchorMargins(UINT nID, const CSize &sizeChild, CRect &rectMargins) const
- {
- return GetAnchorMargins(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID),
- sizeChild, rectMargins);
- }
- //@}
- //@{
- //! @brief Remove a control from the layout
- BOOL RemoveAnchor(HWND hWnd)
- {
- POSITION pos;
- if (!m_mapLayout.Lookup(hWnd, pos))
- return FALSE;
- m_listLayout.RemoveAt(pos);
- return m_mapLayout.RemoveKey(hWnd);
- }
- BOOL RemoveAnchor(UINT nID)
- {
- return RemoveAnchor(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID));
- }
- //@}
- //! @brief Reset the layout content
- void RemoveAllAnchors()
- {
- m_mapLayout.RemoveAll();
- m_listLayout.RemoveAll();
- m_listLayoutCB.RemoveAll();
- }
- //! @brief Reposition and size all the controls in the layout
- void ArrangeLayout() const;
- //! @brief Override to provide dynamic control's layout info
- virtual BOOL ArrangeLayoutCallback(LAYOUTINFO& layout) const;
- //! @brief Override to provide the parent window
- virtual CWnd* GetResizableWnd() const = 0;
- //! @brief Enhance anti-flickering
- void HandleNcCalcSize(BOOL bAfterDefault, LPNCCALCSIZE_PARAMS lpncsp, LRESULT& lResult);
-
- //! @brief Enable resizable style for top level parent windows
- void MakeResizable(LPCREATESTRUCT lpCreateStruct);
- public:
- CResizableLayout()
- {
- m_bNoRecursion = FALSE;
- m_hOldClipRgn = ::CreateRectRgn(0,0,0,0);
- m_nOldClipRgn = 0;
- }
- virtual ~CResizableLayout()
- {
- ::DeleteObject(m_hOldClipRgn);
- // just for safety
- RemoveAllAnchors();
- }
- };
- // @}
- #endif // !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_)
|