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

对话框与窗口

开发平台:

Visual C++

  1. // XTPPropertyGridView.cpp : implementation of the CXTPPropertyGridView class.
  2. //
  3. // This file is a part of the XTREME PROPERTYGRID 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/XTPDrawHelpers.h"
  23. #include "Common/XTPVC80Helpers.h"
  24. #include "Common/XTPResourceManager.h"
  25. #include "Common/XTPToolTipContext.h"
  26. #include "XTPPropertyGridInplaceEdit.h"
  27. #include "XTPPropertyGridInplaceButton.h"
  28. #include "XTPPropertyGridInplaceList.h"
  29. #include "XTPPropertyGridItem.h"
  30. #include "XTPPropertyGrid.h"
  31. #include "XTPPropertyGridDefines.h"
  32. #include "XTPPropertyGridPaintManager.h"
  33. #ifdef _DEBUG
  34. #define new DEBUG_NEW
  35. #undef THIS_FILE
  36. static char THIS_FILE[] = __FILE__;
  37. #endif
  38. const UINT PGV_HIT_SPLITTER = 0x100;
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CXTPPropertyGridToolTip
  41. CXTPPropertyGridToolTip::CXTPPropertyGridToolTip()
  42. {
  43. m_pGrid = NULL;
  44. }
  45. BEGIN_MESSAGE_MAP(CXTPPropertyGridToolTip, CWnd)
  46. //{{AFX_MSG_MAP(CXTPPropertyGridView)
  47. ON_WM_ERASEBKGND()
  48. ON_WM_PAINT()
  49. ON_WM_NCHITTEST_EX()
  50. //}}AFX_MSG_MAP
  51. END_MESSAGE_MAP()
  52. LRESULT CXTPPropertyGridToolTip::OnNcHitTest(CPoint /*point*/)
  53. {
  54. return (LRESULT)HTTRANSPARENT;
  55. }
  56. void CXTPPropertyGridToolTip::Create(CXTPPropertyGridView* pParentWnd)
  57. {
  58. CWnd::CreateEx(0, AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)), _T(""), WS_POPUP, CXTPEmptyRect(), pParentWnd, 0);
  59. m_pGrid = pParentWnd;
  60. }
  61. void CXTPPropertyGridToolTip::Activate(BOOL bActive, CXTPPropertyGridItem* pItem, BOOL bValuePart)
  62. {
  63. if (bActive)
  64. {
  65. ASSERT(pItem);
  66. m_fnt.DeleteObject();
  67. LOGFONT lf;
  68. m_pGrid->GetPaintManager()->GetItemFont(pItem, bValuePart)->GetLogFont(&lf);
  69. m_fnt.CreateFontIndirect(&lf);
  70. CString strText;
  71. GetWindowText(strText);
  72. CWindowDC dc(this);
  73. CXTPFontDC font(&dc, &m_fnt);
  74. CXTPWindowRect rc (this);
  75. rc.right = rc.left + dc.GetTextExtent(strText).cx + 8;
  76. CRect rcWork = XTPMultiMonitor()->GetWorkArea();
  77. if (rc.right > rcWork.right)
  78. rc.OffsetRect(rcWork.right - rc.right, 0);
  79. if (rc.left < rcWork.left)
  80. rc.OffsetRect(rcWork.left - rc.left, 0);
  81. MoveWindow(rc);
  82. ShowWindow(SW_SHOWNOACTIVATE);
  83. }
  84. else
  85. {
  86. DestroyWindow();
  87. }
  88. }
  89. BOOL CXTPPropertyGridToolTip::OnEraseBkgnd(CDC*)
  90. {
  91. return TRUE;
  92. }
  93. void CXTPPropertyGridToolTip::OnPaint()
  94. {
  95. CPaintDC dc(this);
  96. CXTPClientRect rc(this);
  97. COLORREF clrText = GetXtremeColor(COLOR_INFOTEXT);
  98. dc.FillSolidRect(rc, GetXtremeColor(COLOR_INFOBK));
  99. dc.Draw3dRect(rc, clrText, clrText);
  100. CString strText;
  101. GetWindowText(strText);
  102. dc.SetTextColor(clrText);
  103. dc.SetBkMode(TRANSPARENT);
  104. CXTPFontDC font(&dc, &m_fnt);
  105. CRect rcText(rc);
  106. rcText.left += 4;
  107. dc.DrawText(strText, rcText, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX);
  108. }
  109. /////////////////////////////////////////////////////////////////////////////
  110. // CXTPPropertyGridView
  111. CXTPPropertyGridView::CXTPPropertyGridView()
  112. {
  113. m_properetySort = xtpGridSortCategorized;
  114. m_dDivider = .5;
  115. m_bAutoDivider = TRUE;
  116. m_bTracking = FALSE;
  117. m_bVariableSplitterPos = TRUE;
  118. m_pSelected = NULL;
  119. m_pCategories = new CXTPPropertyGridItems();
  120. m_hCursor = XTPResourceManager()->LoadCursor(XTP_IDC_HSPLITBAR);
  121. m_nLockUpdate = 0;
  122. m_pGrid = NULL;
  123. m_nItemHeight = 0;
  124. m_pFocusedButton = NULL;
  125. m_pHotButton = NULL;
  126. EnableAutomation();
  127. }
  128. CXTPPropertyGridView::~CXTPPropertyGridView()
  129. {
  130. m_wndTip.DestroyWindow();
  131. DestroyWindow();
  132. m_pCategories->Clear();
  133. m_pCategories->InternalRelease();
  134. }
  135. IMPLEMENT_DYNAMIC(CXTPPropertyGridView, CListBox)
  136. BEGIN_MESSAGE_MAP(CXTPPropertyGridView, CListBox)
  137. //{{AFX_MSG_MAP(CXTPPropertyGridView)
  138. ON_WM_ERASEBKGND()
  139. ON_WM_PAINT()
  140. ON_WM_NCPAINT()
  141. ON_WM_NCCALCSIZE()
  142. ON_WM_LBUTTONDOWN()
  143. ON_WM_RBUTTONDOWN()
  144. ON_WM_LBUTTONDBLCLK()
  145. ON_CONTROL_REFLECT(LBN_SELCHANGE, OnSelectionChanged)
  146. ON_WM_SETCURSOR()
  147. ON_WM_LBUTTONUP()
  148. ON_WM_CAPTURECHANGED()
  149. ON_WM_MOUSEMOVE()
  150. ON_WM_SIZE()
  151. ON_WM_KEYDOWN()
  152. ON_WM_SYSKEYDOWN()
  153. ON_WM_KEYUP()
  154. ON_WM_SYSKEYUP()
  155. ON_WM_CHAR()
  156. ON_WM_GETDLGCODE()
  157. ON_WM_VSCROLL()
  158. ON_WM_MOUSEWHEEL()
  159. ON_WM_SETFOCUS()
  160. ON_WM_KILLFOCUS()
  161. ON_MESSAGE(WM_GETOBJECT, OnGetObject)
  162. //}}AFX_MSG_MAP
  163. END_MESSAGE_MAP()
  164. /////////////////////////////////////////////////////////////////////////////
  165. // CXTPPropertyGridView message handlers
  166. void CXTPPropertyGridView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  167. {
  168. if (GetScrollBarCtrl(SB_VERT) == pScrollBar)
  169. {
  170. OnScrollControl();
  171. }
  172. else
  173. {
  174. CListBox::OnVScroll(nSBCode, nPos, pScrollBar);
  175. }
  176. }
  177. struct CXTPPropertyGridView::WNDRECT
  178. {
  179. HWND hWnd;
  180. RECT rc;
  181. };
  182. LRESULT CXTPPropertyGridView::OnScrollControl()
  183. {
  184. if (GetCount() == 0)
  185. return 0;
  186. CArray<WNDRECT, WNDRECT&> arrRects;
  187. SetRedraw(FALSE);
  188. RECT rcTopOrig = {0, 0, 0, 0};
  189. GetItemRect(0, &rcTopOrig);
  190. HWND hWnd = ::GetWindow(m_hWnd, GW_CHILD);
  191. while (hWnd)
  192. {
  193. if (GetWindowLong(hWnd, GWL_STYLE) & WS_VISIBLE)
  194. {
  195. RECT rc;
  196. ::GetWindowRect(hWnd, &rc);
  197. WNDRECT wndRect;
  198. wndRect.hWnd = hWnd;
  199. wndRect.rc = rc;
  200. arrRects.Add(wndRect);
  201. }
  202. hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  203. }
  204. LRESULT lResult = Default();
  205. SetRedraw(TRUE);
  206. RECT rcTopDest = {0, 0, 0, 0};
  207. GetItemRect(0, &rcTopDest);
  208. int nOffset = rcTopDest.top - rcTopOrig.top;
  209. for (int i = 0; i < (int)arrRects.GetSize(); i++)
  210. {
  211. WNDRECT& wndRect = arrRects[i];
  212. RECT rc = wndRect.rc;
  213. ScreenToClient(&rc);
  214. ::OffsetRect(&rc, 0, nOffset);
  215. ::SetWindowPos(wndRect.hWnd, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
  216. SWP_NOACTIVATE | SWP_NOZORDER);
  217. }
  218. RedrawWindow(0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME | RDW_ALLCHILDREN);
  219. return lResult;
  220. }
  221. BOOL CXTPPropertyGridView::OnMouseWheel(UINT /*nFlags*/, short /*zDelta*/, CPoint /*pt*/)
  222. {
  223. return (BOOL)OnScrollControl();
  224. }
  225. void CXTPPropertyGridView::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  226. {
  227. lpMeasureItemStruct->itemHeight = m_nItemHeight;
  228. GetPaintManager()->MeasureItem(lpMeasureItemStruct);
  229. }
  230. void CXTPPropertyGridView::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  231. {
  232. ASSERT(lpDrawItemStruct->CtlType == ODT_LISTBOX);
  233. CXTPPropertyGridItem* pItem = (CXTPPropertyGridItem*)lpDrawItemStruct->itemData;
  234. CXTPPropertyGridPaintManager* pPaintManager = GetPaintManager();
  235. if (pItem == NULL)
  236. return;
  237. if ((int)lpDrawItemStruct->itemID == GetCount() - 1)
  238. {
  239. CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  240. CXTPClientRect rc(this);
  241. rc.top = lpDrawItemStruct->rcItem.bottom;
  242. pDC->FillSolidRect(rc, pPaintManager->GetItemMetrics()->m_clrBack);
  243. }
  244. if (!((m_pGrid->GetStyle() & XTP_PGS_OWNERDRAW) &&
  245. (SendNotifyMessage(XTP_PGN_DRAWITEM, (LPARAM)lpDrawItemStruct) == TRUE)))
  246. {
  247. pPaintManager->DrawItem(lpDrawItemStruct);
  248. }
  249. }
  250. BOOL CXTPPropertyGridView::OnEraseBkgnd(CDC*)
  251. {
  252. return TRUE;
  253. }
  254. void CXTPPropertyGridView::OnPaint()
  255. {
  256. CPaintDC dc(this);
  257. CXTPClientRect rc(this);
  258. CXTPBufferDC buffer(dc, rc);
  259. ASSERT(m_pGrid);
  260. GetPaintManager()->FillPropertyGridView(&buffer);
  261. CWnd::DefWindowProc(WM_PAINT, (WPARAM)buffer.m_hDC, 0);
  262. }
  263. void CXTPPropertyGridView::OnNcPaint()
  264. {
  265. Default();
  266. CWindowDC dc(this);
  267. CXTPWindowRect rc(this);
  268. rc.OffsetRect(-rc.TopLeft());
  269. ASSERT(m_pGrid);
  270. GetPaintManager()->DrawPropertyGridBorder(&dc, rc, FALSE);
  271. }
  272. void CXTPPropertyGridView::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
  273. {
  274. GetPaintManager()->DrawPropertyGridBorder(NULL, lpncsp->rgrc[0], TRUE);
  275. CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
  276. }
  277. CXTPPropertyGridItem* CXTPPropertyGridView::InsertCategory(int nIndex, LPCTSTR strCaption, CXTPPropertyGridItem* pCategory)
  278. {
  279. ASSERT(nIndex >= 0 && nIndex <= m_pCategories->GetCount());
  280. if (nIndex < 0 || nIndex > m_pCategories->GetCount())
  281. nIndex = m_pCategories->GetCount();
  282. if (pCategory == NULL)
  283. pCategory = new CXTPPropertyGridItem(strCaption);
  284. SetPropertySort(xtpGridSortCategorized);
  285. pCategory->m_pGrid = this;
  286. pCategory->m_bCategory = TRUE;
  287. pCategory->m_nFlags = 0;
  288. m_pCategories->InsertAt(nIndex, pCategory);
  289. pCategory->OnCaptionChanged();
  290. if (m_hWnd)
  291. {
  292. int nInsertAt = (nIndex >= m_pCategories->GetCount() - 1) ? GetCount() : m_pCategories->GetAt(nIndex + 1)->m_nIndex;
  293. InsertItem(pCategory, nInsertAt);
  294. }
  295. _RefreshIndexes();
  296. return pCategory;
  297. }
  298. CXTPPropertyGridItem* CXTPPropertyGridView::AddCategory(LPCTSTR strCaption, CXTPPropertyGridItem* pCategory)
  299. {
  300. return InsertCategory(m_pCategories->GetCount(), strCaption, pCategory);
  301. }
  302. void CXTPPropertyGridView::Refresh()
  303. {
  304. _RefreshIndexes();
  305. SetPropertySort(m_properetySort, TRUE);
  306. SAFE_INVALIDATE(m_pGrid);
  307. }
  308. void CXTPPropertyGridView::ResetContent()
  309. {
  310. if (m_pSelected)
  311. {
  312. m_pSelected->OnDeselect();
  313. m_pSelected = NULL;
  314. m_pGrid->OnSelectionChanged(NULL);
  315. }
  316. if (m_hWnd)
  317. {
  318. for (int i = 0; i < GetCount(); i++)
  319. {
  320. CXTPPropertyGridItem* pItem = (CXTPPropertyGridItem*)GetItemDataPtr(i);
  321. ASSERT(pItem);
  322. if (!pItem)
  323. continue;
  324. pItem->SetVisible(FALSE);
  325. }
  326. CListBox::ResetContent();
  327. CFont* pFont = &GetPaintManager()->GetItemMetrics()->m_fontNormal;
  328. SetFont(pFont, FALSE);
  329. CWindowDC dc(this);
  330. CXTPFontDC font(&dc, pFont);
  331. m_nItemHeight = dc.GetTextExtent(_T(" "), 1).cy + 4;
  332. SetItemHeight(0, m_nItemHeight);
  333. }
  334. }
  335. void CXTPPropertyGridView::SetPropertySort(XTPPropertyGridSortOrder sort, BOOL bRrefresh, BOOL bSetRedraw)
  336. {
  337. if (m_nLockUpdate > 0)
  338. {
  339. m_properetySort = sort;
  340. return;
  341. }
  342. if (sort == m_properetySort && !bRrefresh)
  343. return;
  344. if (!m_hWnd)
  345. return;
  346. if (bSetRedraw) SetRedraw(FALSE);
  347. CXTPPropertyGridItem* pTopItem = bRrefresh ? GetItem(GetTopIndex()) : NULL;
  348. CXTPPropertyGridItem* pSelected = GetSelectedItem();
  349. ResetContent();
  350. if (sort == xtpGridSortCategorized)
  351. {
  352. for (int i = 0; i < m_pCategories->GetCount(); i++)
  353. {
  354. CXTPPropertyGridItem* pCategory = m_pCategories->GetAt(i);
  355. InsertItem(pCategory, GetCount());
  356. }
  357. }
  358. else if (sort == xtpGridSortAlphabetical || sort == xtpGridSortNoSort)
  359. {
  360. CXTPPropertyGridItems lstItems;
  361. int i;
  362. for (i = 0; i < m_pCategories->GetCount(); i++)
  363. {
  364. CXTPPropertyGridItem* pCategory = m_pCategories->GetAt(i);
  365. if (!pCategory->IsHidden())
  366. lstItems.AddTail(pCategory->m_pChilds);
  367. }
  368. if (sort != xtpGridSortNoSort)
  369. lstItems.Sort();
  370. for (i = 0; i < lstItems.GetCount(); i++)
  371. {
  372. CXTPPropertyGridItem* pItem = lstItems.GetAt(i);
  373. InsertItem(pItem, GetCount());
  374. }
  375. }
  376. else
  377. {
  378. ASSERT(FALSE);
  379. }
  380. _RefreshIndexes();
  381. if (pTopItem && pTopItem->IsVisible())
  382. {
  383. SetTopIndex(pTopItem->m_nIndex);
  384. }
  385. if (pSelected)
  386. {
  387. pSelected->Select();
  388. }
  389. OnSelectionChanged();
  390. if (bSetRedraw) SetRedraw(TRUE);
  391. if (sort != m_properetySort)
  392. {
  393. m_properetySort = sort;
  394. m_pGrid->OnSortChanged();
  395. }
  396. }
  397. void CXTPPropertyGridView::SetDividerPos(int nDivider)
  398. {
  399. double dWidth = (double)CXTPWindowRect(this).Width();
  400. if (!m_bAutoDivider)
  401. {
  402. m_dDivider = nDivider;
  403. m_dDivider = __max(m_dDivider, 1.0);
  404. if (dWidth != 0)
  405. {
  406. m_dDivider = __min(m_dDivider, dWidth);
  407. }
  408. }
  409. else
  410. {
  411. m_dDivider = dWidth == 0 ? .5 : (double)nDivider / dWidth;
  412. m_dDivider = __max(m_dDivider, .1);
  413. m_dDivider = __min(m_dDivider, .85);
  414. }
  415. }
  416. int CXTPPropertyGridView::GetDividerPos() const
  417. {
  418. return int(m_dDivider * (m_bAutoDivider ? CXTPWindowRect(this).Width() : 1));
  419. }
  420. void CXTPPropertyGridView::LockDivider()
  421. {
  422. m_dDivider = GetDividerPos();
  423. m_bAutoDivider = FALSE;
  424. }
  425. int  CXTPPropertyGridView::InsertItem(CXTPPropertyGridItem* pItem, int nIndex)
  426. {
  427. if (m_nLockUpdate > 0) return 0;
  428. if (!m_hWnd) return 0;
  429. if (pItem->IsHidden())
  430. return 0;
  431. pItem->OnBeforeInsert();
  432. nIndex = (int)::SendMessage(m_hWnd, LB_INSERTSTRING, nIndex, (LPARAM)pItem);
  433. ASSERT(nIndex != -1);
  434. SetItemDataPtr(nIndex, pItem);
  435. if (GetStyle() & LBS_OWNERDRAWVARIABLE)
  436. {
  437. MEASUREITEMSTRUCT measureItemStruct =
  438. {
  439. ODT_LISTBOX, 0, nIndex, 0, m_nItemHeight, (ULONG_PTR)pItem
  440. };
  441. MeasureItem(&measureItemStruct);
  442. SetItemHeight(nIndex, measureItemStruct.itemHeight);
  443. }
  444. pItem->SetVisible(TRUE);
  445. int nItemsInserted = 1;
  446. if (pItem->m_bExpanded)
  447. {
  448. nItemsInserted += _DoExpand(pItem, nIndex);
  449. }
  450. return nItemsInserted;
  451. }
  452. int CXTPPropertyGridView::_DoExpand(CXTPPropertyGridItem* pItem, int nIndex)
  453. {
  454. int nStart = nIndex;
  455. for (int i = 0; i < pItem->GetChilds()->GetCount(); i++)
  456. {
  457. CXTPPropertyGridItem* pChild = pItem->GetChilds()->GetAt(i);
  458. nIndex += InsertItem(pChild, nIndex + 1);
  459. }
  460. return nIndex - nStart;
  461. }
  462. void CXTPPropertyGridView::_RefreshIndexes()
  463. {
  464. if (m_hWnd)
  465. {
  466. for (int i = 0; i < GetCount(); i++)
  467. {
  468. CXTPPropertyGridItem* pItem = (CXTPPropertyGridItem*)GetItemDataPtr(i);
  469. ASSERT(pItem);
  470. if (!pItem)
  471. continue;
  472. if (pItem->m_nIndex != i)
  473. {
  474. pItem->m_nIndex = i;
  475. pItem->OnIndexChanged();
  476. }
  477. }
  478. }
  479. }
  480. void CXTPPropertyGridView::_DoCollapse(CXTPPropertyGridItem* pItem)
  481. {
  482. ASSERT(pItem);
  483. if (!pItem)
  484. return;
  485. ASSERT(pItem->m_bExpanded);
  486. int nIndex = pItem->m_nIndex + 1;
  487. while (nIndex < GetCount())
  488. {
  489. CXTPPropertyGridItem* pChild = (CXTPPropertyGridItem*)GetItemDataPtr(nIndex);
  490. ASSERT(pChild);
  491. if (!pChild || !pChild->HasParent(pItem))
  492. break;
  493. pChild->SetVisible(FALSE);
  494. DeleteString(nIndex);
  495. }
  496. _RefreshIndexes();
  497. }
  498. CXTPPropertyGridItem* CXTPPropertyGridView::GetItem(int nIndex) const
  499. {
  500. if (nIndex < 0 || nIndex >= GetCount())
  501. return 0;
  502. CXTPPropertyGridItem* pItem = (CXTPPropertyGridItem*)GetItemDataPtr(nIndex);
  503. if ((ULONG_PTR)pItem == (ULONG_PTR)(-1))
  504. return NULL;
  505. ASSERT(pItem);
  506. return pItem;
  507. }
  508. void CXTPPropertyGridView::SwitchExpandState(int nItem)
  509. {
  510. CXTPPropertyGridItem* pItem = GetItem(nItem);
  511. if (!pItem || !pItem->IsExpandable())
  512. return;
  513. if (pItem->m_bExpanded)
  514. pItem->Collapse();
  515. else
  516. pItem->Expand();
  517. }
  518. void CXTPPropertyGridView::OnLButtonDown(UINT nFlags, CPoint point)
  519. {
  520. if (HitTest(point) == PGV_HIT_SPLITTER)
  521. {
  522. SetFocus();
  523. SetCapture();
  524. if (m_pSelected) m_pSelected->OnValidateEdit();
  525. m_bTracking = TRUE;
  526. return;
  527. }
  528. CXTPPropertyGridItem* pItem = ItemFromPoint(point);
  529. if (pItem)
  530. {
  531. SetFocus();
  532. if (GetFocus() != this)
  533. return;
  534. if ((ItemFromPoint(point) == pItem) && pItem->OnLButtonDown(nFlags, point))
  535. return;
  536. }
  537. CListBox::OnLButtonDown(nFlags, point);
  538. }
  539. CXTPPropertyGridItem* CXTPPropertyGridView::ItemFromPoint(CPoint point) const
  540. {
  541. BOOL bOutside = FALSE;
  542. int nIndex = CListBox::ItemFromPoint(point, bOutside);
  543. if (nIndex != -1 && !bOutside)
  544. {
  545. CXTPPropertyGridItem* pItem  = GetItem(nIndex);
  546. if (!pItem)
  547. return NULL;
  548. if (GetStyle() & LBS_OWNERDRAWVARIABLE)
  549. {
  550. CRect rc;
  551. GetItemRect(nIndex, rc);
  552. if (!rc.PtInRect(point))
  553. return NULL;
  554. }
  555. return pItem;
  556. }
  557. return NULL;
  558. }
  559. void CXTPPropertyGridView::FocusInplaceButton(CXTPPropertyGridInplaceButton* pButton)
  560. {
  561. if (pButton != m_pFocusedButton)
  562. {
  563. if (pButton) SetFocus();
  564. m_pFocusedButton = pButton;
  565. Invalidate(FALSE);
  566. }
  567. }
  568. void CXTPPropertyGridView::OnMouseMove(UINT nFlags, CPoint point)
  569. {
  570. if (m_bTracking)
  571. {
  572. SetDividerPos(point.x);
  573. if (m_pSelected) m_pSelected->OnSelect();
  574. Invalidate(FALSE);
  575. return;
  576. }
  577. CXTPPropertyGridItem* pItem = ItemFromPoint(point);
  578. CXTPPropertyGridInplaceButton* pButton = NULL;
  579. if (pItem)
  580. pButton = pItem->GetInplaceButtons()->HitTest(point);
  581. if (pButton != m_pHotButton)
  582. {
  583. m_pHotButton = pButton;
  584. Invalidate(FALSE);
  585. TRACKMOUSEEVENT tme =
  586. {
  587. sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, 0
  588. };
  589. _TrackMouseEvent (&tme);
  590. }
  591. ShowToolTip(point);
  592. CListBox::OnMouseMove(nFlags, point);
  593. }
  594. void CXTPPropertyGridView::OnLButtonUp(UINT nFlags, CPoint point)
  595. {
  596. if (m_bTracking)
  597. {
  598. ReleaseCapture();
  599. m_bTracking = FALSE;
  600. }
  601. CXTPPropertyGridItem* pItem = ItemFromPoint(point);
  602. if (pItem)
  603. {
  604. pItem->OnLButtonUp(nFlags, point);
  605. }
  606. CListBox::OnLButtonUp(nFlags, point);
  607. }
  608. void CXTPPropertyGridView::OnCaptureChanged(CWnd* pWnd)
  609. {
  610. m_bTracking = FALSE;
  611. CListBox::OnCaptureChanged(pWnd);
  612. }
  613. void CXTPPropertyGridView::OnLButtonDblClk(UINT nFlags, CPoint point)
  614. {
  615. CListBox::OnLButtonDblClk(nFlags, point);
  616. CXTPPropertyGridItem* pItem = ItemFromPoint(point);
  617. if (pItem)
  618. {
  619. pItem->OnLButtonDblClk(nFlags, point);
  620. if (pItem == ItemFromPoint(point))
  621. {
  622. SendNotifyMessage(XTP_PGN_DBLCLICK, (LPARAM)pItem);
  623. }
  624. }
  625. }
  626. void CXTPPropertyGridView::OnRButtonDown(UINT nFlags, CPoint point)
  627. {
  628. CListBox::OnRButtonDown(nFlags, point);
  629. CXTPPropertyGridItem* pItem = ItemFromPoint(point);
  630. if (pItem)
  631. {
  632. pItem->OnRButtonDown(nFlags, point);
  633. if (pItem == ItemFromPoint(point))
  634. {
  635. SendNotifyMessage(XTP_PGN_RCLICK, (LPARAM)pItem);
  636. }
  637. }
  638. }
  639. LRESULT CXTPPropertyGridView::SendNotifyMessage(WPARAM wParam, LPARAM lParam)
  640. {
  641. ASSERT(m_pGrid);
  642. if (!m_pGrid)
  643. return 0;
  644. return m_pGrid->SendNotifyMessage(wParam, lParam);
  645. }
  646. CXTPPropertyGridItem* CXTPPropertyGridView::GetSelectedItem()
  647. {
  648. return m_hWnd ? GetItem(GetCurSel()) : 0;
  649. }
  650. void CXTPPropertyGridView::OnChar(UINT nChar, UINT nRepCntr, UINT nFlags)
  651. {
  652. if (m_bTracking) return;
  653. if (m_pFocusedButton && nChar != VK_TAB)
  654. return;
  655. if (::GetFocus() != m_hWnd)
  656. return;
  657. CXTPPropertyGridItem* pItem = GetSelectedItem();
  658. if (nChar == '+' && pItem && pItem->HasChilds() && pItem->IsExpandable() && !pItem->m_bExpanded)
  659. {
  660. pItem->Expand();
  661. return;
  662. }
  663. if (nChar == '-' && pItem && pItem->HasChilds() && pItem->IsExpandable() && pItem->m_bExpanded)
  664. {
  665. pItem->Collapse();
  666. return;
  667. }
  668. if (nChar == VK_TAB)
  669. {
  670. if (m_pFocusedButton)
  671. {
  672. BOOL bForward = GetKeyState(VK_SHIFT) >= 0;
  673. m_pGrid->OnNavigate(bForward ? xtpGridUIInplaceEdit : xtpGridUIViewNext, bForward, pItem);
  674. }
  675. else
  676. {
  677. m_pGrid->OnNavigate(xtpGridUIView, GetKeyState(VK_SHIFT) >= 0, pItem);
  678. }
  679. return;
  680. }
  681. if (pItem && (nChar != VK_RETURN || !pItem->HasChilds()))
  682. {
  683. if (pItem->OnChar(nChar))
  684. return;
  685. }
  686. CWnd::OnChar(nChar, nRepCntr, nFlags);
  687. }
  688. UINT CXTPPropertyGridView::OnGetDlgCode()
  689. {
  690. return DLGC_WANTARROWS | DLGC_WANTTAB | DLGC_WANTCHARS;
  691. }
  692. INT_PTR CXTPPropertyGridView::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
  693. {
  694. ASSERT_VALID(this);
  695. ASSERT(::IsWindow(m_hWnd));
  696. // check child windows first by calling CControlBar
  697. INT_PTR nHit = CWnd::OnToolHitTest(point, pTI);
  698. if (nHit != -1)
  699. return nHit;
  700. if (m_pHotButton)
  701. {
  702. CString strTip = m_pHotButton->GetTooltip();
  703. if (strTip.GetLength() == 0)
  704. return -1;
  705. CXTPToolTipContext::FillInToolInfo(pTI, m_hWnd, m_pHotButton->GetRect(),
  706. m_pHotButton->GetID(), strTip);
  707. return m_pHotButton->GetID();
  708. }
  709. CXTPPropertyGridItem* pItem = ItemFromPoint(point);
  710. if (pItem)
  711. {
  712. nHit = pItem->GetID();
  713. CString strTip = pItem->GetTooltip();
  714. if (strTip.GetLength() == 0)
  715. return -1;
  716. CXTPToolTipContext::FillInToolInfo(pTI, m_hWnd, pItem->GetItemRect(),
  717. nHit, strTip, strTip, pItem->GetDescription(), GetImageManager());
  718. return nHit;
  719. }
  720. return -1;
  721. }
  722. void CXTPPropertyGridView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  723. {
  724. CListBox::OnKeyUp(nChar, nRepCnt, nFlags);
  725. }
  726. void CXTPPropertyGridView::OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  727. {
  728. CListBox::OnSysKeyUp(nChar, nRepCnt, nFlags);
  729. }
  730. void CXTPPropertyGridView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  731. {
  732. CXTPPropertyGridItem* pItem = GetSelectedItem();
  733. if (m_pFocusedButton && m_pFocusedButton->GetItem() == pItem)
  734. {
  735. m_pFocusedButton->OnKeyDown(nChar);
  736. return;
  737. }
  738. if ((GetKeyState(VK_CONTROL) < 0) && (nChar == VK_RIGHT || nChar == VK_LEFT))
  739. {
  740. CXTPDrawHelpers::KeyToLayout(this, nChar);
  741. SetDividerPos(GetDividerPos() + (nChar == VK_RIGHT ? 3 : -3));
  742. if (m_pSelected) m_pSelected->OnSelect();
  743. Invalidate(FALSE);
  744. return;
  745. }
  746. if (nChar == VK_RIGHT)
  747. {
  748. if (pItem && pItem->HasChilds() && !pItem->m_bExpanded && pItem->IsExpandable())
  749. {
  750. pItem->Expand();
  751. return;
  752. }
  753. }
  754. else if (nChar == VK_LEFT)
  755. {
  756. if (pItem && pItem->HasChilds() && pItem->m_bExpanded && pItem->IsExpandable())
  757. {
  758. pItem->Collapse();
  759. return;
  760. }
  761. }
  762. if (nChar == VK_RETURN)
  763. {
  764. SwitchExpandState(GetCurSel());
  765. return ;
  766. }
  767. if (nChar == VK_F4 && m_pSelected)
  768. {
  769. CXTPPropertyGridInplaceButton* pButton = m_pSelected->GetInplaceButtons()->Find(XTP_ID_PROPERTYGRID_COMBOBUTTON);
  770. if (pButton)
  771. m_pSelected->OnInplaceButtonDown(pButton);
  772. }
  773. if (m_pSelected && m_pSelected->OnKeyDown(nChar))
  774. {
  775. return;
  776. }
  777. CListBox::OnKeyDown(nChar, nRepCnt, nFlags);
  778. }
  779. void CXTPPropertyGridView::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  780. {
  781. if ((nChar == VK_DOWN || nChar == VK_UP) && m_pSelected)
  782. {
  783. CXTPPropertyGridInplaceButton* pButton = m_pSelected->GetInplaceButtons()->Find(XTP_ID_PROPERTYGRID_COMBOBUTTON);
  784. if (pButton)
  785. m_pSelected->OnInplaceButtonDown(pButton);
  786. }
  787. CListBox::OnSysKeyDown(nChar, nRepCnt, nFlags);
  788. }
  789. BOOL CXTPPropertyGridView::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  790. {
  791. static BOOL bRelay = FALSE;
  792. if (m_wndTip.GetSafeHwnd() && m_wndTip.IsWindowVisible() && !bRelay)
  793. {
  794. bRelay = TRUE;
  795. RelayToolTipEvent(message);
  796. bRelay = FALSE;
  797. }
  798. if (message == WM_MOUSELEAVE && m_pHotButton)
  799. {
  800. m_pHotButton = NULL;
  801. Invalidate(FALSE);
  802. }
  803. if (m_pGrid->GetToolTipContext())
  804. {
  805. m_pGrid->GetToolTipContext()->FilterToolTipMessage(this, message, wParam, lParam);
  806. }
  807. return CWnd::OnWndMsg(message, wParam, lParam, pResult);
  808. }
  809. void CXTPPropertyGridView::OnSelectionChanged()
  810. {
  811. CXTPPropertyGridItem* pItem = GetSelectedItem();
  812. if (m_pSelected) m_pSelected->OnDeselect();
  813. if (pItem) pItem->OnSelect();
  814. m_pSelected = pItem;
  815. if (m_pSelected) m_pGrid->OnSelectionChanged(m_pSelected);
  816. }
  817. int CXTPPropertyGridView::HitTest(CPoint point) const
  818. {
  819. if (!m_bVariableSplitterPos)
  820. return -1;
  821. int nDivider = GetDividerPos();
  822. if ((point.x > nDivider - 4 && point.x <= nDivider + 2) && (GetCount() > 0))
  823. return PGV_HIT_SPLITTER;
  824. return -1;
  825. }
  826. BOOL CXTPPropertyGridView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  827. {
  828. if (nHitTest == HTCLIENT)
  829. {
  830. CPoint point;
  831. GetCursorPos(&point);
  832. ScreenToClient(&point);
  833. if (HitTest(point) == PGV_HIT_SPLITTER)
  834. {
  835. SetCursor(m_hCursor);
  836. return TRUE;
  837. }
  838. }
  839. return CListBox::OnSetCursor(pWnd, nHitTest, message);
  840. }
  841. void CXTPPropertyGridView::OnSize(UINT nType, int cx, int cy)
  842. {
  843. CListBox::OnSize(nType, cx, cy);
  844. OnSelectionChanged();
  845. Invalidate(FALSE);
  846. }
  847. // ToolTips routings
  848. void CXTPPropertyGridView::_ShowToolTip(CRect rcBound, CRect rcText, CXTPPropertyGridItem* pItem, BOOL bValuePart)
  849. {
  850. if (!m_wndTip.GetSafeHwnd())
  851. return;
  852. m_wndTip.SetWindowText(m_strTipText);
  853. m_wndTip.MoveWindow(rcText);
  854. m_wndTip.Activate(TRUE, pItem, bValuePart);
  855. m_rcToolTip = rcBound;
  856. TRACKMOUSEEVENT tme =
  857. {
  858. sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, 0
  859. };
  860. _TrackMouseEvent (&tme);
  861. }
  862. CSize CXTPPropertyGridView::_GetTextExtent(const CString& str, CXTPPropertyGridItem* pItem, BOOL bValuePart)
  863. {
  864. CWindowDC dc(this);
  865. CXTPFontDC font(&dc, GetPaintManager()->GetItemFont(pItem, bValuePart));
  866. return dc.GetTextExtent(str);
  867. }
  868. void CXTPPropertyGridView::ShowToolTip(CPoint pt)
  869. {
  870. if (CXTPMouseMonitor::IsMouseHooked())
  871. return;
  872. if (!m_pGrid->m_bEnableTooltips)
  873. return;
  874. if (!m_wndTip.GetSafeHwnd())
  875. {
  876. m_wndTip.Create(this);
  877. }
  878. if (m_pHotButton)
  879. return;
  880. CXTPPropertyGridItem* pItem = ItemFromPoint(pt);
  881. if (!pItem || pItem->IsCategory() || !pItem->GetTooltip().IsEmpty())
  882. return;
  883. int nDividerPos = GetDividerPos();
  884. CRect rc = pItem->GetItemRect();
  885. CRect rcCaption(rc.left, rc.top, rc.left + nDividerPos, rc.bottom);
  886. if (rcCaption.PtInRect(pt))
  887. {
  888. if (m_strTipText == pItem->GetCaption())
  889. return;
  890. if (pItem->GetMarkupUIElement())
  891. return;
  892. m_strTipText = pItem->GetCaption();
  893. ClientToScreen(&rcCaption);
  894. CRect rcCaptionText(rcCaption);
  895. rcCaptionText.left += pItem->m_nIndent * XTP_PGI_EXPAND_BORDER + 3 - 3 -1;
  896. rcCaptionText.top--;
  897. GetPaintManager()->AdjustItemCaptionRect(pItem, rcCaptionText);
  898. int nTextExtent = _GetTextExtent(m_strTipText, pItem, FALSE).cx;
  899. if (nTextExtent + 3 > rcCaptionText.Width())
  900. {
  901. if (GetExStyle() & WS_EX_LAYOUTRTL)
  902. {
  903. rcCaptionText.left = rcCaption.right - nTextExtent - 7 - (pItem->m_nIndent * XTP_PGI_EXPAND_BORDER);
  904. }
  905. _ShowToolTip(rcCaption, rcCaptionText, pItem, FALSE);
  906. }
  907. }
  908. else
  909. {
  910. if (m_strTipText == pItem->GetViewValue())
  911. return;
  912. if (pItem->IsMultiLine())
  913. return;
  914. m_strTipText = pItem->GetViewValue();
  915. if (GetFocus() && GetFocus()->IsKindOf(RUNTIME_CLASS(CXTPPropertyGridInplaceEdit)))
  916. {
  917. if (((CXTPPropertyGridInplaceEdit*)(GetFocus()))->GetItem() == pItem)
  918. return;
  919. }
  920. CRect rcValue(rc.left + nDividerPos, rc.top, rc.right, rc.bottom);
  921. ClientToScreen(&rcValue);
  922. CRect rcValueText = pItem->GetValueRect();
  923. rcValueText.InflateRect(1, 2, 0, 1);
  924. ClientToScreen(&rcValueText);
  925. int nTextExtent = _GetTextExtent(m_strTipText, pItem, TRUE).cx;
  926. if (nTextExtent + 3 > rcValueText.Width())
  927. {
  928. if (GetExStyle() & WS_EX_LAYOUTRTL)
  929. {
  930. rcValueText.left = rcValueText.right - 8 - nTextExtent;
  931. }
  932. _ShowToolTip(rcValue, rcValueText, pItem, TRUE);
  933. }
  934. }
  935. }
  936. void CXTPPropertyGridView::RelayToolTipEvent(UINT message)
  937. {
  938. if (m_wndTip.GetSafeHwnd() && m_wndTip.IsWindowVisible())
  939. {
  940. CRect rc;
  941. m_wndTip.GetWindowRect(rc);
  942. CPoint pt;
  943. GetCursorPos(&pt);
  944. if (!m_rcToolTip.PtInRect(pt) || m_pHotButton)
  945. {
  946. m_strTipText = "";
  947. m_wndTip.Activate(FALSE, 0, 0);
  948. }
  949. switch (message)
  950. {
  951. case WM_MOUSEWHEEL:
  952. m_strTipText = "";
  953. m_wndTip.Activate(FALSE, 0, 0);
  954. break;
  955. case WM_KEYDOWN:
  956. case WM_SYSKEYDOWN:
  957. case WM_LBUTTONDOWN:
  958. case WM_RBUTTONDOWN:
  959. case WM_MBUTTONDOWN:
  960. case WM_LBUTTONUP:
  961. case WM_RBUTTONUP:
  962. case WM_MBUTTONUP:
  963. case WM_MOUSELEAVE:
  964. m_wndTip.Activate(FALSE, 0, 0);
  965. break;
  966. }
  967. }
  968. }
  969. void CXTPPropertyGridView::OnSetFocus(CWnd* pOldWnd)
  970. {
  971. m_pFocusedButton = NULL;
  972. CListBox::OnSetFocus(pOldWnd);
  973. if (GetStyle() & LBS_MULTIPLESEL)
  974. Invalidate(FALSE);
  975. }
  976. void CXTPPropertyGridView::OnKillFocus (CWnd* pNewWnd)
  977. {
  978. m_pFocusedButton = NULL;
  979. CListBox::OnKillFocus(pNewWnd);
  980. if (GetStyle() & LBS_MULTIPLESEL)
  981. Invalidate(FALSE);
  982. }
  983. CXTPPropertyGridPaintManager* CXTPPropertyGridView::GetPaintManager() const
  984. {
  985. return m_pGrid->GetPaintManager();
  986. }
  987. CXTPImageManager* CXTPPropertyGridView::GetImageManager() const
  988. {
  989. return m_pGrid->GetImageManager();
  990. }
  991. //////////////////////////////////////////////////////////////////////////
  992. // Accessible
  993. LRESULT CXTPPropertyGridView::OnGetObject(WPARAM wParam, LPARAM lParam)
  994. {
  995. if (lParam != OBJID_CLIENT)
  996. return (LRESULT)Default();
  997. LPUNKNOWN lpUnknown = GetInterface(&IID_IAccessible);
  998. if (!lpUnknown)
  999. return E_FAIL;
  1000. return LresultFromObject(IID_IAccessible, wParam, lpUnknown);
  1001. }
  1002. BEGIN_INTERFACE_MAP(CXTPPropertyGridView, CCmdTarget)
  1003. INTERFACE_PART(CXTPPropertyGridView, IID_IAccessible, ExternalAccessible)
  1004. END_INTERFACE_MAP()
  1005. CCmdTarget* CXTPPropertyGridView::GetAccessible()
  1006. {
  1007. return this;
  1008. }
  1009. HRESULT CXTPPropertyGridView::GetAccessibleParent(IDispatch* FAR* ppdispParent)
  1010. {
  1011. *ppdispParent = NULL;
  1012. if (GetSafeHwnd())
  1013. {
  1014. return AccessibleObjectFromWindow(GetSafeHwnd(), OBJID_WINDOW, IID_IDispatch, (void**)ppdispParent);
  1015. }
  1016. return E_FAIL;
  1017. }
  1018. HRESULT CXTPPropertyGridView::GetAccessibleChildCount(long FAR* pChildCount)
  1019. {
  1020. if (pChildCount == 0)
  1021. {
  1022. return E_INVALIDARG;
  1023. }
  1024. *pChildCount = CListBox::GetCount();
  1025. return S_OK;
  1026. }
  1027. HRESULT CXTPPropertyGridView::GetAccessibleChild(VARIANT varChild, IDispatch* FAR* ppdispChild)
  1028. {
  1029. *ppdispChild = NULL;
  1030. int nChild = GetChildIndex(&varChild);
  1031. if (nChild <= 0)
  1032. {
  1033. return E_INVALIDARG;
  1034. }
  1035. CXTPPropertyGridItem* pItem = GetItem(nChild - 1);
  1036. if (!pItem)
  1037. {
  1038. return E_INVALIDARG;
  1039. }
  1040. *ppdispChild = pItem->GetIDispatch(TRUE);
  1041. return S_OK;
  1042. }
  1043. HRESULT CXTPPropertyGridView::GetAccessibleName(VARIANT varChild, BSTR* pszName)
  1044. {
  1045. int nChild = GetChildIndex(&varChild);
  1046. if (nChild == CHILDID_SELF || nChild == -1)
  1047. {
  1048. *pszName = SysAllocString(L"Properties Window");
  1049. return S_OK;
  1050. }
  1051. return E_INVALIDARG;
  1052. }
  1053. HRESULT CXTPPropertyGridView::GetAccessibleRole(VARIANT varChild, VARIANT* pvarRole)
  1054. {
  1055. pvarRole->vt = VT_EMPTY;
  1056. int nChild = GetChildIndex(&varChild);
  1057. if (nChild == CHILDID_SELF)
  1058. {
  1059. pvarRole->vt = VT_I4;
  1060. pvarRole->lVal = ROLE_SYSTEM_TABLE;
  1061. return S_OK;
  1062. }
  1063. return E_INVALIDARG;
  1064. }
  1065. HRESULT CXTPPropertyGridView::GetAccessibleState(VARIANT varChild, VARIANT* pvarState)
  1066. {
  1067. pvarState->vt = VT_I4;
  1068. pvarState->lVal = 0;
  1069. int nChild = GetChildIndex(&varChild);
  1070. if (nChild == CHILDID_SELF)
  1071. {
  1072. pvarState->lVal = STATE_SYSTEM_FOCUSABLE;
  1073. }
  1074. return S_OK;
  1075. }
  1076. HRESULT CXTPPropertyGridView::AccessibleLocation(long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varChild)
  1077. {
  1078. *pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0;
  1079. if (!GetSafeHwnd())
  1080. return S_OK;
  1081. CRect rc;
  1082. GetWindowRect(&rc);
  1083. int nChild = GetChildIndex(&varChild);
  1084. if (nChild != CHILDID_SELF)
  1085. {
  1086. return E_INVALIDARG;
  1087. }
  1088. *pxLeft = rc.left;
  1089. *pyTop = rc.top;
  1090. *pcxWidth = rc.Width();
  1091. *pcyHeight = rc.Height();
  1092. return S_OK;
  1093. }
  1094. HRESULT CXTPPropertyGridView::AccessibleHitTest(long xLeft, long yTop, VARIANT* pvarID)
  1095. {
  1096. if (pvarID == NULL)
  1097. return E_INVALIDARG;
  1098. pvarID->vt = VT_EMPTY;
  1099. if (!GetSafeHwnd())
  1100. return S_FALSE;
  1101. if (!CXTPWindowRect(this).PtInRect(CPoint(xLeft, yTop)))
  1102. return S_FALSE;
  1103. pvarID->vt = VT_I4;
  1104. pvarID->lVal = CHILDID_SELF;
  1105. CPoint pt(xLeft, yTop);
  1106. ScreenToClient(&pt);
  1107. CXTPPropertyGridItem* pItem = ItemFromPoint(pt);
  1108. if (pItem)
  1109. {
  1110. pvarID->vt = VT_DISPATCH;
  1111. pvarID->pdispVal = pItem->GetIDispatch(TRUE);
  1112. }
  1113. return S_OK;
  1114. }