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.

1466 lines
42 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: proppag_.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //////////////////////////////////////////////////////////////////////////
  11. // private helper functions
  12. BOOL CALLBACK EnumThreadWndProc(HWND hwnd, /* enumerated HWND */
  13. LPARAM lParam /* pass a HWND* for return value*/ )
  14. {
  15. ASSERT(hwnd);
  16. HWND hParentWnd = GetParent(hwnd);
  17. // the main window of the MMC console should staitsfy this condition
  18. if ( ((hParentWnd == GetDesktopWindow()) || (hParentWnd == NULL)) && IsWindowVisible(hwnd) )
  19. {
  20. HWND* pH = (HWND*)lParam;
  21. *pH = hwnd;
  22. return FALSE; // stop enumerating
  23. }
  24. return TRUE;
  25. }
  26. HWND FindMMCMainWindow()
  27. {
  28. DWORD dwThreadID = ::GetCurrentThreadId();
  29. ASSERT(dwThreadID != 0);
  30. HWND hWnd = NULL;
  31. EnumThreadWindows(dwThreadID, EnumThreadWndProc,(LPARAM)&hWnd);
  32. ASSERT(hWnd != NULL);
  33. return hWnd;
  34. }
  35. ////////////////////////////////////////////////////////////////////
  36. // CHiddenWndBase : Utility Hidden Window
  37. BOOL CHiddenWndBase::Create(HWND hWndParent)
  38. {
  39. ASSERT(hWndParent == NULL || ::IsWindow(hWndParent));
  40. RECT rcPos;
  41. ZeroMemory(&rcPos, sizeof(RECT));
  42. HWND hWnd = CWindowImpl<CHiddenWndBase>::Create(hWndParent,
  43. rcPos, //RECT& rcPos,
  44. NULL, //LPCTSTR szWindowName = NULL,
  45. (hWndParent) ? WS_CHILD : WS_POPUP, //DWORD dwStyle = WS_CHILD | WS_VISIBLE,
  46. 0x0, //DWORD dwExStyle = 0,
  47. 0 //UINT nID = 0
  48. );
  49. return hWnd != NULL;
  50. }
  51. /////////////////////////////////////////////////////////////////////////////
  52. // CSheetWnd
  53. const UINT CSheetWnd::s_SheetMessage = WM_USER + 100;
  54. const UINT CSheetWnd::s_SelectPageMessage = WM_USER + 101;
  55. LRESULT CSheetWnd::OnSheetMessage(UINT, WPARAM wParam, LPARAM lParam, BOOL&)
  56. {
  57. ASSERT(m_pHolder != NULL);
  58. m_pHolder->OnSheetMessage(wParam,lParam);
  59. return 1;
  60. }
  61. LRESULT CSheetWnd::OnSelectPageMessage(UINT, WPARAM wParam, LPARAM, BOOL&)
  62. {
  63. TRACE(_T("CSheetWnd::OnSelectPageMessage()\n"));
  64. ASSERT(m_pHolder != NULL);
  65. int nPage = m_pHolder->OnSelectPageMessage((long)wParam);
  66. if (nPage >= 0)
  67. {
  68. // can use SendMessage() because the sheet has been created already
  69. VERIFY(PropSheet_SetCurSel(m_pHolder->m_hSheetWindow, NULL, nPage));
  70. }
  71. ::SetForegroundWindow(::GetParent(m_hWnd));
  72. return 1;
  73. }
  74. LRESULT CSheetWnd::OnClose(UINT, WPARAM, LPARAM, BOOL&)
  75. {
  76. return 1;
  77. }
  78. /////////////////////////////////////////////////////////////////////////////
  79. // CCloseDialogInfo
  80. struct FIND_MSG_BOX_INFO
  81. {
  82. LPCTSTR lpszTitle;
  83. HWND hWnd;
  84. HWND hWndParent;
  85. };
  86. BOOL CALLBACK EnumMessageBoxProc(HWND hwnd, LPARAM lParam)
  87. {
  88. static const size_t BuffSizeInCharacters = 256;
  89. FIND_MSG_BOX_INFO* pInfo = (FIND_MSG_BOX_INFO*)lParam;
  90. if (::GetParent(hwnd) != pInfo->hWndParent)
  91. return TRUE;
  92. TCHAR szTitle[BuffSizeInCharacters] = {0};
  93. ::GetWindowText(hwnd, szTitle, BuffSizeInCharacters);
  94. TRACE(_T("Title <%s>\n"), szTitle);
  95. if (_wcsnicmp(szTitle, pInfo->lpszTitle, BuffSizeInCharacters) == 0)
  96. {
  97. pInfo->hWnd = hwnd;
  98. return FALSE;
  99. }
  100. return TRUE;
  101. }
  102. HWND FindMessageBox(LPCTSTR lpszTitle, HWND hWndParent)
  103. {
  104. FIND_MSG_BOX_INFO info;
  105. info.hWndParent = hWndParent;
  106. info.lpszTitle = lpszTitle;
  107. info.hWnd = NULL;
  108. EnumWindows(EnumMessageBoxProc, (LPARAM)&info);
  109. if (info.hWnd != NULL)
  110. return info.hWnd;
  111. return NULL;
  112. }
  113. BOOL CCloseDialogInfo::CloseMessageBox(HWND hWndParent)
  114. {
  115. BOOL bClosed = FALSE;
  116. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  117. LPCTSTR lpszMsgBoxTitle = AfxGetApp()->m_pszAppName;
  118. HWND hWndMessageBox = FindMessageBox(lpszMsgBoxTitle, hWndParent);
  119. if (hWndMessageBox != NULL)
  120. {
  121. // figure out if there is a cancel button or not
  122. HWND hWndCtrl = ::GetDlgItem(hWndMessageBox, IDCANCEL);
  123. if (hWndCtrl != NULL)
  124. {
  125. VERIFY(::SendMessage(hWndMessageBox, WM_CLOSE, 0, 0) == 0);
  126. bClosed = TRUE;
  127. }
  128. else
  129. {
  130. // does it have just the OK button?
  131. hWndCtrl = ::GetDlgItem(hWndMessageBox, IDOK);
  132. if (hWndCtrl != NULL)
  133. {
  134. VERIFY(::SendMessage(hWndMessageBox, WM_COMMAND, IDOK, 0) == 0);
  135. bClosed = TRUE;
  136. }
  137. else
  138. {
  139. // does it have a NO button?
  140. hWndCtrl = ::GetDlgItem(hWndMessageBox, IDNO);
  141. if (hWndCtrl != NULL)
  142. {
  143. VERIFY(::SendMessage(hWndMessageBox, WM_COMMAND, IDNO, 0) == 0);
  144. bClosed = TRUE;
  145. }
  146. }
  147. }
  148. }
  149. return bClosed;
  150. }
  151. BOOL CCloseDialogInfo::CloseDialog(BOOL bCheckForMsgBox)
  152. {
  153. if (bCheckForMsgBox)
  154. CloseMessageBox(m_hWnd);
  155. return (::SendMessage(m_hWnd, WM_CLOSE, 0, 0) == 0);
  156. }
  157. /////////////////////////////////////////////////////////////////////////////
  158. // CPropertyPageHolderBase
  159. CPropertyPageHolderBase::CPropertyPageHolderBase(CContainerNode* pContNode, CTreeNode* pNode,
  160. CComponentDataObject* pComponentData)
  161. {
  162. m_szSheetTitle = (LPCWSTR)NULL;
  163. m_pDummySheet = NULL;
  164. // default setting for a self deleting modeless property sheet,
  165. // automatically deleting all the pages
  166. m_bWizardMode = FALSE;
  167. m_bAutoDelete = TRUE;
  168. m_bAutoDeletePages = TRUE;
  169. m_forceContextHelpButton = useDefault;
  170. m_pContHolder = NULL;
  171. m_nCreatedCount = 0;
  172. m_hSheetWindow = NULL;
  173. m_pSheetWnd = NULL;
  174. m_nStartPageCode = -1; // not set
  175. m_hConsoleHandle = 0;
  176. m_hEventHandle = NULL;
  177. m_pSheetCallback = NULL;
  178. // setup from arguments
  179. // For tasks in can be null ASSERT(pContNode != NULL); // must always have a valid container node to refer to
  180. m_pContNode = pContNode;
  181. ASSERT((pNode == NULL) || (pNode->GetContainer() == m_pContNode) );
  182. m_pNode = pNode;
  183. ASSERT(pComponentData != NULL);
  184. m_pComponentData = pComponentData;
  185. m_hMainWnd = NULL;
  186. LPCONSOLE pConsole = m_pComponentData->GetConsole();
  187. if (pConsole != NULL)
  188. {
  189. pConsole->GetMainWindow(&m_hMainWnd);
  190. }
  191. m_dwLastErr = 0x0;
  192. m_pPropChangePage = NULL;
  193. m_pWatermarkInfo = NULL;
  194. }
  195. CPropertyPageHolderBase::~CPropertyPageHolderBase()
  196. {
  197. FinalDestruct();
  198. ASSERT(m_pSheetWnd == NULL);
  199. SAFE_RELEASE(m_pSheetCallback);
  200. if (m_hEventHandle != NULL)
  201. {
  202. VERIFY(::CloseHandle(m_hEventHandle));
  203. m_hEventHandle = NULL;
  204. }
  205. if (m_pDummySheet != NULL)
  206. delete m_pDummySheet;
  207. }
  208. void CPropertyPageHolderBase::Attach(CPropertyPageHolderBase* pContHolder)
  209. {
  210. ASSERT( (m_pContHolder == NULL) && (pContHolder != NULL) );
  211. m_pContHolder = pContHolder;
  212. m_bWizardMode = pContHolder->IsWizardMode();
  213. }
  214. BOOL CPropertyPageHolderBase::EnableSheetControl(UINT nCtrlID, BOOL bEnable)
  215. {
  216. if (m_pContHolder != NULL)
  217. {
  218. return m_pContHolder->EnableSheetControl(nCtrlID, bEnable);
  219. }
  220. ASSERT(::IsWindow(m_hSheetWindow));
  221. HWND hWndCtrl = ::GetDlgItem(m_hSheetWindow, nCtrlID);
  222. if (hWndCtrl == NULL)
  223. return FALSE;
  224. return ::EnableWindow(hWndCtrl, bEnable);
  225. }
  226. HRESULT CPropertyPageHolderBase::CreateModelessSheet(CTreeNode* pNode, CComponentDataObject* pComponentData)
  227. {
  228. ASSERT(pNode != NULL);
  229. ASSERT(pComponentData != NULL);
  230. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  231. // get an interface to a sheet provider
  232. IPropertySheetProvider* pSheetProvider;
  233. HRESULT hr = pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetProvider,(void**)&pSheetProvider);
  234. ASSERT(SUCCEEDED(hr));
  235. ASSERT(pSheetProvider != NULL);
  236. // get an interface to a sheet callback
  237. IPropertySheetCallback* pSheetCallback;
  238. hr = pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetCallback,(void**)&pSheetCallback);
  239. ASSERT(SUCCEEDED(hr));
  240. ASSERT(pSheetCallback != NULL);
  241. // create a data object for this node
  242. IDataObject* pDataObject;
  243. hr = pComponentData->QueryDataObject((MMC_COOKIE)pNode, CCT_SCOPE, &pDataObject);
  244. ASSERT(SUCCEEDED(hr));
  245. ASSERT(pDataObject != NULL);
  246. // get a sheet
  247. hr = pSheetProvider->CreatePropertySheet(_T("SHEET TITLE"), TRUE, (MMC_COOKIE)pNode, pDataObject, 0x0 /*dwOptions*/);
  248. ASSERT(SUCCEEDED(hr));
  249. pDataObject->Release();
  250. HWND hWnd = NULL;
  251. hr = pComponentData->GetConsole()->GetMainWindow(&hWnd);
  252. ASSERT(SUCCEEDED(hr));
  253. ASSERT(hWnd == ::FindMMCMainWindow());
  254. IUnknown* pUnkComponentData = pComponentData->GetUnknown(); // no addref
  255. hr = pSheetProvider->AddPrimaryPages(pUnkComponentData,
  256. TRUE /*bCreateHandle*/,
  257. hWnd,
  258. TRUE /* bScopePane*/);
  259. ASSERT(SUCCEEDED(hr));
  260. hr = pSheetProvider->Show(reinterpret_cast<LONG_PTR>(hWnd), 0);
  261. ASSERT(SUCCEEDED(hr));
  262. // final interface release
  263. pSheetProvider->Release();
  264. pSheetCallback->Release();
  265. return hr;
  266. }
  267. HRESULT CPropertyPageHolderBase::CreateModelessSheet(CTreeNode* pCookieNode)
  268. {
  269. ASSERT(!IsWizardMode());
  270. ASSERT(m_pContHolder == NULL);
  271. ASSERT(m_pComponentData != NULL);
  272. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  273. // get an interface to a sheet provider
  274. IPropertySheetProvider* pSheetProvider;
  275. HRESULT hr = m_pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetProvider,(void**)&pSheetProvider);
  276. ASSERT(SUCCEEDED(hr));
  277. ASSERT(pSheetProvider != NULL);
  278. // get an interface to a sheet callback
  279. IPropertySheetCallback* pSheetCallback;
  280. hr = m_pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetCallback,(void**)&pSheetCallback);
  281. ASSERT(SUCCEEDED(hr));
  282. ASSERT(pSheetCallback != NULL);
  283. // create a data object for this node
  284. IDataObject* pDataObject;
  285. hr = m_pComponentData->QueryDataObject((MMC_COOKIE)pCookieNode, CCT_SCOPE, &pDataObject);
  286. ASSERT(SUCCEEDED(hr));
  287. ASSERT(pDataObject != NULL);
  288. // get a sheet
  289. hr = pSheetProvider->CreatePropertySheet(m_szSheetTitle, TRUE, (MMC_COOKIE)pCookieNode, pDataObject, 0x0 /*dwOptions*/);
  290. ASSERT(SUCCEEDED(hr));
  291. pDataObject->Release();
  292. HWND hWnd = GetMainWindow();
  293. ASSERT(hWnd == ::FindMMCMainWindow());
  294. IUnknown* pUnkComponentData = m_pComponentData->GetUnknown(); // no addref
  295. hr = pSheetProvider->AddPrimaryPages(pUnkComponentData,
  296. TRUE /*bCreateHandle*/,
  297. NULL /*hWnd*/,
  298. FALSE /* bScopePane*/);
  299. ASSERT(SUCCEEDED(hr));
  300. hr = pSheetProvider->Show(reinterpret_cast<LONG_PTR>(hWnd), 0);
  301. ASSERT(SUCCEEDED(hr));
  302. // final interface release
  303. pSheetProvider->Release();
  304. pSheetCallback->Release();
  305. return hr;
  306. }
  307. HRESULT CPropertyPageHolderBase::CreateModelessSheet(LPPROPERTYSHEETCALLBACK pSheetCallback, LONG_PTR hConsoleHandle)
  308. {
  309. ASSERT(m_pContHolder == NULL);
  310. ASSERT(pSheetCallback != NULL);
  311. ASSERT(m_pSheetCallback == NULL);
  312. //
  313. // REVIEW_JEFFJON : seems to be NULL when called from CComponentDataObject::CreatePropertySheet()
  314. //
  315. m_hConsoleHandle = hConsoleHandle;
  316. m_bWizardMode = FALSE; // we go modeless
  317. ASSERT(m_pNode != NULL);
  318. CPropertyPageHolderTable* pPPHTable = m_pComponentData->GetPropertyPageHolderTable();
  319. ASSERT(pPPHTable != NULL);
  320. // add the property sheet holder to the holder table
  321. pPPHTable->Add(this);
  322. // notify the node it has a sheet up
  323. m_pNode->OnCreateSheet();
  324. // temporarily attach the sheet callback to this object to add pages
  325. // do not addref, we will not hold on to it;
  326. m_pSheetCallback = pSheetCallback;
  327. HRESULT hr = AddAllPagesToSheet();
  328. m_pSheetCallback = NULL; // detach
  329. return hr;
  330. }
  331. void CPropertyPageHolderBase::SetWatermarkInfo(CWatermarkInfo* pWatermarkInfo)
  332. {
  333. ASSERT(m_pWatermarkInfo == NULL);
  334. ASSERT(pWatermarkInfo != NULL);
  335. }
  336. HRESULT CPropertyPageHolderBase::DoModalWizard()
  337. {
  338. ASSERT(m_pContHolder == NULL);
  339. ASSERT(m_pComponentData != NULL);
  340. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  341. m_bWizardMode = TRUE;
  342. // get an interface to a sheet provider
  343. IPropertySheetProvider* pSheetProvider;
  344. HRESULT hr = m_pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetProvider,(void**)&pSheetProvider);
  345. ASSERT(SUCCEEDED(hr));
  346. ASSERT(pSheetProvider != NULL);
  347. // get an interface to a sheet callback
  348. IPropertySheetCallback* pSheetCallback;
  349. hr = m_pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetCallback,(void**)&pSheetCallback);
  350. ASSERT(SUCCEEDED(hr));
  351. ASSERT(pSheetCallback != NULL);
  352. m_pSheetCallback = pSheetCallback; // save to add/remove pages
  353. // Create a dummy data object. AddPrimaryPages will call
  354. // IextendPropertySheet2::QueryPagesFor() and
  355. // IextendPropertySheet2::CreatePropertyPages()
  356. // that will ignore the un-initialized data object
  357. MMC_COOKIE cookie = -1;
  358. DATA_OBJECT_TYPES type = CCT_UNINITIALIZED;
  359. IDataObject* pDataObject;
  360. hr = m_pComponentData->QueryDataObject(cookie, type, &pDataObject);
  361. ASSERT(SUCCEEDED(hr));
  362. ASSERT(pDataObject != NULL);
  363. // Switch Watermark information, AddPrimaryPages will call
  364. // IextendPropertySheet2::GetWatermarks()
  365. CWatermarkInfo* pOldWatermarkInfo = NULL;
  366. if (m_pWatermarkInfo != NULL)
  367. pOldWatermarkInfo = m_pComponentData->SetWatermarkInfo(m_pWatermarkInfo);
  368. // create sheet
  369. hr = pSheetProvider->CreatePropertySheet( m_szSheetTitle, FALSE /* wizard*/,
  370. (MMC_COOKIE)cookie, pDataObject, MMC_PSO_NEWWIZARDTYPE /*dwOptions*/);
  371. ASSERT(SUCCEEDED(hr));
  372. // add pages to sheet
  373. hr = AddAllPagesToSheet();
  374. ASSERT(SUCCEEDED(hr));
  375. // add pages
  376. hr = pSheetProvider->AddPrimaryPages((IExtendPropertySheet2*)m_pComponentData, FALSE, NULL,FALSE);
  377. ASSERT(SUCCEEDED(hr));
  378. // restore the old watermark info
  379. if (pOldWatermarkInfo != NULL)
  380. m_pComponentData->SetWatermarkInfo(pOldWatermarkInfo);
  381. // for further dynamic page manipulation, don't use the Console's sheet callback interface
  382. // but resurt to the Win32 API's
  383. m_pSheetCallback->Release();
  384. m_pSheetCallback = NULL;
  385. // show the modal wizard
  386. HWND hWnd = GetMainWindow();
  387. ASSERT(hWnd != NULL);
  388. hr = pSheetProvider->Show((LONG_PTR)hWnd, 0);
  389. ASSERT(SUCCEEDED(hr));
  390. pSheetProvider->Release();
  391. pDataObject->Release();
  392. return hr;
  393. }
  394. INT_PTR CPropertyPageHolderBase::DoModalDialog(LPCTSTR pszCaption)
  395. {
  396. ASSERT(m_pDummySheet == NULL);
  397. m_bWizardMode = TRUE;
  398. m_bAutoDelete = FALSE; // use on the stack
  399. m_pDummySheet = new CPropertySheet();
  400. m_pDummySheet->m_psh.dwFlags |= PSH_NOAPPLYNOW;
  401. m_pDummySheet->m_psh.pszCaption = pszCaption;
  402. VERIFY(SUCCEEDED(AddAllPagesToSheet()));
  403. return m_pDummySheet->DoModal();
  404. }
  405. void CPropertyPageHolderBase::SetSheetWindow(HWND hSheetWindow)
  406. {
  407. ASSERT(hSheetWindow != NULL);
  408. if (m_pContHolder != NULL)
  409. {
  410. // we will use the HWND of the parent holder
  411. m_pContHolder->SetSheetWindow(hSheetWindow);
  412. return;
  413. }
  414. ASSERT( (m_hSheetWindow == NULL) || ((m_hSheetWindow == hSheetWindow)) );
  415. m_hSheetWindow = hSheetWindow;
  416. if (IsWizardMode())
  417. {
  418. if (m_forceContextHelpButton != useDefault)
  419. {
  420. DWORD dwStyle = ::GetWindowLong(m_hSheetWindow, GWL_EXSTYLE);
  421. if (m_forceContextHelpButton == forceOn)
  422. {
  423. dwStyle |= WS_EX_CONTEXTHELP; // force the [?] button
  424. }
  425. else
  426. {
  427. ASSERT(m_forceContextHelpButton == forceOff);
  428. dwStyle &= ~WS_EX_CONTEXTHELP; // get rid of the [?] button
  429. }
  430. ::SetWindowLong(m_hSheetWindow, GWL_EXSTYLE, dwStyle);
  431. }
  432. if (m_pDummySheet != NULL)
  433. {
  434. VERIFY(PushDialogHWnd(m_hSheetWindow));
  435. }
  436. return;
  437. }
  438. // hook up hidden window only when in sheet mode
  439. if(m_pSheetWnd == NULL)
  440. {
  441. CWinApp* pApp = AfxGetApp();
  442. ASSERT(pApp);
  443. ASSERT(!IsWizardMode());
  444. m_pSheetWnd = new CSheetWnd(this);
  445. VERIFY(m_pSheetWnd->Create(hSheetWindow));
  446. ASSERT(::GetParent(m_pSheetWnd->m_hWnd) == hSheetWindow);
  447. GetComponentData()->OnCreateSheet(this, m_pSheetWnd->m_hWnd);
  448. if (m_nStartPageCode > -1)
  449. {
  450. // we do a PostMessage() because we are in to middle of a page creation
  451. // and MFC does not digest this
  452. ::PostMessage(m_hSheetWindow, PSM_SETCURSEL, OnSelectPageMessage(m_nStartPageCode), NULL);
  453. }
  454. // if needed, set the wizard title
  455. if (!m_szSheetTitle.IsEmpty())
  456. {
  457. ::SetWindowText(m_hSheetWindow, (LPCWSTR)m_szSheetTitle);
  458. }
  459. }
  460. }
  461. void CPropertyPageHolderBase::SetSheetTitle(LPCWSTR lpszSheetTitle)
  462. {
  463. ASSERT(!IsWizardMode());
  464. if (m_pContHolder != NULL)
  465. {
  466. // defer to parent holder
  467. m_pContHolder->SetSheetTitle(lpszSheetTitle);
  468. return;
  469. }
  470. m_szSheetTitle = lpszSheetTitle;
  471. // if the sheet has been created already, set right away
  472. if (m_hSheetWindow != NULL && !m_szSheetTitle.IsEmpty())
  473. {
  474. ::SetWindowText(m_hSheetWindow, (LPCWSTR)m_szSheetTitle);
  475. }
  476. }
  477. void CPropertyPageHolderBase::SetSheetTitle(UINT nStringFmtID, CTreeNode* pNode)
  478. {
  479. ASSERT(!IsWizardMode());
  480. if (m_pContHolder != NULL)
  481. {
  482. // defer to parent holder
  483. m_pContHolder->SetSheetTitle(nStringFmtID, pNode);
  484. return;
  485. }
  486. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  487. CString szFmt;
  488. VERIFY(szFmt.LoadString(nStringFmtID));
  489. m_szSheetTitle.Format((LPCWSTR)szFmt, pNode->GetDisplayName());
  490. // if the sheet has been created already, set right away
  491. if (m_hSheetWindow != NULL && !m_szSheetTitle.IsEmpty())
  492. {
  493. ::SetWindowText(m_hSheetWindow, (LPCWSTR)m_szSheetTitle);
  494. }
  495. }
  496. void CPropertyPageHolderBase::AddRef()
  497. {
  498. if(m_pContHolder != NULL)
  499. {
  500. m_pContHolder->AddRef();
  501. return;
  502. }
  503. m_nCreatedCount++;
  504. }
  505. void CPropertyPageHolderBase::Release()
  506. {
  507. if(m_pContHolder != NULL)
  508. {
  509. m_pContHolder->Release();
  510. return;
  511. }
  512. m_nCreatedCount--;
  513. if (m_nCreatedCount > 0)
  514. return;
  515. if(IsWizardMode())
  516. {
  517. if (m_pDummySheet != NULL)
  518. VERIFY(PopDialogHWnd());
  519. }
  520. else
  521. {
  522. // hidden window created only in sheet mode
  523. if (m_pSheetWnd != NULL)
  524. {
  525. if (m_pSheetWnd->m_hWnd != NULL)
  526. m_pSheetWnd->DestroyWindow();
  527. }
  528. }
  529. if (m_bAutoDelete)
  530. delete this;
  531. }
  532. BOOL CPropertyPageHolderBase::IsWizardMode()
  533. {
  534. if(m_pContHolder != NULL)
  535. {
  536. return m_pContHolder->IsWizardMode();
  537. }
  538. return m_bWizardMode;
  539. }
  540. BOOL CPropertyPageHolderBase::IsModalSheet()
  541. {
  542. if(m_pContHolder != NULL)
  543. {
  544. return m_pContHolder->IsModalSheet();
  545. }
  546. return m_pDummySheet != NULL;
  547. }
  548. void CPropertyPageHolderBase::ForceDestroy()
  549. {
  550. ASSERT(!IsWizardMode()); // should never occur on modal wizard
  551. // contained by other holder
  552. if (m_pContHolder != NULL)
  553. {
  554. ASSERT(!m_bAutoDelete); // container responsible for deleting this holder
  555. m_pContHolder->ForceDestroy();
  556. return;
  557. }
  558. // this is the primary holder
  559. ASSERT(m_bAutoDelete); // should be self deleting sheet
  560. HWND hSheetWindow = m_hSheetWindow;
  561. if (hSheetWindow != NULL)
  562. {
  563. ASSERT(::IsWindow(hSheetWindow));
  564. // this message will cause the sheet to close all the pages,
  565. // and eventually the destruction of "this"
  566. VERIFY(::PostMessage(hSheetWindow, WM_COMMAND, IDCANCEL, 0L) != 0);
  567. }
  568. else
  569. {
  570. // explicitely delete "this", there is no sheet created
  571. delete this;
  572. }
  573. }
  574. DWORD CPropertyPageHolderBase::NotifyConsole(CPropertyPageBase* pPage)
  575. {
  576. if(m_pContHolder != NULL)
  577. {
  578. return m_pContHolder->NotifyConsole(pPage);
  579. }
  580. ASSERT(m_pNode != NULL);
  581. if (IsWizardMode())
  582. {
  583. ASSERT(m_hConsoleHandle == NULL);
  584. return 0x0;
  585. }
  586. m_pPropChangePage = pPage; // to pass to the main thread
  587. m_dwLastErr = 0x0;
  588. if (m_hEventHandle == NULL)
  589. {
  590. // REVIEWED-2002/03/08-JeffJon-Squatting isn't an issue here because this is not a
  591. // named event
  592. m_hEventHandle = ::CreateEvent(NULL,TRUE /*bManualReset*/,FALSE /*signalled*/, NULL);
  593. ASSERT(m_hEventHandle != NULL);
  594. }
  595. if (m_hConsoleHandle != NULL)
  596. {
  597. MMCPropertyChangeNotify(m_hConsoleHandle, reinterpret_cast<LPARAM>(this));
  598. DWORD dwRet;
  599. do
  600. {
  601. ASSERT(::IsWindow(m_hSheetWindow));
  602. dwRet = MsgWaitForMultipleObjects(1,&m_hEventHandle,FALSE,INFINITE, QS_SENDMESSAGE);
  603. if(dwRet == (WAIT_OBJECT_0+1))
  604. {
  605. MSG tempMSG;
  606. PeekMessage(&tempMSG,m_hSheetWindow,0,0,PM_NOREMOVE);
  607. }
  608. }
  609. while(dwRet == (WAIT_OBJECT_0+1));
  610. }
  611. VERIFY(0 != ::ResetEvent(m_hEventHandle));
  612. m_pPropChangePage = NULL; // reset
  613. return m_dwLastErr;
  614. }
  615. void CPropertyPageHolderBase::AcknowledgeNotify()
  616. {
  617. if(m_pContHolder != NULL)
  618. {
  619. m_pContHolder->AcknowledgeNotify();
  620. return;
  621. }
  622. ASSERT(!IsWizardMode());
  623. ASSERT(m_hEventHandle != NULL);
  624. //TRACE(_T("before SetEvent\n"));
  625. VERIFY(0 != ::SetEvent(m_hEventHandle));
  626. //TRACE(_T("after SetEvent\n"));
  627. }
  628. BOOL CPropertyPageHolderBase::OnPropertyChange(BOOL bScopePane, long* pChangeMask)
  629. {
  630. ASSERT(!IsWizardMode());
  631. CPropertyPageBase* pPage = GetPropChangePage();
  632. if (pPage == NULL)
  633. return FALSE;
  634. return pPage->OnPropertyChange(bScopePane, pChangeMask);
  635. }
  636. BOOL CPropertyPageHolderBase::SetWizardButtons(DWORD dwFlags)
  637. {
  638. ASSERT(IsWizardMode());
  639. if (m_pContHolder != NULL)
  640. {
  641. ASSERT(m_hSheetWindow == NULL);
  642. return m_pContHolder->SetWizardButtons(dwFlags);
  643. }
  644. ASSERT(::IsWindow(m_hSheetWindow));
  645. return (BOOL)SendMessage(m_hSheetWindow, PSM_SETWIZBUTTONS, 0, dwFlags);
  646. }
  647. HRESULT CPropertyPageHolderBase::AddPageToSheet(CPropertyPageBase* pPage)
  648. {
  649. if (m_pContHolder != NULL)
  650. {
  651. ASSERT(m_hSheetWindow == NULL);
  652. return m_pContHolder->AddPageToSheet(pPage);
  653. }
  654. CWinApp* pApp = AfxGetApp();
  655. ASSERT(pApp);
  656. if (m_pSheetCallback != NULL)
  657. {
  658. VERIFY(SUCCEEDED(MMCPropPageCallback((void*)(&pPage->m_psp97))));
  659. }
  660. HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(&pPage->m_psp97);
  661. if (hPage == NULL)
  662. return E_UNEXPECTED;
  663. pPage->m_hPage = hPage;
  664. if (m_pSheetCallback != NULL)
  665. return m_pSheetCallback->AddPage(hPage);
  666. else if (m_pDummySheet != NULL)
  667. {
  668. m_pDummySheet->AddPage(pPage);
  669. return S_OK;
  670. }
  671. else
  672. {
  673. ASSERT(::IsWindow(m_hSheetWindow));
  674. return PropSheet_AddPage(m_hSheetWindow, hPage) ? S_OK : E_FAIL;
  675. }
  676. }
  677. HRESULT CPropertyPageHolderBase::AddPageToSheetRaw(HPROPSHEETPAGE hPage)
  678. {
  679. ASSERT(m_pSheetCallback != NULL);
  680. if ((hPage == NULL) || (m_pSheetCallback == NULL))
  681. return E_INVALIDARG;
  682. if (m_pContHolder != NULL)
  683. {
  684. ASSERT(m_hSheetWindow == NULL);
  685. return m_pContHolder->AddPageToSheetRaw(hPage);
  686. }
  687. // assume this is not a n MFC property page
  688. return m_pSheetCallback->AddPage(hPage);
  689. }
  690. HRESULT CPropertyPageHolderBase::RemovePageFromSheet(CPropertyPageBase* pPage)
  691. {
  692. if (m_pContHolder != NULL)
  693. {
  694. ASSERT(m_hSheetWindow == NULL);
  695. return m_pContHolder->RemovePageFromSheet(pPage);
  696. }
  697. ASSERT(pPage->m_hPage != NULL);
  698. if (m_pSheetCallback != NULL)
  699. return m_pSheetCallback->RemovePage(pPage->m_hPage);
  700. else
  701. {
  702. ASSERT(::IsWindow(m_hSheetWindow));
  703. PropSheet_RemovePage(m_hSheetWindow, 0, pPage->m_hPage); // returns void
  704. return S_OK;
  705. }
  706. }
  707. HRESULT CPropertyPageHolderBase::AddAllPagesToSheet()
  708. {
  709. POSITION pos;
  710. int nPage = 0;
  711. HRESULT hr = OnAddPage(nPage, NULL); // zero means add before the first
  712. ASSERT(SUCCEEDED(hr));
  713. if (FAILED(hr))
  714. return hr;
  715. for( pos = m_pageList.GetHeadPosition(); pos != NULL; )
  716. {
  717. CPropertyPageBase* pPropPage = m_pageList.GetNext(pos);
  718. hr = AddPageToSheet(pPropPage);
  719. ASSERT(SUCCEEDED(hr));
  720. if (FAILED(hr))
  721. return hr;
  722. nPage++;
  723. hr = OnAddPage(nPage, pPropPage); // get called on nPage == 1,2, n-1
  724. ASSERT(SUCCEEDED(hr));
  725. if (FAILED(hr))
  726. return hr;
  727. }
  728. // add after the last
  729. return OnAddPage(-1, NULL); // -1 means
  730. }
  731. void CPropertyPageHolderBase::AddPageToList(CPropertyPageBase* pPage)
  732. {
  733. ASSERT(pPage != NULL);
  734. pPage->SetHolder(this);
  735. m_pageList.AddTail(pPage);
  736. }
  737. BOOL CPropertyPageHolderBase::RemovePageFromList(CPropertyPageBase* pPage, BOOL bDeleteObject)
  738. {
  739. ASSERT(pPage != NULL);
  740. POSITION pos = m_pageList.Find(pPage);
  741. if (pos == NULL)
  742. return FALSE;
  743. m_pageList.RemoveAt(pos);
  744. if (bDeleteObject)
  745. delete pPage;
  746. return TRUE;
  747. }
  748. void CPropertyPageHolderBase::DeleteAllPages()
  749. {
  750. if (!m_bAutoDeletePages)
  751. return;
  752. // assume all pages out of the heap
  753. while (!m_pageList.IsEmpty())
  754. {
  755. delete m_pageList.RemoveTail();
  756. }
  757. }
  758. void CPropertyPageHolderBase::FinalDestruct()
  759. {
  760. DeleteAllPages();
  761. if (IsWizardMode() || (m_pContHolder != NULL))
  762. return;
  763. if (m_hConsoleHandle != NULL)
  764. {
  765. MMCFreeNotifyHandle(m_hConsoleHandle);
  766. }
  767. // tell the component data object that the sheet is going away
  768. GetComponentData()->OnDeleteSheet(this,m_pNode);
  769. if (m_pSheetWnd != NULL)
  770. {
  771. delete m_pSheetWnd;
  772. m_pSheetWnd = NULL;
  773. }
  774. ASSERT(m_dlgInfoStack.IsEmpty());
  775. }
  776. BOOL CPropertyPageHolderBase::PushDialogHWnd(HWND hWndModalDlg)
  777. {
  778. return m_dlgInfoStack.Push(hWndModalDlg, 0x0);
  779. }
  780. BOOL CPropertyPageHolderBase::PopDialogHWnd()
  781. {
  782. return m_dlgInfoStack.Pop();
  783. }
  784. void CPropertyPageHolderBase::CloseModalDialogs(HWND hWndPage)
  785. {
  786. m_dlgInfoStack.ForceClose(hWndPage);
  787. }
  788. /////////////////////////////////////////////////////////////////////////////
  789. // CPropertyPageBase
  790. BEGIN_MESSAGE_MAP(CPropertyPageBase, CPropertyPage)
  791. ON_WM_CREATE()
  792. ON_WM_DESTROY()
  793. ON_WM_CONTEXTMENU()
  794. ON_MESSAGE(WM_HELP, OnHelp)
  795. ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
  796. END_MESSAGE_MAP()
  797. CPropertyPageBase::CPropertyPageBase(UINT nIDTemplate,
  798. UINT nIDCaption) :
  799. CPropertyPage(nIDTemplate, nIDCaption)
  800. {
  801. m_hPage = NULL;
  802. m_pPageHolder = NULL;
  803. m_bIsDirty = FALSE;
  804. m_nPrevPageID = 0;
  805. // hack to have new struct size with old MFC and new NT 5.0 headers
  806. ZeroMemory(&m_psp97, sizeof(PROPSHEETPAGE));
  807. // REVIEWED-2002/03/08-JeffJon-This is acceptable usage
  808. memcpy(&m_psp97, &m_psp, m_psp.dwSize);
  809. m_psp97.dwSize = sizeof(PROPSHEETPAGE);
  810. }
  811. CPropertyPageBase::~CPropertyPageBase()
  812. {
  813. }
  814. int CPropertyPageBase::OnCreate(LPCREATESTRUCT lpCreateStruct)
  815. {
  816. m_pPageHolder->AddRef();
  817. int res = CPropertyPage::OnCreate(lpCreateStruct);
  818. ASSERT(res == 0);
  819. ASSERT(m_hWnd != NULL);
  820. ASSERT(::IsWindow(m_hWnd));
  821. HWND hParent = ::GetParent(m_hWnd);
  822. ASSERT(hParent);
  823. m_pPageHolder->SetSheetWindow(hParent);
  824. return res;
  825. }
  826. void CPropertyPageBase::OnDestroy()
  827. {
  828. ASSERT(m_hWnd != NULL);
  829. CPropertyPage::OnDestroy();
  830. m_pPageHolder->Release();
  831. }
  832. void CPropertyPageBase::OnWhatsThis()
  833. {
  834. //
  835. // Display context help for a control
  836. //
  837. if ( m_hWndWhatsThis )
  838. {
  839. //
  840. // Build our own HELPINFO struct to pass to the underlying
  841. // CS help functions built into the framework
  842. //
  843. int iCtrlID = ::GetDlgCtrlID(m_hWndWhatsThis);
  844. HELPINFO helpInfo;
  845. ZeroMemory(&helpInfo, sizeof(HELPINFO));
  846. helpInfo.cbSize = sizeof(HELPINFO);
  847. helpInfo.hItemHandle = m_hWndWhatsThis;
  848. helpInfo.iCtrlId = iCtrlID;
  849. m_pPageHolder->GetComponentData()->OnDialogContextHelp(m_nIDHelp, &helpInfo);
  850. }
  851. }
  852. BOOL CPropertyPageBase::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
  853. {
  854. const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  855. if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
  856. {
  857. //
  858. // Display context help for a control
  859. //
  860. m_pPageHolder->GetComponentData()->OnDialogContextHelp(m_nIDHelp, pHelpInfo);
  861. }
  862. return TRUE;
  863. }
  864. void CPropertyPageBase::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
  865. {
  866. //
  867. // point is in screen coordinates
  868. //
  869. CMenu bar;
  870. if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
  871. {
  872. CMenu& popup = *bar.GetSubMenu (0);
  873. ASSERT(popup.m_hMenu);
  874. if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
  875. point.x, // in screen coordinates
  876. point.y, // in screen coordinates
  877. this) ) // route commands through main window
  878. {
  879. m_hWndWhatsThis = 0;
  880. ScreenToClient (&point);
  881. CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
  882. CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
  883. if ( pChild )
  884. {
  885. m_hWndWhatsThis = pChild->m_hWnd;
  886. }
  887. }
  888. }
  889. }
  890. BOOL CPropertyPageBase::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  891. {
  892. NMHDR* hdr = reinterpret_cast<NMHDR*>(lParam);
  893. if (hdr &&
  894. hdr->code == PSN_HELP)
  895. {
  896. OnWizardHelp();
  897. }
  898. return CPropertyPage::OnNotify(wParam, lParam, pResult);
  899. }
  900. void CPropertyPageBase::OnCancel()
  901. {
  902. CString szTitle;
  903. GetWindowText(szTitle);
  904. TRACE(_T("CPropertyPageBase::OnCancel()called on <%s>\n"),(LPCTSTR)szTitle);
  905. CWinApp* pApp = AfxGetApp();
  906. ASSERT(pApp);
  907. ASSERT(::IsWindow(m_hWnd));
  908. m_pPageHolder->CloseModalDialogs(m_hWnd);
  909. }
  910. BOOL CPropertyPageBase::OnApply()
  911. {
  912. if (IsDirty())
  913. {
  914. if (m_pPageHolder->NotifyConsole(this) == 0x0)
  915. {
  916. SetDirty(FALSE);
  917. return TRUE;
  918. }
  919. else
  920. {
  921. #ifdef _DEBUG
  922. // test only
  923. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  924. AfxMessageBox(_T("Apply Failed"));
  925. #endif
  926. return FALSE;
  927. }
  928. }
  929. return TRUE;
  930. }
  931. void CPropertyPageBase::SetDirty(BOOL bDirty)
  932. {
  933. if (!m_pPageHolder->IsWizardMode())
  934. {
  935. SetModified(bDirty);
  936. }
  937. m_bIsDirty = bDirty;
  938. }
  939. void CPropertyPageBase::InitWiz97(BOOL bHideHeader,
  940. UINT nIDHeaderTitle,
  941. UINT nIDHeaderSubTitle,
  942. bool hasHelp)
  943. {
  944. if (bHideHeader)
  945. {
  946. // for first and last page of the wizard
  947. m_psp97.dwFlags |= PSP_HIDEHEADER;
  948. }
  949. else
  950. {
  951. // for intermediate pages
  952. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  953. m_szHeaderTitle.LoadString(nIDHeaderTitle);
  954. m_szHeaderSubTitle.LoadString(nIDHeaderSubTitle);
  955. m_psp97.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  956. m_psp97.pszHeaderTitle = (LPCTSTR)m_szHeaderTitle;
  957. m_psp97.pszHeaderSubTitle = (LPCTSTR)m_szHeaderSubTitle;
  958. }
  959. if (hasHelp)
  960. {
  961. m_psp97.dwFlags |= PSP_HASHELP;
  962. }
  963. }
  964. /////////////////////////////////////////////////////////////////////////////
  965. // CPropertyPageHolderTable
  966. #define PPAGE_HOLDER_ARRAY_DEF_SIZE (10)
  967. CPropertyPageHolderTable::CPropertyPageHolderTable(CComponentDataObject* pComponentData)
  968. {
  969. m_pComponentData = pComponentData;
  970. size_t arraySizeInBytes = sizeof(PPAGE_HOLDER_TABLE_ENTRY) * PPAGE_HOLDER_ARRAY_DEF_SIZE;
  971. m_pEntries = (PPAGE_HOLDER_TABLE_ENTRY*)malloc(arraySizeInBytes);
  972. if (m_pEntries != NULL)
  973. {
  974. memset(m_pEntries,0, arraySizeInBytes);
  975. }
  976. m_nSize = PPAGE_HOLDER_ARRAY_DEF_SIZE;
  977. }
  978. CPropertyPageHolderTable::~CPropertyPageHolderTable()
  979. {
  980. #ifdef _DEBUG
  981. for (int k=0; k < m_nSize; k++)
  982. {
  983. ASSERT(m_pEntries[k].pPPHolder == NULL);
  984. ASSERT(m_pEntries[k].pNode == NULL);
  985. }
  986. #endif
  987. free(m_pEntries);
  988. }
  989. void CPropertyPageHolderTable::Add(CPropertyPageHolderBase* pPPHolder)
  990. {
  991. ASSERT(pPPHolder != NULL);
  992. ASSERT(pPPHolder->GetTreeNode() != NULL);
  993. for (int k=0; k < m_nSize; k++)
  994. {
  995. if (m_pEntries[k].pPPHolder == NULL) // get the first empty spot
  996. {
  997. m_pEntries[k].pPPHolder = pPPHolder;
  998. m_pEntries[k].pNode = pPPHolder->GetTreeNode();
  999. m_pEntries[k].hWnd = NULL;
  1000. return;
  1001. }
  1002. }
  1003. // all full, need to grow the array
  1004. int nAlloc = m_nSize*2;
  1005. PPAGE_HOLDER_TABLE_ENTRY* temp = (PPAGE_HOLDER_TABLE_ENTRY*)realloc(m_pEntries, sizeof(PPAGE_HOLDER_TABLE_ENTRY)*nAlloc);
  1006. if (temp)
  1007. {
  1008. m_pEntries = temp;
  1009. memset(&m_pEntries[m_nSize], 0, sizeof(PPAGE_HOLDER_TABLE_ENTRY)*m_nSize);
  1010. m_pEntries[m_nSize].pPPHolder = pPPHolder;
  1011. m_pEntries[m_nSize].pNode = pPPHolder->GetTreeNode();
  1012. m_pEntries[m_nSize].hWnd = NULL;
  1013. m_nSize = nAlloc;
  1014. }
  1015. }
  1016. void CPropertyPageHolderTable::AddWindow(CPropertyPageHolderBase* pPPHolder, HWND hWnd)
  1017. {
  1018. // By now, the PPHolder might have gone away, so use it as a cookie
  1019. // but do not call any methods on it.
  1020. // The node is still valid, because we do not delete nodes from secondary
  1021. // threads
  1022. ASSERT(pPPHolder != NULL);
  1023. for (int k=0; k < m_nSize; k++)
  1024. {
  1025. if (m_pEntries[k].pPPHolder == pPPHolder)
  1026. {
  1027. ASSERT(m_pEntries[k].pNode != NULL);
  1028. ASSERT(m_pEntries[k].pNode->GetSheetCount() > 0);
  1029. m_pEntries[k].hWnd = hWnd;
  1030. return; // assume no more that one holder entry
  1031. }
  1032. }
  1033. }
  1034. void CPropertyPageHolderTable::Remove(CPropertyPageHolderBase* pPPHolder)
  1035. {
  1036. // By now, the PPHolder might have gone away, so use it as a cookie
  1037. // but do not call any methods on it.
  1038. // The node is still valid, because we do not delete nodes from secondary
  1039. // threads
  1040. ASSERT(pPPHolder != NULL);
  1041. for (int k=0; k < m_nSize; k++)
  1042. {
  1043. if (m_pEntries[k].pPPHolder == pPPHolder)
  1044. {
  1045. ASSERT(m_pEntries[k].pNode != NULL);
  1046. ASSERT(m_pEntries[k].pNode->GetSheetCount() > 0);
  1047. m_pEntries[k].pPPHolder = NULL;
  1048. m_pEntries[k].pNode = NULL;
  1049. m_pEntries[k].hWnd = NULL;
  1050. return; // assume no more that one holder entry
  1051. }
  1052. }
  1053. }
  1054. void CPropertyPageHolderTable::DeleteSheetsOfNode(CTreeNode* pNode)
  1055. {
  1056. ASSERT(pNode != NULL);
  1057. int nCount = BroadcastCloseMessageToSheets(pNode);
  1058. WaitForSheetShutdown(nCount);
  1059. }
  1060. void CPropertyPageHolderTable::WaitForAllToShutDown()
  1061. {
  1062. int nCount = 0;
  1063. // allocate and array of HWND's for broadcast
  1064. HWND* hWndArr = new HWND[m_nSize];
  1065. if (hWndArr)
  1066. {
  1067. memset(hWndArr, 0x0, m_nSize*sizeof(HWND));
  1068. for (int k=0; k < m_nSize; k++)
  1069. {
  1070. if (m_pEntries[k].pPPHolder != NULL)
  1071. {
  1072. m_pEntries[k].pPPHolder = NULL;
  1073. m_pEntries[k].pNode = NULL;
  1074. hWndArr[k] = ::GetParent(m_pEntries[k].hWnd);
  1075. m_pEntries[k].hWnd = NULL;
  1076. nCount++;
  1077. }
  1078. }
  1079. // wait for shutdown (wait for posted messages to come through
  1080. WaitForSheetShutdown(nCount, hWndArr);
  1081. delete [] hWndArr;
  1082. }
  1083. }
  1084. void CPropertyPageHolderTable::BroadcastSelectPage(CTreeNode* pNode, long nPageCode)
  1085. {
  1086. for (int k=0; k < m_nSize; k++)
  1087. {
  1088. if ((m_pEntries[k].hWnd != NULL) && (m_pEntries[k].pNode == pNode))
  1089. {
  1090. ::PostMessage(m_pEntries[k].hWnd, CSheetWnd::s_SelectPageMessage, (WPARAM)nPageCode, 0);
  1091. }
  1092. }
  1093. }
  1094. void CPropertyPageHolderTable::BroadcastMessageToSheets(CTreeNode* pNode, WPARAM wParam, LPARAM lParam)
  1095. {
  1096. for (int k=0; k < m_nSize; k++)
  1097. {
  1098. if ((m_pEntries[k].hWnd != NULL) && (m_pEntries[k].pNode == pNode))
  1099. {
  1100. ::PostMessage(m_pEntries[k].hWnd, CSheetWnd::s_SheetMessage, wParam, lParam);
  1101. }
  1102. }
  1103. }
  1104. int CPropertyPageHolderTable::BroadcastCloseMessageToSheets(CTreeNode* pNode)
  1105. {
  1106. ASSERT(m_nSize > 0);
  1107. int nCount = 0;
  1108. // allocate and array of HWND's for broadcast
  1109. HWND* hWndArr = new HWND[m_nSize];
  1110. if (hWndArr)
  1111. {
  1112. memset(hWndArr, 0x0, m_nSize*sizeof(HWND));
  1113. // find the HWND's that map to this node and its children
  1114. for (int k=0; k < m_nSize; k++)
  1115. {
  1116. if (m_pEntries[k].hWnd != NULL)
  1117. {
  1118. if (m_pEntries[k].pNode == pNode)
  1119. {
  1120. hWndArr[nCount++] = ::GetParent(m_pEntries[k].hWnd);
  1121. }
  1122. else if (pNode->IsContainer())
  1123. {
  1124. if (m_pEntries[k].pNode->HasContainer((CContainerNode*)pNode))
  1125. {
  1126. hWndArr[nCount++] = ::GetParent(m_pEntries[k].hWnd);
  1127. }
  1128. }
  1129. }
  1130. }
  1131. // shut down the sheets
  1132. for (int j=0; j < nCount; j++)
  1133. ::PostMessage(hWndArr[j], WM_COMMAND, IDCANCEL, 0);
  1134. delete [] hWndArr;
  1135. }
  1136. return nCount;
  1137. }
  1138. void CPropertyPageHolderTable::WaitForSheetShutdown(int nCount, HWND* hWndArr)
  1139. {
  1140. ASSERT(m_pComponentData != NULL);
  1141. HWND hWnd = m_pComponentData->GetHiddenWindow();
  1142. ASSERT(::IsWindow(hWnd));
  1143. MSG tempMSG;
  1144. DWORD dwTimeStart = ::GetTickCount();
  1145. while(nCount > 0)
  1146. {
  1147. if ( hWndArr != NULL && (::GetTickCount() > dwTimeStart + 2000) )
  1148. {
  1149. // force sheets shut down
  1150. for (int j=0; j < nCount; j++)
  1151. ::PostMessage(hWndArr[j], WM_COMMAND, IDCANCEL, 0);
  1152. hWndArr = NULL;
  1153. }
  1154. if (::PeekMessage(&tempMSG,hWnd, CHiddenWnd::s_NodePropertySheetDeleteMessage,
  1155. CHiddenWnd::s_NodePropertySheetDeleteMessage,
  1156. PM_REMOVE))
  1157. {
  1158. TRACE(_T("-------------------->>>>enter while peek loop, nCount = %d\n"),nCount);
  1159. DispatchMessage(&tempMSG);
  1160. nCount--;
  1161. }
  1162. }
  1163. }
  1164. /////////////////////////////////////////////////////////////////////////////
  1165. // CHelpDialog
  1166. BEGIN_MESSAGE_MAP(CHelpDialog, CDialog)
  1167. ON_WM_CONTEXTMENU()
  1168. ON_MESSAGE(WM_HELP, OnHelp)
  1169. ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
  1170. END_MESSAGE_MAP()
  1171. CHelpDialog::CHelpDialog(UINT nIDTemplate, CComponentDataObject* pComponentData) :
  1172. m_hWndWhatsThis(0),
  1173. m_pComponentData(pComponentData),
  1174. CDialog(nIDTemplate)
  1175. {
  1176. }
  1177. CHelpDialog::CHelpDialog(UINT nIDTemplate, CWnd* pParentWnd, CComponentDataObject* pComponentData) :
  1178. m_hWndWhatsThis(0),
  1179. m_pComponentData(pComponentData),
  1180. CDialog(nIDTemplate, pParentWnd)
  1181. {
  1182. }
  1183. void CHelpDialog::OnWhatsThis()
  1184. {
  1185. //
  1186. // Display context help for a control
  1187. //
  1188. if ( m_hWndWhatsThis )
  1189. {
  1190. //
  1191. // Build our own HELPINFO struct to pass to the underlying
  1192. // CS help functions built into the framework
  1193. //
  1194. int iCtrlID = ::GetDlgCtrlID(m_hWndWhatsThis);
  1195. HELPINFO helpInfo;
  1196. ZeroMemory(&helpInfo, sizeof(HELPINFO));
  1197. helpInfo.cbSize = sizeof(HELPINFO);
  1198. helpInfo.hItemHandle = m_hWndWhatsThis;
  1199. helpInfo.iCtrlId = iCtrlID;
  1200. m_pComponentData->OnDialogContextHelp(m_nIDHelp, &helpInfo);
  1201. }
  1202. }
  1203. BOOL CHelpDialog::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
  1204. {
  1205. const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  1206. if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
  1207. {
  1208. //
  1209. // Display context help for a control
  1210. //
  1211. m_pComponentData->OnDialogContextHelp(m_nIDHelp, pHelpInfo);
  1212. }
  1213. return TRUE;
  1214. }
  1215. void CHelpDialog::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
  1216. {
  1217. //
  1218. // point is in screen coordinates
  1219. //
  1220. CMenu bar;
  1221. if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
  1222. {
  1223. CMenu& popup = *bar.GetSubMenu (0);
  1224. ASSERT(popup.m_hMenu);
  1225. if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
  1226. point.x, // in screen coordinates
  1227. point.y, // in screen coordinates
  1228. this) ) // route commands through main window
  1229. {
  1230. m_hWndWhatsThis = 0;
  1231. ScreenToClient (&point);
  1232. CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
  1233. CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
  1234. if ( pChild )
  1235. {
  1236. m_hWndWhatsThis = pChild->m_hWnd;
  1237. }
  1238. }
  1239. }
  1240. }