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

对话框与窗口

开发平台:

Visual C++

  1. // XTPDockingPaneAutoHidePanel.cpp : implementation of the CXTPDockingPaneAutoHidePanel class.
  2. //
  3. // This file is a part of the XTREME DOCKINGPANE 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/Resource.h"
  22. #include "Common/XTPVC80Helpers.h"
  23. #include "Common/XTPDrawHelpers.h"
  24. #include "Common/XTPColorManager.h"
  25. #include "Common/XTPImageManager.h"
  26. #include "Common/XTPResourceManager.h"
  27. #include "TabManager/XTPTabManager.h"
  28. #include "XTPDockingPane.h"
  29. #include "XTPDockingPaneManager.h"
  30. #include "XTPDockingPaneTabbedContainer.h"
  31. #include "XTPDockingPaneAutoHidePanel.h"
  32. #include "XTPDockingPaneLayout.h"
  33. #include "XTPDockingPaneSplitterContainer.h"
  34. #ifdef _DEBUG
  35. #define new DEBUG_NEW
  36. #undef THIS_FILE
  37. static char THIS_FILE[] = __FILE__;
  38. #endif
  39. #define TID_CHECKACTIVE 1
  40. #define TID_CLOSE 4
  41. #define TID_SLIDEIN 2
  42. #define TID_SLIDEOUT 3
  43. double CXTPDockingPaneAutoHideWnd::m_dAnimationDelay = -1;
  44. int CXTPDockingPaneAutoHideWnd::m_nAnimationInterval = 16;                 // smother animation
  45. int CXTPDockingPaneAutoHideWnd::m_nAnimationDuration = 128;                // fast slide completion
  46. BOOL CXTPDockingPaneAutoHidePanel::m_bCloseActiveWindow = TRUE;
  47. DWORD CXTPDockingPaneAutoHideWnd::m_nMouseHoverDelay = HOVER_DEFAULT;
  48. UINT CXTPDockingPaneAutoHideWnd::m_nInactiveCollapseDelay = 100;
  49. void CXTPDockingPaneAutoHideWnd::GetMinMaxInfo (LPMINMAXINFO pMinMaxInfo, BOOL bIncludeSplitter /*= TRUE*/) const
  50. {
  51. ZeroMemory(pMinMaxInfo, sizeof(MINMAXINFO));
  52. pMinMaxInfo->ptMaxTrackSize = CPoint(32000, 32000);
  53. if (!m_pPane || !m_pPane->m_pSelectedPane)
  54. return;
  55. m_pPane->m_pSelectedPane->GetMinMaxInfo(pMinMaxInfo);
  56. m_pPane->AdjustMinMaxInfoClientRect(pMinMaxInfo, TRUE);
  57. if (!bIncludeSplitter)
  58. return;
  59. if (m_direction == xtpPaneDockLeft || m_direction == xtpPaneDockRight)
  60. {
  61. pMinMaxInfo->ptMinTrackSize.x += 4;
  62. pMinMaxInfo->ptMaxTrackSize.x += 4;
  63. }
  64. else
  65. {
  66. pMinMaxInfo->ptMinTrackSize.y += 4;
  67. pMinMaxInfo->ptMaxTrackSize.y += 4;
  68. }
  69. }
  70. CXTPDockingPaneAutoHideWnd::CXTPDockingPaneAutoHideWnd(CXTPDockingPaneAutoHidePanel* pPanel, CXTPDockingPaneTabbedContainer* pPane)
  71. : m_pPanel(pPanel), m_pPane(pPane)
  72. {
  73. ASSERT(pPane);
  74. if (!pPane)
  75. return;
  76. ASSERT(pPane->m_pSelectedPane);
  77. if (!pPane->m_pSelectedPane)
  78. return;
  79. m_bTracking = FALSE;
  80. m_direction = m_pPanel->GetDirection();
  81. m_bHoriz = (m_direction == xtpPaneDockTop || m_direction == xtpPaneDockBottom);
  82. CXTPDockingPaneManager* pManager = GetDockingPaneManager();
  83. CWnd* pSite = pManager->GetSite();
  84. CXTPDockingPaneBase* pTopPane = pManager->GetTopPane();
  85. CRect rcClient = pTopPane->GetPaneWindowRect();
  86. MINMAXINFO mmInfo;
  87. GetMinMaxInfo(&mmInfo);
  88. CSize szDocking = CSize(
  89. max(mmInfo.ptMinTrackSize.x, min(mmInfo.ptMaxTrackSize.x, pPane->m_pSelectedPane->m_szDocking.cx + 4)),
  90. max(mmInfo.ptMinTrackSize.y, min(mmInfo.ptMaxTrackSize.y, pPane->m_pSelectedPane->m_szDocking.cy + 4)));
  91. switch (pManager->GetRTLDirection(m_direction))
  92. {
  93. case xtpPaneDockLeft:
  94. rcClient.right = rcClient.left + szDocking.cx;
  95. break;
  96. case xtpPaneDockRight:
  97. rcClient.left = rcClient.right - szDocking.cx;
  98. break;
  99. case xtpPaneDockTop:
  100. rcClient.bottom = rcClient.top + szDocking.cy;
  101. break;
  102. case xtpPaneDockBottom:
  103. rcClient.top = rcClient.bottom - szDocking.cy;
  104. break;
  105. }
  106. pSite->ScreenToClient(&rcClient);
  107. CRect rcAvail, rc;
  108. BOOL bResizable = GetAvailableRect(rcAvail, rc);
  109. HCURSOR hCursor = !bResizable || pManager->IsSplittersLocked() ? AfxGetApp()->LoadStandardCursor(IDC_ARROW) :
  110. XTPResourceManager()->LoadCursor(!m_bHoriz ? XTP_IDC_HSPLITBAR :  XTP_IDC_VSPLITBAR);
  111. m_rcWindow = rcClient;
  112. CreateEx(pSite->GetExStyle() & WS_EX_LAYOUTRTL, AfxRegisterWndClass(0, hCursor), _T(""),
  113. WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rcClient, pSite, 0);
  114. m_nSlideStep = 0;
  115. m_nStepsCount = 1;
  116. if (m_dAnimationDelay != .0 && m_nAnimationInterval != 0)
  117. {
  118. if (m_dAnimationDelay > 0)
  119. {
  120. // keep the animation delay behaviour relative to 50 ms frame interval as per original
  121. // implementation
  122. m_nStepsCount = int((m_bHoriz ? m_rcWindow.Width() : m_rcWindow.Height()) * m_dAnimationDelay * 50 / m_nAnimationInterval);
  123. }
  124. else
  125. {
  126. m_nStepsCount = m_nAnimationDuration/m_nAnimationInterval;
  127. }
  128. }
  129. if (m_nStepsCount < 1) m_nStepsCount = 1;
  130. m_bSlideOut = FALSE;
  131. if (m_nStepsCount > 1)
  132. SetTimer(TID_SLIDEIN, m_nAnimationInterval, NULL);
  133. DoSlideStep();
  134. m_pPane->ShowWindow(SW_SHOW);
  135. SetTimer(TID_CHECKACTIVE, m_nInactiveCollapseDelay, NULL);
  136. m_nDeactivationCount = 6;
  137. }
  138. CXTPDockingPaneManager* CXTPDockingPaneAutoHideWnd::GetDockingPaneManager() const
  139. {
  140. ASSERT(m_pPanel);
  141. return m_pPanel ? m_pPanel->GetDockingPaneManager() : NULL;
  142. }
  143. void CXTPDockingPaneAutoHideWnd::DoSlideStep()
  144. {
  145. CRect rc(m_rcWindow);
  146. switch (m_direction)
  147. {
  148. case xtpPaneDockLeft:
  149. rc.right = rc.left + (m_nSlideStep + 1) * m_rcWindow.Width() / m_nStepsCount;
  150. break;
  151. case xtpPaneDockRight:
  152. rc.left = rc.right - (m_nSlideStep + 1) * m_rcWindow.Width() / m_nStepsCount;
  153. break;
  154. case xtpPaneDockTop:
  155. rc.bottom = rc.top + (m_nSlideStep + 1) * m_rcWindow.Height() / m_nStepsCount;
  156. break;
  157. case xtpPaneDockBottom:
  158. rc.top = rc.bottom - (m_nSlideStep + 1) * m_rcWindow.Height() / m_nStepsCount;
  159. break;
  160. }
  161. SetWindowPos(&CWnd::wndTop, rc.left, rc.top, rc.Width(), rc.Height(), SWP_SHOWWINDOW | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
  162. Invalidate(FALSE);
  163. }
  164. void CXTPDockingPaneAutoHideWnd::RecalcLayout(BOOL /*bNotify*/)
  165. {
  166. if (!m_pPane || !m_pPane->GetSafeHwnd())
  167. return;
  168. AFX_SIZEPARENTPARAMS layout;
  169. layout.bStretch = TRUE;
  170. GetClientRect(&layout.rect);
  171. CRect rcClient(layout.rect);
  172. layout.hDWP = ::BeginDeferWindowPos(8); // reasonable guess
  173. CRect rcPane(CPoint(0, 0), m_rcWindow.Size());
  174. switch (m_direction)
  175. {
  176. case xtpPaneDockLeft:
  177. rcPane.OffsetRect(- m_rcWindow.Width() + rcClient.Width(), 0);
  178. rcPane.right -= 4;
  179. break;
  180. case xtpPaneDockTop:
  181. rcPane.OffsetRect(0, - m_rcWindow.Height() + rcClient.Height());
  182. rcPane.bottom -= 4;
  183. break;
  184. case xtpPaneDockRight:
  185. rcPane.left += 4;
  186. break;
  187. case xtpPaneDockBottom:
  188. rcPane.top += 4;
  189. break;
  190. }
  191. m_pPane->OnSizeParent(this, rcPane, &layout);
  192. if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))
  193. TRACE0("Warning: DeferWindowPos failed - low system resources.n");
  194. }
  195. IMPLEMENT_DYNAMIC(CXTPDockingPaneAutoHideWnd, CMiniFrameWnd)
  196. BEGIN_MESSAGE_MAP(CXTPDockingPaneAutoHideWnd, CMiniFrameWnd)
  197. ON_WM_PAINT()
  198. ON_WM_TIMER()
  199. ON_WM_CLOSE()
  200. ON_WM_LBUTTONDOWN()
  201. ON_WM_MOUSEMOVE()
  202. ON_WM_ERASEBKGND()
  203. END_MESSAGE_MAP()
  204. void CXTPDockingPaneAutoHideWnd::CloseWindow()
  205. {
  206. if (!IsWindow(m_hWnd))
  207. return;
  208. ShowWindow(SW_HIDE);
  209. if (m_pPane && m_pPane->GetSafeHwnd() && m_pPane->GetParent() == this)
  210. {
  211. m_pPane->ShowWindow(SW_HIDE);
  212. m_pPane->SetDockingSite(GetDockingPaneManager()->GetSite());
  213. }
  214. m_pPane = 0;
  215. if (m_pPanel && m_pPanel->m_pActiveWnd == this)
  216. m_pPanel->m_pActiveWnd = 0;
  217. PostMessage(WM_CLOSE);
  218. }
  219. void CXTPDockingPaneAutoHideWnd::PostNcDestroy()
  220. {
  221. if (m_pPanel && m_pPanel->m_pActiveWnd == this)
  222. m_pPanel->m_pActiveWnd = 0;
  223. if (m_dwRef <= 1)
  224. {
  225. delete this;
  226. }
  227. else
  228. {
  229. InternalRelease();
  230. }
  231. }
  232. void CXTPDockingPaneAutoHideWnd::OnTimer(UINT_PTR nIDEvent)
  233. {
  234. if (nIDEvent == TID_CLOSE)
  235. {
  236. CloseWindow();
  237. return;
  238. }
  239. if (!m_pPane)
  240. return;
  241. if (m_pPanel && m_pPanel->m_pActiveWnd != this)
  242. return;
  243. if (nIDEvent == TID_CHECKACTIVE)
  244. {
  245. if (m_bTracking)
  246. return;
  247. CPoint pt;
  248. GetCursorPos(&pt);
  249. if (!m_pPane->IsActive() && !CXTPWindowRect(this).PtInRect(pt) && !CXTPWindowRect(m_pPanel).PtInRect(pt))
  250. {
  251. if (!m_bSlideOut)
  252. {
  253. if (--m_nDeactivationCount <= 0)
  254. {
  255. m_nDeactivationCount = 0;
  256. InternalAddRef();
  257. if (!CXTPDockingPaneAutoHidePanel::m_bCloseActiveWindow || GetDockingPaneManager()->NotifyAction(xtpPaneActionCollapsing, m_pPane->GetSelected()))
  258. {
  259. m_nDeactivationCount = 6;
  260. }
  261. else
  262. {
  263. m_bSlideOut = TRUE;
  264. if (m_hWnd) SetTimer(TID_SLIDEOUT, m_nAnimationInterval, NULL);
  265. }
  266. InternalRelease();
  267. }
  268. }
  269. }
  270. else
  271. {
  272. m_nDeactivationCount = 6;
  273. if (m_bSlideOut)
  274. {
  275. m_bSlideOut = FALSE;
  276. KillTimer(TID_SLIDEOUT);
  277. SetTimer(TID_SLIDEIN, m_nAnimationInterval, NULL);
  278. }
  279. }
  280. return;
  281. }
  282. if (nIDEvent == TID_SLIDEOUT && m_bSlideOut)
  283. {
  284. m_nSlideStep--;
  285. if (m_nSlideStep > -1) DoSlideStep();
  286. else
  287. {
  288. m_bSlideOut = FALSE;
  289. KillTimer(TID_SLIDEOUT);
  290. InternalAddRef();
  291. GetDockingPaneManager()->NotifyAction(xtpPaneActionCollapsed, m_pPane->GetSelected());
  292. CloseWindow();
  293. InternalRelease();
  294. }
  295. return;
  296. }
  297. if (nIDEvent == TID_SLIDEIN && !m_bSlideOut)
  298. {
  299. m_nSlideStep++;
  300. if (m_nSlideStep < m_nStepsCount) DoSlideStep();
  301. else
  302. {
  303. m_nSlideStep = m_nStepsCount - 1;
  304. KillTimer(TID_SLIDEIN);
  305. GetDockingPaneManager()->NotifyAction(xtpPaneActionExpanded, m_pPane->GetSelected());
  306. }
  307. return;
  308. }
  309. }
  310. void CXTPDockingPaneAutoHideWnd::OnMouseMove(UINT nFlags, CPoint point)
  311. {
  312. if (m_bSlideOut)
  313. {
  314. OnTimer(TID_CHECKACTIVE);
  315. return;
  316. }
  317. CMiniFrameWnd::OnMouseMove(nFlags, point);
  318. }
  319. void CXTPDockingPaneAutoHideWnd::OnClose()
  320. {
  321. CMiniFrameWnd::OnClose();
  322. }
  323. BOOL CXTPDockingPaneAutoHideWnd::OnEraseBkgnd(CDC* /*pDC*/)
  324. {
  325. return TRUE;
  326. }
  327. void CXTPDockingPaneAutoHideWnd::OnPaint()
  328. {
  329. CPaintDC dc(this);
  330. if (!m_pPane)
  331. return;
  332. CXTPDockingPanePaintManager* pPaintManager = m_pPane->CXTPDockingPaneBase::GetPaintManager();
  333. CXTPClientRect rc(this);
  334. dc.FillSolidRect(rc, pPaintManager->GetXtremeColor(XPCOLOR_3DFACE));
  335. switch (m_direction)
  336. {
  337. case xtpPaneDockLeft:
  338. dc.Draw3dRect(rc.right - 1, rc.top, 1, rc.Height(), pPaintManager->GetXtremeColor(COLOR_BTNTEXT), pPaintManager->GetXtremeColor(COLOR_BTNTEXT));
  339. dc.Draw3dRect(rc.right - 2, rc.top, 1, rc.Height(), pPaintManager->GetXtremeColor(COLOR_3DSHADOW), pPaintManager->GetXtremeColor(COLOR_3DSHADOW));
  340. break;
  341. case xtpPaneDockTop:
  342. dc.Draw3dRect(rc.left, rc.bottom - 1, rc.Width(), 1, pPaintManager->GetXtremeColor(COLOR_BTNTEXT), pPaintManager->GetXtremeColor(COLOR_BTNTEXT));
  343. dc.Draw3dRect(rc.left, rc.bottom - 2, rc.Width(), 1, pPaintManager->GetXtremeColor(COLOR_3DSHADOW), pPaintManager->GetXtremeColor(COLOR_3DSHADOW));
  344. break;
  345. case xtpPaneDockRight:
  346. dc.Draw3dRect(rc.left + 1, rc.top, 1, rc.Height(), pPaintManager->GetXtremeColor(COLOR_3DHIGHLIGHT), pPaintManager->GetXtremeColor(COLOR_3DHIGHLIGHT));
  347. break;
  348. case xtpPaneDockBottom:
  349. dc.Draw3dRect(rc.left, rc.top + 1, rc.Width(), 1, pPaintManager->GetXtremeColor(COLOR_3DHIGHLIGHT), pPaintManager->GetXtremeColor(COLOR_3DHIGHLIGHT));
  350. break;
  351. }
  352. }
  353. void CXTPDockingPaneAutoHideWnd::Reposition(CRect rc, CRect rcClient)
  354. {
  355. CWnd* pSite = GetDockingPaneManager()->GetSite();
  356. switch (GetDockingPaneManager()->GetRTLDirection(m_direction))
  357. {
  358. case xtpPaneDockLeft:  rc.left = rcClient.left; break;
  359. case xtpPaneDockRight: rc.right = rcClient.right; break;
  360. case xtpPaneDockTop: rc.top = rcClient.top; break;
  361. case xtpPaneDockBottom: rc.bottom = rcClient.bottom; break;
  362. }
  363. if (!m_bHoriz) m_pPane->m_pSelectedPane->m_szDocking.cx = rc.Width();
  364. else m_pPane->m_pSelectedPane->m_szDocking.cy = rc.Height();
  365. pSite->ScreenToClient(&rc);
  366. m_rcWindow = rc;
  367. MoveWindow(m_rcWindow);
  368. Invalidate(FALSE);
  369. }
  370. BOOL CXTPDockingPaneAutoHideWnd::GetAvailableRect(CRect& rcAvail, CRect& rc) const
  371. {
  372. CXTPDockingPaneManager* pManager = GetDockingPaneManager();
  373. if (!pManager)
  374. return FALSE;
  375. CRect rcClient = pManager->GetTopPane()->GetPaneWindowRect();
  376. int nGap = pManager->m_nSplitterGap + 4;
  377. rcAvail = rcClient;
  378. MINMAXINFO mmInfo;
  379. GetMinMaxInfo(&mmInfo, m_direction == xtpPaneDockRight || m_direction == xtpPaneDockBottom);
  380. switch (m_direction)
  381. {
  382. case xtpPaneDockLeft:
  383. rcAvail.DeflateRect(max(mmInfo.ptMinTrackSize.x, nGap), 0, nGap, 0);
  384. if (rcAvail.right - rcClient.left > mmInfo.ptMaxTrackSize.x)
  385. rcAvail.right = mmInfo.ptMaxTrackSize.x + rcClient.left;
  386. if (rcAvail.left >= rcAvail.right)
  387. return FALSE;
  388. rc.left = rc.right - 4;
  389. break;
  390. case xtpPaneDockRight:
  391. rcAvail.DeflateRect(nGap, 0, max(mmInfo.ptMinTrackSize.x, nGap), 0);
  392. if (rcClient.right - rcAvail.left > mmInfo.ptMaxTrackSize.x)
  393. rcAvail.left = rcClient.right - mmInfo.ptMaxTrackSize.x;
  394. if (rcAvail.left >= rcAvail.right)
  395. return FALSE;
  396. rc.right = rc.left + 4;
  397. break;
  398. case xtpPaneDockTop:
  399. rcAvail.DeflateRect(0, max(mmInfo.ptMinTrackSize.y, nGap), 0, nGap);
  400. if (rcAvail.bottom - rcClient.top > mmInfo.ptMaxTrackSize.y)
  401. rcAvail.bottom = mmInfo.ptMaxTrackSize.y + rcClient.top;
  402. if (rcAvail.top >= rcAvail.bottom)
  403. return FALSE;
  404. rc.top = rc.bottom - 4;
  405. break;
  406. case xtpPaneDockBottom:
  407. rcAvail.DeflateRect(0, nGap, 0, max(mmInfo.ptMinTrackSize.y, nGap));
  408. if (rcClient.bottom - rcAvail.top > mmInfo.ptMaxTrackSize.y)
  409. rcAvail.top = rcClient.bottom - mmInfo.ptMaxTrackSize.y;
  410. if (rcAvail.top >= rcAvail.bottom)
  411. return FALSE;
  412. rc.bottom = rc.top + 4;
  413. break;
  414. }
  415. return TRUE;
  416. }
  417. void CXTPDockingPaneAutoHideWnd::OnLButtonDown(UINT /*nFlags*/, CPoint point)
  418. {
  419. CXTPDockingPaneManager* pManager = GetDockingPaneManager();
  420. if (!pManager || pManager->IsSplittersLocked())
  421. return;
  422. if (!m_pPane)
  423. return;
  424. CXTPWindowRect rc(this);
  425. CRect rcClient = pManager->GetTopPane()->GetPaneWindowRect();
  426. CRect rcAvail;
  427. if (!GetAvailableRect(rcAvail, rc))
  428. return;
  429. if (m_pPane->OnAction(xtpPaneActionSplitterResizing))
  430. return;
  431. m_bTracking = TRUE;
  432. if (pManager->IsSplitterTrackerUsed())
  433. {
  434. if (GetExStyle() & WS_EX_LAYOUTRTL)
  435. point = rc.TopLeft();
  436. else ClientToScreen(&point);
  437. CXTPSplitterTracker tracker;
  438. if (tracker.Track(this, rcAvail, rc, point, !m_bHoriz))
  439. {
  440. Reposition(rc, rcClient);
  441. }
  442. }
  443. else
  444. {
  445. SetCapture();
  446. while (CWnd::GetCapture() == this)
  447. {
  448. MSG msg;
  449. while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
  450. {
  451. if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
  452. return;
  453. DispatchMessage(&msg);
  454. }
  455. if (!GetMessage(&msg, NULL, 0, 0))
  456. break;
  457. if (msg.message == WM_MOUSEMOVE)
  458. {
  459. point = CPoint(msg.lParam);
  460. ClientToScreen(&point);
  461. point.x = max(min(point.x, rcAvail.right), rcAvail.left);
  462. point.y = max(min(point.y, rcAvail.bottom), rcAvail.top);
  463. if (!m_bHoriz)
  464. {
  465. if (rc.left == point.x)
  466. continue;
  467. rc.OffsetRect(point.x - rc.left, 0);
  468. }
  469. else
  470. {
  471. if (rc.top == point.y)
  472. continue;
  473. rc.OffsetRect(0, point.y - rc.top);
  474. }
  475. Reposition(rc, rcClient);
  476. }
  477. else if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) break;
  478. else if (msg.message == WM_LBUTTONUP) break;
  479. else ::DispatchMessage(&msg);
  480. }
  481. if (CWnd::GetCapture() == this) ReleaseCapture();
  482. }
  483. m_bTracking = FALSE;
  484. m_pPane->OnAction(xtpPaneActionSplitterResized);
  485. }
  486. //////////////////////////////////////////////////////////////////////////
  487. // CPanelDropTarget
  488. class CXTPDockingPaneAutoHidePanel::CPanelDropTarget : public COleDropTarget
  489. {
  490. virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* /*pDataObject*/, DWORD /*dwKeyState*/, CPoint point)
  491. {
  492. CXTPDockingPaneAutoHidePanel* pPanel = (CXTPDockingPaneAutoHidePanel*)pWnd;
  493. ASSERT_VALID(pPanel);
  494. if (!pPanel->GetPaintManager()->GetPanelPaintManager()->m_bSelectOnDragOver)
  495. return DROPEFFECT_NONE;
  496. CXTPDockingPane* pPane = pPanel->HitTest(point);
  497. if (pPane)
  498. {
  499. if (!(pPanel->m_pActiveWnd && pPanel->m_pActiveWnd->GetPane()->GetSelected() == pPane))
  500. {
  501. pPanel->ShowPane(pPane, FALSE);
  502. }
  503. }
  504. return DROPEFFECT_NONE;
  505. }
  506. };
  507. //////////////////////////////////////////////////////////////////////////
  508. // CAutoHidePanelTabManager
  509. class CXTPDockingPaneAutoHidePanel::CAutoHidePanelTabManager : public CXTPTabManager
  510. {
  511. public:
  512. CAutoHidePanelTabManager()
  513. {
  514. FindNavigateButton(xtpTabNavigateButtonLeft)->SetFlags(xtpTabNavigateButtonNone);
  515. FindNavigateButton(xtpTabNavigateButtonRight)->SetFlags(xtpTabNavigateButtonNone);
  516. }
  517. virtual void Reposition()
  518. {
  519. }
  520. virtual BOOL DrawIcon(CDC* pDC, CPoint pt, CXTPTabManagerItem* pItem, BOOL bDraw, CSize& szIcon) const
  521. {
  522. if (!pItem)
  523. return TRUE;
  524. if (GetPanel()->GetPaintManager()->GetPanelPaintManager()->m_bShowIcons == FALSE)
  525. return FALSE;
  526. CXTPImageManagerIcon* pImage = ((CXTPDockingPane*)pItem->GetData())->GetIcon(szIcon.cx);
  527. if (!pImage)
  528. return FALSE;
  529. if (!bDraw)
  530. {
  531. return TRUE;
  532. }
  533. pItem->DrawImage(pDC, CRect(pt, szIcon), pImage);
  534. return TRUE;
  535. }
  536. virtual void RedrawControl(LPCRECT lpRect, BOOL /*bAnimate*/)
  537. {
  538. if (GetPanel()->m_hWnd) GetPanel()->InvalidateRect(lpRect, FALSE);
  539. }
  540. virtual CXTPTabPaintManager* GetPaintManager() const
  541. {
  542. return GetPanel()->GetPaintManager()->GetPanelPaintManager();
  543. }
  544. CXTPTabManagerItem* Add()
  545. {
  546. return AddItem(GetItemCount());
  547. }
  548. XTPTabPosition GetPosition() const
  549. {
  550. switch (GetPanel()->GetDirection())
  551. {
  552. case xtpPaneDockLeft: return xtpTabPositionRight;
  553. case xtpPaneDockRight: return xtpTabPositionLeft;
  554. case xtpPaneDockTop: return xtpTabPositionBottom;
  555. case xtpPaneDockBottom: return xtpTabPositionTop;
  556. }
  557. return xtpTabPositionTop;
  558. }
  559. void PerformMouseMove(HWND hwnd, CPoint pt)
  560. {
  561. CXTPTabManager::PerformMouseMove(hwnd, pt);
  562. }
  563. CXTPDockingPaneAutoHidePanel* GetPanel() const;
  564. public:
  565. CAutoHidePanelTabManagersArray* m_pArray;
  566. CRect m_rcManager;
  567. };
  568. class CXTPDockingPaneAutoHidePanel::CAutoHidePanelTabManagersArray : public CArray<CAutoHidePanelTabManager*, CAutoHidePanelTabManager*>
  569. {
  570. public:
  571. ~CAutoHidePanelTabManagersArray()
  572. {
  573. FreeAll();
  574. }
  575. void FreeAll()
  576. {
  577. for (int i = 0; i < GetSize(); i++)
  578. {
  579. delete GetAt(i);
  580. }
  581. RemoveAll();
  582. }
  583. CAutoHidePanelTabManager* AddManager()
  584. {
  585. CAutoHidePanelTabManager* pManager = new CAutoHidePanelTabManager();
  586. Add(pManager);
  587. pManager->m_pArray = this;
  588. return pManager;
  589. }
  590. void Draw(CDC* pDC)
  591. {
  592. CRect rcClipBox;
  593. pDC->GetClipBox(rcClipBox);
  594. CXTPTabPaintManager* pPaintManager = m_pAutoHidePanel->GetPaintManager()->GetPanelPaintManager();
  595. for (int i = 0; i < GetSize(); i++)
  596. {
  597. CAutoHidePanelTabManager* pManager = GetAt(i);
  598. if (CRect().IntersectRect(rcClipBox, pManager->m_rcManager))
  599. pPaintManager->DrawTabControl(pManager, pDC, pManager->m_rcManager);
  600. }
  601. }
  602. public:
  603. CXTPDockingPaneAutoHidePanel* m_pAutoHidePanel;
  604. };
  605. CXTPDockingPaneAutoHidePanel* CXTPDockingPaneAutoHidePanel::CAutoHidePanelTabManager::GetPanel() const
  606. {
  607. return m_pArray->m_pAutoHidePanel;
  608. }
  609. //////////////////////////////////////////////////////////////////////////
  610. // CXTPDockingPaneAutoHidePanel
  611. int CXTPDockingPaneAutoHidePanel::GetPanelHeight() const
  612. {
  613. CXTPTabPaintManager::CAppearanceSet* pAppearanceSet = GetPaintManager()->GetPanelPaintManager()->GetAppearanceSet();
  614. return pAppearanceSet->GetButtonHeight(NULL) +
  615. pAppearanceSet->m_rcHeaderMargin.bottom + pAppearanceSet->m_rcHeaderMargin.top;
  616. }
  617. void CXTPDockingPaneAutoHidePanel::RefreshManagersArray(CDC* pDC, CRect rcClient)
  618. {
  619. BOOL bIndent = (m_direction == xtpPaneDockLeft || m_direction == xtpPaneDockRight)
  620. && (m_pLayout->m_wndPanels[xtpPaneDockTop] != NULL && !m_pLayout->m_wndPanels[xtpPaneDockTop]->IsEmpty());
  621. if (bIndent)
  622. {
  623. rcClient.top += GetPanelHeight();
  624. }
  625. m_pTabManagers->FreeAll();
  626. CRect rcMargins = GetPaintManager()->GetPanelPaintManager()->GetAppearanceSet()->GetHeaderMargin();
  627. POSITION pos = GetHeadPosition();
  628. while (pos)
  629. {
  630. CXTPDockingPaneTabbedContainer* pContainer = (CXTPDockingPaneTabbedContainer*)GetNext(pos);
  631. if (pContainer->IsEmpty())
  632. continue;
  633. CAutoHidePanelTabManager* pManager = m_pTabManagers->AddManager();
  634. POSITION posPane = pContainer->GetHeadPosition();
  635. while (posPane)
  636. {
  637. CXTPDockingPane* pPane = (CXTPDockingPane*)pContainer->GetNext(posPane);
  638. CXTPTabManagerItem* pItem = pManager->Add();
  639. pItem->SetData((DWORD_PTR)pPane);
  640. if (pContainer->GetSelected() == pPane) pManager->SetSelectedItem(pItem);
  641. pItem->SetCaption(pPane->GetShortTitle());
  642. pItem->SetColor(pPane->GetItemColor());
  643. pItem->SetEnabled(pPane->GetEnabled() & xtpPaneEnableClient);
  644. }
  645. pManager->GetPaintManager()->RepositionTabControl(pManager, pDC, rcClient);
  646. pManager->m_rcManager = rcClient;
  647. if (m_direction == xtpPaneDockLeft || m_direction == xtpPaneDockRight)
  648. {
  649. rcClient.top += pManager->GetItemsLength() + rcMargins.left + rcMargins.right + 8;
  650. }
  651. else
  652. {
  653. rcClient.left += pManager->GetItemsLength() + rcMargins.left + rcMargins.right + 8;
  654. }
  655. }
  656. }
  657. CXTPDockingPaneAutoHidePanel::CXTPDockingPaneAutoHidePanel(CXTPDockingPaneLayout* pLayout)
  658. : CXTPDockingPaneBaseContainer(xtpPaneTypeAutoHidePanel, pLayout)
  659. {
  660. m_direction = xtpPaneDockLeft;
  661. m_pActiveWnd = 0;
  662. m_pTabManagers = new CAutoHidePanelTabManagersArray();
  663. m_pTabManagers->m_pAutoHidePanel = this;
  664. m_pDropTarget = new CPanelDropTarget();
  665. m_rcFrameRect.SetRectEmpty();
  666. }
  667. CXTPDockingPaneAutoHidePanel::~CXTPDockingPaneAutoHidePanel()
  668. {
  669. if (m_pActiveWnd)
  670. {
  671. m_pActiveWnd->m_pPane = 0;
  672. m_pActiveWnd->m_pPanel = 0;
  673. CloseActiveWindow();
  674. }
  675. if (m_hWnd)
  676. DestroyWindow();
  677. delete m_pTabManagers;
  678. delete m_pDropTarget;
  679. }
  680. void CXTPDockingPaneAutoHidePanel::_InsertPane(CXTPDockingPaneBase* pPane)
  681. {
  682. m_lstPanes.AddTail(pPane);
  683. pPane->SetParentContainer(this);
  684. pPane->SetDockingSite(m_pDockingSite);
  685. GetDockingPaneManager()->RecalcFrameLayout(this, TRUE);
  686. pPane->OnParentContainerChanged(this);
  687. if (pPane->GetType() == xtpPaneTypeTabbedContainer)
  688. {
  689. CWnd* pFocus = GetFocus();
  690. if (((CXTPDockingPaneTabbedContainer*)pPane)->GetSafeHwnd() && pFocus->GetSafeHwnd() && (pFocus == ((CXTPDockingPaneTabbedContainer*)pPane) || ((CXTPDockingPaneTabbedContainer*)pPane)->IsChild(pFocus)))
  691. GetDockingPaneManager()->GetSite()->SetFocus();
  692. }
  693. if (m_hWnd) Invalidate(FALSE);
  694. }
  695. void CXTPDockingPaneAutoHidePanel::RemovePane(CXTPDockingPaneBase* pPane)
  696. {
  697. POSITION pos = m_lstPanes.Find(pPane);
  698. ASSERT(pos);
  699. m_lstPanes.RemoveAt(pos);
  700. if (m_hWnd) Invalidate(FALSE);
  701. GetDockingPaneManager()->RecalcFrameLayout(this, TRUE);
  702. if (m_lstPanes.IsEmpty())
  703. {
  704. if (m_hWnd) DestroyWindow();
  705. }
  706. pPane->m_pParentContainer = NULL;
  707. }
  708. void CXTPDockingPaneAutoHidePanel::Create(CWnd* pParent)
  709. {
  710. CWnd::Create(_T("XTPDockingPaneAutoHidePanel"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CXTPEmptyRect(), pParent, 0);
  711. m_pDropTarget->Register(this);
  712. }
  713. void CXTPDockingPaneAutoHidePanel::OnSizeParentEx(CWnd* pParent, CRect& rect, LPVOID lParam)
  714. {
  715. AFX_SIZEPARENTPARAMS* lpLayout = (AFX_SIZEPARENTPARAMS*)lParam;
  716. if (IsEmpty())
  717. {
  718. if (m_hWnd) DestroyWindow();
  719. return;
  720. }
  721. if (!m_hWnd)
  722. Create(pParent);
  723. if (m_rcFrameRect != rect)
  724. {
  725. CloseActiveWindow();
  726. m_rcFrameRect = rect;
  727. }
  728. int nHeight = GetPanelHeight();
  729. CRect rcClient(rect);
  730. switch (m_direction)
  731. {
  732. case xtpPaneDockLeft:
  733. rcClient.right = rect.left = rect.left + nHeight;
  734. break;
  735. case xtpPaneDockRight:
  736. rcClient.left = rect.right = rect.right - nHeight;
  737. break;
  738. case xtpPaneDockTop:
  739. rcClient.bottom = rect.top = rect.top + nHeight;
  740. break;
  741. case xtpPaneDockBottom:
  742. rcClient.top = rect.bottom = rect.bottom - nHeight;
  743. break;
  744. }
  745. CClientDC dc(this);
  746. CRect rcPanel(rcClient);
  747. rcPanel.OffsetRect(-rcPanel.TopLeft());
  748. RefreshManagersArray(&dc, rcPanel);
  749. if (lpLayout->hDWP != NULL)
  750. {
  751. MoveWindow(rcClient);
  752. Invalidate(FALSE);
  753. }
  754. }
  755. BEGIN_MESSAGE_MAP(CXTPDockingPaneAutoHidePanel, CWnd)
  756. ON_WM_PAINT()
  757. ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
  758. ON_WM_LBUTTONDOWN()
  759. ON_WM_RBUTTONDOWN()
  760. ON_WM_RBUTTONUP()
  761. ON_WM_MOUSEMOVE()
  762. ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
  763. ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave)
  764. END_MESSAGE_MAP()
  765. LRESULT CXTPDockingPaneAutoHidePanel::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
  766. {
  767. CDC* pDC = CDC::FromHandle((HDC)wParam);
  768. if (pDC)
  769. {
  770. OnDraw(pDC);
  771. }
  772. return TRUE;
  773. }
  774. void CXTPDockingPaneAutoHidePanel::OnPaint()
  775. {
  776. CPaintDC dcPaint(this);
  777. CXTPBufferDC dc(dcPaint);
  778. OnDraw(&dc);
  779. }
  780. void CXTPDockingPaneAutoHidePanel::OnDraw(CDC* pDC)
  781. {
  782. CXTPClientRect rc(this);
  783. CXTPPaintManagerColorGradient& clr = GetPaintManager()->GetPanelPaintManager()->GetColorSet()->m_clrAutoHideFace;
  784. if (clr.clrDark == clr.clrLight)
  785. {
  786. pDC->FillSolidRect(rc, clr.clrDark);
  787. }
  788. else
  789. {
  790. CRect rcFill(rc);
  791. if (m_direction == xtpPaneDockRight)
  792. {
  793. rcFill.left -= CXTPClientRect(GetParent()).Width() - rcFill.Width();
  794. }
  795. rcFill.right = rcFill.left + max(rcFill.Width(), GetSystemMetrics(SM_CXFULLSCREEN) / 2);
  796. XTPDrawHelpers()->GradientFill(pDC, rcFill, clr.clrLight, clr.clrDark, TRUE, rc);
  797. }
  798. m_pTabManagers->Draw(pDC);
  799. }
  800. CXTPTabManagerItem* CXTPDockingPaneAutoHidePanel::GetPaneTab(CXTPDockingPane* pPane) const
  801. {
  802. for (int i = 0; i < m_pTabManagers->GetSize(); i++)
  803. {
  804. CAutoHidePanelTabManager* pTabManager = m_pTabManagers->GetAt(i);
  805. for (int j = 0; j < pTabManager->GetItemCount(); j++)
  806. {
  807. CXTPTabManagerItem* pItem = pTabManager->GetItem(j);
  808. if ((CXTPDockingPane*)pItem->GetData() == pPane)
  809. {
  810. return pItem;
  811. }
  812. }
  813. }
  814. return NULL;
  815. }
  816. CXTPDockingPane* CXTPDockingPaneAutoHidePanel::HitTest(CPoint point) const
  817. {
  818. for (int i = 0; i < m_pTabManagers->GetSize(); i++)
  819. {
  820. CXTPTabManagerItem* pItem = m_pTabManagers->GetAt(i)->HitTest(point);
  821. if (pItem)
  822. {
  823. return (CXTPDockingPane*)pItem->GetData();
  824. }
  825. }
  826. return NULL;
  827. }
  828. void CXTPDockingPaneAutoHidePanel::CloseActiveWindows()
  829. {
  830. for (int i = 0; i < 4; i++)
  831. {
  832. SAFE_CALLPTR(m_pLayout->m_wndPanels[i], CloseActiveWindow());
  833. }
  834. }
  835. void CXTPDockingPaneAutoHidePanel::CloseActiveWindow(BOOL bDelayed)
  836. {
  837. if (!m_bCloseActiveWindow)
  838. return;
  839. if (m_pActiveWnd)
  840. {
  841. if (m_pActiveWnd->m_pPane)
  842. {
  843. if (GetDockingPaneManager()->NotifyAction(xtpPaneActionCollapsing, m_pActiveWnd->m_pPane->GetSelected()))
  844. return;
  845. GetDockingPaneManager()->NotifyAction(xtpPaneActionCollapsed,
  846. m_pActiveWnd->m_pPane->GetSelected());
  847. }
  848. if (bDelayed)
  849. {
  850. // let the window close itself
  851. if (m_pActiveWnd->m_pPane)
  852. {
  853. m_pActiveWnd->m_pPane->ShowWindow(SW_HIDE);
  854. m_pActiveWnd->m_pPane->SetDockingSite(GetDockingPaneManager()->GetSite());
  855. m_pActiveWnd->m_pPane = 0;
  856. }
  857. m_pActiveWnd->SetTimer(TID_CLOSE, 50, NULL);
  858. }
  859. else
  860. {
  861. m_pActiveWnd->CloseWindow();
  862. }
  863. m_pActiveWnd = 0;
  864. }
  865. }
  866. void CXTPDockingPaneAutoHidePanel::ShowPane(CXTPDockingPane* pPane, BOOL bSetFocus)
  867. {
  868. if (m_pActiveWnd && m_pActiveWnd->m_pPane && m_pActiveWnd->m_pPane->GetSelected() == pPane)
  869. {
  870. if (bSetFocus) m_pActiveWnd->m_pPane->SelectPane(pPane, TRUE, FALSE);
  871. if (m_pActiveWnd->m_bSlideOut)
  872. {
  873. m_pActiveWnd->OnTimer(TID_CHECKACTIVE);
  874. }
  875. return;
  876. }
  877. CloseActiveWindows();
  878. if (GetDockingPaneManager()->NotifyAction(xtpPaneActionExpanding, pPane))
  879. return;
  880. CXTPDockingPaneTabbedContainer* pContainer = ((CXTPDockingPaneTabbedContainer*)pPane->m_pParentContainer);
  881. ASSERT(pContainer);
  882. if (!pContainer)
  883. return;
  884. ASSERT(pContainer->GetType() == xtpPaneTypeTabbedContainer);
  885. pContainer->SelectPane(pPane, FALSE, TRUE);
  886. CXTPDockingPaneAutoHideWnd* pActiveWnd = new CXTPDockingPaneAutoHideWnd(this, pContainer);
  887. if (bSetFocus) pContainer->SelectPane(pPane, TRUE, FALSE);
  888. if (m_hWnd) Invalidate(FALSE);
  889. GetDockingPaneManager()->RecalcFrameLayout(this);
  890. m_pActiveWnd = pActiveWnd;
  891. }
  892. void CXTPDockingPaneAutoHidePanel::OnLButtonDown(UINT /*nFlags*/, CPoint point)
  893. {
  894. CXTPDockingPane* pPane = HitTest(point);
  895. if (pPane)
  896. {
  897. if (m_pActiveWnd && m_pActiveWnd->m_pPane->GetSelected() == pPane)
  898. {
  899. pPane->SetFocus();
  900. }
  901. else
  902. {
  903. ShowPane(pPane);
  904. }
  905. }
  906. }
  907. void CXTPDockingPaneAutoHidePanel::OnRButtonDown(UINT /*nFlags*/, CPoint point)
  908. {
  909. CXTPDockingPane* pPane = HitTest(point);
  910. if (pPane)
  911. {
  912. GetDockingPaneManager()->NotifyOwner(XTP_DPN_RCLICK, (LPARAM)(CXTPDockingPaneBase*)pPane);
  913. }
  914. }
  915. void CXTPDockingPaneAutoHidePanel::OnRButtonUp(UINT /*nFlags*/, CPoint point)
  916. {
  917. XTP_DOCKINGPANE_CLICK menu;
  918. menu.pPane = HitTest(point);
  919. menu.pContainer = this;
  920. ClientToScreen(&point);
  921. menu.pt = point;
  922. menu.rcExclude.SetRectEmpty();
  923. if (GetDockingPaneManager()->NotifyOwner(XTP_DPN_CONTEXTMENU, (LPARAM)&menu))
  924. return;
  925. }
  926. void CXTPDockingPaneAutoHidePanel::OnMouseMove(UINT nFlags, CPoint point)
  927. {
  928. for (int i = 0; i < m_pTabManagers->GetSize(); i++)
  929. {
  930. m_pTabManagers->GetAt(i)->PerformMouseMove(m_hWnd, point);
  931. }
  932. CXTPDockingPane* pPane = HitTest(point);
  933. if (pPane)
  934. {
  935. TRACKMOUSEEVENT tme =
  936. {
  937. sizeof(TRACKMOUSEEVENT), TME_HOVER | TME_LEAVE, m_hWnd, CXTPDockingPaneAutoHideWnd::m_nMouseHoverDelay
  938. };
  939. _TrackMouseEvent(&tme);
  940. }
  941. CWnd::OnMouseMove(nFlags, point);
  942. }
  943. void CXTPDockingPaneAutoHidePanel::OnMouseLeave()
  944. {
  945. OnMouseMove(0, CPoint(-1, -1));
  946. }
  947. LRESULT CXTPDockingPaneAutoHidePanel::OnMouseHover(WPARAM, LPARAM lParam)
  948. {
  949. CPoint point(lParam);
  950. CXTPDockingPane* pPane = HitTest(point);
  951. if (pPane)
  952. {
  953. if (!CXTPDrawHelpers::IsTopParentActive(m_hWnd) || (m_pActiveWnd && m_pActiveWnd->m_pPane->GetSelected() == pPane))
  954. return 1;
  955. ShowPane(pPane, FALSE);
  956. }
  957. return 1;
  958. }
  959. void CXTPDockingPaneAutoHidePanel::Copy(CXTPDockingPaneBase* pCloneBase, CXTPPaneToPaneMap* pMap, DWORD /*dwIgnoredOptions*/)
  960. {
  961. CXTPDockingPaneAutoHidePanel* pClone = (CXTPDockingPaneAutoHidePanel*)pCloneBase;
  962. ASSERT(pClone);
  963. if (!pClone)
  964. return;
  965. m_direction = pClone->m_direction;
  966. m_pDockingSite = GetDockingPaneManager()->GetSite();
  967. POSITION pos = pClone->GetHeadPosition();
  968. while (pos)
  969. {
  970. CXTPDockingPaneBase* pPane = (CXTPDockingPaneBase*)pClone->GetNext(pos);
  971. if (!pPane->IsEmpty() || pMap)
  972. {
  973. _InsertPane(pPane->Clone(m_pLayout, pMap));
  974. }
  975. }
  976. }
  977. void CXTPDockingPaneAutoHidePanel::InvalidatePane(BOOL /*bSelectionChanged*/)
  978. {
  979. if (!m_hWnd)
  980. return;
  981. CClientDC dc(this);
  982. CXTPClientRect rcPanel(this);
  983. RefreshManagersArray(&dc, rcPanel);
  984. Invalidate(FALSE);
  985. }
  986. void CXTPDockingPaneAutoHidePanel::OnChildContainerChanged(CXTPDockingPaneBase* /*pContainer*/)
  987. {
  988. if (m_pActiveWnd)
  989. {
  990. if (!m_bCloseActiveWindow)
  991. {
  992. GetDockingPaneManager()->RecalcFrameLayout(this);
  993. m_pActiveWnd->RecalcLayout(TRUE);
  994. }
  995. else
  996. {
  997. CloseActiveWindow(GetDockingPaneManager()->m_bAttachingPane);
  998. }
  999. }
  1000. }
  1001. void CXTPDockingPaneAutoHidePanel::DeletePane()
  1002. {
  1003. InternalRelease();
  1004. }
  1005. void CXTPDockingPaneAutoHidePanel::OnFinalRelease()
  1006. {
  1007. if (m_hWnd != NULL)
  1008. DestroyWindow();
  1009. CCmdTarget::OnFinalRelease();
  1010. }