XTResize.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:13k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTResize.cpp: implementation of the CXTResize class.
  2. //
  3. // This file is a part of the XTREME CONTROLS MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Common/XTPDrawHelpers.h"
  22. #include "XTResizeRect.h"
  23. #include "XTResizePoint.h"
  24. #include "XTResize.h"
  25. #include "XTResizeGroupBox.h"
  26. #ifdef _DEBUG
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #define new DEBUG_NEW
  30. #endif
  31. #ifndef OBM_SIZE
  32. #define OBM_SIZE 32766
  33. #endif
  34. #define ENTRY_WINDOWPLACEMENT _T("WindowPlacement")
  35. #define IDC_SIZEICON 0x7FFF
  36. //////////////////////////////////////////////////////////////////////
  37. // Construction/Destruction
  38. //////////////////////////////////////////////////////////////////////
  39. CXTResize::CXTResize(CWnd* pWnd, const UINT nFlags) :
  40. m_pWnd(pWnd),
  41. m_nFlagsXX(nFlags),
  42. m_szMin(0, 0),
  43. m_szMax(0, 0),
  44. m_szWindow(0, 0),
  45. m_szInitWindow(0, 0),
  46. m_strSection(_T(""))
  47. {
  48. }
  49. CXTResize::~CXTResize()
  50. {
  51. RemoveAllControls();
  52. }
  53. //////////////////////////////////////////////////////////////////////
  54. BOOL CXTResize::RemoveResize(const UINT nID)
  55. {
  56. // search for an item with the given id
  57. int iItem;
  58. for (iItem = (int)m_arrItems.GetSize(); iItem--;)
  59. {
  60. CWnd* pWnd = m_arrItems[iItem]->m_pWnd;
  61. ASSERT_VALID(pWnd);
  62. if (pWnd->GetDlgCtrlID() == (int) nID)
  63. {
  64. CXTResizeItem* pItem = m_arrItems[iItem];
  65. if (pItem != NULL)
  66. {
  67. m_arrItems.RemoveAt(iItem);
  68. SAFE_DELETE(pItem);
  69. return TRUE;
  70. }
  71. }
  72. }
  73. return FALSE;
  74. }
  75. void CXTResize::RemoveAllControls()
  76. {
  77. // free allocated memory
  78. int iIndex;
  79. for (iIndex = 0; iIndex < m_arrItems.GetSize(); ++iIndex)
  80. {
  81. CXTResizeItem* pItem = m_arrItems.GetAt(iIndex);
  82. SAFE_DELETE(pItem);
  83. }
  84. // empty array
  85. m_arrItems.RemoveAll();
  86. }
  87. void CXTResize::SetResize(const UINT nID, const HWND hWnd, const XT_RESIZERECT& rrcSizing)
  88. {
  89. CXTResizeItem* pItem = 0;
  90. // search for an item with the given id
  91. int i;
  92. for (i = (int)m_arrItems.GetSize(); i--;)
  93. {
  94. CWnd* pWnd = m_arrItems[i]->m_pWnd;
  95. if (pWnd && ::IsWindow(pWnd->m_hWnd) && (pWnd->GetDlgCtrlID() == (int)nID))
  96. {
  97. pItem = m_arrItems[i];
  98. }
  99. }
  100. // if we didn't find it then create one
  101. if (pItem == 0)
  102. {
  103. HWND hWndChild = hWnd;
  104. if (hWndChild == NULL)
  105. {
  106. CWnd* pWnd = m_pWnd->GetDlgItem(nID);
  107. if (pWnd && ::IsWindow(pWnd->m_hWnd))
  108. {
  109. hWndChild = pWnd->m_hWnd;
  110. }
  111. }
  112. bool bDelete = false;
  113. CWnd* pWnd = m_pWnd->FromHandlePermanent(hWndChild);
  114. if (pWnd == NULL)
  115. {
  116. // there is no permanent window, create one
  117. pWnd = new CWnd; // CXTResizeItem handles the delete
  118. pWnd->Attach(hWndChild);
  119. bDelete = true;
  120. }
  121. CRect rcWindow;
  122. pWnd->GetWindowRect(rcWindow);
  123. m_pWnd->ScreenToClient(rcWindow);
  124. pItem = new CXTResizeItem(pWnd, rrcSizing, rcWindow, bDelete);
  125. pItem->MakeTransparent(this);
  126. m_arrItems.Add(pItem);
  127. }
  128. else
  129. {
  130. // the item already exists, just add the new sizing option
  131. pItem->m_rrcSizing += rrcSizing;
  132. }
  133. // we should only allow sizing within the rect {0, 0, 1, 1}
  134. ASSERT((CXTResizeRect(0, 0, 1, 1) & pItem->m_rrcSizing) == pItem->m_rrcSizing);
  135. }
  136. void CXTResize::Init()
  137. {
  138. if (m_pWnd == NULL)
  139. return;
  140. // clear the control list when initializing.  The reason for this is we may have a
  141. // static window that calls Init() multiple times for example CDialog::DoModal().
  142. RemoveAllControls();
  143. // get the dialog size
  144. CRect rcWindow;
  145. m_pWnd->GetClientRect(rcWindow);
  146. m_szWindow = m_szInitWindow = rcWindow.Size();
  147. if (!HasFlag(xtResizeNoMinsize))
  148. {
  149. // set minimum size to current window size
  150. m_szMin = m_szWindow;
  151. }
  152. // set the clip children style to prevent flickering
  153. if (!HasFlag(xtResizeNoClipChildren))
  154. {
  155. m_pWnd->ModifyStyle(0, WS_CLIPCHILDREN);
  156. }
  157. // add the size icon
  158. if (!HasFlag(xtResizeNoSizeIcon))
  159. {
  160. // Create the size icon if it already doesn't exist.
  161. if (!::IsWindow(m_scSizeIcon.m_hWnd))
  162. {
  163. int cxGrip = GetSystemMetrics(SM_CXVSCROLL);
  164. int cyGrip = GetSystemMetrics(SM_CYHSCROLL);
  165. CRect rcIcon(rcWindow);
  166. rcIcon.OffsetRect(-1, -1);
  167. rcIcon.left = rcIcon.right - cxGrip;
  168. rcIcon.top = rcIcon.bottom - cyGrip;
  169. m_scSizeIcon.Create(WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP,
  170. rcIcon, m_pWnd, IDC_SIZEICON);
  171. }
  172. m_scSizeIcon.SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0,
  173. SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
  174. SetResize(IDC_SIZEICON, SZ_REPOS(1));
  175. }
  176. }
  177. void CXTResize::Offset(CPoint ptOffset)
  178. {
  179. if (m_arrItems.GetSize() > 0)
  180. {
  181. HDWP hDWP = ::BeginDeferWindowPos((int)m_arrItems.GetSize());
  182. int i;
  183. for (i = 0; i < (int)m_arrItems.GetSize(); i++)
  184. {
  185. CXTResizeRect rrcSizing = m_arrItems[i]->m_rrcSizing;
  186. m_arrItems[i]->m_rrcSizing = CRect(ptOffset.x, ptOffset.y, ptOffset.x, ptOffset.y);
  187. m_arrItems[i]->m_bInitialSize = TRUE;
  188. Defer(hDWP, m_arrItems[i], 1, 1);
  189. m_arrItems[i]->m_rrcSizing = rrcSizing;
  190. }
  191. ::EndDeferWindowPos(hDWP);
  192. // refresh group box items.
  193. for (i = 0; i < m_arrItems.GetSize(); i++)
  194. {
  195. if (m_arrItems[i]->m_bIsGroupBox)
  196. m_arrItems[i]->m_pWnd->Invalidate();
  197. }
  198. }
  199. }
  200. void CXTResize::AjustResizeRect(CSize&)
  201. {
  202. }
  203. void CXTResize::Size()
  204. {
  205. if (m_arrItems.GetSize() > 0)
  206. {
  207. CSize szWindow = CXTPClientRect(m_pWnd).Size();
  208. if (szWindow.cx == 0 || szWindow.cy == 0)
  209. return;
  210. AjustResizeRect(szWindow);
  211. CSize szDelta = szWindow - m_szWindow;
  212. if (szDelta == CSize(0, 0))
  213. return;
  214. HDWP hDWP = ::BeginDeferWindowPos((int)m_arrItems.GetSize());
  215. int i;
  216. for (i = 0; i < (int)m_arrItems.GetSize(); i++)
  217. {
  218. Defer(hDWP, m_arrItems[i], szDelta.cx, szDelta.cy);
  219. }
  220. ::EndDeferWindowPos(hDWP);
  221. // refresh group box items.
  222. for (i = 0; i < m_arrItems.GetSize(); i++)
  223. {
  224. if (m_arrItems[i]->m_bIsGroupBox)
  225. m_arrItems[i]->m_pWnd->Invalidate();
  226. }
  227. m_szWindow = szWindow;
  228. }
  229. }
  230. void CXTResize::Reset()
  231. {
  232. int iSize = (int)m_arrItems.GetSize();
  233. int i;
  234. for (i = 0; i < iSize; i++)
  235. {
  236. CXTResizeItem* pItem = m_arrItems[i];
  237. pItem->m_bInitialSize = FALSE;
  238. pItem->m_rrcWindow = pItem->m_rrcInitWindow;
  239. }
  240. }
  241. BOOL CXTResize::Defer(HDWP& hDWP, CXTResizeItem* pItem, int dx, int dy)
  242. {
  243. HWND hWnd = pItem->m_pWnd->m_hWnd;
  244. if (::IsWindow(hWnd))
  245. {
  246. if (!pItem->m_bInitialSize)
  247. {
  248. CRect rcWindow;
  249. m_pWnd->GetClientRect(rcWindow);
  250. dx = rcWindow.Width() - m_szInitWindow.cx;
  251. dy = rcWindow.Height() - m_szInitWindow.cy;
  252. pItem->m_bInitialSize = TRUE;
  253. }
  254. CXTResizeRect rrcItem = pItem->m_rrcWindow;
  255. rrcItem.left += dx * pItem->m_rrcSizing.left;
  256. rrcItem.top += dy * pItem->m_rrcSizing.top;
  257. rrcItem.right += dx * pItem->m_rrcSizing.right;
  258. rrcItem.bottom += dy * pItem->m_rrcSizing.bottom;
  259. if (rrcItem != pItem->m_rrcWindow)
  260. {
  261. int x = (int) rrcItem.left;
  262. int y = (int) rrcItem.top;
  263. int cx = (int) rrcItem.Width();
  264. int cy = (int) rrcItem.Height();
  265. // Set positioning flags
  266. UINT uFlags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER;
  267. CRect rOld;
  268. CRect rNew = rrcItem;
  269. // get the size of the dialog item in client coordinates.
  270. pItem->m_pWnd->GetWindowRect(&rOld);
  271. m_pWnd->ScreenToClient(&rOld);
  272. // if the x-y coordinates have not changed, there is no reason
  273. // to move the dialog item.
  274. if (rNew.TopLeft() == rOld.TopLeft())
  275. uFlags |= SWP_NOMOVE;
  276. // if the cx-cy size has not changed, there is no reason to
  277. // size the dialog item.  If size has changed, don't
  278. // copy bits of the client area (i.e. have them invalidated/redrawn)
  279. if (rNew.Size() == rOld.Size())
  280. uFlags |= SWP_NOSIZE;
  281. else
  282. uFlags |= SWP_NOCOPYBITS;
  283. hDWP = ::DeferWindowPos(hDWP, hWnd, 0, x, y, cx, cy, uFlags);
  284. if (hDWP == NULL)
  285. {
  286. TRACE(_T("DeferWindowPos failed for ID %in"), GetDlgCtrlID(hWnd));
  287. return FALSE;
  288. }
  289. pItem->m_rrcWindow = rrcItem;
  290. }
  291. }
  292. return TRUE;
  293. }
  294. void CXTResize::GetMinMaxInfo(MINMAXINFO* pMMI)
  295. {
  296. CXTPClientRect rcClient(m_pWnd);
  297. CXTPWindowRect rcWindow(m_pWnd);
  298. if (rcClient.IsRectEmpty())
  299. return;
  300. CSize szBorder(rcWindow.Width() - rcClient.Width(), rcWindow.Height() - rcClient.Height());
  301. if (m_szWindow != CSize(0, 0))
  302. {
  303. if (HasFlag(xtResizeNoHorizontal))
  304. {
  305. pMMI->ptMaxTrackSize.x = pMMI->ptMaxSize.x = m_szWindow.cx + szBorder.cx;
  306. }
  307. if (HasFlag(xtResizeNoVertical))
  308. {
  309. pMMI->ptMaxTrackSize.y = pMMI->ptMaxSize.y = m_szWindow.cy + szBorder.cy;
  310. }
  311. }
  312. if (m_szMin.cx != 0) pMMI->ptMinTrackSize.x = m_szMin.cx + szBorder.cx;
  313. if (m_szMin.cy != 0) pMMI->ptMinTrackSize.y = m_szMin.cy + szBorder.cy;
  314. if (m_szMax.cx != 0) pMMI->ptMaxTrackSize.x = m_szMax.cx + szBorder.cx;
  315. if (m_szMax.cy != 0) pMMI->ptMaxTrackSize.y = m_szMax.cy + szBorder.cy;
  316. }
  317. BOOL CXTResize::AutoLoadPlacement(LPCTSTR pszSection)
  318. {
  319. m_strSection = pszSection;
  320. ASSERT(!m_strSection.IsEmpty());
  321. return LoadPlacement(m_strSection);
  322. }
  323. BOOL CXTResize::LoadPlacement(LPCTSTR pszSection)
  324. {
  325. BOOL bResult = FALSE;
  326. UINT nBytes = 0;
  327. BYTE* pBytes = 0;
  328. AfxGetApp()->GetProfileBinary(pszSection, ENTRY_WINDOWPLACEMENT, &pBytes, &nBytes);
  329. if (nBytes == sizeof(WINDOWPLACEMENT))
  330. {
  331. bResult = m_pWnd->SetWindowPlacement((WINDOWPLACEMENT*) pBytes);
  332. }
  333. if (pBytes && nBytes) delete[] pBytes;
  334. return bResult;
  335. }
  336. BOOL CXTResize::SavePlacement(LPCTSTR pszSection)
  337. {
  338. WINDOWPLACEMENT wp;
  339. if (!m_pWnd->GetWindowPlacement(&wp))
  340. return FALSE;
  341. AfxGetApp()->WriteProfileBinary(pszSection, ENTRY_WINDOWPLACEMENT, (BYTE*) &wp, sizeof(wp));
  342. return TRUE;
  343. }
  344. void CXTResize::SetFlag(XTResize eFlag)
  345. {
  346. m_nFlagsXX &= (eFlag^0xFFFFFFFF);
  347. m_nFlagsXX |= eFlag;
  348. }
  349. void CXTResize::SetResize(CWnd* pWnd, const CXTResizeRect& rrcSizing, CRect rcWindow)
  350. {
  351. CXTResizeItem *pItem = new CXTResizeItem(pWnd, rrcSizing, rcWindow, FALSE);
  352. m_arrItems.Add(pItem);
  353. }
  354. void CXTResize::UpdateControlRect(CWnd* pWnd)
  355. {
  356. if(!pWnd)
  357. return;
  358. for (int i = (int)m_arrItems.GetSize(); i--;)
  359. {
  360. if(m_arrItems[i]->m_pWnd->m_hWnd == pWnd->m_hWnd)
  361. {
  362. CRect rect;
  363. pWnd->GetWindowRect(&rect);
  364. m_pWnd->ScreenToClient(&rect);
  365. m_arrItems[i]->m_rrcWindow = rect;
  366. break;
  367. }
  368. }
  369. }
  370. //////////////////////////////////////////////////////////////////////
  371. // CXTResizeItem
  372. //////////////////////////////////////////////////////////////////////
  373. CXTResizeItem::CXTResizeItem(CWnd* pWnd, const CXTResizeRect& rrcSizing, CRect& rcWindow, BOOL bAutoDelete)
  374. : m_pWnd(pWnd)
  375. , m_rrcSizing(rrcSizing)
  376. , m_rrcWindow(rcWindow)
  377. , m_rrcInitWindow(rcWindow)
  378. , m_bAutoDelete(bAutoDelete)
  379. , m_bInitialSize(FALSE)
  380. , m_bIsGroupBox(FALSE)
  381. {
  382. }
  383. CXTResizeItem::~CXTResizeItem()
  384. {
  385. if (m_bAutoDelete)
  386. {
  387. m_pWnd->Detach();
  388. SAFE_DELETE(m_pWnd);
  389. }
  390. }
  391. bool CXTResizeItem::MakeTransparent(CXTResize* pXTResize)
  392. {
  393. if (pXTResize->HasFlag(xtResizeNoTransparentGroup))
  394. {
  395. return false;
  396. }
  397. if (m_pWnd && ::IsWindow(m_pWnd->m_hWnd))
  398. {
  399. TCHAR szClassName[8];
  400. ::GetClassName(m_pWnd->m_hWnd, szClassName, 8);
  401. // not a CButton derived class.
  402. if (_tcsicmp(szClassName, _T("Button")) != 0)
  403. {
  404. return false;
  405. }
  406. // get the window style if not a group box, return.
  407. DWORD dwStyle = ::GetWindowLong(m_pWnd->m_hWnd, GWL_STYLE);
  408. if ((dwStyle & (BS_GROUPBOX | WS_TABSTOP)) == BS_GROUPBOX)
  409. {
  410. // we don't want CXTResizeGroupBox transparent.
  411. if (m_pWnd->IsKindOf(RUNTIME_CLASS(CXTResizeGroupBox)))
  412. {
  413. return false;
  414. }
  415. // Get the extended style for the group box.
  416. DWORD dwStyleEx = ::GetWindowLong(m_pWnd->m_hWnd, GWL_EXSTYLE);
  417. // add the WS_EX_TRANSPARENT flag to the group box.
  418. ::SetWindowLong(m_pWnd->m_hWnd, GWL_EXSTYLE,
  419. dwStyleEx | WS_EX_TRANSPARENT);
  420. // apply the style for the window.
  421. ::SetWindowPos(m_pWnd->m_hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
  422. SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
  423. m_bIsGroupBox = TRUE;
  424. return true;
  425. }
  426. }
  427. return false;
  428. }
  429. //////////////////////////////////////////////////////////////////////
  430. // CXTSizeIcon
  431. //////////////////////////////////////////////////////////////////////
  432. CXTSizeIcon::CXTSizeIcon()
  433. {
  434. // Load the size cursor
  435. m_hCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE);
  436. }
  437. CXTSizeIcon::~CXTSizeIcon()
  438. {
  439. }
  440. BEGIN_MESSAGE_MAP(CXTSizeIcon, CScrollBar)
  441. //{{AFX_MSG_MAP(CXTSizeIcon)
  442. ON_WM_SETCURSOR()
  443. //}}AFX_MSG_MAP
  444. END_MESSAGE_MAP()
  445. /////////////////////////////////////////////////////////////////////////////
  446. // CXTSizeIcon message handlers
  447. BOOL CXTSizeIcon::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  448. {
  449. // Set the cursor to the size cursor.
  450. if (nHitTest == HTCLIENT && m_hCursor != NULL)
  451. {
  452. ::SetCursor(m_hCursor);
  453. return TRUE;
  454. }
  455. return CScrollBar::OnSetCursor(pWnd, nHitTest, message);
  456. }