XTResize.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:13k
- // XTResize.cpp: implementation of the CXTResize class.
- //
- // This file is a part of the XTREME CONTROLS MFC class library.
- // (c)1998-2008 Codejock Software, All Rights Reserved.
- //
- // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
- // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
- // CONSENT OF CODEJOCK SOFTWARE.
- //
- // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
- // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
- // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
- // SINGLE COMPUTER.
- //
- // CONTACT INFORMATION:
- // support@codejock.com
- // http://www.codejock.com
- //
- /////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "Common/XTPDrawHelpers.h"
- #include "XTResizeRect.h"
- #include "XTResizePoint.h"
- #include "XTResize.h"
- #include "XTResizeGroupBox.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #define new DEBUG_NEW
- #endif
- #ifndef OBM_SIZE
- #define OBM_SIZE 32766
- #endif
- #define ENTRY_WINDOWPLACEMENT _T("WindowPlacement")
- #define IDC_SIZEICON 0x7FFF
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CXTResize::CXTResize(CWnd* pWnd, const UINT nFlags) :
- m_pWnd(pWnd),
- m_nFlagsXX(nFlags),
- m_szMin(0, 0),
- m_szMax(0, 0),
- m_szWindow(0, 0),
- m_szInitWindow(0, 0),
- m_strSection(_T(""))
- {
- }
- CXTResize::~CXTResize()
- {
- RemoveAllControls();
- }
- //////////////////////////////////////////////////////////////////////
- BOOL CXTResize::RemoveResize(const UINT nID)
- {
- // search for an item with the given id
- int iItem;
- for (iItem = (int)m_arrItems.GetSize(); iItem--;)
- {
- CWnd* pWnd = m_arrItems[iItem]->m_pWnd;
- ASSERT_VALID(pWnd);
- if (pWnd->GetDlgCtrlID() == (int) nID)
- {
- CXTResizeItem* pItem = m_arrItems[iItem];
- if (pItem != NULL)
- {
- m_arrItems.RemoveAt(iItem);
- SAFE_DELETE(pItem);
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- void CXTResize::RemoveAllControls()
- {
- // free allocated memory
- int iIndex;
- for (iIndex = 0; iIndex < m_arrItems.GetSize(); ++iIndex)
- {
- CXTResizeItem* pItem = m_arrItems.GetAt(iIndex);
- SAFE_DELETE(pItem);
- }
- // empty array
- m_arrItems.RemoveAll();
- }
- void CXTResize::SetResize(const UINT nID, const HWND hWnd, const XT_RESIZERECT& rrcSizing)
- {
- CXTResizeItem* pItem = 0;
- // search for an item with the given id
- int i;
- for (i = (int)m_arrItems.GetSize(); i--;)
- {
- CWnd* pWnd = m_arrItems[i]->m_pWnd;
- if (pWnd && ::IsWindow(pWnd->m_hWnd) && (pWnd->GetDlgCtrlID() == (int)nID))
- {
- pItem = m_arrItems[i];
- }
- }
- // if we didn't find it then create one
- if (pItem == 0)
- {
- HWND hWndChild = hWnd;
- if (hWndChild == NULL)
- {
- CWnd* pWnd = m_pWnd->GetDlgItem(nID);
- if (pWnd && ::IsWindow(pWnd->m_hWnd))
- {
- hWndChild = pWnd->m_hWnd;
- }
- }
- bool bDelete = false;
- CWnd* pWnd = m_pWnd->FromHandlePermanent(hWndChild);
- if (pWnd == NULL)
- {
- // there is no permanent window, create one
- pWnd = new CWnd; // CXTResizeItem handles the delete
- pWnd->Attach(hWndChild);
- bDelete = true;
- }
- CRect rcWindow;
- pWnd->GetWindowRect(rcWindow);
- m_pWnd->ScreenToClient(rcWindow);
- pItem = new CXTResizeItem(pWnd, rrcSizing, rcWindow, bDelete);
- pItem->MakeTransparent(this);
- m_arrItems.Add(pItem);
- }
- else
- {
- // the item already exists, just add the new sizing option
- pItem->m_rrcSizing += rrcSizing;
- }
- // we should only allow sizing within the rect {0, 0, 1, 1}
- ASSERT((CXTResizeRect(0, 0, 1, 1) & pItem->m_rrcSizing) == pItem->m_rrcSizing);
- }
- void CXTResize::Init()
- {
- if (m_pWnd == NULL)
- return;
- // clear the control list when initializing. The reason for this is we may have a
- // static window that calls Init() multiple times for example CDialog::DoModal().
- RemoveAllControls();
- // get the dialog size
- CRect rcWindow;
- m_pWnd->GetClientRect(rcWindow);
- m_szWindow = m_szInitWindow = rcWindow.Size();
- if (!HasFlag(xtResizeNoMinsize))
- {
- // set minimum size to current window size
- m_szMin = m_szWindow;
- }
- // set the clip children style to prevent flickering
- if (!HasFlag(xtResizeNoClipChildren))
- {
- m_pWnd->ModifyStyle(0, WS_CLIPCHILDREN);
- }
- // add the size icon
- if (!HasFlag(xtResizeNoSizeIcon))
- {
- // Create the size icon if it already doesn't exist.
- if (!::IsWindow(m_scSizeIcon.m_hWnd))
- {
- int cxGrip = GetSystemMetrics(SM_CXVSCROLL);
- int cyGrip = GetSystemMetrics(SM_CYHSCROLL);
- CRect rcIcon(rcWindow);
- rcIcon.OffsetRect(-1, -1);
- rcIcon.left = rcIcon.right - cxGrip;
- rcIcon.top = rcIcon.bottom - cyGrip;
- m_scSizeIcon.Create(WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP,
- rcIcon, m_pWnd, IDC_SIZEICON);
- }
- m_scSizeIcon.SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
- SetResize(IDC_SIZEICON, SZ_REPOS(1));
- }
- }
- void CXTResize::Offset(CPoint ptOffset)
- {
- if (m_arrItems.GetSize() > 0)
- {
- HDWP hDWP = ::BeginDeferWindowPos((int)m_arrItems.GetSize());
- int i;
- for (i = 0; i < (int)m_arrItems.GetSize(); i++)
- {
- CXTResizeRect rrcSizing = m_arrItems[i]->m_rrcSizing;
- m_arrItems[i]->m_rrcSizing = CRect(ptOffset.x, ptOffset.y, ptOffset.x, ptOffset.y);
- m_arrItems[i]->m_bInitialSize = TRUE;
- Defer(hDWP, m_arrItems[i], 1, 1);
- m_arrItems[i]->m_rrcSizing = rrcSizing;
- }
- ::EndDeferWindowPos(hDWP);
- // refresh group box items.
- for (i = 0; i < m_arrItems.GetSize(); i++)
- {
- if (m_arrItems[i]->m_bIsGroupBox)
- m_arrItems[i]->m_pWnd->Invalidate();
- }
- }
- }
- void CXTResize::AjustResizeRect(CSize&)
- {
- }
- void CXTResize::Size()
- {
- if (m_arrItems.GetSize() > 0)
- {
- CSize szWindow = CXTPClientRect(m_pWnd).Size();
- if (szWindow.cx == 0 || szWindow.cy == 0)
- return;
- AjustResizeRect(szWindow);
- CSize szDelta = szWindow - m_szWindow;
- if (szDelta == CSize(0, 0))
- return;
- HDWP hDWP = ::BeginDeferWindowPos((int)m_arrItems.GetSize());
- int i;
- for (i = 0; i < (int)m_arrItems.GetSize(); i++)
- {
- Defer(hDWP, m_arrItems[i], szDelta.cx, szDelta.cy);
- }
- ::EndDeferWindowPos(hDWP);
- // refresh group box items.
- for (i = 0; i < m_arrItems.GetSize(); i++)
- {
- if (m_arrItems[i]->m_bIsGroupBox)
- m_arrItems[i]->m_pWnd->Invalidate();
- }
- m_szWindow = szWindow;
- }
- }
- void CXTResize::Reset()
- {
- int iSize = (int)m_arrItems.GetSize();
- int i;
- for (i = 0; i < iSize; i++)
- {
- CXTResizeItem* pItem = m_arrItems[i];
- pItem->m_bInitialSize = FALSE;
- pItem->m_rrcWindow = pItem->m_rrcInitWindow;
- }
- }
- BOOL CXTResize::Defer(HDWP& hDWP, CXTResizeItem* pItem, int dx, int dy)
- {
- HWND hWnd = pItem->m_pWnd->m_hWnd;
- if (::IsWindow(hWnd))
- {
- if (!pItem->m_bInitialSize)
- {
- CRect rcWindow;
- m_pWnd->GetClientRect(rcWindow);
- dx = rcWindow.Width() - m_szInitWindow.cx;
- dy = rcWindow.Height() - m_szInitWindow.cy;
- pItem->m_bInitialSize = TRUE;
- }
- CXTResizeRect rrcItem = pItem->m_rrcWindow;
- rrcItem.left += dx * pItem->m_rrcSizing.left;
- rrcItem.top += dy * pItem->m_rrcSizing.top;
- rrcItem.right += dx * pItem->m_rrcSizing.right;
- rrcItem.bottom += dy * pItem->m_rrcSizing.bottom;
- if (rrcItem != pItem->m_rrcWindow)
- {
- int x = (int) rrcItem.left;
- int y = (int) rrcItem.top;
- int cx = (int) rrcItem.Width();
- int cy = (int) rrcItem.Height();
- // Set positioning flags
- UINT uFlags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER;
- CRect rOld;
- CRect rNew = rrcItem;
- // get the size of the dialog item in client coordinates.
- pItem->m_pWnd->GetWindowRect(&rOld);
- m_pWnd->ScreenToClient(&rOld);
- // if the x-y coordinates have not changed, there is no reason
- // to move the dialog item.
- if (rNew.TopLeft() == rOld.TopLeft())
- uFlags |= SWP_NOMOVE;
- // if the cx-cy size has not changed, there is no reason to
- // size the dialog item. If size has changed, don't
- // copy bits of the client area (i.e. have them invalidated/redrawn)
- if (rNew.Size() == rOld.Size())
- uFlags |= SWP_NOSIZE;
- else
- uFlags |= SWP_NOCOPYBITS;
- hDWP = ::DeferWindowPos(hDWP, hWnd, 0, x, y, cx, cy, uFlags);
- if (hDWP == NULL)
- {
- TRACE(_T("DeferWindowPos failed for ID %in"), GetDlgCtrlID(hWnd));
- return FALSE;
- }
- pItem->m_rrcWindow = rrcItem;
- }
- }
- return TRUE;
- }
- void CXTResize::GetMinMaxInfo(MINMAXINFO* pMMI)
- {
- CXTPClientRect rcClient(m_pWnd);
- CXTPWindowRect rcWindow(m_pWnd);
- if (rcClient.IsRectEmpty())
- return;
- CSize szBorder(rcWindow.Width() - rcClient.Width(), rcWindow.Height() - rcClient.Height());
- if (m_szWindow != CSize(0, 0))
- {
- if (HasFlag(xtResizeNoHorizontal))
- {
- pMMI->ptMaxTrackSize.x = pMMI->ptMaxSize.x = m_szWindow.cx + szBorder.cx;
- }
- if (HasFlag(xtResizeNoVertical))
- {
- pMMI->ptMaxTrackSize.y = pMMI->ptMaxSize.y = m_szWindow.cy + szBorder.cy;
- }
- }
- if (m_szMin.cx != 0) pMMI->ptMinTrackSize.x = m_szMin.cx + szBorder.cx;
- if (m_szMin.cy != 0) pMMI->ptMinTrackSize.y = m_szMin.cy + szBorder.cy;
- if (m_szMax.cx != 0) pMMI->ptMaxTrackSize.x = m_szMax.cx + szBorder.cx;
- if (m_szMax.cy != 0) pMMI->ptMaxTrackSize.y = m_szMax.cy + szBorder.cy;
- }
- BOOL CXTResize::AutoLoadPlacement(LPCTSTR pszSection)
- {
- m_strSection = pszSection;
- ASSERT(!m_strSection.IsEmpty());
- return LoadPlacement(m_strSection);
- }
- BOOL CXTResize::LoadPlacement(LPCTSTR pszSection)
- {
- BOOL bResult = FALSE;
- UINT nBytes = 0;
- BYTE* pBytes = 0;
- AfxGetApp()->GetProfileBinary(pszSection, ENTRY_WINDOWPLACEMENT, &pBytes, &nBytes);
- if (nBytes == sizeof(WINDOWPLACEMENT))
- {
- bResult = m_pWnd->SetWindowPlacement((WINDOWPLACEMENT*) pBytes);
- }
- if (pBytes && nBytes) delete[] pBytes;
- return bResult;
- }
- BOOL CXTResize::SavePlacement(LPCTSTR pszSection)
- {
- WINDOWPLACEMENT wp;
- if (!m_pWnd->GetWindowPlacement(&wp))
- return FALSE;
- AfxGetApp()->WriteProfileBinary(pszSection, ENTRY_WINDOWPLACEMENT, (BYTE*) &wp, sizeof(wp));
- return TRUE;
- }
- void CXTResize::SetFlag(XTResize eFlag)
- {
- m_nFlagsXX &= (eFlag^0xFFFFFFFF);
- m_nFlagsXX |= eFlag;
- }
- void CXTResize::SetResize(CWnd* pWnd, const CXTResizeRect& rrcSizing, CRect rcWindow)
- {
- CXTResizeItem *pItem = new CXTResizeItem(pWnd, rrcSizing, rcWindow, FALSE);
- m_arrItems.Add(pItem);
- }
- void CXTResize::UpdateControlRect(CWnd* pWnd)
- {
- if(!pWnd)
- return;
- for (int i = (int)m_arrItems.GetSize(); i--;)
- {
- if(m_arrItems[i]->m_pWnd->m_hWnd == pWnd->m_hWnd)
- {
- CRect rect;
- pWnd->GetWindowRect(&rect);
- m_pWnd->ScreenToClient(&rect);
- m_arrItems[i]->m_rrcWindow = rect;
- break;
- }
- }
- }
- //////////////////////////////////////////////////////////////////////
- // CXTResizeItem
- //////////////////////////////////////////////////////////////////////
- CXTResizeItem::CXTResizeItem(CWnd* pWnd, const CXTResizeRect& rrcSizing, CRect& rcWindow, BOOL bAutoDelete)
- : m_pWnd(pWnd)
- , m_rrcSizing(rrcSizing)
- , m_rrcWindow(rcWindow)
- , m_rrcInitWindow(rcWindow)
- , m_bAutoDelete(bAutoDelete)
- , m_bInitialSize(FALSE)
- , m_bIsGroupBox(FALSE)
- {
- }
- CXTResizeItem::~CXTResizeItem()
- {
- if (m_bAutoDelete)
- {
- m_pWnd->Detach();
- SAFE_DELETE(m_pWnd);
- }
- }
- bool CXTResizeItem::MakeTransparent(CXTResize* pXTResize)
- {
- if (pXTResize->HasFlag(xtResizeNoTransparentGroup))
- {
- return false;
- }
- if (m_pWnd && ::IsWindow(m_pWnd->m_hWnd))
- {
- TCHAR szClassName[8];
- ::GetClassName(m_pWnd->m_hWnd, szClassName, 8);
- // not a CButton derived class.
- if (_tcsicmp(szClassName, _T("Button")) != 0)
- {
- return false;
- }
- // get the window style if not a group box, return.
- DWORD dwStyle = ::GetWindowLong(m_pWnd->m_hWnd, GWL_STYLE);
- if ((dwStyle & (BS_GROUPBOX | WS_TABSTOP)) == BS_GROUPBOX)
- {
- // we don't want CXTResizeGroupBox transparent.
- if (m_pWnd->IsKindOf(RUNTIME_CLASS(CXTResizeGroupBox)))
- {
- return false;
- }
- // Get the extended style for the group box.
- DWORD dwStyleEx = ::GetWindowLong(m_pWnd->m_hWnd, GWL_EXSTYLE);
- // add the WS_EX_TRANSPARENT flag to the group box.
- ::SetWindowLong(m_pWnd->m_hWnd, GWL_EXSTYLE,
- dwStyleEx | WS_EX_TRANSPARENT);
- // apply the style for the window.
- ::SetWindowPos(m_pWnd->m_hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
- m_bIsGroupBox = TRUE;
- return true;
- }
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////
- // CXTSizeIcon
- //////////////////////////////////////////////////////////////////////
- CXTSizeIcon::CXTSizeIcon()
- {
- // Load the size cursor
- m_hCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE);
- }
- CXTSizeIcon::~CXTSizeIcon()
- {
- }
- BEGIN_MESSAGE_MAP(CXTSizeIcon, CScrollBar)
- //{{AFX_MSG_MAP(CXTSizeIcon)
- ON_WM_SETCURSOR()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CXTSizeIcon message handlers
- BOOL CXTSizeIcon::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
- {
- // Set the cursor to the size cursor.
- if (nHitTest == HTCLIENT && m_hCursor != NULL)
- {
- ::SetCursor(m_hCursor);
- return TRUE;
- }
- return CScrollBar::OnSetCursor(pWnd, nHitTest, message);
- }