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.

607 lines
19 KiB

  1. //==============================================================;
  2. //
  3. // This source code is only intended as a supplement to
  4. // existing Microsoft documentation.
  5. //
  6. //
  7. //
  8. //
  9. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  10. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  11. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  12. // PURPOSE.
  13. //
  14. // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  15. //
  16. //
  17. //
  18. //==============================================================;
  19. #include <stdio.h>
  20. #include <windows.h>
  21. #include "Space.h"
  22. #include "Comp.h"
  23. #include "CompData.h"
  24. #include "DataObj.h"
  25. #include "globals.h"
  26. #include "resource.h"
  27. const GUID CSpaceVehicle::thisGuid = { 0xb95e11f4, 0x6be7, 0x11d3, {0x91, 0x56, 0x0, 0xc0, 0x4f, 0x65, 0xb3, 0xf9} };
  28. const GUID CRocket::thisGuid = { 0xb95e11f5, 0x6be7, 0x11d3, {0x91, 0x56, 0x0, 0xc0, 0x4f, 0x65, 0xb3, 0xf9} };
  29. //==============================================================
  30. //
  31. // CSpaceVehicle implementation
  32. //
  33. //
  34. CSpaceVehicle::CSpaceVehicle() : m_cchildren(NUMBER_OF_CHILDREN)
  35. {
  36. for (int n = 0; n < m_cchildren; n++) {
  37. children[n] = new CRocket(_T("Rocket"), n+1, 500000, 265, 75000, this);
  38. }
  39. }
  40. CSpaceVehicle::~CSpaceVehicle()
  41. {
  42. for (int n = 0; n < m_cchildren; n++)
  43. if (children[n]) {
  44. delete children[n];
  45. }
  46. }
  47. HRESULT CSpaceVehicle::OnShow(IConsole *pConsole, BOOL bShow, HSCOPEITEM scopeitem)
  48. {
  49. HRESULT hr = S_OK;
  50. IHeaderCtrl *pHeaderCtrl = NULL;
  51. IResultData *pResultData = NULL;
  52. if (bShow) {
  53. hr = pConsole->QueryInterface(IID_IHeaderCtrl, (void **)&pHeaderCtrl);
  54. _ASSERT( SUCCEEDED(hr) );
  55. hr = pConsole->QueryInterface(IID_IResultData, (void **)&pResultData);
  56. _ASSERT( SUCCEEDED(hr) );
  57. // Set the column headers in the results pane
  58. hr = pHeaderCtrl->InsertColumn( 0, L"Rocket Class", 0, MMCLV_AUTO );
  59. _ASSERT( S_OK == hr );
  60. hr = pHeaderCtrl->InsertColumn( 1, L"Rocket Weight", 0, MMCLV_AUTO );
  61. _ASSERT( S_OK == hr );
  62. hr = pHeaderCtrl->InsertColumn( 2, L"Rocket Height", 0, MMCLV_AUTO );
  63. _ASSERT( S_OK == hr );
  64. hr = pHeaderCtrl->InsertColumn( 3, L"Rocket Payload", 0, MMCLV_AUTO );
  65. _ASSERT( S_OK == hr );
  66. hr = pHeaderCtrl->InsertColumn( 4, L"Status", 0, MMCLV_AUTO );
  67. _ASSERT( S_OK == hr );
  68. // insert items here
  69. RESULTDATAITEM rdi;
  70. hr = pResultData->DeleteAllRsltItems();
  71. _ASSERT( SUCCEEDED(hr) );
  72. if (!bExpanded) {
  73. // create the child nodes, then expand them
  74. for (int n = 0; n < m_cchildren; n++)
  75. {
  76. BOOL childDeleteStatus = children[n]->getDeletedStatus();
  77. // If the child is deleted by the user do not insert it.
  78. if ( !childDeleteStatus)
  79. {
  80. ZeroMemory(&rdi, sizeof(RESULTDATAITEM) );
  81. rdi.mask = RDI_STR | // Displayname is valid
  82. RDI_IMAGE |
  83. RDI_PARAM; // nImage is valid
  84. rdi.nImage = children[n]->GetBitmapIndex();
  85. rdi.str = MMC_CALLBACK;
  86. rdi.nCol = 0;
  87. rdi.lParam = (LPARAM)children[n];
  88. hr = pResultData->InsertItem( &rdi );
  89. _ASSERT( SUCCEEDED(hr) );
  90. }
  91. }
  92. }
  93. pHeaderCtrl->Release();
  94. pResultData->Release();
  95. }
  96. return hr;
  97. }
  98. HRESULT CSpaceVehicle::OnAddMenuItems(IContextMenuCallback *pContextMenuCallback, long *pInsertionsAllowed)
  99. {
  100. HRESULT hr = S_OK;
  101. CONTEXTMENUITEM menuItemsNew[] =
  102. {
  103. {
  104. L"New future vehicle", L"Add a new future vehicle",
  105. IDM_NEW_SPACE, CCM_INSERTIONPOINTID_PRIMARY_NEW, 0, CCM_SPECIAL_DEFAULT_ITEM
  106. },
  107. { NULL, NULL, 0, 0, 0 }
  108. };
  109. // Loop through and add each of the menu items, we
  110. // want to add to new menu, so see if it is allowed.
  111. if (*pInsertionsAllowed & CCM_INSERTIONALLOWED_NEW)
  112. {
  113. for (LPCONTEXTMENUITEM m = menuItemsNew; m->strName; m++)
  114. {
  115. hr = pContextMenuCallback->AddItem(m);
  116. if (FAILED(hr))
  117. break;
  118. }
  119. }
  120. return hr;
  121. }
  122. HRESULT CSpaceVehicle::OnMenuCommand(IConsole *pConsole, IConsoleNameSpace *pConsoleNameSpace, long lCommandID, IDataObject *pDataObject)
  123. {
  124. switch (lCommandID)
  125. {
  126. case IDM_NEW_SPACE:
  127. if (m_cchildren < MAX_NUMBER_OF_CHILDREN)
  128. { //create new Rocket
  129. children[m_cchildren] = new CRocket(_T("Rocket"), m_cchildren+1, 500000, 265, 75000, this);
  130. pConsole->MessageBox(L"Created a new future vehicle", L"Menu Command", MB_OK|MB_ICONINFORMATION, NULL);
  131. m_cchildren++;
  132. // We created a new object in result pane. We need to insert this object
  133. // in all the views, call UpdateAllViews for this.
  134. // Pass pointer to data object passed into OnMenuCommand.
  135. HRESULT hr;
  136. hr = pConsole->UpdateAllViews(pDataObject, m_hParentHScopeItem, UPDATE_SCOPEITEM);
  137. _ASSERT( S_OK == hr);
  138. }
  139. else
  140. pConsole->MessageBox(L"No more future vehicles allowed", L"Menu Command", MB_OK|MB_ICONWARNING, NULL);
  141. break;
  142. }
  143. return S_OK;
  144. }
  145. //==============================================================
  146. //
  147. // CRocket implementation
  148. //
  149. //
  150. CRocket::CRocket(_TCHAR *szName, int id, LONG lWeight, LONG lHeight, LONG lPayload, CSpaceVehicle *pParent)
  151. : szName(NULL), lWeight(0), lHeight(0), lPayload(0), iStatus(STOPPED), m_pParent(pParent)
  152. {
  153. if (szName) {
  154. this->szName = new _TCHAR[(_tcslen(szName) + 1) * sizeof(_TCHAR)];
  155. _tcscpy(this->szName, szName);
  156. }
  157. this->nId = id;
  158. this->lWeight = lWeight;
  159. this->lHeight = lHeight;
  160. this->lPayload = lPayload;
  161. m_ppHandle = 0;
  162. isDeleted = FALSE;
  163. }
  164. CRocket::~CRocket()
  165. {
  166. if (szName)
  167. delete [] szName;
  168. }
  169. const _TCHAR *CRocket::GetDisplayName(int nCol)
  170. {
  171. static _TCHAR buf[128];
  172. switch (nCol) {
  173. case 0:
  174. _stprintf(buf, _T("%s (#%d)"), szName ? szName : _T(""), nId);
  175. break;
  176. case 1:
  177. _stprintf(buf, _T("%ld metric tons"), lWeight);
  178. break;
  179. case 2:
  180. _stprintf(buf, _T("%ld meters"), lHeight);
  181. break;
  182. case 3:
  183. _stprintf(buf, _T("%ld kilos"), lPayload);
  184. break;
  185. case 4:
  186. _stprintf(buf, _T("%s"),
  187. iStatus == RUNNING ? _T("running") :
  188. iStatus == PAUSED ? _T("paused") :
  189. iStatus == STOPPED ? _T("stopped") : _T("unknown"));
  190. break;
  191. }
  192. return buf;
  193. }
  194. HRESULT CRocket::OnRename(LPOLESTR pszNewName)
  195. {
  196. HRESULT hr = S_FALSE;
  197. if (szName)
  198. {
  199. delete [] szName;
  200. szName = NULL;
  201. }
  202. MAKE_TSTRPTR_FROMWIDE(ptrname, pszNewName);
  203. szName = new _TCHAR[(_tcslen(ptrname) + 1) * sizeof(_TCHAR)];
  204. _tcscpy(szName, ptrname);
  205. return hr;
  206. }
  207. // handle anything special when the user clicks Apply or Ok
  208. // on the property sheet. This sample directly accesses the
  209. // operated-on object, so there's nothing special to do...
  210. // ...except to update all views
  211. HRESULT CRocket::OnPropertyChange(IConsole *pConsole, CComponent *pComponent)
  212. {
  213. HRESULT hr = S_FALSE;
  214. //Call IConsole::UpdateAllViews to redraw the item
  215. //in all views. We need a data object because of the
  216. //way UpdateAllViews is implemented, and because
  217. //MMCN_PROPERTY_CHANGE doesn't give us one
  218. LPDATAOBJECT pDataObject;
  219. hr = pComponent->QueryDataObject((MMC_COOKIE)this, CCT_RESULT, &pDataObject );
  220. _ASSERT( S_OK == hr);
  221. hr = pConsole->UpdateAllViews(pDataObject, nId, UPDATE_RESULTITEM);
  222. _ASSERT( S_OK == hr);
  223. pDataObject->Release();
  224. return hr;
  225. }
  226. HRESULT CRocket::OnSelect(CComponent *pComponent, IConsole *pConsole, BOOL bScope, BOOL bSelect)
  227. {
  228. // enable rename, refresh, and delete verbs
  229. IConsoleVerb *pConsoleVerb;
  230. HRESULT hr = pConsole->QueryConsoleVerb(&pConsoleVerb);
  231. _ASSERT(SUCCEEDED(hr));
  232. hr = pConsoleVerb->SetVerbState(MMC_VERB_RENAME, ENABLED, TRUE);
  233. hr = pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  234. hr = pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE);
  235. // can't get to properties (via the standard methods) unless
  236. // we tell MMC to display the Properties menu item and
  237. // toolbar button, this will give the user a visual cue that
  238. // there's "something" to do
  239. hr = pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
  240. //also set MMC_VERB_PROPERTIES as the default verb
  241. hr = pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES);
  242. pConsoleVerb->Release();
  243. // now set toolbar button states
  244. if (bSelect) {
  245. switch (iStatus)
  246. {
  247. case RUNNING:
  248. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTART, BUTTONPRESSED, TRUE);
  249. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTART, ENABLED, FALSE);
  250. pComponent->getToolbar()->SetButtonState(ID_BUTTONPAUSE, BUTTONPRESSED, FALSE);
  251. pComponent->getToolbar()->SetButtonState(ID_BUTTONPAUSE, ENABLED, TRUE);
  252. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTOP, BUTTONPRESSED, FALSE);
  253. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTOP, ENABLED, TRUE);
  254. break;
  255. case PAUSED:
  256. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTART, BUTTONPRESSED, FALSE);
  257. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTART, ENABLED, TRUE);
  258. pComponent->getToolbar()->SetButtonState(ID_BUTTONPAUSE, BUTTONPRESSED, TRUE);
  259. pComponent->getToolbar()->SetButtonState(ID_BUTTONPAUSE, ENABLED, FALSE);
  260. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTOP, BUTTONPRESSED, FALSE);
  261. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTOP, ENABLED, TRUE);
  262. break;
  263. case STOPPED:
  264. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTART, BUTTONPRESSED, FALSE);
  265. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTART, ENABLED, TRUE);
  266. pComponent->getToolbar()->SetButtonState(ID_BUTTONPAUSE, BUTTONPRESSED, FALSE);
  267. pComponent->getToolbar()->SetButtonState(ID_BUTTONPAUSE, ENABLED, TRUE);
  268. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTOP, BUTTONPRESSED, TRUE);
  269. pComponent->getToolbar()->SetButtonState(ID_BUTTONSTOP, ENABLED, FALSE);
  270. break;
  271. }
  272. }
  273. return S_OK;
  274. }
  275. // Implement the dialog proc
  276. BOOL CALLBACK CRocket::DialogProc(
  277. HWND hwndDlg, // handle to dialog box
  278. UINT uMsg, // message
  279. WPARAM wParam, // first message parameter
  280. LPARAM lParam // second message parameter
  281. )
  282. {
  283. static CRocket *pRocket = NULL;
  284. switch (uMsg) {
  285. case WM_INITDIALOG:
  286. // catch the "this" pointer so we can actually operate on the object
  287. pRocket = reinterpret_cast<CRocket *>(reinterpret_cast<PROPSHEETPAGE *>(lParam)->lParam);
  288. SetDlgItemText(hwndDlg, IDC_ROCKET_NAME, pRocket->szName);
  289. SetDlgItemInt(hwndDlg, IDC_ROCKET_HEIGHT, pRocket->lHeight, FALSE);
  290. SetDlgItemInt(hwndDlg, IDC_ROCKET_WEIGHT, pRocket->lWeight, FALSE);
  291. SetDlgItemInt(hwndDlg, IDC_ROCKET_PAYLOAD, pRocket->lPayload, FALSE);
  292. _ASSERT( CB_ERR != SendDlgItemMessage(hwndDlg, IDC_ROCKET_STATUS, CB_INSERTSTRING, 0, (LPARAM)_T("Running")) );
  293. _ASSERT( CB_ERR != SendDlgItemMessage(hwndDlg, IDC_ROCKET_STATUS, CB_INSERTSTRING, 1, (LPARAM)_T("Paused")) );
  294. _ASSERT( CB_ERR != SendDlgItemMessage(hwndDlg, IDC_ROCKET_STATUS, CB_INSERTSTRING, 2, (LPARAM)_T("Stopped")) );
  295. SendDlgItemMessage(hwndDlg, IDC_ROCKET_STATUS, CB_SETCURSEL, (WPARAM)pRocket->iStatus, 0);
  296. break;
  297. case WM_COMMAND:
  298. // turn the Apply button on
  299. if (HIWORD(wParam) == EN_CHANGE ||
  300. HIWORD(wParam) == CBN_SELCHANGE)
  301. SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
  302. break;
  303. case WM_DESTROY:
  304. // tell MMC that we're done with the property sheet (we got this
  305. // handle in CreatePropertyPages
  306. MMCFreeNotifyHandle(pRocket->m_ppHandle);
  307. break;
  308. case WM_NOTIFY:
  309. switch (((NMHDR *) lParam)->code) {
  310. case PSN_APPLY:
  311. // update the information
  312. if (pRocket->szName) {
  313. delete [] pRocket->szName;
  314. pRocket->szName = NULL;
  315. }
  316. {
  317. int n = SendDlgItemMessage(hwndDlg, IDC_ROCKET_NAME, WM_GETTEXTLENGTH, 0, 0);
  318. if (n != 0) {
  319. pRocket->szName = new _TCHAR[n + 1];
  320. GetDlgItemText(hwndDlg, IDC_ROCKET_NAME, pRocket->szName, n + 1);
  321. }
  322. }
  323. pRocket->lHeight = GetDlgItemInt(hwndDlg, IDC_ROCKET_HEIGHT, NULL, FALSE);
  324. pRocket->lWeight = GetDlgItemInt(hwndDlg, IDC_ROCKET_WEIGHT, NULL, FALSE);
  325. pRocket->lPayload = GetDlgItemInt(hwndDlg, IDC_ROCKET_PAYLOAD, NULL, FALSE);
  326. pRocket->iStatus = (ROCKET_STATUS)SendDlgItemMessage(hwndDlg, IDC_ROCKET_STATUS, CB_GETCURSEL, 0, 0);
  327. // ask MMC to send us a message (on the main thread) so
  328. // we know the Apply button was clicked.
  329. HRESULT hr = MMCPropertyChangeNotify(pRocket->m_ppHandle, (long)pRocket);
  330. _ASSERT(SUCCEEDED(hr));
  331. return PSNRET_NOERROR;
  332. }
  333. break;
  334. }
  335. return DefWindowProc(hwndDlg, uMsg, wParam, lParam);
  336. }
  337. HRESULT CRocket::HasPropertySheets()
  338. {
  339. // say "yes" when MMC asks if we have pages
  340. return S_OK;
  341. }
  342. HRESULT CRocket::CreatePropertyPages(IPropertySheetCallback *lpProvider, LONG_PTR handle)
  343. {
  344. PROPSHEETPAGE psp;
  345. HPROPSHEETPAGE hPage = NULL;
  346. // cache this handle so we can call MMCPropertyChangeNotify
  347. m_ppHandle = handle;
  348. // create the property page for this node.
  349. // NOTE: if your node has multiple pages, put the following
  350. // in a loop and create multiple pages calling
  351. // lpProvider->AddPage() for each page.
  352. psp.dwSize = sizeof(PROPSHEETPAGE);
  353. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USEICONID;
  354. psp.hInstance = g_hinst;
  355. psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_LARGE);
  356. psp.pfnDlgProc = DialogProc;
  357. psp.lParam = reinterpret_cast<LPARAM>(this);
  358. psp.pszTitle = MAKEINTRESOURCE(IDS_PST_ROCKET);
  359. psp.pszIcon = MAKEINTRESOURCE(IDI_PSI_ROCKET);
  360. hPage = CreatePropertySheetPage(&psp);
  361. _ASSERT(hPage);
  362. return lpProvider->AddPage(hPage);
  363. }
  364. HRESULT CRocket::GetWatermarks(HBITMAP *lphWatermark,
  365. HBITMAP *lphHeader,
  366. HPALETTE *lphPalette,
  367. BOOL *bStretch)
  368. {
  369. return S_FALSE;
  370. }
  371. HRESULT CRocket::OnSetToolbar(IControlbar *pControlbar, IToolbar *pToolbar, BOOL bScope, BOOL bSelect)
  372. {
  373. HRESULT hr = S_OK;
  374. if (bSelect) {
  375. // Always make sure the menuButton is attached
  376. hr = pControlbar->Attach(TOOLBAR, pToolbar);
  377. } else {
  378. // Always make sure the toolbar is detached
  379. hr = pControlbar->Detach(pToolbar);
  380. }
  381. return hr;
  382. }
  383. HRESULT CRocket::OnToolbarCommand(IConsole *pConsole, MMC_CONSOLE_VERB verb, IDataObject *pDataObject)
  384. {
  385. _TCHAR szVehicle[128];
  386. static _TCHAR buf[128];
  387. _stprintf(buf, _T("%s (#%d)"), szName ? szName : _T(""), nId);
  388. switch (verb)
  389. {
  390. case ID_BUTTONSTART:
  391. iStatus = RUNNING;
  392. break;
  393. case ID_BUTTONPAUSE:
  394. iStatus = PAUSED;
  395. break;
  396. case ID_BUTTONSTOP:
  397. iStatus = STOPPED;
  398. break;
  399. }
  400. wsprintf(szVehicle, _T("%s has been %s"), buf,
  401. (long)verb == ID_BUTTONSTART ? _T("started") :
  402. (long)verb == ID_BUTTONPAUSE ? _T("paused") :
  403. (long)verb == ID_BUTTONSTOP ? _T("stopped") : _T("!!!unknown command!!!"));
  404. int ret = 0;
  405. MAKE_WIDEPTR_FROMTSTR_ALLOC(wszVehicle, szVehicle);
  406. pConsole->MessageBox(wszVehicle,
  407. L"Vehicle command", MB_OK | MB_ICONINFORMATION, &ret);
  408. // Now call IConsole::UpdateAllViews to redraw the item in all views
  409. HRESULT hr;
  410. hr = pConsole->UpdateAllViews(pDataObject, nId, UPDATE_RESULTITEM);
  411. _ASSERT( S_OK == hr);
  412. return S_OK;
  413. }
  414. HRESULT CRocket::OnUpdateItem(IConsole *pConsole, long item, ITEM_TYPE itemtype)
  415. {
  416. HRESULT hr = S_FALSE;
  417. _ASSERT(NULL != this || isDeleted || RESULT == itemtype);
  418. //redraw the item
  419. IResultData *pResultData = NULL;
  420. hr = pConsole->QueryInterface(IID_IResultData, (void **)&pResultData);
  421. _ASSERT( SUCCEEDED(hr) );
  422. HRESULTITEM myhresultitem;
  423. _ASSERT(NULL != &myhresultitem);
  424. //lparam == this. See CSpaceStation::OnShow
  425. hr = pResultData->FindItemByLParam( (LPARAM)this, &myhresultitem );
  426. if ( FAILED(hr) )
  427. {
  428. // Failed : Reason may be that current view does not have this item.
  429. // So exit gracefully.
  430. hr = S_FALSE;
  431. } else
  432. {
  433. hr = pResultData->UpdateItem( myhresultitem );
  434. _ASSERT( SUCCEEDED(hr) );
  435. }
  436. pResultData->Release();
  437. return hr;
  438. }
  439. HRESULT CRocket::OnRefresh(IConsole *pConsole)
  440. {
  441. //Call IConsole::UpdateAllViews to redraw all views
  442. //owned by the parent scope item
  443. IDataObject *dummy = NULL;
  444. HRESULT hr;
  445. hr = pConsole->UpdateAllViews(dummy, m_pParent->GetParentScopeItem(), UPDATE_SCOPEITEM);
  446. _ASSERT( S_OK == hr);
  447. return hr;
  448. }
  449. HRESULT CRocket::OnDelete(IConsole *pConsoleComp)
  450. {
  451. HRESULT hr;
  452. //Delete the item
  453. IResultData *pResultData = NULL;
  454. hr = pConsoleComp->QueryInterface(IID_IResultData, (void **)&pResultData);
  455. _ASSERT( SUCCEEDED(hr) );
  456. HRESULTITEM myhresultitem;
  457. //lparam == this. See CSpaceVehicle::OnShow
  458. hr = pResultData->FindItemByLParam( (LPARAM)this, &myhresultitem );
  459. if ( FAILED(hr) )
  460. {
  461. // Failed : Reason may be that current view does not have this item.
  462. // So exit gracefully.
  463. hr = S_FALSE;
  464. } else
  465. {
  466. hr = pResultData->DeleteItem( myhresultitem, 0 );
  467. _ASSERT( SUCCEEDED(hr) );
  468. }
  469. pResultData->Release();
  470. //Now set isDeleted member so that the parent doesn't try to
  471. //to insert it again in CSpaceVehicle::OnShow. Admittedly, a hack...
  472. isDeleted = TRUE;
  473. return hr;
  474. }