Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2215 lines
59 KiB

  1. /*--------------------------------------------------------------------------*
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1992 - 1999
  5. *
  6. * File: ftab.h
  7. *
  8. * Contents: Implementation file for CFolderTab, CFolderTabView
  9. *
  10. * History: 06-May-99 vivekj Created
  11. *
  12. *--------------------------------------------------------------------------*/
  13. #include "stdafx.h"
  14. #include "ftab.h"
  15. #include "amcview.h"
  16. #include <oleacc.h>
  17. /*
  18. * if we're supporting old platforms, we need to build MSAA stubs
  19. */
  20. #if (_WINNT_WIN32 < 0x0500)
  21. #include <winable.h>
  22. #define COMPILE_MSAA_STUBS
  23. #include "msaastub.h"
  24. #define WM_GETOBJECT 0x003D
  25. #endif
  26. #ifdef DBG
  27. CTraceTag tagTabAccessibility (_T("Accessibility"), _T("Tab Control"));
  28. #endif
  29. /*+-------------------------------------------------------------------------*
  30. * ValueOf
  31. *
  32. * Returns the value contained in the given variant. The variant is
  33. * expected to be of type VT_I4.
  34. *--------------------------------------------------------------------------*/
  35. inline LONG ValueOf (VARIANT& var)
  36. {
  37. ASSERT (V_VT (&var) == VT_I4); // prevalidation is expected
  38. return (V_I4 (&var));
  39. }
  40. /*+-------------------------------------------------------------------------*
  41. * CTabAccessible
  42. *
  43. * Implements the accessibility interface IAccessible for CFolderTabView.
  44. *--------------------------------------------------------------------------*/
  45. class CTabAccessible :
  46. public CMMCIDispatchImpl<IAccessible, &GUID_NULL, &LIBID_Accessibility>,
  47. public CTiedComObject<CFolderTabView>
  48. {
  49. typedef CTabAccessible ThisClass;
  50. typedef CFolderTabView CMyTiedObject;
  51. public:
  52. BEGIN_MMC_COM_MAP(ThisClass)
  53. END_MMC_COM_MAP()
  54. DECLARE_NOT_AGGREGATABLE(ThisClass)
  55. public:
  56. // *** IAccessible methods ***
  57. MMC_METHOD1 (get_accParent, IDispatch** /*ppdispParent*/);
  58. MMC_METHOD1 (get_accChildCount, long* /*pChildCount*/);
  59. MMC_METHOD2 (get_accChild, VARIANT /*varChildID*/, IDispatch ** /*ppdispChild*/);
  60. MMC_METHOD2 (get_accName, VARIANT /*varChildID*/, BSTR* /*pszName*/);
  61. MMC_METHOD2 (get_accValue, VARIANT /*varChildID*/, BSTR* /*pszValue*/);
  62. MMC_METHOD2 (get_accDescription, VARIANT /*varChildID*/, BSTR* /*pszDescription*/);
  63. MMC_METHOD2 (get_accRole, VARIANT /*varChildID*/, VARIANT */*pvarRole*/);
  64. MMC_METHOD2 (get_accState, VARIANT /*varChildID*/, VARIANT */*pvarState*/);
  65. MMC_METHOD2 (get_accHelp, VARIANT /*varChildID*/, BSTR* /*pszHelp*/);
  66. MMC_METHOD3 (get_accHelpTopic, BSTR* /*pszHelpFile*/, VARIANT /*varChildID*/, long* /*pidTopic*/);
  67. MMC_METHOD2 (get_accKeyboardShortcut, VARIANT /*varChildID*/, BSTR* /*pszKeyboardShortcut*/);
  68. MMC_METHOD1 (get_accFocus, VARIANT * /*pvarFocusChild*/);
  69. MMC_METHOD1 (get_accSelection, VARIANT * /*pvarSelectedChildren*/);
  70. MMC_METHOD2 (get_accDefaultAction, VARIANT /*varChildID*/, BSTR* /*pszDefaultAction*/);
  71. MMC_METHOD2 (accSelect, long /*flagsSelect*/, VARIANT /*varChildID*/);
  72. MMC_METHOD5 (accLocation, long* /*pxLeft*/, long* /*pyTop*/, long* /*pcxWidth*/, long* /*pcyHeight*/, VARIANT /*varChildID*/);
  73. MMC_METHOD3 (accNavigate, long /*navDir*/, VARIANT /*varStart*/, VARIANT * /*pvarEndUpAt*/);
  74. MMC_METHOD3 (accHitTest, long /*xLeft*/, long /*yTop*/, VARIANT * /*pvarChildAtPoint*/);
  75. MMC_METHOD1 (accDoDefaultAction, VARIANT /*varChildID*/);
  76. MMC_METHOD2 (put_accName, VARIANT /*varChildID*/, BSTR /*szName*/);
  77. MMC_METHOD2 (put_accValue, VARIANT /*varChildID*/, BSTR /*pszValue*/);
  78. };
  79. //############################################################################
  80. //############################################################################
  81. //
  82. // Implementation of class CFolderTabMetrics
  83. //
  84. //############################################################################
  85. //############################################################################
  86. CFolderTabMetrics::CFolderTabMetrics()
  87. : m_dwStyle(0), m_textHeight(0)
  88. {
  89. }
  90. int CFolderTabMetrics::GetXOffset() const {return 8;}
  91. int CFolderTabMetrics::GetXMargin() const {return 2;}
  92. int CFolderTabMetrics::GetYMargin() const {return 1;}
  93. int CFolderTabMetrics::GetYBorder() const {return 1;}
  94. int CFolderTabMetrics::GetExtraYSpace() const {return 0;}
  95. int CFolderTabMetrics::GetTabHeight() const {return GetTextHeight() + 2 * GetYMargin() + 2 * GetYBorder();}
  96. int CFolderTabMetrics::GetUpDownWidth() const {return 2*GetTabHeight();} //for nice square buttons
  97. int CFolderTabMetrics::GetUpDownHeight()const {return GetTabHeight();} // the up-down control is as tall as the tabs
  98. //############################################################################
  99. //############################################################################
  100. //
  101. // Implementation of class CFolderTab
  102. //
  103. //############################################################################
  104. //############################################################################
  105. CFolderTab::CFolderTab()
  106. {
  107. }
  108. CFolderTab::CFolderTab(const CFolderTab &other)
  109. {
  110. *this = other;
  111. }
  112. CFolderTab &
  113. CFolderTab::operator = (const CFolderTab &other)
  114. {
  115. if((CFolderTab *) this == (CFolderTab *) &other)
  116. return *this;
  117. m_sText = other.m_sText;
  118. m_rect = other.m_rect;
  119. m_clsid = other.m_clsid;
  120. m_dwStyle = other.m_dwStyle;
  121. m_textHeight = other.m_textHeight;
  122. return *this;
  123. }
  124. /*+-------------------------------------------------------------------------*
  125. *
  126. * CFolderTab::GetWidth
  127. *
  128. * PURPOSE: Returns the width of the tab.
  129. *
  130. * RETURNS:
  131. * int
  132. *
  133. *+-------------------------------------------------------------------------*/
  134. int
  135. CFolderTab::GetWidth() const
  136. {
  137. return m_rect.Width() + 1; // rect.Width() returns right-left, need to add 1 for inclusive width.
  138. }
  139. /*+-------------------------------------------------------------------------*
  140. *
  141. * CFolderTab::SetWidth
  142. *
  143. * PURPOSE: Sets the width of the tab.
  144. *
  145. * PARAMETERS:
  146. * int nWidth :
  147. *
  148. * RETURNS:
  149. * void
  150. *
  151. *+-------------------------------------------------------------------------*/
  152. void
  153. CFolderTab::SetWidth(int nWidth)
  154. {
  155. ASSERT(nWidth > 0);
  156. ASSERT(GetWidth() >= nWidth);
  157. int delta = nWidth - (m_rect.Width() + 1);
  158. m_rect.right = m_rect.left + nWidth -1;
  159. m_rgPts[2].x+=delta;
  160. m_rgPts[3].x+=delta;
  161. SetRgn();
  162. }
  163. /*+-------------------------------------------------------------------------*
  164. *
  165. * CFolderTab::Offset
  166. *
  167. * PURPOSE: Adds a certain offset to the internal array of points.
  168. *
  169. * PARAMETERS:
  170. * const CPoint :
  171. *
  172. * RETURNS:
  173. * void
  174. *
  175. *+-------------------------------------------------------------------------*/
  176. void
  177. CFolderTab::Offset(const CPoint &point)
  178. {
  179. m_rect.OffsetRect(point);
  180. m_rgPts[0].Offset(point);
  181. m_rgPts[1].Offset(point);
  182. m_rgPts[2].Offset(point);
  183. m_rgPts[3].Offset(point);
  184. m_rgn.OffsetRgn(point);
  185. }
  186. void
  187. CFolderTab::SetRgn()
  188. {
  189. m_rgn.DeleteObject();
  190. m_rgn.CreatePolygonRgn(m_rgPts, 4, WINDING);
  191. }
  192. /*+-------------------------------------------------------------------------*
  193. *
  194. * CFolderTab::ComputeRgn
  195. *
  196. * PURPOSE: Compute the the points, rect and region for a tab.
  197. * Input x is starting x pos.
  198. *
  199. * PARAMETERS:
  200. * CDC& dc :
  201. * int x :
  202. *
  203. * RETURNS:
  204. * int: The actual width of the tab
  205. *
  206. *+-------------------------------------------------------------------------*/
  207. int
  208. CFolderTab::ComputeRgn(CDC& dc, int x)
  209. {
  210. CRect& rc = m_rect;
  211. rc.SetRectEmpty();
  212. // calculate desired text rectangle
  213. dc.DrawText(m_sText, &rc, DT_CALCRECT);
  214. rc.right += 2*GetXOffset() + 2*GetXMargin(); // add margins
  215. rc.bottom = rc.top + GetTabHeight();
  216. rc += CPoint(x,0); // shift right
  217. // create region
  218. GetTrapezoid(rc, m_rgPts);
  219. SetRgn();
  220. return rc.Width();
  221. }
  222. /*+-------------------------------------------------------------------------*
  223. *
  224. * CFolderTab::GetTrapezoid
  225. *
  226. * PURPOSE: Given the bounding rect, compute trapezoid region.
  227. * Note that the right and bottom edges not included in rect or
  228. * trapezoid; these are normal rules of geometry.
  229. *
  230. * PARAMETERS:
  231. * const CRect :
  232. * CPoint* pts :
  233. *
  234. * RETURNS:
  235. * void
  236. *
  237. *+-------------------------------------------------------------------------*/
  238. void CFolderTab::GetTrapezoid(const CRect& rc, CPoint* pts) const
  239. {
  240. pts[0] = CPoint(rc.left, rc.top );
  241. pts[1] = CPoint(rc.left + GetXOffset(), rc.bottom );
  242. pts[2] = CPoint(rc.right- GetXOffset()-1, rc.bottom );
  243. pts[3] = CPoint(rc.right-1, rc.top );
  244. }
  245. //////////////////
  246. // Draw tab in normal or highlighted state
  247. //
  248. int CFolderTab::Draw(CDC& dc, CFont& font, BOOL bSelected, bool bFocused)
  249. {
  250. return DrawTrapezoidal(dc, font, bSelected, bFocused);
  251. }
  252. /*+-------------------------------------------------------------------------*
  253. *
  254. * CFolderTab::DrawTrapezoidal
  255. *
  256. * PURPOSE: Draws a trapezoidal tab.
  257. *
  258. * PARAMETERS:
  259. * CDC& dc :
  260. * CFont& font :
  261. * BOOL bSelected :
  262. * bool bFocused :
  263. *
  264. * RETURNS:
  265. * int
  266. *
  267. *+-------------------------------------------------------------------------*/
  268. int CFolderTab::DrawTrapezoidal(CDC& dc, CFont& font, BOOL bSelected, bool bFocused)
  269. {
  270. COLORREF bgColor = GetSysColor(bSelected ? COLOR_WINDOW : COLOR_3DFACE);
  271. COLORREF fgColor = GetSysColor(bSelected ? COLOR_WINDOWTEXT : COLOR_BTNTEXT);
  272. CBrush brush(bgColor); // background brush
  273. dc.SetBkColor(bgColor); // text background
  274. dc.SetTextColor(fgColor); // text color = fg color
  275. CPen blackPen (PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME));
  276. CPen shadowPen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
  277. // Fill trapezoid
  278. CPoint pts[4];
  279. CRect rc = m_rect;
  280. GetTrapezoid(rc, pts);
  281. CPen* pOldPen = dc.SelectObject(&blackPen);
  282. dc.FillRgn(&m_rgn, &brush);
  283. // Draw edges. This is requires two corrections:
  284. // 1) Trapezoid dimensions don't include the right and bottom edges,
  285. // so must use one pixel less on bottom (cybottom)
  286. // 2) the endpoint of LineTo is not included when drawing the line, so
  287. // must add one pixel (cytop)
  288. //
  289. {
  290. pts[1].y--; // correction #1: true bottom edge y-coord
  291. pts[2].y--; // ...ditto
  292. pts[3].y--; // correction #2: extend final LineTo
  293. }
  294. dc.MoveTo(pts[0]); // upper left
  295. dc.LineTo(pts[1]); // bottom left
  296. dc.SelectObject(&shadowPen); // bottom line is shadow color
  297. dc.MoveTo(pts[1]); // line is inside trapezoid bottom
  298. dc.LineTo(pts[2]); // ...
  299. dc.SelectObject(&blackPen); // upstroke is black
  300. dc.LineTo(pts[3]); // y-1 to include endpoint
  301. if(!bSelected)
  302. {
  303. // if not highlighted, upstroke has a 3D shadow, one pixel inside
  304. pts[2].x--; // offset left one pixel
  305. pts[3].x--; // ...ditto
  306. dc.SelectObject(&shadowPen);
  307. dc.MoveTo(pts[2]);
  308. dc.LineTo(pts[3]);
  309. }
  310. dc.SelectObject(pOldPen);
  311. // draw text
  312. rc.DeflateRect(GetXOffset() + GetXMargin(), GetYMargin());
  313. CFont* pOldFont = dc.SelectObject(&font);
  314. dc.DrawText(m_sText, &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
  315. dc.SelectObject(pOldFont);
  316. if(bFocused) // draw the focus rectangle
  317. {
  318. // make some more space.
  319. rc.top--;
  320. rc.bottom++;
  321. rc.left--;
  322. rc.right++;
  323. dc.DrawFocusRect(&rc);
  324. }
  325. return m_rect.right;
  326. }
  327. //############################################################################
  328. //############################################################################
  329. //
  330. // Implementation of class CFolderTabView
  331. //
  332. //############################################################################
  333. //############################################################################
  334. IMPLEMENT_DYNAMIC(CFolderTabView, CView)
  335. BEGIN_MESSAGE_MAP(CFolderTabView, CView)
  336. ON_WM_PAINT()
  337. ON_WM_LBUTTONDOWN()
  338. ON_WM_SETFOCUS()
  339. ON_WM_KILLFOCUS()
  340. ON_WM_MOUSEACTIVATE()
  341. ON_WM_KEYDOWN()
  342. ON_WM_SETTINGCHANGE()
  343. ON_WM_SIZE()
  344. ON_WM_HSCROLL()
  345. ON_MESSAGE(WM_GETOBJECT, OnGetObject)
  346. END_MESSAGE_MAP()
  347. CFolderTabView::CFolderTabView(CView *pParentView)
  348. : m_bVisible(false), m_pParentView(pParentView)
  349. {
  350. m_iCurItem = -1; // nothing currently selected
  351. m_dwStyle = 0;
  352. m_textHeight = 0;
  353. m_sizeX = 0;
  354. m_sizeY = 0;
  355. m_hWndUpDown = NULL;
  356. m_nPos = 0; // the first tab is the one drawn
  357. m_fHaveFocus = false;
  358. }
  359. CFolderTabView::~CFolderTabView()
  360. {
  361. }
  362. /*+-------------------------------------------------------------------------*
  363. * CFolderTabView::ScFireAccessibilityEvent
  364. *
  365. * Fires accessibility events for the folder tab view
  366. *--------------------------------------------------------------------------*/
  367. SC CFolderTabView::ScFireAccessibilityEvent (
  368. DWORD dwEvent, /* I:event to fire */
  369. LONG idObject) /* I:object generating the event */
  370. {
  371. DECLARE_SC (sc, _T("CFolderTabView::ScFireAccessibilityEvent"));
  372. /*
  373. * Accessibility events are fired after the event takes place (e.g.
  374. * EVENT_OBJECT_CREATE is sent after the child is created, not before).
  375. * Because of this the child ID for EVENT_OBJECT_DESTROY is not
  376. * necessarily valid, so we shouldn't validate in that case.
  377. */
  378. if (dwEvent != EVENT_OBJECT_DESTROY)
  379. {
  380. sc = ScValidateChildID (idObject);
  381. if (sc)
  382. return (sc);
  383. }
  384. NotifyWinEvent (dwEvent, m_hWnd, OBJID_CLIENT, idObject); // returns void
  385. return (sc);
  386. }
  387. /*+-------------------------------------------------------------------------*
  388. *
  389. * CFolderTabView::OnHScroll
  390. *
  391. * PURPOSE: Called when the position of the scroll bar is changed
  392. *
  393. * PARAMETERS:
  394. * UINT nSBCode :
  395. * UINT nPos :
  396. * CScrollBar* pScrollBar :
  397. *
  398. * RETURNS:
  399. * void
  400. *
  401. *+-------------------------------------------------------------------------*/
  402. void
  403. CFolderTabView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar )
  404. {
  405. // we're only interested in SB_THUMBPOSITION
  406. if(nSBCode != SB_THUMBPOSITION)
  407. return;
  408. // if the position has not changed, do nothing.
  409. if(nPos == m_nPos)
  410. return;
  411. m_nPos = nPos; // change the position
  412. RecomputeLayout();
  413. InvalidateRect(NULL, true); // redraw everything.
  414. }
  415. /*+-------------------------------------------------------------------------*
  416. * CFolderTabView::OnSetFocus
  417. *
  418. * WM_SETFOCUS handler for CFolderTabView.
  419. *--------------------------------------------------------------------------*/
  420. void CFolderTabView::OnSetFocus(CWnd* pOldWnd)
  421. {
  422. m_fHaveFocus = true;
  423. InvalidateRect(NULL);
  424. BC::OnSetFocus(pOldWnd);
  425. /*
  426. * If we have any tabs, one of them will get the focus. Fire the
  427. * focus accessibility event, ignoring errors. We do this after
  428. * calling the base class, so this focus event will override the
  429. * "focus to the window" event sent by the system on our behalf.
  430. */
  431. if (GetItemCount() > 0)
  432. ScFireAccessibilityEvent (EVENT_OBJECT_FOCUS, m_iCurItem+1 /*1-based*/);
  433. }
  434. /*+-------------------------------------------------------------------------*
  435. * CFolderTabView::OnKillFocus
  436. *
  437. * WM_KILLFOCUS handler for CFolderTabView.
  438. *--------------------------------------------------------------------------*/
  439. void CFolderTabView::OnKillFocus(CWnd* pNewWnd)
  440. {
  441. m_fHaveFocus = false;
  442. InvalidateRect(NULL);
  443. BC::OnKillFocus(pNewWnd);
  444. }
  445. /*+-------------------------------------------------------------------------*
  446. * CFolderTabView::OnMouseActivate
  447. *
  448. * WM_MOUSEACTIVATE handler for CFolderTabView.
  449. *--------------------------------------------------------------------------*/
  450. int CFolderTabView::OnMouseActivate( CWnd* pDesktopWnd, UINT nHitTest, UINT message )
  451. {
  452. //short-circuit the MFC base class code, which sets the keyboard focus here as well...
  453. return MA_ACTIVATE;
  454. }
  455. /*+-------------------------------------------------------------------------*
  456. * CFolderTabView::OnCmdMsg
  457. *
  458. * WM_COMMAND handler for CFolderTabView.
  459. *--------------------------------------------------------------------------*/
  460. BOOL CFolderTabView::OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo )
  461. {
  462. // Do normal command routing
  463. if (BC::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  464. return TRUE;
  465. // if view didn't handle it, give parent view a chance
  466. if (m_pParentView != NULL)
  467. return static_cast<CWnd*>(m_pParentView)->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  468. else
  469. return FALSE;
  470. }
  471. /*+-------------------------------------------------------------------------*
  472. * CFolderTabView::OnKeyDown
  473. *
  474. * WM_KEYDOWN handler for CFolderTabView.
  475. *--------------------------------------------------------------------------*/
  476. void CFolderTabView::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
  477. {
  478. int cSize = m_tabList.size();
  479. if( (cSize == 0) || ( (nChar != VK_LEFT) && (nChar != VK_RIGHT) ) )
  480. {
  481. BC::OnKeyDown(nChar, nRepCnt, nFlags);
  482. return;
  483. }
  484. ASSERT( (nChar == VK_LEFT) || (nChar == VK_RIGHT) );
  485. int iNew = GetSelectedItem() + (nChar==VK_LEFT ? -1 : 1);
  486. if(iNew < 0)
  487. iNew = 0; // does not wrap
  488. if(iNew >= cSize)
  489. iNew = cSize -1; // does not wrap
  490. SelectItem(iNew, true /*bEnsureVisible*/);
  491. }
  492. /*+-------------------------------------------------------------------------*
  493. * CFolderTabView::OnSettingChange
  494. *
  495. * WM_SETTINGCHANGE handler for CFolderTabView.
  496. *--------------------------------------------------------------------------*/
  497. void CFolderTabView::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
  498. {
  499. CView::OnSettingChange(uFlags, lpszSection);
  500. if (uFlags == SPI_SETNONCLIENTMETRICS)
  501. {
  502. DeleteFonts ();
  503. CreateFonts ();
  504. InvalidateRect(NULL, true); // redraw everything.
  505. RecomputeLayout ();
  506. }
  507. }
  508. //////////////////
  509. // Create folder tab control from static control.
  510. // Destroys the static control. This is convenient for dialogs
  511. //
  512. BOOL CFolderTabView::CreateFromStatic(UINT nID, CWnd* pParent)
  513. {
  514. CStatic wndStatic;
  515. if(!wndStatic.SubclassDlgItem(nID, pParent))
  516. return FALSE;
  517. CRect rc;
  518. wndStatic.GetWindowRect(&rc);
  519. pParent->ScreenToClient(&rc);
  520. wndStatic.DestroyWindow();
  521. rc.bottom = rc.top + GetDesiredHeight();
  522. return Create(WS_CHILD|WS_VISIBLE, rc, pParent, nID);
  523. }
  524. /*+-------------------------------------------------------------------------*
  525. *
  526. * CFolderTabView::Create
  527. *
  528. * PURPOSE: Creates the folder tab control
  529. *
  530. * PARAMETERS:
  531. * DWORD dwStyle :
  532. * const RECT :
  533. * CWnd* pParent :
  534. * UINT nID :
  535. * DWORD dwFtabStyle :
  536. *
  537. * RETURNS:
  538. * BOOL
  539. *
  540. *+-------------------------------------------------------------------------*/
  541. BOOL CFolderTabView::Create(DWORD dwStyle, const RECT& rc,
  542. CWnd* pParent, UINT nID, DWORD dwFtabStyle)
  543. {
  544. ASSERT(pParent);
  545. ASSERT(dwStyle & WS_CHILD);
  546. m_dwStyle = dwFtabStyle;
  547. static LPCTSTR lpClassName = _T("AMCCustomTab");
  548. static BOOL bRegistered = FALSE; // registered?
  549. if(!bRegistered)
  550. {
  551. WNDCLASS wc;
  552. memset(&wc, 0, sizeof(wc));
  553. wc.lpfnWndProc = ::DefWindowProc; // will get hooked by MFC
  554. wc.hInstance = AfxGetInstanceHandle();
  555. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  556. wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
  557. wc.lpszMenuName = NULL;
  558. wc.lpszClassName = lpClassName;
  559. if(!AfxRegisterClass(&wc))
  560. {
  561. TRACE(_T("*** CFolderTabView::AfxRegisterClass failed!\n"));
  562. return FALSE;
  563. }
  564. bRegistered = TRUE;
  565. }
  566. if(!BC::CreateEx(0, lpClassName, NULL, dwStyle, rc, pParent, nID))
  567. return FALSE;
  568. // initialize fonts
  569. CreateFonts();
  570. /*
  571. * Bug 141015: Create a buddy window for the up-down control. It will
  572. * never be visible, but we need it so UDM_GETPOS sent to the up-down
  573. * will work. Narrator will send this message when the up-down becomes
  574. * visible, but it will fail if there's no buddy (sad, but true). It
  575. * fails by returning an LRESULT with a non-zero high-order word
  576. * (specifically, 0x00010000), so Narrator translates and announces
  577. * "65536" instead of the true value.
  578. *
  579. * This is only required for Narrator support, so if it fails it's
  580. * not sufficient reason to fail CFolderTabView creation altogether.
  581. */
  582. HWND hwndBuddy = CreateWindow (_T("edit"), NULL, WS_CHILD, 0, 0, 0, 0,
  583. m_hWnd, 0, AfxGetInstanceHandle(), NULL);
  584. // create the up-down control
  585. DWORD dwUpDownStyle = WS_CHILD | WS_BORDER |
  586. UDS_SETBUDDYINT | // for Narrator support
  587. UDS_HORZ /*to display the arrows left to right*/; // NOTE: the control is created invisible on purpose.
  588. m_hWndUpDown = CreateUpDownControl(dwUpDownStyle, 0, 0,
  589. GetUpDownWidth(), //width
  590. GetUpDownHeight(), //height
  591. m_hWnd,
  592. 1 /*nID*/,
  593. AfxGetInstanceHandle(),
  594. hwndBuddy,
  595. 0 /*nUpper*/,
  596. 0 /*nLower*/,
  597. 0 /*nPos*/);
  598. return TRUE;
  599. }
  600. void CFolderTabView::CreateFonts ()
  601. {
  602. LOGFONT lf;
  603. SystemParametersInfo (SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, false);
  604. m_fontNormal.CreateFontIndirect(&lf);
  605. // Get the font height (converting from points to pixels)
  606. CClientDC dc(NULL);
  607. TEXTMETRIC tm;
  608. CFont *pFontOld = dc.SelectObject(&m_fontNormal);
  609. dc.GetTextMetrics(&tm);
  610. m_textHeight = tm.tmHeight;
  611. // set the old font back.
  612. dc.SelectObject(pFontOld);
  613. lf.lfWeight = FW_BOLD;
  614. m_fontSelected.CreateFontIndirect(&lf);
  615. }
  616. void CFolderTabView::DeleteFonts ()
  617. {
  618. m_fontNormal.DeleteObject();
  619. m_fontSelected.DeleteObject();
  620. }
  621. //////////////////
  622. // copy a font
  623. //
  624. static void CopyFont(CFont& dst, CFont& src)
  625. {
  626. dst.DeleteObject();
  627. LOGFONT lf;
  628. VERIFY(src.GetLogFont(&lf));
  629. dst.CreateFontIndirect(&lf);
  630. }
  631. //////////////////
  632. // Set normal, selected fonts
  633. //
  634. void CFolderTabView::SetFonts(CFont& fontNormal, CFont& fontSelected)
  635. {
  636. CopyFont(m_fontNormal, fontNormal);
  637. CopyFont(m_fontSelected, fontSelected);
  638. }
  639. //////////////////
  640. // Paint function
  641. //
  642. void CFolderTabView::OnDraw(CDC* pDC)
  643. {
  644. }
  645. void CFolderTabView::OnPaint()
  646. {
  647. Paint (m_fHaveFocus);
  648. }
  649. /*+-------------------------------------------------------------------------*
  650. *
  651. * CFolderTabView::EnsureVisible
  652. *
  653. * PURPOSE: Changes the layout to ensure that the specified tab is visible.
  654. *
  655. * NOTE: Does NOT invalidate the rect, for efficiency.
  656. *
  657. * PARAMETERS:
  658. * UINT iTab :
  659. *
  660. * RETURNS:
  661. * void
  662. *
  663. *+-------------------------------------------------------------------------*/
  664. void
  665. CFolderTabView::EnsureVisible(int iTab)
  666. {
  667. if((iTab < 0) || (iTab > m_tabList.size()))
  668. {
  669. ASSERT(0 && "Should not come here.");
  670. return;
  671. }
  672. if(!::IsWindowVisible(m_hWndUpDown))
  673. return; // the up-down control is hidden, meaning that all tabs are visible
  674. RecomputeLayout(); // make sure we have the correct dimensions
  675. if(m_nPos == iTab)
  676. return; // the tab already shows as much as it can.
  677. if(m_nPos > iTab) // the first visible tab is to the right of iTab. Make iTab the first visible tab
  678. {
  679. m_nPos = iTab;
  680. RecomputeLayout();
  681. return;
  682. }
  683. iterator iter = m_tabList.begin();
  684. std::advance(iter, iTab); // get the correct item
  685. CRect rcCurTab = iter->GetRect();
  686. // loop: Increase the start tab position until the right edge of iTab fits.
  687. while((m_nPos < iTab) && (rcCurTab.right > m_sizeX))
  688. {
  689. m_nPos++;
  690. RecomputeLayout();
  691. rcCurTab = iter->GetRect();
  692. }
  693. }
  694. /*+-------------------------------------------------------------------------*
  695. *
  696. * CFolderTabView::Paint
  697. *
  698. * PURPOSE: Completely redraws the tab control.
  699. *
  700. * PARAMETERS:
  701. * bool bFocused :
  702. *
  703. * RETURNS:
  704. * void
  705. *
  706. *+-------------------------------------------------------------------------*/
  707. void
  708. CFolderTabView::Paint(bool bFocused)
  709. {
  710. CPaintDC dc(this); // device context for painting
  711. CRect rc;
  712. GetClientRect(&rc);
  713. // draw all the normal (non-selected) tabs
  714. iterator iterSelected = m_tabList.end();
  715. int i = 0;
  716. bool bDraw = true;
  717. for(iterator iter= m_tabList.begin(); iter!= m_tabList.end(); ++iter, i++)
  718. {
  719. if(i!=m_iCurItem)
  720. {
  721. if(bDraw && iter->Draw(dc, m_fontNormal, FALSE, false) > rc.right)
  722. bDraw = false;
  723. }
  724. else
  725. {
  726. iterSelected = iter;
  727. }
  728. }
  729. ASSERT(iterSelected != m_tabList.end());
  730. /*
  731. * Bug 350942: selected tab shouldn't be bold
  732. */
  733. // draw selected tab last so it will be "on top" of the others
  734. iterSelected->Draw(dc, /*m_fontSelected*/ m_fontNormal, TRUE, bFocused);
  735. // draw border: line along the top edge, excluding seleted tab
  736. CPoint pts[4];
  737. CRect rcCurTab = iterSelected->GetRect();
  738. iterSelected->GetTrapezoid(&rcCurTab, pts);
  739. CPen blackPen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME));
  740. CPen* pOldPen = dc.SelectObject(&blackPen);
  741. int y = pts[0].y;
  742. dc.MoveTo(rc.left, y);
  743. dc.LineTo(pts[0].x, y);
  744. dc.MoveTo(pts[3].x, y);
  745. dc.LineTo(rc.right, y);
  746. dc.SelectObject(pOldPen);
  747. }
  748. /*+-------------------------------------------------------------------------*
  749. *
  750. * CFolderTabView::OnLButtonDown
  751. *
  752. * PURPOSE: Selects the tab pointed to on a left mouse click
  753. *
  754. * PARAMETERS:
  755. * UINT nFlags :
  756. * CPoint pt :
  757. *
  758. * RETURNS:
  759. * void
  760. *
  761. *+-------------------------------------------------------------------------*/
  762. void
  763. CFolderTabView::OnLButtonDown(UINT nFlags, CPoint pt)
  764. {
  765. int iTab = HitTest(pt);
  766. if(iTab>=0 && iTab!=m_iCurItem)
  767. {
  768. SelectItem(iTab, true /*bEnsureVisible*/);
  769. }
  770. }
  771. /*+-------------------------------------------------------------------------*
  772. *
  773. * CFolderTabView::HitTest
  774. *
  775. * PURPOSE: Computes which tab is at the specified point.
  776. *
  777. * PARAMETERS:
  778. * CPoint pt :
  779. *
  780. * RETURNS:
  781. * int: The tab index, or -1 if none.
  782. *
  783. *+-------------------------------------------------------------------------*/
  784. int
  785. CFolderTabView::HitTest(CPoint pt)
  786. {
  787. CRect rc;
  788. GetClientRect(&rc);
  789. if(rc.PtInRect(pt))
  790. {
  791. int i = 0;
  792. for( iterator iter= m_tabList.begin(); iter!= m_tabList.end(); ++iter, i++)
  793. {
  794. if(iter->HitTest(pt))
  795. return i;
  796. }
  797. }
  798. return -1;
  799. }
  800. /*+-------------------------------------------------------------------------*
  801. *
  802. * CFolderTabView::SelectItem
  803. *
  804. * PURPOSE: Selects the iTab'th tab and returns the index of the tab selected,
  805. * or -1 if an error occurred.
  806. *
  807. * PARAMETERS:
  808. * int iTab :
  809. * bool bEnsureVisible : If true, repositions the tab to make it visible.
  810. *
  811. * RETURNS:
  812. * int
  813. *
  814. *+-------------------------------------------------------------------------*/
  815. int
  816. CFolderTabView::SelectItem(int iTab, bool bEnsureVisible)
  817. {
  818. if(iTab<0 || iTab>=GetItemCount())
  819. return -1; // bad
  820. bool bSendTabChanged = (iTab != m_iCurItem); // send a message only if a different item got selected
  821. // repaint the control
  822. m_iCurItem = iTab; // set new selected tab
  823. if(bEnsureVisible)
  824. EnsureVisible(iTab);
  825. else
  826. RecomputeLayout();
  827. InvalidateRect(NULL, true);
  828. if(bSendTabChanged)
  829. {
  830. /*
  831. * If the selection changed, fire the selection accessibility event.
  832. * We do it before sending FTN_TABCHANGED so that if the FTN_TABCHANGED
  833. * handler selects another item, observers will get the selection
  834. * events in the right order (ignore errors)
  835. */
  836. ScFireAccessibilityEvent (EVENT_OBJECT_SELECTION, m_iCurItem+1 /*1-based*/);
  837. /*
  838. * if our window has the focus, focus changes with selection,
  839. * so send focus event, too (ignore errors)
  840. */
  841. if (m_fHaveFocus)
  842. ScFireAccessibilityEvent (EVENT_OBJECT_FOCUS, m_iCurItem+1 /*1-based*/);
  843. // send the FTN_TABCHANGED message
  844. NMFOLDERTAB nm;
  845. nm.hwndFrom = m_hWnd;
  846. nm.idFrom = GetDlgCtrlID();
  847. nm.code = FTN_TABCHANGED;
  848. nm.iItem = iTab;
  849. CWnd* pParent = GetParent();
  850. pParent->SendMessage(WM_NOTIFY, nm.idFrom, (LPARAM)&nm);
  851. }
  852. return m_iCurItem;
  853. }
  854. int
  855. CFolderTabView::SelectItemByClsid(const CLSID& clsid)
  856. {
  857. bool bFound = false;
  858. int i=0;
  859. for(iterator iter= m_tabList.begin(); iter!= m_tabList.end(); ++iter, i++)
  860. {
  861. if(IsEqualGUID(iter->GetClsid(),clsid))
  862. {
  863. bFound = true;
  864. break;
  865. }
  866. }
  867. if(!bFound)
  868. {
  869. ASSERT(0 && "Invalid folder tab.");
  870. return -1;
  871. }
  872. return SelectItem(i);
  873. }
  874. CFolderTab &
  875. CFolderTabView::GetItem(int iPos)
  876. {
  877. ASSERT(!(iPos<0 || iPos>=GetItemCount()));
  878. CFolderTabList::iterator iter = m_tabList.begin();
  879. std::advance(iter, iPos);
  880. return *iter;
  881. }
  882. int CFolderTabView::AddItem(LPCTSTR lpszText, const CLSID& clsid)
  883. {
  884. CFolderTab tab;
  885. tab.SetText(lpszText);
  886. tab.SetClsid(clsid);
  887. tab.SetStyle(m_dwStyle);
  888. tab.SetTextHeight(m_textHeight);
  889. m_tabList.push_back(tab);
  890. RecomputeLayout();
  891. InvalidateRect(NULL, true);
  892. int nNewItemIndex = m_tabList.size() - 1; // 0-based
  893. /*
  894. * tell observers we created a new tab, after it's been created (ignore errors)
  895. */
  896. ScFireAccessibilityEvent (EVENT_OBJECT_CREATE, nNewItemIndex+1 /*1-based*/);
  897. return (nNewItemIndex);
  898. }
  899. BOOL CFolderTabView::RemoveItem(int iPos)
  900. {
  901. if( (iPos < 0) || (iPos>= m_tabList.size()) )
  902. return false;
  903. CFolderTabList::iterator iter = m_tabList.begin();
  904. std::advance(iter, iPos);
  905. m_tabList.erase(iter);
  906. /*
  907. * tell observers we destroyed a tab, after it's been destroyed but before
  908. * we might send selection/focus notifications in SelectItem (ignore errors)
  909. */
  910. ScFireAccessibilityEvent (EVENT_OBJECT_DESTROY, iPos+1 /*1-based*/);
  911. /*
  912. * If we're deleting the currently selected tab, the selection needs to
  913. * move somewhere else. If there are tabs following the current one,
  914. * we'll move the selection to the next tab; otherwise, we'll move to
  915. * the previous one.
  916. */
  917. if ((iPos == m_iCurItem) && !m_tabList.empty())
  918. {
  919. /*
  920. * if there are tabs to the following the one we just deleted,
  921. * increment m_iCurItem so the subsequent call to SelectItem
  922. * will recognize that the selection change and send the proper
  923. * notifications.
  924. */
  925. if (m_iCurItem < m_tabList.size())
  926. m_iCurItem++;
  927. SelectItem (m_iCurItem-1, true /*bEnsureVisible*/);
  928. }
  929. else
  930. {
  931. /*
  932. * if we deleted a tab before the selected tab, decrement the
  933. * selected tab index to keep things in sync
  934. * m_iCurItem will become -1 when the last tab is removed, which is correct
  935. */
  936. if (iPos <= m_iCurItem)
  937. m_iCurItem--;
  938. InvalidateRect(NULL, true);
  939. RecomputeLayout();
  940. }
  941. return true;
  942. }
  943. void CFolderTabView::DeleteAllItems()
  944. {
  945. const int cChildren = m_tabList.size();
  946. m_tabList.clear();
  947. m_iCurItem = -1; // nothing is selected
  948. InvalidateRect(NULL, true);
  949. RecomputeLayout();
  950. /*
  951. * Tell accessibility observers that each tab is destroyed. Notify
  952. * in last-to-first order so IDs remain sane during this process.
  953. */
  954. for (int idChild = cChildren /*1-based*/; idChild >= 1; idChild--)
  955. {
  956. ScFireAccessibilityEvent (EVENT_OBJECT_DESTROY, idChild);
  957. }
  958. /*
  959. * If we have the focus, tell accessibility observers that the
  960. * control itself has the focus. We do this to be consistent with
  961. * other controls (like the list view)
  962. */
  963. if (m_fHaveFocus)
  964. ScFireAccessibilityEvent (EVENT_OBJECT_FOCUS, CHILDID_SELF);
  965. }
  966. void CFolderTabView::OnSize(UINT nType, int cx, int cy)
  967. {
  968. m_sizeX = cx;
  969. m_sizeY = cy;
  970. CView::OnSize(nType, cx, cy);
  971. if (nType != SIZE_MINIMIZED)
  972. {
  973. RecomputeLayout();
  974. }
  975. }
  976. /*+-------------------------------------------------------------------------*
  977. *
  978. * CFolderTabView::ShowUpDownControl
  979. *
  980. * PURPOSE: Shows or hides the up/down control
  981. *
  982. * PARAMETERS:
  983. * BOOL bShow : true to show, false to hide.
  984. *
  985. * RETURNS:
  986. * void
  987. *
  988. *+-------------------------------------------------------------------------*/
  989. void
  990. CFolderTabView::ShowUpDownControl(BOOL bShow)
  991. {
  992. BOOL bVisible = (m_hWndUpDown != NULL) && ::IsWindowVisible(m_hWndUpDown); // was the up-down control visible previously?
  993. if(bShow)
  994. {
  995. if(!bVisible)
  996. {
  997. ::SendMessage(m_hWndUpDown, UDM_SETRANGE32, (WPARAM) 0 /*iLow*/, (LPARAM) m_tabList.size()-1 /*zero-based*/);
  998. ::SendMessage(m_hWndUpDown, UDM_SETPOS, (WPARAM) 0, (LPARAM) m_nPos /*nPos*/);
  999. ::ShowWindow(m_hWndUpDown, SW_SHOW);
  1000. InvalidateRect(NULL, true);
  1001. }
  1002. }
  1003. else
  1004. {
  1005. // hide the updown control
  1006. if(m_hWndUpDown)
  1007. ::ShowWindow(m_hWndUpDown, SW_HIDE);
  1008. if(bVisible) // invalidate only on a transition from visible to invisible
  1009. InvalidateRect(NULL, true);
  1010. m_nPos = 0;
  1011. }
  1012. }
  1013. /*+-------------------------------------------------------------------------*
  1014. *
  1015. * CFolderTabView::GetTotalTabWidth
  1016. *
  1017. * PURPOSE: Computes the total width of all the tabs.
  1018. *
  1019. * PARAMETERS:
  1020. * CClientDC& dc :
  1021. *
  1022. * RETURNS:
  1023. * int
  1024. *
  1025. *+-------------------------------------------------------------------------*/
  1026. int
  1027. CFolderTabView::GetTotalTabWidth(CClientDC& dc)
  1028. {
  1029. int x = 0;
  1030. // compute the width "as is", ie without taking into account the actual space available.
  1031. for(iterator iter = m_tabList.begin(); iter!= m_tabList.end(); ++iter)
  1032. {
  1033. x += iter->ComputeRgn(dc, x) - GetXOffset();
  1034. }
  1035. return x;
  1036. }
  1037. /*+-------------------------------------------------------------------------*
  1038. *
  1039. * CFolderTabView::ComputeRegion
  1040. *
  1041. * PURPOSE: Computes the location and regions for all the tabs
  1042. *
  1043. * PARAMETERS:
  1044. * CClientDC& dc :
  1045. *
  1046. * RETURNS:
  1047. * int
  1048. *
  1049. *+-------------------------------------------------------------------------*/
  1050. int
  1051. CFolderTabView::ComputeRegion(CClientDC& dc)
  1052. {
  1053. int x = GetTotalTabWidth(dc);
  1054. // subtract the top-left x coordinate of the m_nPos'th tab from all x coordinates, thereby creating a shift
  1055. iterator iter = m_tabList.begin();
  1056. std::advance(iter, m_nPos); // advance to the m_nPos'th tab
  1057. int xOffset = iter->GetRect().left;
  1058. x = GetUpDownWidth() - xOffset; // shift everything to the left by xOffset
  1059. for(iterator iterTemp = m_tabList.begin(); iterTemp!= m_tabList.end(); ++iterTemp)
  1060. {
  1061. x += iterTemp->ComputeRgn(dc, x) - GetXOffset();
  1062. }
  1063. return x;
  1064. }
  1065. /*+-------------------------------------------------------------------------*
  1066. *
  1067. * CFolderTabView::RecomputeLayout
  1068. *
  1069. * PURPOSE: Determines the location of all the tabs, and whether or not the
  1070. * up/down control should be displayed.
  1071. *
  1072. * RETURNS:
  1073. * void
  1074. *
  1075. *+-------------------------------------------------------------------------*/
  1076. void
  1077. CFolderTabView::RecomputeLayout()
  1078. {
  1079. // set the size of the updown control
  1080. if(m_hWndUpDown)
  1081. ::SetWindowPos(m_hWndUpDown, NULL /*hWndInsertAfter*/, 0 /*left*/, 0 /*top*/,
  1082. GetUpDownWidth(), GetUpDownHeight(), SWP_NOMOVE| SWP_NOZORDER);
  1083. // set the correct text height for the tabs
  1084. for(iterator iterTemp = m_tabList.begin(); iterTemp!= m_tabList.end(); ++iterTemp)
  1085. iterTemp->SetTextHeight(GetTextHeight());
  1086. CClientDC dc(this);
  1087. CFont* pOldFont = dc.SelectObject(&m_fontSelected); // use the bold font to compute with.
  1088. int totalWidth = GetTotalTabWidth(dc); // the width of ALL tabs
  1089. if(totalWidth <= m_sizeX)
  1090. {
  1091. // there's enough space to show all tabs. Hide the updown control
  1092. ShowUpDownControl(false);
  1093. }
  1094. else
  1095. {
  1096. // not enough width for all tabs.
  1097. BOOL bVisible = ::IsWindowVisible(m_hWndUpDown); // was the up-down control visible previously?
  1098. if(!bVisible) // the up-down control was not visible, so make it visible.
  1099. {
  1100. m_nPos = 0;
  1101. ShowUpDownControl(true);
  1102. }
  1103. ComputeRegion(dc); // make sure we leave space for the tab
  1104. }
  1105. dc.SelectObject(pOldFont);
  1106. }
  1107. void CFolderTabView::Layout(CRect& rectTotal, CRect& rectFTab)
  1108. {
  1109. int cy = GetTabHeight() + GetExtraYSpace();
  1110. rectFTab = rectTotal;
  1111. if(!IsVisible())
  1112. return;
  1113. rectFTab.top = rectFTab.bottom - cy;
  1114. rectTotal.bottom= rectFTab.top;
  1115. }
  1116. /*+-------------------------------------------------------------------------*
  1117. * CFolderTabView::OnGetObject
  1118. *
  1119. * WM_GETOBJECT handler for CFolderTabView.
  1120. *--------------------------------------------------------------------------*/
  1121. LRESULT CFolderTabView::OnGetObject (WPARAM wParam, LPARAM lParam)
  1122. {
  1123. DECLARE_SC (sc, _T("CFolderTabView::OnGetObject"));
  1124. /*
  1125. * ignore requests for objects other than OBJID_CLIENT
  1126. */
  1127. if (lParam != OBJID_CLIENT)
  1128. {
  1129. Trace (tagTabAccessibility, _T("WM_GETOBJECT: (lParam != OBJID_CLIENT), returning 0"));
  1130. return (0);
  1131. }
  1132. /*
  1133. * create our accessibility object
  1134. */
  1135. if ((sc = CTiedComObjectCreator<CTabAccessible>::ScCreateAndConnect(*this, m_spTabAcc)).IsError() ||
  1136. (sc = ScCheckPointers (m_spTabAcc, E_UNEXPECTED)).IsError())
  1137. {
  1138. sc.TraceAndClear();
  1139. Trace (tagTabAccessibility, _T("WM_GETOBJECT: error creating IAccessible object, returning 0"));
  1140. return (0);
  1141. }
  1142. /*
  1143. * return a pointer to the IAccessible interface
  1144. */
  1145. Trace (tagTabAccessibility, _T("WM_GETOBJECT: returning IAccessible*"));
  1146. return (LresultFromObject (IID_IAccessible, wParam, m_spTabAcc));
  1147. }
  1148. /*+-------------------------------------------------------------------------*
  1149. * CFolderTabView::Scget_accParent
  1150. *
  1151. * Retrieves the IDispatch interface of the object's parent.
  1152. *--------------------------------------------------------------------------*/
  1153. SC CFolderTabView::Scget_accParent(IDispatch ** ppdispParent)
  1154. {
  1155. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accParent"));
  1156. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accParent"));
  1157. sc = ScCheckPointers (ppdispParent);
  1158. if(sc)
  1159. return (sc);
  1160. /*
  1161. * return the accessibility interface for the OBJID_WINDOW object
  1162. */
  1163. sc = AccessibleObjectFromWindow (m_hWnd, OBJID_WINDOW, IID_IDispatch,
  1164. (void **)ppdispParent);
  1165. return (sc);
  1166. }
  1167. /*+-------------------------------------------------------------------------*
  1168. * CFolderTabView::Scget_accChildCount
  1169. *
  1170. * Retrieves the number of children belonging to this object.
  1171. *--------------------------------------------------------------------------*/
  1172. SC CFolderTabView::Scget_accChildCount(long* pChildCount)
  1173. {
  1174. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accChildCount"));
  1175. sc = ScCheckPointers (pChildCount);
  1176. if(sc)
  1177. return (sc);
  1178. *pChildCount = GetItemCount();
  1179. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accChildCount: returning %d"), GetItemCount());
  1180. return (sc);
  1181. }
  1182. /*+-------------------------------------------------------------------------*
  1183. * CFolderTabView::Scget_accChild
  1184. *
  1185. * Retrieves the address of an IDispatch interface for the specified child.
  1186. *--------------------------------------------------------------------------*/
  1187. SC CFolderTabView::Scget_accChild(VARIANT varChildID, IDispatch ** ppdispChild)
  1188. {
  1189. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accChild"));
  1190. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accChild"));
  1191. sc = ScCheckPointers (ppdispChild);
  1192. if (sc)
  1193. return (sc);
  1194. // init out parameter
  1195. (*ppdispChild) = NULL;
  1196. sc = ScValidateChildID (varChildID);
  1197. if(sc)
  1198. return (sc);
  1199. /*
  1200. * all children are simple elements exposed through their parent,
  1201. * not accessible objects in their own right
  1202. */
  1203. sc = S_FALSE;
  1204. Trace (tagTabAccessibility, TEXT("returning parent's IDispatch for child %d"), ValueOf(varChildID));
  1205. return (sc);
  1206. }
  1207. /*+-------------------------------------------------------------------------*
  1208. * CFolderTabView::Scget_accName
  1209. *
  1210. * Retrieves the name of the specified object.
  1211. *--------------------------------------------------------------------------*/
  1212. SC CFolderTabView::Scget_accName(VARIANT varChildID, BSTR* pbstrName)
  1213. {
  1214. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accName"));
  1215. sc = ScCheckPointers (pbstrName);
  1216. if(sc)
  1217. return (sc);
  1218. // init out parameter
  1219. *pbstrName = NULL;
  1220. sc = ScValidateChildID (varChildID);
  1221. if(sc)
  1222. return (sc);
  1223. /*
  1224. * the tab control itself doesn't have a name; otherwise, get the
  1225. * name of the requested tab
  1226. */
  1227. LONG idChild = ValueOf (varChildID);
  1228. if (idChild == CHILDID_SELF)
  1229. {
  1230. sc = S_FALSE;
  1231. }
  1232. else
  1233. {
  1234. CFolderTab& tab = GetItem (idChild-1);
  1235. CComBSTR bstrName (tab.GetText());
  1236. *pbstrName = bstrName.Detach();
  1237. }
  1238. #ifdef DBG
  1239. USES_CONVERSION;
  1240. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accName: child %d, returning \"%s\""),
  1241. idChild,
  1242. (*pbstrName) ? W2T(*pbstrName) : _T("<None>"));
  1243. #endif
  1244. return (sc);
  1245. }
  1246. /*+-------------------------------------------------------------------------*
  1247. * CFolderTabView::Scget_accValue
  1248. *
  1249. * Retrieves the value of the specified object. Not all objects have a value.
  1250. *--------------------------------------------------------------------------*/
  1251. SC CFolderTabView::Scget_accValue(VARIANT varChildID, BSTR* pbstrValue)
  1252. {
  1253. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accValue"));
  1254. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accValue"));
  1255. sc = ScValidateChildID (varChildID);
  1256. if(sc)
  1257. return (sc);
  1258. /*
  1259. * tabs don't have values
  1260. */
  1261. sc = S_FALSE;
  1262. return (sc);
  1263. }
  1264. /*+-------------------------------------------------------------------------*
  1265. * CFolderTabView::Scget_accDescription
  1266. *
  1267. * Retrieves a string that describes the visual appearance of the specified
  1268. * object. Not all objects have a description.
  1269. *--------------------------------------------------------------------------*/
  1270. SC CFolderTabView::Scget_accDescription(VARIANT varChildID, BSTR* pbstrDescription)
  1271. {
  1272. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accDescription"));
  1273. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accDescription"));
  1274. sc = ScValidateChildID (varChildID);
  1275. if(sc)
  1276. return (sc);
  1277. /*
  1278. * tabs don't have descriptions
  1279. */
  1280. sc = S_FALSE;
  1281. return (sc);
  1282. }
  1283. /*+-------------------------------------------------------------------------*
  1284. * CFolderTabView::Scget_accRole
  1285. *
  1286. * Retrieves information that describes the role of the specified object.
  1287. *--------------------------------------------------------------------------*/
  1288. SC CFolderTabView::Scget_accRole(VARIANT varChildID, VARIANT *pvarRole)
  1289. {
  1290. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accRole"));
  1291. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accRole"));
  1292. sc = ScCheckPointers (pvarRole);
  1293. if(sc)
  1294. return (sc);
  1295. // init out parameter
  1296. VariantInit (pvarRole);
  1297. sc = ScValidateChildID (varChildID);
  1298. if(sc)
  1299. return (sc);
  1300. /*
  1301. * the tab control has a "page tab list" role; an individual tab has a
  1302. * "page tab" role
  1303. */
  1304. V_VT(pvarRole) = VT_I4;
  1305. V_I4(pvarRole) = (ValueOf (varChildID) == CHILDID_SELF)
  1306. ? ROLE_SYSTEM_PAGETABLIST
  1307. : ROLE_SYSTEM_PAGETAB;
  1308. return (sc);
  1309. }
  1310. /*+-------------------------------------------------------------------------*
  1311. * CFolderTabView::Scget_accState
  1312. *
  1313. * Retrieves the current state of the specified object.
  1314. *--------------------------------------------------------------------------*/
  1315. SC CFolderTabView::Scget_accState(VARIANT varChildID, VARIANT *pvarState)
  1316. {
  1317. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accState"));
  1318. sc = ScValidateChildID (varChildID);
  1319. if(sc)
  1320. return (sc);
  1321. LONG idChild = ValueOf (varChildID);
  1322. /*
  1323. * all items are focusable
  1324. */
  1325. V_VT(pvarState) = VT_I4;
  1326. V_I4(pvarState) = STATE_SYSTEM_FOCUSABLE;
  1327. /*
  1328. * is this for a tab?
  1329. */
  1330. if (idChild != CHILDID_SELF)
  1331. {
  1332. /*
  1333. * all tabs are selectable
  1334. */
  1335. V_I4(pvarState) |= STATE_SYSTEM_SELECTABLE;
  1336. /*
  1337. * if this is the selected item, give it the selected state
  1338. */
  1339. if ((idChild - 1 /*1-based*/) == GetSelectedItem())
  1340. {
  1341. V_I4(pvarState) |= STATE_SYSTEM_SELECTED;
  1342. /*
  1343. * if the tab control also has the focus, give the selected
  1344. * item the focused state as well
  1345. */
  1346. if (m_fHaveFocus)
  1347. V_I4(pvarState) |= STATE_SYSTEM_FOCUSED;
  1348. }
  1349. }
  1350. else
  1351. {
  1352. if (m_fHaveFocus)
  1353. V_I4(pvarState) |= STATE_SYSTEM_FOCUSED;
  1354. }
  1355. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accState: child %d, returning 0x%08x"), idChild, V_I4(pvarState));
  1356. return (sc);
  1357. }
  1358. /*+-------------------------------------------------------------------------*
  1359. * CFolderTabView::Scget_accHelp
  1360. *
  1361. * Retrieves an object's Help property string. Not all objects need to
  1362. * support this property.
  1363. *--------------------------------------------------------------------------*/
  1364. SC CFolderTabView::Scget_accHelp(VARIANT varChildID, BSTR* pbstrHelp)
  1365. {
  1366. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accHelp"));
  1367. sc = ScCheckPointers (pbstrHelp);
  1368. if (sc)
  1369. return (sc);
  1370. /*
  1371. * no help
  1372. */
  1373. *pbstrHelp = NULL;
  1374. sc = ScValidateChildID (varChildID);
  1375. if (sc)
  1376. return (sc);
  1377. return (sc = S_FALSE);
  1378. }
  1379. /*+-------------------------------------------------------------------------*
  1380. * CFolderTabView::Scget_accHelpTopic
  1381. *
  1382. * Retrieves the full path of the WinHelp file associated with the specified
  1383. * object and the identifier of the appropriate topic within that file. Not
  1384. * all objects need to support this property.
  1385. *--------------------------------------------------------------------------*/
  1386. SC CFolderTabView::Scget_accHelpTopic(BSTR* pbstrHelpFile, VARIANT varChildID, long* pidTopic)
  1387. {
  1388. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accHelpTopic"));
  1389. sc = ScCheckPointers (pbstrHelpFile, pidTopic);
  1390. if (sc)
  1391. return (sc);
  1392. /*
  1393. * no help topic
  1394. */
  1395. *pbstrHelpFile = NULL;
  1396. *pidTopic = 0;
  1397. sc = ScValidateChildID (varChildID);
  1398. if (sc)
  1399. return (sc);
  1400. return (sc = S_FALSE);
  1401. }
  1402. /*+-------------------------------------------------------------------------*
  1403. * CFolderTabView::Scget_accKeyboardShortcut
  1404. *
  1405. * Retrieves the specified object's shortcut key or access key (also known
  1406. * as the mnemonic). All objects that have a shortcut key or access key
  1407. * should support this property.
  1408. *--------------------------------------------------------------------------*/
  1409. SC CFolderTabView::Scget_accKeyboardShortcut(VARIANT varChildID, BSTR* pbstrKeyboardShortcut)
  1410. {
  1411. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accKeyboardShortcut"));
  1412. sc = ScCheckPointers (pbstrKeyboardShortcut);
  1413. if (sc)
  1414. return (sc);
  1415. /*
  1416. * no shortcut keys
  1417. */
  1418. *pbstrKeyboardShortcut = NULL;
  1419. sc = ScValidateChildID (varChildID);
  1420. if (sc)
  1421. return (sc);
  1422. return (sc = S_FALSE);
  1423. }
  1424. /*+-------------------------------------------------------------------------*
  1425. * CFolderTabView::Scget_accFocus
  1426. *
  1427. * Retrieves the object that has the keyboard focus.
  1428. *--------------------------------------------------------------------------*/
  1429. SC CFolderTabView::Scget_accFocus(VARIANT * pvarFocusChild)
  1430. {
  1431. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accFocus"));
  1432. sc = ScCheckPointers (pvarFocusChild);
  1433. if (sc)
  1434. return (sc);
  1435. /*
  1436. * if we have the focus, return the (1-based) ID of the selected tab;
  1437. * otherwise, return VT_EMPTY
  1438. */
  1439. if (m_fHaveFocus)
  1440. {
  1441. V_VT(pvarFocusChild) = VT_I4;
  1442. V_I4(pvarFocusChild) = GetSelectedItem() + 1;
  1443. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accFocus: returning %d"), V_I4(pvarFocusChild));
  1444. }
  1445. else
  1446. {
  1447. V_VT(pvarFocusChild) = VT_EMPTY;
  1448. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accFocus: returning VT_EMPTY"));
  1449. }
  1450. return (sc);
  1451. }
  1452. /*+-------------------------------------------------------------------------*
  1453. * CFolderTabView::Scget_accSelection
  1454. *
  1455. * Retrieves the selected children of this object.
  1456. *--------------------------------------------------------------------------*/
  1457. SC CFolderTabView::Scget_accSelection(VARIANT * pvarSelectedChildren)
  1458. {
  1459. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accSelection"));
  1460. sc = ScCheckPointers (pvarSelectedChildren);
  1461. if (sc)
  1462. return (sc);
  1463. /*
  1464. * return the (1-based) ID of the selected tab, if there is one
  1465. */
  1466. if (GetSelectedItem() != -1)
  1467. {
  1468. V_VT(pvarSelectedChildren) = VT_I4;
  1469. V_I4(pvarSelectedChildren) = GetSelectedItem() + 1;
  1470. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accSelection: returning %d"), V_I4(pvarSelectedChildren));
  1471. }
  1472. else
  1473. {
  1474. V_VT(pvarSelectedChildren) = VT_EMPTY;
  1475. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accSelection: returning VT_EMPTY"));
  1476. }
  1477. return (sc);
  1478. }
  1479. /*+-------------------------------------------------------------------------*
  1480. * CFolderTabView::Scget_accDefaultAction
  1481. *
  1482. * Retrieves a string that describes the object's default action. Not all
  1483. * objects have a default action.
  1484. *--------------------------------------------------------------------------*/
  1485. SC CFolderTabView::Scget_accDefaultAction(VARIANT varChildID, BSTR* pbstrDefaultAction)
  1486. {
  1487. DECLARE_SC (sc, TEXT("CFolderTabView::Scget_accDefaultAction"));
  1488. sc = ScCheckPointers (pbstrDefaultAction);
  1489. if (sc)
  1490. return (sc);
  1491. /*
  1492. * default to "no default action"
  1493. */
  1494. *pbstrDefaultAction = NULL;
  1495. sc = ScValidateChildID (varChildID);
  1496. if(sc)
  1497. return (sc);
  1498. /*
  1499. * individual tabs have a default action of "Switch", just like WC_TABCONTROL
  1500. */
  1501. if (ValueOf(varChildID) != CHILDID_SELF)
  1502. {
  1503. CString strDefaultAction (MAKEINTRESOURCE (IDS_TabAccessiblity_DefaultAction));
  1504. CComBSTR bstrDefaultAction (strDefaultAction);
  1505. *pbstrDefaultAction = bstrDefaultAction.Detach();
  1506. }
  1507. else
  1508. {
  1509. sc = S_FALSE; // no default action
  1510. }
  1511. #ifdef DBG
  1512. USES_CONVERSION;
  1513. Trace (tagTabAccessibility, TEXT("CFolderTabView::Scget_accDefaultAction: child %d, returning \"%s\""),
  1514. ValueOf(varChildID),
  1515. (*pbstrDefaultAction) ? W2T(*pbstrDefaultAction) : _T("<None>"));
  1516. #endif
  1517. return (sc);
  1518. }
  1519. /*+-------------------------------------------------------------------------*
  1520. * CFolderTabView::ScaccSelect
  1521. *
  1522. * Modifies the selection or moves the keyboard focus of the specified
  1523. * object.
  1524. *--------------------------------------------------------------------------*/
  1525. SC CFolderTabView::ScaccSelect(long flagsSelect, VARIANT varChildID)
  1526. {
  1527. DECLARE_SC (sc, TEXT("CFolderTabView::ScaccSelect"));
  1528. Trace (tagTabAccessibility, TEXT("CFolderTabView::ScaccSelect"));
  1529. sc = ScValidateChildID (varChildID);
  1530. if(sc)
  1531. return (sc);
  1532. LONG idChild = ValueOf(varChildID);
  1533. /*
  1534. * can't select the tab control itself, only child elements
  1535. */
  1536. if (idChild == CHILDID_SELF)
  1537. return (sc = E_INVALIDARG);
  1538. /*
  1539. * the tab control doesn't support multiple selection, so reject
  1540. * requests dealing with multiple selection
  1541. */
  1542. const long lInvalidFlags = SELFLAG_EXTENDSELECTION |
  1543. SELFLAG_ADDSELECTION |
  1544. SELFLAG_REMOVESELECTION;
  1545. if (flagsSelect & lInvalidFlags)
  1546. return (sc = E_INVALIDARG);
  1547. /*
  1548. * activate this view, if we're requested to take the focus
  1549. */
  1550. if (flagsSelect & SELFLAG_TAKEFOCUS)
  1551. {
  1552. CFrameWnd* pFrame = GetParentFrame();
  1553. sc = ScCheckPointers (pFrame, E_FAIL);
  1554. if (sc)
  1555. return (sc);
  1556. pFrame->SetActiveView (this);
  1557. }
  1558. /*
  1559. * select the given tab, if requested
  1560. */
  1561. if (flagsSelect & SELFLAG_TAKESELECTION)
  1562. {
  1563. if (SelectItem (idChild - 1 /*0-based*/, true /*bEnsureVisible*/) == -1)
  1564. return (sc = E_FAIL);
  1565. }
  1566. return (sc);
  1567. }
  1568. /*+-------------------------------------------------------------------------*
  1569. * CFolderTabView::ScaccLocation
  1570. *
  1571. * Retrieves the specified object's current screen location.
  1572. *--------------------------------------------------------------------------*/
  1573. SC CFolderTabView::ScaccLocation (
  1574. long* pxLeft,
  1575. long* pyTop,
  1576. long* pcxWidth,
  1577. long* pcyHeight,
  1578. VARIANT varChildID)
  1579. {
  1580. DECLARE_SC (sc, TEXT("CFolderTabView::ScaccLocation"));
  1581. Trace (tagTabAccessibility, TEXT("CFolderTabView::ScaccLocation"));
  1582. sc = ScCheckPointers (pxLeft, pyTop, pcxWidth, pcyHeight);
  1583. if(sc)
  1584. return (sc);
  1585. // init out parameters
  1586. *pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0;
  1587. sc = ScValidateChildID (varChildID);
  1588. if(sc)
  1589. return (sc);
  1590. LONG idChild = ValueOf(varChildID);
  1591. CRect rectLocation;
  1592. /*
  1593. * for the tab control itself, get the location of the entire window
  1594. */
  1595. if (idChild == CHILDID_SELF)
  1596. GetWindowRect (rectLocation);
  1597. /*
  1598. * otherwise, get the rectangle of the tab and convert it to screen coords
  1599. */
  1600. else
  1601. {
  1602. rectLocation = GetItem(idChild-1).GetRect();
  1603. MapWindowPoints (NULL, rectLocation);
  1604. }
  1605. *pxLeft = rectLocation.left;
  1606. *pyTop = rectLocation.top;
  1607. *pcxWidth = rectLocation.Width();
  1608. *pcyHeight = rectLocation.Height();
  1609. return (sc);
  1610. }
  1611. /*+-------------------------------------------------------------------------*
  1612. * CFolderTabView::ScaccNavigate
  1613. *
  1614. * Traverses to another user interface element within a container and if
  1615. * possible, retrieves the object.
  1616. *--------------------------------------------------------------------------*/
  1617. SC CFolderTabView::ScaccNavigate (long lNavDir, VARIANT varStart, VARIANT * pvarEndUpAt)
  1618. {
  1619. DECLARE_SC (sc, TEXT("CFolderTabView::ScaccNavigate"));
  1620. sc = ScCheckPointers (pvarEndUpAt);
  1621. if (sc)
  1622. return (sc);
  1623. // init out parameters
  1624. VariantInit (pvarEndUpAt);
  1625. sc = ScValidateChildID (varStart);
  1626. if (sc)
  1627. return (sc);
  1628. LONG idFrom = ValueOf (varStart);
  1629. LONG idTo = -1;
  1630. Trace (tagTabAccessibility, TEXT("CFolderTabView::ScaccNavigate: start=%d, direction=%d"), idFrom, lNavDir);
  1631. switch (lNavDir)
  1632. {
  1633. case NAVDIR_UP:
  1634. case NAVDIR_DOWN:
  1635. /*
  1636. * the tab control doesn't have the concept of up and down,
  1637. * so there's no screen element in that direction; just leave
  1638. * idTo == -1 and the code below the switch will take care
  1639. * of the rest
  1640. */
  1641. break;
  1642. case NAVDIR_FIRSTCHILD:
  1643. case NAVDIR_LASTCHILD:
  1644. /*
  1645. * NAVDIR_FIRSTCHILD and NAVDIR_LASTCHILD must be relative
  1646. * to CHILDID_SELF
  1647. */
  1648. if (idFrom != CHILDID_SELF)
  1649. return (sc = E_INVALIDARG);
  1650. idTo = (lNavDir == NAVDIR_FIRSTCHILD) ? 1 : GetItemCount();
  1651. break;
  1652. case NAVDIR_LEFT:
  1653. case NAVDIR_PREVIOUS:
  1654. /*
  1655. * if we're moving relative to a child element, bump idTo;
  1656. * if not, just leave idTo == -1 and the code below the switch
  1657. * will take of the rest
  1658. */
  1659. if (idFrom != CHILDID_SELF)
  1660. idTo = idFrom - 1;
  1661. break;
  1662. case NAVDIR_RIGHT:
  1663. case NAVDIR_NEXT:
  1664. /*
  1665. * if we're moving relative to a child element, bump idTo;
  1666. * if not, just leave idTo == -1 and the code below the switch
  1667. * will take of the rest
  1668. */
  1669. if (idFrom != CHILDID_SELF)
  1670. idTo = idFrom + 1;
  1671. break;
  1672. default:
  1673. return (sc = E_INVALIDARG);
  1674. break;
  1675. }
  1676. /*
  1677. * if we're trying to navigate to an invalid child ID, return "no element
  1678. * in that direction"
  1679. */
  1680. if ((idTo < 1) || (idTo > GetItemCount()))
  1681. {
  1682. V_VT(pvarEndUpAt) = VT_EMPTY;
  1683. sc = S_FALSE;
  1684. Trace (tagTabAccessibility, TEXT("CFolderTabView::ScaccNavigate: VT_EMPTY"));
  1685. }
  1686. /*
  1687. * otherwise return the new child ID (don't change the selection here;
  1688. * the client will call IAccessible::accSelect to do that)
  1689. */
  1690. else
  1691. {
  1692. V_VT(pvarEndUpAt) = VT_I4;
  1693. V_I4(pvarEndUpAt) = idTo;
  1694. Trace (tagTabAccessibility, TEXT("CFolderTabView::ScaccNavigate: end=%d"), idTo);
  1695. }
  1696. return (sc);
  1697. }
  1698. /*+-------------------------------------------------------------------------*
  1699. * CFolderTabView::ScaccHitTest
  1700. *
  1701. * Retrieves the child element or child object at a given point on the screen.
  1702. *--------------------------------------------------------------------------*/
  1703. SC CFolderTabView::ScaccHitTest (long x, long y, VARIANT* pvarChildAtPoint)
  1704. {
  1705. DECLARE_SC (sc, TEXT("CFolderTabView::ScaccHitTest"));
  1706. sc = ScCheckPointers (pvarChildAtPoint);
  1707. if(sc)
  1708. return (sc);
  1709. // init out parameters
  1710. VariantInit (pvarChildAtPoint);
  1711. /*
  1712. * hit-test the given point, converted to client coordinates
  1713. */
  1714. CPoint pt (x, y);
  1715. ScreenToClient (&pt);
  1716. int nHitTest = HitTest (pt);
  1717. Trace (tagTabAccessibility, TEXT("CFolderTabView::ScaccHitTest: x=%d y=%d"), x, y);
  1718. /*
  1719. * not on a tab? see if it's within the client rect
  1720. */
  1721. if (nHitTest == -1)
  1722. {
  1723. CRect rectClient;
  1724. GetClientRect (rectClient);
  1725. if (rectClient.PtInRect (pt))
  1726. {
  1727. V_VT(pvarChildAtPoint) = VT_I4;
  1728. V_I4(pvarChildAtPoint) = CHILDID_SELF;
  1729. }
  1730. else
  1731. {
  1732. V_VT(pvarChildAtPoint) = VT_EMPTY;
  1733. sc = S_FALSE; // no element there
  1734. }
  1735. }
  1736. /*
  1737. * otherwise, it is on a tab; return the 1-based ID
  1738. */
  1739. else
  1740. {
  1741. V_VT(pvarChildAtPoint) = VT_I4;
  1742. V_I4(pvarChildAtPoint) = nHitTest + 1;
  1743. }
  1744. #ifdef DBG
  1745. if (V_VT(pvarChildAtPoint) == VT_I4)
  1746. Trace (tagTabAccessibility, TEXT("CFolderTabView::ScaccHitTest: returning %d"), ValueOf (*pvarChildAtPoint));
  1747. else
  1748. Trace (tagTabAccessibility, TEXT("CFolderTabView::ScaccHitTest: returning VT_EMPTY"));
  1749. #endif
  1750. return (sc);
  1751. }
  1752. /*+-------------------------------------------------------------------------*
  1753. * CFolderTabView::ScaccDoDefaultAction
  1754. *
  1755. * Performs the specified object's default action. Not all objects have a
  1756. * default action.
  1757. *--------------------------------------------------------------------------*/
  1758. SC CFolderTabView::ScaccDoDefaultAction (VARIANT varChildID)
  1759. {
  1760. DECLARE_SC (sc, TEXT("CFolderTabView::ScaccDoDefaultAction"));
  1761. sc = ScValidateChildID (varChildID);
  1762. if(sc)
  1763. return (sc);
  1764. /*
  1765. * the tab control doesn't have a default action
  1766. */
  1767. LONG idChild = ValueOf (varChildID);
  1768. Trace (tagTabAccessibility, TEXT("CFolderTabView::ScaccDoDefaultAction: child %d"), idChild);
  1769. if (idChild == CHILDID_SELF)
  1770. return (sc = E_INVALIDARG);
  1771. /*
  1772. * select the given tab item
  1773. */
  1774. if (SelectItem (idChild - 1 /*0-based*/, true /*bEnsureVisible*/) == -1)
  1775. return (sc = E_FAIL);
  1776. return (sc);
  1777. }
  1778. /*+-------------------------------------------------------------------------*
  1779. * CFolderTabView::Scput_accName
  1780. *
  1781. * This is no longer supported. The SetWindowText or control-specific APIs
  1782. * should be used in place of this method.
  1783. *--------------------------------------------------------------------------*/
  1784. SC CFolderTabView::Scput_accName(VARIANT varChildID, BSTR bstrName)
  1785. {
  1786. DECLARE_SC (sc, TEXT("CFolderTabView::Scput_accName"));
  1787. sc = ScValidateChildID (varChildID);
  1788. if (sc)
  1789. return (sc);
  1790. return (sc = E_NOTIMPL);
  1791. }
  1792. /*+-------------------------------------------------------------------------*
  1793. * CFolderTabView::Scput_accValue
  1794. *
  1795. * This is no longer supported. Control-specific APIs should be used in
  1796. * place of this method.
  1797. *--------------------------------------------------------------------------*/
  1798. SC CFolderTabView::Scput_accValue(VARIANT varChildID, BSTR bstrValue)
  1799. {
  1800. DECLARE_SC (sc, TEXT("CFolderTabView::Scput_accValue"));
  1801. sc = ScValidateChildID (varChildID);
  1802. if (sc)
  1803. return (sc);
  1804. return (sc = E_NOTIMPL);
  1805. }
  1806. /*+-------------------------------------------------------------------------*
  1807. * CFolderTabView::ScValidateChildID
  1808. *
  1809. * Determines if the supplied variant represents a valid child ID.
  1810. *--------------------------------------------------------------------------*/
  1811. SC CFolderTabView::ScValidateChildID (VARIANT &var)
  1812. {
  1813. DECLARE_SC (sc, TEXT("CFolderTabView::ScValidateChildID"));
  1814. /*
  1815. * child IDs must be VT_I4's
  1816. */
  1817. if (V_VT(&var) != VT_I4)
  1818. return (sc = E_INVALIDARG);
  1819. return (ScValidateChildID (ValueOf(var)));
  1820. }
  1821. /*+-------------------------------------------------------------------------*
  1822. * CFolderTabView::ScValidateChildID
  1823. *
  1824. * Determines if the supplied ID is valid child ID.
  1825. *--------------------------------------------------------------------------*/
  1826. SC CFolderTabView::ScValidateChildID (LONG idChild)
  1827. {
  1828. DECLARE_SC (sc, TEXT("CFolderTabView::ScValidateChildID"));
  1829. /*
  1830. * child ID must be either CHILDID_SELF or a valid tab index
  1831. */
  1832. if ((idChild < CHILDID_SELF) || (idChild > GetItemCount()))
  1833. return (sc = E_INVALIDARG);
  1834. return (sc);
  1835. }