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.

1430 lines
36 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. BOOL bEnum = EnumThreadWindows(dwThreadID, EnumThreadWndProc,(LPARAM)&hWnd);
  32. ASSERT(bEnum);
  33. ASSERT(hWnd != NULL);
  34. return hWnd;
  35. }
  36. ////////////////////////////////////////////////////////////////////
  37. // CHiddenWndBase : Utility Hidden Window
  38. BOOL CHiddenWndBase::Create(HWND hWndParent)
  39. {
  40. ASSERT(hWndParent == NULL || ::IsWindow(hWndParent));
  41. RECT rcPos;
  42. ZeroMemory(&rcPos, sizeof(RECT));
  43. HWND hWnd = CWindowImpl<CHiddenWndBase>::Create(hWndParent,
  44. rcPos, //RECT& rcPos,
  45. NULL, //LPCTSTR szWindowName = NULL,
  46. (hWndParent) ? WS_CHILD : WS_POPUP, //DWORD dwStyle = WS_CHILD | WS_VISIBLE,
  47. 0x0, //DWORD dwExStyle = 0,
  48. 0 //UINT nID = 0
  49. );
  50. return hWnd != NULL;
  51. }
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CSheetWnd
  54. const UINT CSheetWnd::s_SheetMessage = WM_USER + 100;
  55. const UINT CSheetWnd::s_SelectPageMessage = WM_USER + 101;
  56. LRESULT CSheetWnd::OnSheetMessage(UINT, WPARAM wParam, LPARAM lParam, BOOL&)
  57. {
  58. ASSERT(m_pHolder != NULL);
  59. m_pHolder->OnSheetMessage(wParam,lParam);
  60. return 1;
  61. }
  62. LRESULT CSheetWnd::OnSelectPageMessage(UINT, WPARAM wParam, LPARAM, BOOL&)
  63. {
  64. TRACE(_T("CSheetWnd::OnSelectPageMessage()\n"));
  65. ASSERT(m_pHolder != NULL);
  66. int nPage = m_pHolder->OnSelectPageMessage((long)wParam);
  67. if (nPage >= 0)
  68. {
  69. // can use SendMessage() because the sheet has been created already
  70. VERIFY(PropSheet_SetCurSel(m_pHolder->m_hSheetWindow, NULL, nPage));
  71. }
  72. ::SetForegroundWindow(::GetParent(m_hWnd));
  73. return 1;
  74. }
  75. LRESULT CSheetWnd::OnClose(UINT, WPARAM, LPARAM, BOOL&)
  76. {
  77. return 1;
  78. }
  79. /////////////////////////////////////////////////////////////////////////////
  80. // CCloseDialogInfo
  81. struct FIND_MSG_BOX_INFO
  82. {
  83. LPCTSTR lpszTitle;
  84. HWND hWnd;
  85. HWND hWndParent;
  86. };
  87. BOOL CALLBACK EnumMessageBoxProc(HWND hwnd, LPARAM lParam)
  88. {
  89. FIND_MSG_BOX_INFO* pInfo = (FIND_MSG_BOX_INFO*)lParam;
  90. if (::GetParent(hwnd) != pInfo->hWndParent)
  91. return TRUE;
  92. TCHAR szTitle[256] = {0};
  93. ::GetWindowText(hwnd, szTitle, 256);
  94. TRACE(_T("Title <%s>\n"), szTitle);
  95. if (_wcsicmp(szTitle, pInfo->lpszTitle) == 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. m_hEventHandle = ::CreateEvent(NULL,TRUE /*bManualReset*/,FALSE /*signalled*/, NULL);
  591. ASSERT(m_hEventHandle != NULL);
  592. }
  593. if (m_hConsoleHandle != NULL)
  594. {
  595. MMCPropertyChangeNotify(m_hConsoleHandle, reinterpret_cast<LPARAM>(this));
  596. DWORD dwRet;
  597. do
  598. {
  599. ASSERT(::IsWindow(m_hSheetWindow));
  600. dwRet = MsgWaitForMultipleObjects(1,&m_hEventHandle,FALSE,INFINITE, QS_SENDMESSAGE);
  601. if(dwRet == (WAIT_OBJECT_0+1))
  602. {
  603. MSG tempMSG;
  604. PeekMessage(&tempMSG,m_hSheetWindow,0,0,PM_NOREMOVE);
  605. }
  606. }
  607. while(dwRet == (WAIT_OBJECT_0+1));
  608. }
  609. VERIFY(0 != ::ResetEvent(m_hEventHandle));
  610. m_pPropChangePage = NULL; // reset
  611. return m_dwLastErr;
  612. }
  613. void CPropertyPageHolderBase::AcknowledgeNotify()
  614. {
  615. if(m_pContHolder != NULL)
  616. {
  617. m_pContHolder->AcknowledgeNotify();
  618. return;
  619. }
  620. ASSERT(!IsWizardMode());
  621. ASSERT(m_hEventHandle != NULL);
  622. //TRACE(_T("before SetEvent\n"));
  623. VERIFY(0 != ::SetEvent(m_hEventHandle));
  624. //TRACE(_T("after SetEvent\n"));
  625. }
  626. BOOL CPropertyPageHolderBase::OnPropertyChange(BOOL bScopePane, long* pChangeMask)
  627. {
  628. ASSERT(!IsWizardMode());
  629. CPropertyPageBase* pPage = GetPropChangePage();
  630. if (pPage == NULL)
  631. return FALSE;
  632. return pPage->OnPropertyChange(bScopePane, pChangeMask);
  633. }
  634. BOOL CPropertyPageHolderBase::SetWizardButtons(DWORD dwFlags)
  635. {
  636. ASSERT(IsWizardMode());
  637. if (m_pContHolder != NULL)
  638. {
  639. ASSERT(m_hSheetWindow == NULL);
  640. return m_pContHolder->SetWizardButtons(dwFlags);
  641. }
  642. ASSERT(::IsWindow(m_hSheetWindow));
  643. return (BOOL)SendMessage(m_hSheetWindow, PSM_SETWIZBUTTONS, 0, dwFlags);
  644. }
  645. HRESULT CPropertyPageHolderBase::AddPageToSheet(CPropertyPageBase* pPage)
  646. {
  647. if (m_pContHolder != NULL)
  648. {
  649. ASSERT(m_hSheetWindow == NULL);
  650. return m_pContHolder->AddPageToSheet(pPage);
  651. }
  652. CWinApp* pApp = AfxGetApp();
  653. ASSERT(pApp);
  654. if (m_pSheetCallback != NULL)
  655. {
  656. VERIFY(SUCCEEDED(MMCPropPageCallback((void*)(&pPage->m_psp97))));
  657. }
  658. HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(&pPage->m_psp97);
  659. if (hPage == NULL)
  660. return E_UNEXPECTED;
  661. pPage->m_hPage = hPage;
  662. if (m_pSheetCallback != NULL)
  663. return m_pSheetCallback->AddPage(hPage);
  664. else if (m_pDummySheet != NULL)
  665. {
  666. m_pDummySheet->AddPage(pPage);
  667. return S_OK;
  668. }
  669. else
  670. {
  671. ASSERT(::IsWindow(m_hSheetWindow));
  672. return PropSheet_AddPage(m_hSheetWindow, hPage) ? S_OK : E_FAIL;
  673. }
  674. }
  675. HRESULT CPropertyPageHolderBase::AddPageToSheetRaw(HPROPSHEETPAGE hPage)
  676. {
  677. ASSERT(m_pSheetCallback != NULL);
  678. if ((hPage == NULL) || (m_pSheetCallback == NULL))
  679. return E_INVALIDARG;
  680. if (m_pContHolder != NULL)
  681. {
  682. ASSERT(m_hSheetWindow == NULL);
  683. return m_pContHolder->AddPageToSheetRaw(hPage);
  684. }
  685. // assume this is not a n MFC property page
  686. return m_pSheetCallback->AddPage(hPage);
  687. }
  688. HRESULT CPropertyPageHolderBase::RemovePageFromSheet(CPropertyPageBase* pPage)
  689. {
  690. if (m_pContHolder != NULL)
  691. {
  692. ASSERT(m_hSheetWindow == NULL);
  693. return m_pContHolder->RemovePageFromSheet(pPage);
  694. }
  695. ASSERT(pPage->m_hPage != NULL);
  696. if (m_pSheetCallback != NULL)
  697. return m_pSheetCallback->RemovePage(pPage->m_hPage);
  698. else
  699. {
  700. ASSERT(::IsWindow(m_hSheetWindow));
  701. PropSheet_RemovePage(m_hSheetWindow, 0, pPage->m_hPage); // returns void
  702. return S_OK;
  703. }
  704. }
  705. HRESULT CPropertyPageHolderBase::AddAllPagesToSheet()
  706. {
  707. POSITION pos;
  708. int nPage = 0;
  709. HRESULT hr = OnAddPage(nPage, NULL); // zero means add before the first
  710. ASSERT(SUCCEEDED(hr));
  711. if (FAILED(hr))
  712. return hr;
  713. for( pos = m_pageList.GetHeadPosition(); pos != NULL; )
  714. {
  715. CPropertyPageBase* pPropPage = m_pageList.GetNext(pos);
  716. hr = AddPageToSheet(pPropPage);
  717. ASSERT(SUCCEEDED(hr));
  718. if (FAILED(hr))
  719. return hr;
  720. nPage++;
  721. hr = OnAddPage(nPage, pPropPage); // get called on nPage == 1,2, n-1
  722. ASSERT(SUCCEEDED(hr));
  723. if (FAILED(hr))
  724. return hr;
  725. }
  726. // add after the last
  727. return OnAddPage(-1, NULL); // -1 means
  728. }
  729. void CPropertyPageHolderBase::AddPageToList(CPropertyPageBase* pPage)
  730. {
  731. ASSERT(pPage != NULL);
  732. pPage->SetHolder(this);
  733. m_pageList.AddTail(pPage);
  734. }
  735. BOOL CPropertyPageHolderBase::RemovePageFromList(CPropertyPageBase* pPage, BOOL bDeleteObject)
  736. {
  737. ASSERT(pPage != NULL);
  738. POSITION pos = m_pageList.Find(pPage);
  739. if (pos == NULL)
  740. return FALSE;
  741. m_pageList.RemoveAt(pos);
  742. if (bDeleteObject)
  743. delete pPage;
  744. return TRUE;
  745. }
  746. void CPropertyPageHolderBase::DeleteAllPages()
  747. {
  748. if (!m_bAutoDeletePages)
  749. return;
  750. // assume all pages out of the heap
  751. while (!m_pageList.IsEmpty())
  752. {
  753. delete m_pageList.RemoveTail();
  754. }
  755. }
  756. void CPropertyPageHolderBase::FinalDestruct()
  757. {
  758. DeleteAllPages();
  759. if (IsWizardMode() || (m_pContHolder != NULL))
  760. return;
  761. if (m_hConsoleHandle != NULL)
  762. {
  763. MMCFreeNotifyHandle(m_hConsoleHandle);
  764. }
  765. // tell the component data object that the sheet is going away
  766. GetComponentData()->OnDeleteSheet(this,m_pNode);
  767. if (m_pSheetWnd != NULL)
  768. {
  769. delete m_pSheetWnd;
  770. m_pSheetWnd = NULL;
  771. }
  772. ASSERT(m_dlgInfoStack.IsEmpty());
  773. }
  774. BOOL CPropertyPageHolderBase::PushDialogHWnd(HWND hWndModalDlg)
  775. {
  776. return m_dlgInfoStack.Push(hWndModalDlg, 0x0);
  777. }
  778. BOOL CPropertyPageHolderBase::PopDialogHWnd()
  779. {
  780. return m_dlgInfoStack.Pop();
  781. }
  782. void CPropertyPageHolderBase::CloseModalDialogs(HWND hWndPage)
  783. {
  784. m_dlgInfoStack.ForceClose(hWndPage);
  785. }
  786. /////////////////////////////////////////////////////////////////////////////
  787. // CPropertyPageBase
  788. BEGIN_MESSAGE_MAP(CPropertyPageBase, CPropertyPage)
  789. ON_WM_CREATE()
  790. ON_WM_DESTROY()
  791. ON_WM_CONTEXTMENU()
  792. ON_MESSAGE(WM_HELP, OnHelp)
  793. ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
  794. END_MESSAGE_MAP()
  795. CPropertyPageBase::CPropertyPageBase(UINT nIDTemplate,
  796. UINT nIDCaption) :
  797. CPropertyPage(nIDTemplate, nIDCaption)
  798. {
  799. m_hPage = NULL;
  800. m_pPageHolder = NULL;
  801. m_bIsDirty = FALSE;
  802. m_nPrevPageID = 0;
  803. // hack to have new struct size with old MFC and new NT 5.0 headers
  804. ZeroMemory(&m_psp97, sizeof(PROPSHEETPAGE));
  805. memcpy(&m_psp97, &m_psp, m_psp.dwSize);
  806. m_psp97.dwSize = sizeof(PROPSHEETPAGE);
  807. }
  808. CPropertyPageBase::~CPropertyPageBase()
  809. {
  810. }
  811. int CPropertyPageBase::OnCreate(LPCREATESTRUCT lpCreateStruct)
  812. {
  813. m_pPageHolder->AddRef();
  814. int res = CPropertyPage::OnCreate(lpCreateStruct);
  815. ASSERT(res == 0);
  816. ASSERT(m_hWnd != NULL);
  817. ASSERT(::IsWindow(m_hWnd));
  818. HWND hParent = ::GetParent(m_hWnd);
  819. ASSERT(hParent);
  820. m_pPageHolder->SetSheetWindow(hParent);
  821. return res;
  822. }
  823. void CPropertyPageBase::OnDestroy()
  824. {
  825. ASSERT(m_hWnd != NULL);
  826. CPropertyPage::OnDestroy();
  827. m_pPageHolder->Release();
  828. }
  829. void CPropertyPageBase::OnWhatsThis()
  830. {
  831. //
  832. // Display context help for a control
  833. //
  834. if ( m_hWndWhatsThis )
  835. {
  836. //
  837. // Build our own HELPINFO struct to pass to the underlying
  838. // CS help functions built into the framework
  839. //
  840. int iCtrlID = ::GetDlgCtrlID(m_hWndWhatsThis);
  841. HELPINFO helpInfo;
  842. ZeroMemory(&helpInfo, sizeof(HELPINFO));
  843. helpInfo.cbSize = sizeof(HELPINFO);
  844. helpInfo.hItemHandle = m_hWndWhatsThis;
  845. helpInfo.iCtrlId = iCtrlID;
  846. m_pPageHolder->GetComponentData()->OnDialogContextHelp(m_nIDHelp, &helpInfo);
  847. }
  848. }
  849. BOOL CPropertyPageBase::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
  850. {
  851. const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  852. if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
  853. {
  854. //
  855. // Display context help for a control
  856. //
  857. m_pPageHolder->GetComponentData()->OnDialogContextHelp(m_nIDHelp, pHelpInfo);
  858. }
  859. return TRUE;
  860. }
  861. void CPropertyPageBase::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
  862. {
  863. //
  864. // point is in screen coordinates
  865. //
  866. CMenu bar;
  867. if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
  868. {
  869. CMenu& popup = *bar.GetSubMenu (0);
  870. ASSERT(popup.m_hMenu);
  871. if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
  872. point.x, // in screen coordinates
  873. point.y, // in screen coordinates
  874. this) ) // route commands through main window
  875. {
  876. m_hWndWhatsThis = 0;
  877. ScreenToClient (&point);
  878. CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
  879. CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
  880. if ( pChild )
  881. {
  882. m_hWndWhatsThis = pChild->m_hWnd;
  883. }
  884. }
  885. }
  886. }
  887. void CPropertyPageBase::OnCancel()
  888. {
  889. CString szTitle;
  890. GetWindowText(szTitle);
  891. TRACE(_T("CPropertyPageBase::OnCancel()called on <%s>\n"),(LPCTSTR)szTitle);
  892. CWinApp* pApp = AfxGetApp();
  893. ASSERT(pApp);
  894. ASSERT(::IsWindow(m_hWnd));
  895. m_pPageHolder->CloseModalDialogs(m_hWnd);
  896. }
  897. BOOL CPropertyPageBase::OnApply()
  898. {
  899. if (IsDirty())
  900. {
  901. if (m_pPageHolder->NotifyConsole(this) == 0x0)
  902. {
  903. SetDirty(FALSE);
  904. return TRUE;
  905. }
  906. else
  907. {
  908. #ifdef _DEBUG
  909. // test only
  910. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  911. AfxMessageBox(_T("Apply Failed"));
  912. #endif
  913. return FALSE;
  914. }
  915. }
  916. return TRUE;
  917. }
  918. void CPropertyPageBase::SetDirty(BOOL bDirty)
  919. {
  920. if (!m_pPageHolder->IsWizardMode())
  921. {
  922. SetModified(bDirty);
  923. }
  924. m_bIsDirty = bDirty;
  925. }
  926. void CPropertyPageBase::InitWiz97(BOOL bHideHeader,
  927. UINT nIDHeaderTitle,
  928. UINT nIDHeaderSubTitle)
  929. {
  930. if (bHideHeader)
  931. {
  932. // for first and last page of the wizard
  933. m_psp97.dwFlags |= PSP_HIDEHEADER;
  934. }
  935. else
  936. {
  937. // for intermediate pages
  938. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  939. m_szHeaderTitle.LoadString(nIDHeaderTitle);
  940. m_szHeaderSubTitle.LoadString(nIDHeaderSubTitle);
  941. m_psp97.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  942. m_psp97.pszHeaderTitle = (LPCTSTR)m_szHeaderTitle;
  943. m_psp97.pszHeaderSubTitle = (LPCTSTR)m_szHeaderSubTitle;
  944. }
  945. }
  946. /////////////////////////////////////////////////////////////////////////////
  947. // CPropertyPageHolderTable
  948. #define PPAGE_HOLDER_ARRAY_DEF_SIZE (10)
  949. CPropertyPageHolderTable::CPropertyPageHolderTable(CComponentDataObject* pComponentData)
  950. {
  951. m_pComponentData = pComponentData;
  952. m_pEntries = (PPAGE_HOLDER_TABLE_ENTRY*)malloc(sizeof(PPAGE_HOLDER_TABLE_ENTRY) * PPAGE_HOLDER_ARRAY_DEF_SIZE);
  953. if (m_pEntries != NULL)
  954. {
  955. memset(m_pEntries,0, sizeof(PPAGE_HOLDER_TABLE_ENTRY) * PPAGE_HOLDER_ARRAY_DEF_SIZE);
  956. }
  957. m_nSize = PPAGE_HOLDER_ARRAY_DEF_SIZE;
  958. }
  959. CPropertyPageHolderTable::~CPropertyPageHolderTable()
  960. {
  961. #ifdef _DEBUG
  962. for (int k=0; k < m_nSize; k++)
  963. {
  964. ASSERT(m_pEntries[k].pPPHolder == NULL);
  965. ASSERT(m_pEntries[k].pNode == NULL);
  966. }
  967. #endif
  968. free(m_pEntries);
  969. }
  970. void CPropertyPageHolderTable::Add(CPropertyPageHolderBase* pPPHolder)
  971. {
  972. ASSERT(pPPHolder != NULL);
  973. ASSERT(pPPHolder->GetTreeNode() != NULL);
  974. for (int k=0; k < m_nSize; k++)
  975. {
  976. if (m_pEntries[k].pPPHolder == NULL) // get the first empty spot
  977. {
  978. m_pEntries[k].pPPHolder = pPPHolder;
  979. m_pEntries[k].pNode = pPPHolder->GetTreeNode();
  980. m_pEntries[k].hWnd = NULL;
  981. return;
  982. }
  983. }
  984. // all full, need to grow the array
  985. int nAlloc = m_nSize*2;
  986. m_pEntries = (PPAGE_HOLDER_TABLE_ENTRY*)realloc(m_pEntries, sizeof(PPAGE_HOLDER_TABLE_ENTRY)*nAlloc);
  987. memset(&m_pEntries[m_nSize], 0, sizeof(PPAGE_HOLDER_TABLE_ENTRY)*m_nSize);
  988. m_pEntries[m_nSize].pPPHolder = pPPHolder;
  989. m_pEntries[m_nSize].pNode = pPPHolder->GetTreeNode();
  990. m_pEntries[m_nSize].hWnd = NULL;
  991. m_nSize = nAlloc;
  992. }
  993. void CPropertyPageHolderTable::AddWindow(CPropertyPageHolderBase* pPPHolder, HWND hWnd)
  994. {
  995. // By now, the PPHolder might have gone away, so use it as a cookie
  996. // but do not call any methods on it.
  997. // The node is still valid, because we do not delete nodes from secondary
  998. // threads
  999. ASSERT(pPPHolder != NULL);
  1000. for (int k=0; k < m_nSize; k++)
  1001. {
  1002. if (m_pEntries[k].pPPHolder == pPPHolder)
  1003. {
  1004. ASSERT(m_pEntries[k].pNode != NULL);
  1005. ASSERT(m_pEntries[k].pNode->GetSheetCount() > 0);
  1006. m_pEntries[k].hWnd = hWnd;
  1007. return; // assume no more that one holder entry
  1008. }
  1009. }
  1010. }
  1011. void CPropertyPageHolderTable::Remove(CPropertyPageHolderBase* pPPHolder)
  1012. {
  1013. // By now, the PPHolder might have gone away, so use it as a cookie
  1014. // but do not call any methods on it.
  1015. // The node is still valid, because we do not delete nodes from secondary
  1016. // threads
  1017. ASSERT(pPPHolder != NULL);
  1018. for (int k=0; k < m_nSize; k++)
  1019. {
  1020. if (m_pEntries[k].pPPHolder == pPPHolder)
  1021. {
  1022. ASSERT(m_pEntries[k].pNode != NULL);
  1023. ASSERT(m_pEntries[k].pNode->GetSheetCount() > 0);
  1024. m_pEntries[k].pPPHolder = NULL;
  1025. m_pEntries[k].pNode = NULL;
  1026. m_pEntries[k].hWnd = NULL;
  1027. return; // assume no more that one holder entry
  1028. }
  1029. }
  1030. }
  1031. void CPropertyPageHolderTable::DeleteSheetsOfNode(CTreeNode* pNode)
  1032. {
  1033. ASSERT(pNode != NULL);
  1034. int nCount = BroadcastCloseMessageToSheets(pNode);
  1035. WaitForSheetShutdown(nCount);
  1036. }
  1037. void CPropertyPageHolderTable::WaitForAllToShutDown()
  1038. {
  1039. int nCount = 0;
  1040. // allocate and array of HWND's for broadcast
  1041. HWND* hWndArr = (HWND*)malloc(m_nSize*sizeof(m_nSize));
  1042. if (hWndArr)
  1043. {
  1044. memset(hWndArr, 0x0, m_nSize*sizeof(m_nSize));
  1045. for (int k=0; k < m_nSize; k++)
  1046. {
  1047. if (m_pEntries[k].pPPHolder != NULL)
  1048. {
  1049. m_pEntries[k].pPPHolder = NULL;
  1050. m_pEntries[k].pNode = NULL;
  1051. hWndArr[k] = ::GetParent(m_pEntries[k].hWnd);
  1052. m_pEntries[k].hWnd = NULL;
  1053. nCount++;
  1054. }
  1055. }
  1056. // wait for shutdown (wait for posted messages to come through
  1057. WaitForSheetShutdown(nCount, hWndArr);
  1058. free(hWndArr);
  1059. }
  1060. }
  1061. void CPropertyPageHolderTable::BroadcastSelectPage(CTreeNode* pNode, long nPageCode)
  1062. {
  1063. for (int k=0; k < m_nSize; k++)
  1064. {
  1065. if ((m_pEntries[k].hWnd != NULL) && (m_pEntries[k].pNode == pNode))
  1066. {
  1067. ::PostMessage(m_pEntries[k].hWnd, CSheetWnd::s_SelectPageMessage, (WPARAM)nPageCode, 0);
  1068. }
  1069. }
  1070. }
  1071. void CPropertyPageHolderTable::BroadcastMessageToSheets(CTreeNode* pNode, WPARAM wParam, LPARAM lParam)
  1072. {
  1073. for (int k=0; k < m_nSize; k++)
  1074. {
  1075. if ((m_pEntries[k].hWnd != NULL) && (m_pEntries[k].pNode == pNode))
  1076. {
  1077. ::PostMessage(m_pEntries[k].hWnd, CSheetWnd::s_SheetMessage, wParam, lParam);
  1078. }
  1079. }
  1080. }
  1081. int CPropertyPageHolderTable::BroadcastCloseMessageToSheets(CTreeNode* pNode)
  1082. {
  1083. ASSERT(m_nSize > 0);
  1084. int nCount = 0;
  1085. // allocate and array of HWND's for broadcast
  1086. HWND* hWndArr = (HWND*)malloc(m_nSize*sizeof(m_nSize));
  1087. if (hWndArr)
  1088. {
  1089. memset(hWndArr, 0x0, m_nSize*sizeof(m_nSize));
  1090. // find the HWND's that map to this node and its children
  1091. for (int k=0; k < m_nSize; k++)
  1092. {
  1093. if (m_pEntries[k].hWnd != NULL)
  1094. {
  1095. if (m_pEntries[k].pNode == pNode)
  1096. {
  1097. hWndArr[nCount++] = ::GetParent(m_pEntries[k].hWnd);
  1098. }
  1099. else if (pNode->IsContainer())
  1100. {
  1101. if (m_pEntries[k].pNode->HasContainer((CContainerNode*)pNode))
  1102. {
  1103. hWndArr[nCount++] = ::GetParent(m_pEntries[k].hWnd);
  1104. }
  1105. }
  1106. }
  1107. }
  1108. // shut down the sheets
  1109. for (int j=0; j < nCount; j++)
  1110. ::PostMessage(hWndArr[j], WM_COMMAND, IDCANCEL, 0);
  1111. free(hWndArr);
  1112. }
  1113. return nCount;
  1114. }
  1115. void CPropertyPageHolderTable::WaitForSheetShutdown(int nCount, HWND* hWndArr)
  1116. {
  1117. ASSERT(m_pComponentData != NULL);
  1118. HWND hWnd = m_pComponentData->GetHiddenWindow();
  1119. ASSERT(::IsWindow(hWnd));
  1120. MSG tempMSG;
  1121. DWORD dwTimeStart = ::GetTickCount();
  1122. while(nCount > 0)
  1123. {
  1124. if ( hWndArr != NULL && (::GetTickCount() > dwTimeStart + 2000) )
  1125. {
  1126. // force sheets shut down
  1127. for (int j=0; j < nCount; j++)
  1128. ::PostMessage(hWndArr[j], WM_COMMAND, IDCANCEL, 0);
  1129. hWndArr = NULL;
  1130. }
  1131. if (::PeekMessage(&tempMSG,hWnd, CHiddenWnd::s_NodePropertySheetDeleteMessage,
  1132. CHiddenWnd::s_NodePropertySheetDeleteMessage,
  1133. PM_REMOVE))
  1134. {
  1135. TRACE(_T("-------------------->>>>enter while peek loop, nCount = %d\n"),nCount);
  1136. DispatchMessage(&tempMSG);
  1137. nCount--;
  1138. }
  1139. }
  1140. }
  1141. /////////////////////////////////////////////////////////////////////////////
  1142. // CHelpDialog
  1143. BEGIN_MESSAGE_MAP(CHelpDialog, CDialog)
  1144. ON_WM_CONTEXTMENU()
  1145. ON_MESSAGE(WM_HELP, OnHelp)
  1146. ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
  1147. END_MESSAGE_MAP()
  1148. CHelpDialog::CHelpDialog(UINT nIDTemplate, CComponentDataObject* pComponentData) :
  1149. m_hWndWhatsThis(0),
  1150. m_pComponentData(pComponentData),
  1151. CDialog(nIDTemplate)
  1152. {
  1153. }
  1154. CHelpDialog::CHelpDialog(UINT nIDTemplate, CWnd* pParentWnd, CComponentDataObject* pComponentData) :
  1155. m_hWndWhatsThis(0),
  1156. m_pComponentData(pComponentData),
  1157. CDialog(nIDTemplate, pParentWnd)
  1158. {
  1159. }
  1160. void CHelpDialog::OnWhatsThis()
  1161. {
  1162. //
  1163. // Display context help for a control
  1164. //
  1165. if ( m_hWndWhatsThis )
  1166. {
  1167. //
  1168. // Build our own HELPINFO struct to pass to the underlying
  1169. // CS help functions built into the framework
  1170. //
  1171. int iCtrlID = ::GetDlgCtrlID(m_hWndWhatsThis);
  1172. HELPINFO helpInfo;
  1173. ZeroMemory(&helpInfo, sizeof(HELPINFO));
  1174. helpInfo.cbSize = sizeof(HELPINFO);
  1175. helpInfo.hItemHandle = m_hWndWhatsThis;
  1176. helpInfo.iCtrlId = iCtrlID;
  1177. m_pComponentData->OnDialogContextHelp(m_nIDHelp, &helpInfo);
  1178. }
  1179. }
  1180. BOOL CHelpDialog::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
  1181. {
  1182. const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  1183. if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
  1184. {
  1185. //
  1186. // Display context help for a control
  1187. //
  1188. m_pComponentData->OnDialogContextHelp(m_nIDHelp, pHelpInfo);
  1189. }
  1190. return TRUE;
  1191. }
  1192. void CHelpDialog::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
  1193. {
  1194. //
  1195. // point is in screen coordinates
  1196. //
  1197. CMenu bar;
  1198. if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
  1199. {
  1200. CMenu& popup = *bar.GetSubMenu (0);
  1201. ASSERT(popup.m_hMenu);
  1202. if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
  1203. point.x, // in screen coordinates
  1204. point.y, // in screen coordinates
  1205. this) ) // route commands through main window
  1206. {
  1207. m_hWndWhatsThis = 0;
  1208. ScreenToClient (&point);
  1209. CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
  1210. CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
  1211. if ( pChild )
  1212. {
  1213. m_hWndWhatsThis = pChild->m_hWnd;
  1214. }
  1215. }
  1216. }
  1217. }