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

对话框与窗口

开发平台:

Visual C++

  1. // XTCaption.cpp : implementation of the CXTCaption 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/XTPWinThemeWrapper.h"
  22. #include "Common/XTPDrawHelpers.h"
  23. #include "Resource.h"
  24. #include "XTDefines.h"
  25. #include "XTUtil.h"
  26. #include "XTGlobal.h"
  27. #include "XTButton.h"
  28. #include "XTThemeManager.h"
  29. #include "XTButtonTheme.h"
  30. #include "XTCaptionTheme.h"
  31. #include "XTCaption.h"
  32. #include "XTCaptionPopupWnd.h"
  33. #ifdef _DEBUG
  34. #define new DEBUG_NEW
  35. #undef THIS_FILE
  36. static char THIS_FILE[] = __FILE__;
  37. #endif
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CXTCaptionButton
  40. IMPLEMENT_THEME_HOST(CXTCaptionButton)
  41. IMPLEMENT_THEME_REFRESH(CXTCaptionButton, CXTButton)
  42. CXTCaptionButton::CXTCaptionButton()
  43. : CXTButton(GetThemeFactoryClass())
  44. , m_pCaption(NULL)
  45. {
  46. }
  47. DWORD CXTCaptionButton::SetXButtonStyle(DWORD /*dwxStyle*/, BOOL bRedraw/*= TRUE*/)
  48. {
  49. DWORD dwOldStyle = m_dwxStyle;
  50. CXTCaption* pCaption = DYNAMIC_DOWNCAST(CXTCaption, GetSafeHwnd() ? GetParent() : 0);
  51. if (pCaption)
  52. {
  53. // set the button font and colors.
  54. SetColorFace(pCaption->m_clrFace);
  55. SetColorText(pCaption->m_clrText);
  56. SetColorShadow(GetXtremeColor(COLOR_3DDKSHADOW));
  57. // set the button font to match caption font.
  58. SetFont(pCaption->GetFont());
  59. // Redraw the button.
  60. if (bRedraw)
  61. Invalidate();
  62. }
  63. return dwOldStyle;
  64. }
  65. /////////////////////////////////////////////////////////////////////////////
  66. // CXTCaption
  67. IMPLEMENT_THEME_HOST(CXTCaption)
  68. IMPLEMENT_THEME_REFRESH(CXTCaption, CStatic)
  69. CXTCaption::CXTCaption()
  70. : CXTThemeManagerStyleHost(GetThemeFactoryClass())
  71. {
  72. m_bAppCaption = false;
  73. m_bUserColors = false;
  74. m_strCaption = _T("");
  75. m_hIcon = NULL;
  76. m_pChildWnd = NULL;
  77. m_pParentView = NULL;
  78. m_pSplitterWnd = NULL;
  79. m_pPopupWnd = NULL;
  80. m_nOffset = 0;
  81. m_nBorder = 0;
  82. m_sizeIcon.cx = __min(XTAuxData().cxSmIcon, 16);
  83. m_sizeIcon.cy = __min(XTAuxData().cySmIcon, 16);
  84. m_dwExStyle = 0L;
  85. m_clrText = ::GetSysColor(COLOR_BTNTEXT);
  86. m_clrBorder = ::GetSysColor(COLOR_3DFACE);
  87. m_clrFace = ::GetSysColor(COLOR_3DFACE);
  88. }
  89. CXTCaption::~CXTCaption()
  90. {
  91. }
  92. IMPLEMENT_DYNAMIC(CXTCaption, CStatic)
  93. BEGIN_MESSAGE_MAP(CXTCaption, CStatic)
  94. //{{AFX_MSG_MAP(CXTCaption)
  95. ON_WM_PAINT()
  96. ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
  97. ON_WM_ERASEBKGND()
  98. ON_WM_WINDOWPOSCHANGED()
  99. ON_WM_SYSCOLORCHANGE()
  100. ON_WM_SIZE()
  101. //}}AFX_MSG_MAP
  102. ON_BN_CLICKED(XT_IDC_BTN_CLOSE, OnCaptButton)
  103. ON_MESSAGE_VOID(CPWN_XT_PUSHPINBUTTON, OnPushPinButton)
  104. ON_MESSAGE_VOID(CPWN_XT_PUSHPINCANCEL, OnPushPinCancel)
  105. END_MESSAGE_MAP()
  106. void CXTCaption::OnSize(UINT nType, int cx, int cy)
  107. {
  108. CStatic::OnSize(nType, cx, cy);
  109. if (m_hIcon != NULL)
  110. RedrawWindow();
  111. }
  112. void CXTCaption::OnPaint()
  113. {
  114. // background is already filled in gray
  115. CPaintDC dc(this);
  116. // Get the client rect.
  117. CXTPClientRect rectClient(this);
  118. // Paint to a memory device context to help
  119. // eliminate screen flicker.
  120. CXTPBufferDC memDC(dc);
  121. // If the caption button is a valid window and visible exclude from painting...
  122. if (::IsWindow(m_btnCaption.m_hWnd) && m_btnCaption.IsWindowVisible())
  123. {
  124. CXTPWindowRect rcButton(&m_btnCaption);
  125. ScreenToClient(&rcButton);
  126. memDC.ExcludeClipRect(&rcButton);
  127. }
  128. // draw the background, text and icon.
  129. DrawCaptionBack(&memDC, rectClient);
  130. DrawCaptionText(&memDC);
  131. DrawCaptionIcon(&memDC, rectClient);
  132. }
  133. LRESULT CXTCaption::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
  134. {
  135. CDC* pDC = CDC::FromHandle((HDC)wParam);
  136. if (pDC)
  137. {
  138. CXTPClientRect rectClient(this);
  139. DrawCaptionBack(pDC, rectClient);
  140. DrawCaptionText(pDC);
  141. DrawCaptionIcon(pDC, rectClient);
  142. }
  143. return 1;
  144. }
  145. BOOL CXTCaption::OnEraseBkgnd(CDC* /*pDC*/)
  146. {
  147. return TRUE;
  148. }
  149. void CXTCaption::DrawCaptionBack(CDC* pDC, CRect& rcItem)
  150. {
  151. GetTheme()->DrawCaptionBack(pDC, this, rcItem);
  152. }
  153. void CXTCaption::DrawCaptionText(CDC* pDC)
  154. {
  155. GetTheme()->DrawCaptionText(pDC, this);
  156. }
  157. void CXTCaption::DrawCaptionIcon(CDC* pDC, CRect& rcItem)
  158. {
  159. GetTheme()->DrawCaptionIcon(pDC, this, rcItem);
  160. }
  161. BOOL CXTCaption::Create(CWnd* pParentWnd, LPCTSTR lpszWindowName, DWORD dwExStyle, DWORD dwStyle, const CRect& rect, UINT nID)
  162. {
  163. // Let the base class create the control.
  164. if (!CStatic::Create(NULL, dwStyle | WS_CLIPCHILDREN, rect, pParentWnd, nID))
  165. {
  166. TRACE(_T("Unable to create caption.n"));
  167. return FALSE;
  168. }
  169. SetFont(&XTAuxData().font);
  170. // save the style.
  171. m_dwExStyle = (dwExStyle & (CPWS_EX_GROOVE_EDGE | CPWS_EX_RAISED_EDGE | CPWS_EX_CLOSEBUTTON));
  172. ModifyStyleEx(0, (dwExStyle & ~m_dwExStyle));
  173. // Save the window text.
  174. m_strCaption = lpszWindowName;
  175. if (HasCloseButton())
  176. {
  177. // Create the caption's close button.
  178. if (!m_btnCaption.Create(NULL, WS_VISIBLE | WS_CHILD | BS_ICON | BS_OWNERDRAW | BS_CENTER | BS_VCENTER,
  179. CRect(0, 0, 0, 0), this, XT_IDC_BTN_CLOSE))
  180. {
  181. TRACE0("Unable to create caption button.n");
  182. return -1;
  183. }
  184. // Create the image list used by frame buttons.
  185. m_ilButton.Create (XT_IDB_BTN_OUT, 16, 1, RGB(255, 0, 255));
  186. // and set the icon for the caption's close button
  187. m_btnCaption.SetIcon(CSize(16, 15), m_ilButton.ExtractIcon(2));
  188. }
  189. else
  190. {
  191. // Create the button to be used with child window.
  192. if (!m_btnCaption.Create(m_strCaption, BS_ICON | BS_OWNERDRAW | BS_VCENTER,
  193. CRect(0, 0, 0, 0), this, XT_IDC_BTN_CLOSE))
  194. {
  195. TRACE0("Unable to create caption button.n");
  196. return FALSE;
  197. }
  198. m_bAppCaption = true;
  199. }
  200. m_btnCaption.SetCaption(this);
  201. m_btnCaption.SetXButtonStyle(0, FALSE);
  202. SetWindowPos(NULL, 0, 0, 0, 0,
  203. SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
  204. return TRUE;
  205. }
  206. void CXTCaption::ModifyCaptionStyle(int nBorderSize, CFont* pFont, LPCTSTR lpszWindText, HICON hIcon)
  207. {
  208. ASSERT(::IsWindow(m_hWnd));
  209. if (nBorderSize != 0)
  210. {
  211. m_nBorder = nBorderSize;
  212. }
  213. if (pFont != NULL)
  214. {
  215. SetFont(pFont);
  216. // button font should match caption
  217. if (::IsWindow(m_btnCaption.m_hWnd))
  218. m_btnCaption.SetFont(GetFont());
  219. }
  220. if (lpszWindText != NULL)
  221. {
  222. m_strCaption = lpszWindText;
  223. }
  224. if (hIcon != NULL)
  225. {
  226. m_hIcon = hIcon;
  227. }
  228. Invalidate();
  229. }
  230. void CXTCaption::SetChildWindow(CWnd* pChild, CWnd* pNotifyWnd)
  231. {
  232. ASSERT_VALID (pChild);      // must be valid.
  233. ASSERT_VALID (pNotifyWnd);  // must be valid.
  234. // save window pointers, and show caption button.
  235. m_pChildWnd = pChild;
  236. SetOwner(pNotifyWnd);
  237. m_pParentView = pChild->GetParent();
  238. ASSERT_KINDOF(CView, m_pParentView);
  239. m_pSplitterWnd = m_pParentView->GetParent();
  240. ASSERT_KINDOF(CSplitterWnd, m_pSplitterWnd);
  241. // get the size of the child and parent windows.
  242. m_pChildWnd->GetClientRect (&m_rcChild);
  243. m_pParentView->GetClientRect (&m_rcParent);
  244. m_pSplitterWnd->GetClientRect (&m_rcSplitter);
  245. // save the size of the childs caption area.
  246. m_nOffset = (m_rcParent.Height() - m_rcChild.Height());
  247. // make the caption button visible.
  248. m_btnCaption.ShowWindow(SW_SHOW);
  249. m_btnCaption.UpdateWindow();
  250. // inflate the size of the parent to add a border, this will
  251. // also be the size of the popup window.
  252. int cx = ::GetSystemMetrics (SM_CXEDGE)*2;
  253. int cy = ::GetSystemMetrics (SM_CYEDGE)*2;
  254. m_rcParent.InflateRect(cx, cy);
  255. }
  256. void CXTCaption::KillChildWindow()
  257. {
  258. // Hide the caption button.
  259. if (::IsWindow(m_btnCaption.m_hWnd))
  260. {
  261. m_btnCaption.ShowWindow(SW_HIDE);
  262. m_btnCaption.SetState(FALSE);
  263. }
  264. // Destroy the pop-up window.
  265. if (::IsWindow(m_pPopupWnd->GetSafeHwnd()))
  266. {
  267. m_pPopupWnd->DestroyWindow();
  268. }
  269. SAFE_DELETE(m_pPopupWnd);
  270. }
  271. BOOL CXTCaption::ShowPopupWindow()
  272. {
  273. // already visible return TRUE.
  274. if (::IsWindowVisible(m_pPopupWnd->GetSafeHwnd()))
  275. return TRUE;
  276. // if not a window yet create it.
  277. if (!::IsWindow(m_pPopupWnd->GetSafeHwnd()))
  278. {
  279. m_pPopupWnd = new CXTCaptionPopupWnd;
  280. if (!m_pPopupWnd->Create(CRect(0, 0, 0, 0), this, m_pChildWnd))
  281. {
  282. SAFE_DELETE(m_pPopupWnd);
  283. return FALSE;
  284. }
  285. }
  286. // view pointer is not valid.
  287. if (!::IsWindow(m_pParentView->GetSafeHwnd()))
  288. return FALSE;
  289. // splitter pointer is not valid.
  290. if (!::IsWindow(m_pSplitterWnd->GetSafeHwnd()))
  291. return FALSE;
  292. CRect rcPopup(m_rcParent);
  293. m_pParentView->ClientToScreen(&rcPopup);
  294. // get the current size of the splitter window.
  295. CRect rcSplitter;
  296. m_pSplitterWnd->GetClientRect(&rcSplitter);
  297. // check to see if the size has changed.
  298. if (rcSplitter.Height() > m_rcSplitter.Height())
  299. {
  300. rcPopup.bottom += (rcSplitter.Height() - m_rcSplitter.Height());
  301. }
  302. else if (m_rcSplitter.Height() > rcSplitter.Height())
  303. {
  304. rcPopup.bottom -= (m_rcSplitter.Height() - rcSplitter.Height());
  305. }
  306. // display the popup window.
  307. m_pPopupWnd->MoveWindow(&rcPopup);
  308. m_pPopupWnd->ShowWindow(SW_SHOW);
  309. m_pPopupWnd->RecalcLayout();
  310. // press the caption button.
  311. m_btnCaption.SetState(TRUE);
  312. return TRUE;
  313. }
  314. void CXTCaption::OnCaptButton()
  315. {
  316. if (HasCloseButton())
  317. {
  318. CWnd* pOwner = GetOwner();
  319. ASSERT_VALID(pOwner);
  320. if (pOwner)
  321. {
  322. // Notify of selection change.
  323. pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(),
  324. BN_CLICKED), (LPARAM)m_hWnd);
  325. }
  326. }
  327. else
  328. {
  329. ShowPopupWindow();
  330. }
  331. }
  332. void CXTCaption::OnPushPinButton()
  333. {
  334. KillChildWindow();
  335. // get the current size of the child's parent window and
  336. // adjust the size of the child accordingly.
  337. m_pParentView->GetClientRect (&m_rcParent);
  338. m_rcChild = m_rcParent;
  339. m_rcChild.top += m_nOffset;
  340. // move the child window to its correct location.
  341. m_pChildWnd->MoveWindow (m_rcChild);
  342. CWnd* pNotifyWnd = GetOwner();
  343. ASSERT_VALID(pNotifyWnd);
  344. if (::IsWindow(pNotifyWnd->GetSafeHwnd()))
  345. {
  346. // Notify that push pin button was pressed.
  347. pNotifyWnd->SendMessage(CPWN_XT_PUSHPINBUTTON);
  348. Invalidate();
  349. }
  350. }
  351. void CXTCaption::OnPushPinCancel()
  352. {
  353. m_btnCaption.SetState(FALSE);
  354. m_pPopupWnd->DestroyWindow();
  355. SAFE_DELETE (m_pPopupWnd);
  356. CWnd* pNotifyWnd = GetOwner();
  357. ASSERT_VALID(pNotifyWnd);
  358. if (::IsWindow(pNotifyWnd->GetSafeHwnd()))
  359. {
  360. // Notify that popup window has lost input focus.
  361. pNotifyWnd->SendMessage(CPWN_XT_PUSHPINCANCEL);
  362. Invalidate();
  363. }
  364. }
  365. void CXTCaption::UpdateCaption(LPCTSTR lpszWindowText, HICON hIcon)
  366. {
  367. ASSERT(::IsWindow(m_hWnd));
  368. CRect rcClient;
  369. GetClientRect(&rcClient);
  370. CDC* pDC = GetDC();
  371. DrawCaptionBack(pDC, rcClient);
  372. if (lpszWindowText != NULL)
  373. {
  374. m_strCaption = lpszWindowText;
  375. UpdateCaptionText(pDC);
  376. }
  377. if (hIcon != NULL)
  378. {
  379. m_hIcon = hIcon;
  380. DrawCaptionIcon(pDC, rcClient);
  381. }
  382. ReleaseDC(pDC);
  383. }
  384. void CXTCaption::UpdateCaptionText(CDC* pDC)
  385. {
  386. if (::IsWindow(m_btnCaption.m_hWnd))
  387. {
  388. m_btnCaption.SetWindowText(m_strCaption);
  389. m_btnCaption.MoveWindow(GetButtonRect());
  390. }
  391. DrawCaptionText(pDC);
  392. }
  393. CRect CXTCaption::GetTextRect() const
  394. {
  395. if (m_strCaption.IsEmpty())
  396. return CXTPEmptyRect();
  397. CXTPClientRect rcClient(this);
  398. // Use a NULL window dc to get the size the caption button
  399. // should be using CDC::GetTextExtent(...).
  400. CWindowDC dc(NULL);
  401. CXTPFontDC fontDC(&dc, GetFont());
  402. TEXTMETRIC tm;
  403. dc.GetTextMetrics(&tm);
  404. // Calculate the button area size.
  405. CSize size = dc.GetTextExtent(m_strCaption, m_strCaption.GetLength());
  406. size.cx += tm.tmAveCharWidth + 12;
  407. size.cy = rcClient.Height();
  408. int iWidth = rcClient.Width() - (m_hIcon ? 18 : 0);
  409. if (size.cx > iWidth)
  410. size.cx = iWidth;
  411. return CRect(m_nBorder, m_nBorder, m_nBorder + size.cx, size.cy - m_nBorder);
  412. }
  413. CRect CXTCaption::GetButtonRect() const
  414. {
  415. if (!::IsWindow(m_btnCaption.m_hWnd))
  416. return CXTPEmptyRect();
  417. if (!HasCloseButton())
  418. return GetTextRect();
  419. CSize szIcon(16, 15);
  420. CXTPClientRect rcClient(this);
  421. CRect rcButton;
  422. rcButton.left = (rcClient.Width() -szIcon.cx)-2;
  423. rcButton.top = (rcClient.Height()-szIcon.cy)/2;
  424. rcButton.right = rcButton.left + szIcon.cx;
  425. rcButton.bottom = rcButton.top + szIcon.cy;
  426. return rcButton;
  427. }
  428. void CXTCaption::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
  429. {
  430. CStatic::OnWindowPosChanged(lpwndpos);
  431. if (::IsWindow(m_btnCaption.m_hWnd))
  432. m_btnCaption.MoveWindow(GetButtonRect());
  433. }
  434. void CXTCaption::SetCaptionColors(COLORREF clrBorder, COLORREF clrFace, COLORREF clrText)
  435. {
  436. ASSERT(::IsWindow(m_hWnd));
  437. m_bUserColors = true;
  438. m_clrBorder = clrBorder;
  439. m_clrFace = clrFace;
  440. m_clrText = clrText;
  441. if (::IsWindow(m_btnCaption.m_hWnd))
  442. {
  443. m_btnCaption.SetColorFace(m_clrFace);
  444. m_btnCaption.SetColorText(m_clrText);
  445. m_btnCaption.SetColorShadow(::GetSysColor(COLOR_3DDKSHADOW));
  446. }
  447. }
  448. void CXTCaption::SetOffice2003Colors(bool b2003Colors/*= true*/)
  449. {
  450. m_bUserColors = b2003Colors;
  451. SetTheme(b2003Colors ? new CXTCaptionThemeOffice2003() : NULL);
  452. }
  453. void CXTCaption::OnSysColorChange()
  454. {
  455. CStatic::OnSysColorChange();
  456. // update caption colors if not user defined.
  457. if (m_bUserColors == false)
  458. {
  459. m_clrText = ::GetSysColor(COLOR_BTNTEXT);
  460. m_clrBorder = ::GetSysColor(COLOR_3DFACE);
  461. m_clrFace = ::GetSysColor(COLOR_3DFACE);
  462. if (::IsWindow(m_btnCaption.m_hWnd))
  463. {
  464. m_btnCaption.SetColorFace(m_clrFace);
  465. m_btnCaption.SetColorText(m_clrText);
  466. m_btnCaption.SetColorShadow(::GetSysColor(COLOR_3DDKSHADOW));
  467. }
  468. }
  469. }