Leaked source code of windows server 2003
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.

864 lines
24 KiB

  1. /*++
  2. Copyright (C) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. ctvctl.cpp
  5. Abstract:
  6. This module implements TreeView OCX for Device Manager snapin
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. // CTVCtl.cpp : Implementation of the CTVCtrl OLE control class.
  12. #include "stdafx.h"
  13. #include <afxcmn.h>
  14. #include "ctv.h"
  15. #include "CTVCtl.h"
  16. #include "resource.h"
  17. #define GET_X_LPARAM(lParam) (int)(short)LOWORD(lParam)
  18. #define GET_Y_LPARAM(lParam) (int)(short)HIWORD(lParam)
  19. IMPLEMENT_DYNCREATE(CTVCtrl, COleControl)
  20. BEGIN_INTERFACE_MAP(CTVCtrl, COleControl)
  21. INTERFACE_PART(CTVCtrl, IID_IDMTVOCX, DMTVOCX)
  22. END_INTERFACE_MAP()
  23. const IID IID_IDMTVOCX = {0x142525f2,0x59d8,0x11d0,{0xab,0xf0,0x00,0x20,0xaf,0x6b,0x0b,0x7a}};
  24. const IID IID_ISnapinCallback = {0x8e0ba98a,0xd161,0x11d0,{0x83,0x53,0x00,0xa0,0xc9,0x06,0x40,0xbf}};
  25. ULONG EXPORT CTVCtrl::XDMTVOCX::AddRef()
  26. {
  27. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  28. return pThis->ExternalAddRef();
  29. }
  30. ULONG EXPORT CTVCtrl::XDMTVOCX::Release()
  31. {
  32. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  33. return pThis->ExternalRelease();
  34. }
  35. HRESULT EXPORT CTVCtrl::XDMTVOCX::QueryInterface(
  36. REFIID iid,
  37. void ** ppvObj
  38. )
  39. {
  40. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  41. return pThis->ExternalQueryInterface(&iid, ppvObj);
  42. }
  43. HTREEITEM EXPORT CTVCtrl::XDMTVOCX::InsertItem(
  44. LPTV_INSERTSTRUCT pis
  45. )
  46. {
  47. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  48. return pThis->InsertItem(pis);
  49. }
  50. HRESULT EXPORT CTVCtrl::XDMTVOCX::DeleteItem(
  51. HTREEITEM hitem
  52. )
  53. {
  54. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  55. return pThis->DeleteItem(hitem);
  56. }
  57. HRESULT EXPORT CTVCtrl::XDMTVOCX::DeleteAllItems(
  58. )
  59. {
  60. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  61. return pThis->DeleteAllItems();
  62. }
  63. HIMAGELIST EXPORT CTVCtrl::XDMTVOCX::SetImageList(
  64. INT iImage,
  65. HIMAGELIST himl
  66. )
  67. {
  68. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  69. return pThis->SetImageList(iImage, himl);
  70. }
  71. HRESULT EXPORT CTVCtrl::XDMTVOCX::SetItem(
  72. TV_ITEM* pitem
  73. )
  74. {
  75. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  76. return pThis->SetItem(pitem);
  77. }
  78. HRESULT EXPORT CTVCtrl::XDMTVOCX::Expand(
  79. UINT Flags,
  80. HTREEITEM hitem
  81. )
  82. {
  83. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  84. return pThis->Expand(Flags, hitem);
  85. }
  86. HRESULT EXPORT CTVCtrl::XDMTVOCX::SelectItem(
  87. UINT Flags,
  88. HTREEITEM hitem
  89. )
  90. {
  91. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  92. return pThis->SelectItem(Flags, hitem);
  93. }
  94. HRESULT EXPORT CTVCtrl::XDMTVOCX::SetStyle(
  95. DWORD dwStyle
  96. )
  97. {
  98. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  99. return pThis->SetStyle(dwStyle);
  100. }
  101. HWND EXPORT CTVCtrl::XDMTVOCX::GetWindowHandle(
  102. )
  103. {
  104. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  105. return pThis->GetWindowHandle();
  106. }
  107. HRESULT EXPORT CTVCtrl::XDMTVOCX::GetItem(
  108. TV_ITEM* pti
  109. )
  110. {
  111. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  112. return pThis->GetItem(pti);
  113. }
  114. HTREEITEM EXPORT CTVCtrl::XDMTVOCX::GetNextItem(
  115. UINT Flags,
  116. HTREEITEM htiRef
  117. )
  118. {
  119. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  120. return pThis->GetNextItem(Flags, htiRef);
  121. }
  122. HRESULT EXPORT CTVCtrl::XDMTVOCX::SelectItem(
  123. HTREEITEM hti
  124. )
  125. {
  126. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  127. return pThis->SelectItem(hti);
  128. }
  129. UINT EXPORT CTVCtrl::XDMTVOCX::GetCount(
  130. )
  131. {
  132. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  133. return pThis->GetCount();
  134. }
  135. HTREEITEM EXPORT CTVCtrl::XDMTVOCX::GetSelectedItem(
  136. )
  137. {
  138. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  139. return pThis->GetSelectedItem();
  140. }
  141. HRESULT EXPORT CTVCtrl::XDMTVOCX::Connect(
  142. IComponent* pIComponent,
  143. MMC_COOKIE cookie
  144. )
  145. {
  146. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  147. return pThis->Connect(pIComponent, cookie);
  148. }
  149. HRESULT EXPORT CTVCtrl::XDMTVOCX::SetActiveConnection(
  150. MMC_COOKIE cookie
  151. )
  152. {
  153. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  154. return pThis->SetActiveConnection(cookie);
  155. }
  156. MMC_COOKIE EXPORT CTVCtrl::XDMTVOCX::GetActiveConnection()
  157. {
  158. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  159. return pThis->GetActiveConnection();
  160. }
  161. long EXPORT CTVCtrl::XDMTVOCX::SetRedraw(BOOL Redraw)
  162. {
  163. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  164. return pThis->SetRedraw(Redraw);
  165. }
  166. BOOL EXPORT CTVCtrl::XDMTVOCX::EnsureVisible(
  167. HTREEITEM hitem
  168. )
  169. {
  170. METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
  171. return pThis->EnsureVisible(hitem);
  172. }
  173. /////////////////////////////////////////////////////////////////////////////
  174. // Message map
  175. BEGIN_MESSAGE_MAP(CTVCtrl, COleControl)
  176. //{{AFX_MSG_MAP(CTVCtrl)
  177. ON_WM_DESTROY()
  178. ON_WM_CONTEXTMENU()
  179. //}}AFX_MSG_MAP
  180. ON_MESSAGE(OCM_COMMAND, OnOcmCommand)
  181. ON_MESSAGE(OCM_NOTIFY, OnOcmNotify)
  182. END_MESSAGE_MAP()
  183. /////////////////////////////////////////////////////////////////////////////
  184. // Dispatch map
  185. BEGIN_DISPATCH_MAP(CTVCtrl, COleControl)
  186. //{{AFX_DISPATCH_MAP(CTVCtrl)
  187. //}}AFX_DISPATCH_MAP
  188. END_DISPATCH_MAP()
  189. /////////////////////////////////////////////////////////////////////////////
  190. // Event map
  191. BEGIN_EVENT_MAP(CTVCtrl, COleControl)
  192. //{{AFX_EVENT_MAP(CTVCtrl)
  193. // NOTE - ClassWizard will add and remove event map entries
  194. // DO NOT EDIT what you see in these blocks of generated code !
  195. //}}AFX_EVENT_MAP
  196. END_EVENT_MAP()
  197. /////////////////////////////////////////////////////////////////////////////
  198. // Initialize class factory and guid
  199. IMPLEMENT_OLECREATE_EX(CTVCtrl, "CTREEVIEW.CTreeViewCtrl.1",
  200. 0xcd6c7868, 0x5864, 0x11d0, 0xab, 0xf0, 0, 0x20, 0xaf, 0x6b, 0xb, 0x7a)
  201. /////////////////////////////////////////////////////////////////////////////
  202. // Type library ID and version
  203. IMPLEMENT_OLETYPELIB(CTVCtrl, _tlid, _wVerMajor, _wVerMinor)
  204. /////////////////////////////////////////////////////////////////////////////
  205. // Interface IDs
  206. const IID BASED_CODE IID_DTV =
  207. { 0xcd6c7866, 0x5864, 0x11d0, { 0xab, 0xf0, 0, 0x20, 0xaf, 0x6b, 0xb, 0x7a}};
  208. const IID BASED_CODE IID_DTVEvents =
  209. { 0xcd6c7867, 0x5864, 0x11d0, { 0xab, 0xf0, 0, 0x20, 0xaf, 0x6b, 0xb, 0x7a}};
  210. /////////////////////////////////////////////////////////////////////////////
  211. // Control type information
  212. static const DWORD BASED_CODE _dwTVOleMisc =
  213. OLEMISC_ACTIVATEWHENVISIBLE |
  214. OLEMISC_SETCLIENTSITEFIRST |
  215. OLEMISC_INSIDEOUT |
  216. OLEMISC_CANTLINKINSIDE |
  217. OLEMISC_RECOMPOSEONRESIZE;
  218. IMPLEMENT_OLECTLTYPE(CTVCtrl, IDS_TV, _dwTVOleMisc)
  219. /////////////////////////////////////////////////////////////////////////////
  220. // CTVCtrl::CTVCtrlFactory::UpdateRegistry -
  221. // Adds or removes system registry entries for CTVCtrl
  222. BOOL CTVCtrl::CTVCtrlFactory::UpdateRegistry(BOOL bRegister)
  223. {
  224. if (bRegister) {
  225. return AfxOleRegisterControlClass(
  226. AfxGetInstanceHandle(),
  227. m_clsid,
  228. m_lpszProgID,
  229. IDS_TV,
  230. IDB_TV,
  231. afxRegApartmentThreading,
  232. _dwTVOleMisc,
  233. _tlid,
  234. _wVerMajor,
  235. _wVerMinor);
  236. } else {
  237. return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
  238. }
  239. }
  240. /////////////////////////////////////////////////////////////////////////////
  241. // CTVCtrl::CTVCtrl - Constructor
  242. CTVCtrl::CTVCtrl()
  243. {
  244. InitializeIIDs(&IID_DTV, &IID_DTVEvents);
  245. m_nConnections = 0;
  246. m_pIComponent = NULL;
  247. m_pISnapinCallback = NULL;
  248. m_Destroyed = FALSE;
  249. }
  250. /////////////////////////////////////////////////////////////////////////////
  251. // CTVCtrl::~CTVCtrl - Destructor
  252. CTVCtrl::~CTVCtrl()
  253. {
  254. if (m_pISnapinCallback) {
  255. m_pISnapinCallback->Release();
  256. }
  257. if (m_pIComponent) {
  258. m_pIComponent->Release();
  259. }
  260. }
  261. /////////////////////////////////////////////////////////////////////////////
  262. // CTVCtrl::OnDraw - Drawing function
  263. void CTVCtrl::OnDraw(
  264. CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
  265. {
  266. DoSuperclassPaint(pdc, rcBounds);
  267. }
  268. /////////////////////////////////////////////////////////////////////////////
  269. // CTVCtrl::DoPropExchange - Persistence support
  270. void CTVCtrl::DoPropExchange(CPropExchange* pPX)
  271. {
  272. ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
  273. COleControl::DoPropExchange(pPX);
  274. }
  275. /////////////////////////////////////////////////////////////////////////////
  276. // CTVCtrl::OnResetState - Reset control to default state
  277. void CTVCtrl::OnResetState()
  278. {
  279. COleControl::OnResetState(); // Resets defaults found in DoPropExchange
  280. }
  281. /////////////////////////////////////////////////////////////////////////////
  282. // CTVCtrl::PreCreateWindow - Modify parameters for CreateWindowEx
  283. BOOL CTVCtrl::PreCreateWindow(CREATESTRUCT& cs)
  284. {
  285. cs.lpszClass = _T("SysTreeView32");
  286. //
  287. // Turn off WS_EX_NOPARENTNOTIFY style bit so that our parents
  288. // receive mouse clicks on our window. I do not know why MFC
  289. // fundation class turns this on for an OCX.
  290. //
  291. cs.dwExStyle &= ~(WS_EX_NOPARENTNOTIFY);
  292. return COleControl::PreCreateWindow(cs);
  293. }
  294. /////////////////////////////////////////////////////////////////////////////
  295. // CTVCtrl::IsSubclassedControl - This is a subclassed control
  296. BOOL CTVCtrl::IsSubclassedControl()
  297. {
  298. return TRUE;
  299. }
  300. /////////////////////////////////////////////////////////////////////////////
  301. // CTVCtrl::OnOcmCommand - Handle command messages
  302. LRESULT CTVCtrl::OnOcmCommand(WPARAM wParam, LPARAM lParam)
  303. {
  304. #ifdef _WIN32
  305. WORD wNotifyCode = HIWORD(wParam);
  306. #else
  307. WORD wNotifyCode = HIWORD(lParam);
  308. #endif
  309. return 0;
  310. }
  311. /////////////////////////////////////////////////////////////////////////////
  312. // CTVCtrl message handlers
  313. ///////////////////////////////////////////////////////////////////////
  314. ///
  315. /// Tree View functions
  316. ///
  317. HRESULT
  318. CTVCtrl::Connect(
  319. IComponent* pIComponent,
  320. MMC_COOKIE cookie
  321. )
  322. {
  323. HRESULT hr = S_OK;
  324. if (0 == m_nConnections) {
  325. ASSERT(NULL == m_pIComponent);
  326. m_pIComponent = pIComponent;
  327. m_pIComponent->AddRef();
  328. hr = m_pIComponent->QueryInterface(IID_ISnapinCallback,
  329. reinterpret_cast<void**>(&m_pISnapinCallback)
  330. );
  331. }
  332. // A single snapin may have multiple nodes that uses us as result pane
  333. // display media, therefore, we may be connected mutlple times.
  334. // However, we get created only when MMC creates a new snapin instance.
  335. // This means, every connection call must provide the same
  336. // pIComponent and pConsole.
  337. //
  338. ASSERT(m_pIComponent == pIComponent);
  339. if (SUCCEEDED(hr)) {
  340. m_nConnections++;
  341. hr = SetActiveConnection(cookie);
  342. }
  343. return hr;
  344. }
  345. HRESULT
  346. CTVCtrl::SetActiveConnection(
  347. MMC_COOKIE cookie
  348. )
  349. {
  350. m_ActiveCookie = cookie;
  351. return S_OK;
  352. }
  353. MMC_COOKIE
  354. CTVCtrl::GetActiveConnection()
  355. {
  356. return m_ActiveCookie;
  357. }
  358. HTREEITEM CTVCtrl::InsertItem(
  359. LPTV_INSERTSTRUCT pis
  360. )
  361. {
  362. return (HTREEITEM)SendMessage(TVM_INSERTITEM, 0, (LPARAM)pis);
  363. }
  364. HRESULT CTVCtrl::DeleteItem(
  365. HTREEITEM hitem
  366. )
  367. {
  368. if (SendMessage(TVM_DELETEITEM, 0, (LPARAM)hitem)) {
  369. return S_OK;
  370. } else {
  371. return E_UNEXPECTED;
  372. }
  373. }
  374. HRESULT CTVCtrl::DeleteAllItems()
  375. {
  376. return DeleteItem((HTREEITEM)TVI_ROOT);
  377. }
  378. HIMAGELIST CTVCtrl::SetImageList(
  379. INT iImage,
  380. HIMAGELIST hmil
  381. )
  382. {
  383. return (HIMAGELIST)SendMessage(TVM_SETIMAGELIST, (WPARAM)iImage, (LPARAM)hmil);
  384. }
  385. HRESULT CTVCtrl::SetItem(
  386. TV_ITEM* pitem
  387. )
  388. {
  389. if (SendMessage(TVM_SETITEM, 0, (LPARAM)pitem)) {
  390. return S_OK;
  391. } else {
  392. return E_UNEXPECTED;
  393. }
  394. }
  395. HRESULT CTVCtrl::Expand(
  396. UINT Flags,
  397. HTREEITEM hitem
  398. )
  399. {
  400. if (SendMessage(TVM_EXPAND, (WPARAM) Flags, (LPARAM)hitem)) {
  401. return S_OK;
  402. } else {
  403. return E_UNEXPECTED;
  404. }
  405. }
  406. HRESULT CTVCtrl::SelectItem(
  407. UINT Flags,
  408. HTREEITEM hitem
  409. )
  410. {
  411. if (SendMessage(TVM_SELECTITEM, (WPARAM)Flags, (LPARAM)hitem)) {
  412. return S_OK;
  413. } else {
  414. return E_UNEXPECTED;
  415. }
  416. }
  417. HRESULT CTVCtrl::SetStyle(
  418. DWORD dwStyle
  419. )
  420. {
  421. if (ModifyStyle(0, dwStyle)) {
  422. return S_OK;
  423. } else {
  424. return E_UNEXPECTED;
  425. }
  426. }
  427. HWND CTVCtrl::GetWindowHandle(
  428. )
  429. {
  430. return m_hWnd;
  431. }
  432. HRESULT CTVCtrl::GetItem(
  433. TV_ITEM* pti
  434. )
  435. {
  436. if (SendMessage(TVM_GETITEM, 0, (LPARAM)pti)) {
  437. return S_OK;
  438. } else {
  439. return E_UNEXPECTED;
  440. }
  441. }
  442. HTREEITEM CTVCtrl::GetNextItem(
  443. UINT Flags,
  444. HTREEITEM htiRef
  445. )
  446. {
  447. return (HTREEITEM) SendMessage(TVM_GETNEXTITEM, (WPARAM)Flags, (LPARAM)htiRef);
  448. }
  449. HRESULT CTVCtrl::SelectItem(
  450. HTREEITEM hti
  451. )
  452. {
  453. if (SendMessage(TVM_SELECTITEM, 0, (LPARAM) hti)) {
  454. return S_OK;
  455. } else {
  456. return S_FALSE;
  457. }
  458. }
  459. UINT CTVCtrl::GetCount(
  460. )
  461. {
  462. return (UINT)SendMessage(TVM_GETCOUNT, 0, 0);
  463. }
  464. HTREEITEM CTVCtrl::HitTest(
  465. LONG x,
  466. LONG y,
  467. UINT* pFlags
  468. )
  469. {
  470. POINT pt;
  471. pt.x = x;
  472. pt.y = y;
  473. ScreenToClient(&pt);
  474. TV_HITTESTINFO tvhti;
  475. tvhti.pt = pt;
  476. HTREEITEM hti = (HTREEITEM)SendMessage(TVM_HITTEST, 0, (LPARAM)&tvhti);
  477. if (hti && pFlags) {
  478. *pFlags = tvhti.flags;
  479. }
  480. return hti;
  481. }
  482. HTREEITEM CTVCtrl::GetSelectedItem(
  483. )
  484. {
  485. return (HTREEITEM)SendMessage(TVM_GETNEXTITEM, TVGN_CARET, 0);
  486. }
  487. HRESULT CTVCtrl::SetRedraw(
  488. BOOL Redraw
  489. )
  490. {
  491. if (Redraw) {
  492. Invalidate();
  493. }
  494. return S_OK;
  495. }
  496. BOOL CTVCtrl::EnsureVisible(
  497. HTREEITEM hitem
  498. )
  499. {
  500. return (BOOL)SendMessage(TVM_ENSUREVISIBLE, 0, (LPARAM)hitem);
  501. }
  502. LRESULT
  503. CTVCtrl::OnOcmNotify(
  504. WPARAM wParam,
  505. LPARAM lParam
  506. )
  507. {
  508. LPARAM param, arg;
  509. MMC_COOKIE cookie = 0;
  510. HRESULT hr = S_FALSE;
  511. TV_NOTIFY_CODE NotifyCode;
  512. TV_ITEM TI;
  513. NotifyCode = TV_NOTIFY_CODE_UNKNOWN;
  514. switch (((NMHDR*)lParam)->code) {
  515. case NM_RCLICK:
  516. case NM_RDBLCLK:
  517. case NM_CLICK:
  518. case NM_DBLCLK:
  519. NotifyCode = DoMouseNotification(((NMHDR*)lParam)->code, &cookie,
  520. &arg, &param);
  521. break;
  522. case TVN_KEYDOWN:
  523. TI.hItem = GetSelectedItem();
  524. TI.mask = TVIF_PARAM;
  525. if (TI.hItem && SUCCEEDED(GetItem(&TI))) {
  526. cookie = (MMC_COOKIE)TI.lParam;
  527. NotifyCode = TV_NOTIFY_CODE_KEYDOWN;
  528. param = ((TV_KEYDOWN*)lParam)->wVKey;
  529. arg = (LPARAM)TI.hItem;
  530. }
  531. break;
  532. case NM_SETFOCUS:
  533. TI.hItem = GetSelectedItem();
  534. TI.mask = TVIF_PARAM;
  535. if (TI.hItem && SUCCEEDED(GetItem(&TI))) {
  536. cookie = (MMC_COOKIE)TI.lParam;
  537. NotifyCode = TV_NOTIFY_CODE_FOCUSCHANGED;
  538. param = 1;
  539. arg = (LPARAM)TI.hItem;
  540. }
  541. break;
  542. case TVN_SELCHANGEDA:
  543. case TVN_SELCHANGEDW:
  544. NotifyCode = TV_NOTIFY_CODE_SELCHANGED;
  545. arg = (LPARAM)((NM_TREEVIEW*)lParam)->itemNew.hItem;
  546. cookie = (MMC_COOKIE)((NM_TREEVIEW*)lParam)->itemNew.lParam;
  547. param = (LPARAM)((NM_TREEVIEW*)lParam)->action;
  548. break;
  549. case TVN_ITEMEXPANDEDA:
  550. case TVN_ITEMEXPANDEDW:
  551. NotifyCode = TV_NOTIFY_CODE_EXPANDED;
  552. arg = (LPARAM)((NM_TREEVIEW*)lParam)->itemNew.hItem;
  553. cookie = (MMC_COOKIE)((NM_TREEVIEW*)lParam)->itemNew.lParam;
  554. param = (LPARAM)((NM_TREEVIEW*)lParam)->action;
  555. break;
  556. default:
  557. NotifyCode = TV_NOTIFY_CODE_UNKNOWN;
  558. break;
  559. }
  560. if (TV_NOTIFY_CODE_UNKNOWN != NotifyCode && m_pISnapinCallback) {
  561. hr = m_pISnapinCallback->tvNotify(*this, cookie, NotifyCode, arg, param);
  562. if (S_FALSE == hr) {
  563. //
  564. // Translate RCLICK to context menu
  565. //
  566. if (TV_NOTIFY_CODE_RCLICK == NotifyCode) {
  567. SendMessage(WM_CONTEXTMENU, (WPARAM)m_hWnd, GetMessagePos());
  568. hr = S_OK;
  569. }
  570. //
  571. // Translate Shift-F10 or VK_APPS to context menu
  572. //
  573. else if (TV_NOTIFY_CODE_KEYDOWN == NotifyCode &&
  574. (VK_F10 == param && GetKeyState(VK_SHIFT) < 0) ||
  575. (VK_APPS == param)) {
  576. RECT rect;
  577. *((HTREEITEM*)&rect) = (HTREEITEM)arg;
  578. if (SendMessage(TVM_GETITEMRECT, TRUE, (LPARAM)&rect)) {
  579. POINT pt;
  580. pt.x = (rect.left + rect.right) / 2;
  581. pt.y = (rect.top + rect.bottom) / 2;
  582. ClientToScreen(&pt);
  583. SendMessage(WM_CONTEXTMENU, (WPARAM)m_hWnd, MAKELPARAM(pt.x, pt.y));
  584. hr = S_OK;
  585. }
  586. }
  587. }
  588. }
  589. //
  590. // On a TVN_KEYDOWN we should always return 0, otherwise the treeview
  591. // control gets confused.
  592. //
  593. if (((NMHDR*)lParam)->code == TVN_KEYDOWN) {
  594. hr = S_FALSE;
  595. }
  596. ASSERT(S_OK == hr || S_FALSE == hr);
  597. if (S_OK == hr) {
  598. return 1;
  599. }
  600. return 0;
  601. }
  602. TV_NOTIFY_CODE
  603. CTVCtrl::DoMouseNotification(
  604. UINT Code,
  605. MMC_COOKIE* pcookie,
  606. LPARAM* parg,
  607. LPARAM* pparam
  608. )
  609. {
  610. DWORD MsgPos;
  611. POINT point;
  612. ASSERT(pparam && parg && pcookie);
  613. *pparam = 0;
  614. *parg = 0;
  615. MsgPos = GetMessagePos();
  616. point.x = GET_X_LPARAM(MsgPos);
  617. point.y = GET_Y_LPARAM(MsgPos);
  618. UINT htFlags;
  619. HTREEITEM hti = HitTest(point.x, point.y, &htFlags);
  620. TV_NOTIFY_CODE NotifyCode = TV_NOTIFY_CODE_UNKNOWN;
  621. if (hti && (htFlags & TVHT_ONITEM)) {
  622. TV_ITEM TI;
  623. TI.hItem = hti;
  624. TI.mask = TVIF_PARAM;
  625. if (SUCCEEDED(GetItem(&TI))) {
  626. switch (Code) {
  627. case NM_RCLICK:
  628. NotifyCode = TV_NOTIFY_CODE_RCLICK;
  629. break;
  630. case NM_RDBLCLK:
  631. NotifyCode = TV_NOTIFY_CODE_RDBLCLK;
  632. break;
  633. case NM_CLICK:
  634. NotifyCode = TV_NOTIFY_CODE_CLICK;
  635. break;
  636. case NM_DBLCLK:
  637. NotifyCode = TV_NOTIFY_CODE_DBLCLK;
  638. break;
  639. default:
  640. NotifyCode = TV_NOTIFY_CODE_UNKNOWN;
  641. break;
  642. }
  643. if (TV_NOTIFY_CODE_UNKNOWN != NotifyCode) {
  644. *parg = (LPARAM)hti;
  645. *pparam = htFlags;
  646. *pcookie = (MMC_COOKIE)TI.lParam;
  647. }
  648. }
  649. }
  650. return NotifyCode;
  651. }
  652. // OnDestroy may be called on two occasions:
  653. // (1). We are the current active result pane window and MMC
  654. // is destroying our parent window(MDI client). Note that
  655. // if we are not the active result pane window, this function
  656. // will not get called until (2).
  657. // (2). our reference count has reached zero.
  658. //
  659. // When (1) happens, the snapin may be still holding reference to us
  660. // thus, even though our window has been destroyed (2) still happens
  661. // (unless PostNcDestory is done which MFC reset m_hWnd)and we end up
  662. // destoying the window twice.
  663. // So, we keep an eye on OnDestroy and do nothing after it has been called.
  664. // We can not wait for PostNcDestroy because we have no idea when it would
  665. // come.
  666. //
  667. void CTVCtrl::OnDestroy()
  668. {
  669. if (!m_Destroyed) {
  670. COleControl::OnDestroy();
  671. m_Destroyed = TRUE;
  672. }
  673. }
  674. void CTVCtrl::OnContextMenu(CWnd* pWnd, CPoint point)
  675. {
  676. POINT pt = point;
  677. UINT htFlags;
  678. HTREEITEM hti = HitTest(pt.x, pt.y, &htFlags);
  679. if (hti) {
  680. TV_ITEM TI;
  681. TI.hItem = hti;
  682. TI.mask = TVIF_PARAM;
  683. if (SUCCEEDED(GetItem(&TI))) {
  684. m_pISnapinCallback->tvNotify(*this, (MMC_COOKIE)TI.lParam,
  685. TV_NOTIFY_CODE_CONTEXTMENU,
  686. (LPARAM)hti, (LPARAM)&point );
  687. }
  688. }
  689. }
  690. // The upmost frame window may have its own accelerator table and may take
  691. // away certain key combinations we really need.
  692. BOOL CTVCtrl::PreTranslateMessage(MSG* pMsg)
  693. {
  694. if (WM_KEYDOWN == pMsg->message &&
  695. (VK_DELETE == pMsg->wParam ||
  696. VK_RETURN == pMsg->wParam)) {
  697. OnKeyDown((UINT)pMsg->wParam, LOWORD(pMsg->lParam), HIWORD(pMsg->lParam));
  698. return TRUE;
  699. }
  700. else if (WM_SYSKEYDOWN == pMsg->message && VK_F10 == pMsg->wParam &&
  701. GetKeyState(VK_SHIFT) < 0) {
  702. // Shift-F10 will be translated to WM_CONTEXTMENU
  703. OnSysKeyDown((UINT)pMsg->wParam, LOWORD(pMsg->lParam), HIWORD(pMsg->lParam));
  704. return TRUE;
  705. }
  706. return COleControl::PreTranslateMessage(pMsg);
  707. }