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.

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