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.

1302 lines
36 KiB

  1. // wizards.cpp - Add Query Node and Add Object Wizards
  2. #include "stdafx.h"
  3. #include "wizards.h"
  4. #include "namemap.h"
  5. #include "cmndlgs.h"
  6. #include <algorithm>
  7. #include <atlgdi.h>
  8. #include <windowsx.h>
  9. #undef SubclassWindow
  10. HRESULT GetClassNameList(QueryObjVector& vObjects, tstring& strNames, LPCWSTR pszSeparator);
  11. #define CHECK_OFF INDEXTOSTATEIMAGEMASK(1)
  12. #define CHECK_ON INDEXTOSTATEIMAGEMASK(2)
  13. //////////////////////////////////////////////////////////////////////////////////////////
  14. // CAddQueryWelcomePage
  15. LRESULT CAddQueryWelcomePage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  16. {
  17. if( !m_pWizard ) return 0;
  18. HFONT hfont = m_pWizard->GetWelcomeFont();
  19. if( hfont )
  20. {
  21. ::SendMessage(GetDlgItem(IDC_WELCOME), WM_SETFONT, (WPARAM)hfont, (LPARAM)0);
  22. }
  23. return 0;
  24. }
  25. BOOL CAddQueryWelcomePage::OnSetActive()
  26. {
  27. ::PostMessage(GetParent(), PSM_SETTITLE, 0, (LPARAM)IDS_ADDQUERY_WIZ);
  28. ::PostMessage(GetParent(), PSM_SETWIZBUTTONS, (WPARAM)0, (LPARAM)PSWIZB_NEXT);
  29. return TRUE;
  30. }
  31. //////////////////////////////////////////////////////////////////////////////////////////
  32. // CQueryWizPage
  33. LRESULT CQueryWizPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  34. {
  35. // display current scope
  36. DisplayScope();
  37. // Limit display name
  38. Edit_LimitText(GetDlgItem(IDC_NAME), 255);
  39. return TRUE;
  40. }
  41. BOOL CQueryWizPage::OnSetActive()
  42. {
  43. UpdateButtons();
  44. return TRUE;
  45. }
  46. BOOL CQueryWizPage::OnKillActive()
  47. {
  48. GetItemText(GetDlgItem(IDC_NAME), m_strQueryName);
  49. return TRUE;
  50. }
  51. LRESULT CQueryWizPage::OnNameChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  52. {
  53. UpdateButtons();
  54. return 0;
  55. }
  56. LRESULT CQueryWizPage::OnScopeChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  57. {
  58. // if user changes scope selection then update query and display the correct scope
  59. if( m_pQueryNode)
  60. {
  61. m_pQueryNode->SetLocalScope(Button_GetCheck(GetDlgItem(IDC_LOCALSCOPE)) == BST_CHECKED);
  62. }
  63. DisplayScope();
  64. return 0;
  65. }
  66. LRESULT CQueryWizPage::OnCreateQuery( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  67. {
  68. if( !m_pQueryNode ) return 0;
  69. HRESULT hr = m_pQueryNode->EditQuery(m_hWnd);
  70. if( hr == S_OK )
  71. {
  72. tstring strTempQuery;
  73. m_pQueryNode->ExpandQuery(strTempQuery);
  74. SetDlgItemText( IDC_FILTER, strTempQuery.c_str() );
  75. // User may have changed scope and scope source, so redisplay
  76. DisplayScope();
  77. // get comma separated list of object classes associated with query
  78. tstring strClasses;
  79. GetClassNameList(m_pQueryNode->Objects(), strClasses, L", ");
  80. SetDlgItemText( IDC_OBJCLASS, strClasses.c_str() );
  81. UpdateButtons();
  82. }
  83. return 0;
  84. }
  85. void CQueryWizPage::UpdateButtons()
  86. {
  87. if( !m_pQueryNode ) return;
  88. DWORD dwButtons = PSWIZB_BACK;
  89. LPCWSTR pszTemp = m_pQueryNode->Query();
  90. if( pszTemp && wcslen(pszTemp) && ::Edit_GetTextLength(GetDlgItem(IDC_NAME)) )
  91. {
  92. dwButtons |= PSWIZB_NEXT;
  93. }
  94. ::PropSheet_SetWizButtons(GetParent(), dwButtons);
  95. }
  96. void CQueryWizPage::DisplayScope()
  97. {
  98. if( !m_pQueryNode ) return;
  99. Button_SetCheck(GetDlgItem(IDC_LOCALSCOPE), m_pQueryNode->UseLocalScope() ? BST_CHECKED:BST_UNCHECKED);
  100. Button_SetCheck(GetDlgItem(IDC_QUERYSCOPE), m_pQueryNode->UseLocalScope() ? BST_UNCHECKED:BST_CHECKED);
  101. tstring strScope = m_pQueryNode->Scope();
  102. tstring strDisplay;
  103. GetScopeDisplayString(strScope, strDisplay);
  104. SetDlgItemText( IDC_SCOPE, strDisplay.c_str() );
  105. }
  106. //////////////////////////////////////////////////////////////////////////////////////////
  107. // CQueryIconPage
  108. LRESULT CQueryIconPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  109. {
  110. // Load up our image list, and fill in the listbox
  111. HIMAGELIST hImageList = ::ImageList_LoadBitmap( _Module.GetModuleInstance(), MAKEINTRESOURCE(IDB_QUERY32), 32, 0, RGB(255, 0, 255) );
  112. // Load the icon list
  113. ListView_SetImageList( GetDlgItem(IDC_ICONLIST), hImageList, LVSIL_NORMAL );
  114. // Get the dimensions for the number of icons
  115. HBITMAP hBitmap = ::LoadBitmap( _Module.GetModuleInstance(), MAKEINTRESOURCE(IDB_QUERY32) );
  116. BITMAP bm;
  117. int nIcons = 0;
  118. GetObject (hBitmap, sizeof(BITMAP), (LPSTR)&bm);
  119. nIcons = (bm.bmHeight == 0) ? 0 : (int)bm.bmWidth / (int)bm.bmHeight;
  120. ::DeleteObject(hBitmap);
  121. // Set the icon spacing
  122. ListView_SetIconSpacing( GetDlgItem(IDC_ICONLIST), 40, 40 );
  123. // Add the icons to the list
  124. LV_ITEM lvi;
  125. ZeroMemory( &lvi, sizeof(LV_ITEM) );
  126. lvi.mask = LVIF_IMAGE;
  127. lvi.iItem = 0x7ffffff;
  128. for( int i = 0; i < nIcons; i++ )
  129. {
  130. lvi.iImage = i;
  131. ListView_InsertItem( GetDlgItem(IDC_ICONLIST), &lvi );
  132. }
  133. return TRUE;
  134. }
  135. BOOL CQueryIconPage::OnSetActive()
  136. {
  137. UpdateButtons();
  138. // Select current choice
  139. HWND hwndIconList = GetDlgItem(IDC_ICONLIST);
  140. if( m_pQueryNode && hwndIconList && ::IsWindow(hwndIconList) )
  141. {
  142. if (ListView_GetSelectedCount(hwndIconList) == 0 )
  143. {
  144. ListView_SetItemState( hwndIconList, m_pQueryNode->GetImage(), LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED );
  145. }
  146. }
  147. return TRUE;
  148. }
  149. BOOL CQueryIconPage::OnKillActive()
  150. {
  151. return TRUE;
  152. }
  153. LRESULT CQueryIconPage::OnIconSelected( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
  154. {
  155. // On select icon... update the internal icon number
  156. int nItem = -1;
  157. HWND hwndIconList = GetDlgItem(IDC_ICONLIST);
  158. while( m_pQueryNode && hwndIconList && ::IsWindow(hwndIconList) && ((nItem = ListView_GetNextItem(hwndIconList, nItem, LVNI_SELECTED)) != -1) )
  159. {
  160. m_pQueryNode->SetImage(nItem);
  161. }
  162. UpdateButtons();
  163. return 0;
  164. }
  165. void CQueryIconPage::UpdateButtons()
  166. {
  167. if( !m_pQueryNode ) return;
  168. DWORD dwButtons = PSWIZB_BACK;
  169. if( m_pQueryNode->GetImage() != -1 )
  170. dwButtons |= PSWIZB_NEXT;
  171. ::PropSheet_SetWizButtons(GetParent(), dwButtons);
  172. }
  173. //////////////////////////////////////////////////////////////////////////////////////////
  174. // CObjectWizPage
  175. LRESULT CObjectWizPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  176. {
  177. // default to define query objects
  178. Button_SetCheck(GetDlgItem(IDC_DEFINE_QUERY_OBJS), BST_CHECKED);
  179. return TRUE;
  180. }
  181. BOOL CObjectWizPage::OnSetActive()
  182. {
  183. if( !m_pvpClassInfo || m_pvpClassInfo->empty() ) return FALSE;
  184. DisplayNameMap* pNameMap = DisplayNames::GetClassMap();
  185. ASSERT( pNameMap );
  186. if( !pNameMap ) return FALSE;
  187. // Create list of new object classes
  188. std::vector<CClassInfo*>::iterator itpClass = m_pvpClassInfo->begin();
  189. tstring strClasses = pNameMap->GetAttributeDisplayName((*itpClass)->Name());
  190. for( itpClass++; itpClass != m_pvpClassInfo->end(); ++itpClass )
  191. {
  192. strClasses += L", ";
  193. strClasses += pNameMap->GetAttributeDisplayName((*itpClass)->Name());
  194. }
  195. SetDlgItemText( IDC_OBJCLASS, strClasses.c_str() );
  196. ::PostMessage(GetParent(), PSM_SETWIZBUTTONS, (WPARAM)0, (LPARAM)PSWIZB_BACK|PSWIZB_NEXT);
  197. return TRUE;
  198. }
  199. LRESULT CObjectWizPage::OnSkipChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  200. {
  201. m_bSkipObjects = Button_GetCheck(GetDlgItem(IDC_SKIP_QUERY_OBJS)) == BST_CHECKED;
  202. return 0;
  203. }
  204. //////////////////////////////////////////////////////////////////////////////////////////
  205. // CMenuWizPage
  206. LRESULT CMenuWizPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  207. {
  208. HWND hwndList = GetDlgItem(IDC_MENULIST);
  209. ASSERT(hwndList != NULL);
  210. if( !hwndList || !::IsWindow(hwndList) ) return 0;
  211. m_MenuLV.Attach(hwndList);
  212. RECT rc;
  213. BOOL bStat = m_MenuLV.GetClientRect(&rc);
  214. ASSERT(bStat);
  215. if( !bStat ) return 0;
  216. int iWidth = (rc.right - rc.left) - GetSystemMetrics(SM_CXVSCROLL);
  217. CString strName;
  218. strName.LoadString(IDS_NAME);
  219. int iCol = m_MenuLV.InsertColumn(0, strName, LVCFMT_LEFT, iWidth/4, 0);
  220. ASSERT(iCol == 0);
  221. strName.LoadString(IDS_TYPE);
  222. iCol = m_MenuLV.InsertColumn(1, strName, LVCFMT_LEFT, iWidth/4, 1);
  223. ASSERT(iCol == 1);
  224. strName.LoadString(IDS_DETAILS);
  225. iCol = m_MenuLV.InsertColumn(2, strName, LVCFMT_LEFT, iWidth/2, 2);
  226. ASSERT(iCol == 2);
  227. m_MenuLV.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
  228. return 0;
  229. }
  230. BOOL CMenuWizPage::OnSetActive()
  231. {
  232. HWND hwndLV = GetDlgItem(IDC_MENULIST);
  233. if( !hwndLV || !::IsWindow(hwndLV) ) return FALSE;
  234. if( !m_pClassInfo ) return FALSE;
  235. ListView_DeleteAllItems(hwndLV);
  236. // Display selection text with current class name
  237. DisplayNameMap* dnMap = DisplayNames::GetClassMap();
  238. if( !dnMap ) return FALSE;
  239. LPCWSTR pszTemp = m_pClassInfo->Name();
  240. if( !pszTemp ) return FALSE;
  241. LPCWSTR pszClass = dnMap->GetAttributeDisplayName( pszTemp );
  242. if( !pszClass ) return FALSE;
  243. CString strSelect;
  244. strSelect.Format(IDS_SELECT_MENUS, pszClass);
  245. SetDlgItemText( IDC_SELECT_MENUS, strSelect );
  246. // Display list of current menu commands
  247. menucmd_vector::iterator itMenu;
  248. for( itMenu = m_pClassInfo->Menus().begin(); itMenu != m_pClassInfo->Menus().end(); ++itMenu )
  249. {
  250. AddMenuItem(*itMenu);
  251. }
  252. EnableDlgItem( m_hWnd, IDC_REMOVEMENU, FALSE );
  253. ::PostMessage(GetParent(), PSM_SETWIZBUTTONS, (WPARAM)0, (LPARAM)PSWIZB_BACK|PSWIZB_NEXT);
  254. return TRUE;
  255. }
  256. LRESULT CMenuWizPage::OnAddMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  257. {
  258. if( !m_pClassInfo ) return 0;
  259. CAddMenuDlg dlg(*m_pClassInfo);
  260. if( dlg.DoModal() == IDOK )
  261. {
  262. CMenuCmd* pMenuNew = dlg.GetMenu();
  263. ASSERT(pMenuNew != NULL);
  264. if( pMenuNew )
  265. {
  266. // Use temp string because string class fails an assignement like: strX = strX.c_str()
  267. // (it relases the private buffer first and then assigns the string)
  268. tstring strName = pMenuNew->Name();
  269. pMenuNew->SetName(m_pStringTable, strName.c_str());
  270. // Add menu to list
  271. AddMenuItem(pMenuNew);
  272. // Add to menu vector (note that temp CMenuCmdPtr will delete pMenuNew
  273. // after the vector copies it)
  274. m_pClassInfo->Menus().push_back(CMenuCmdPtr(pMenuNew));
  275. }
  276. }
  277. return 0;
  278. }
  279. void CMenuWizPage::AddMenuItem(CMenuCmd* pMenuCmd)
  280. {
  281. if( !pMenuCmd ) return;
  282. // Set first column to menu name
  283. LVITEM lvi;
  284. lvi.mask = LVIF_PARAM | LVIF_TEXT;
  285. lvi.iSubItem = 0;
  286. lvi.iItem = 0xfffffff; // large number
  287. lvi.lParam = pMenuCmd->ID();
  288. lvi.pszText = const_cast<LPWSTR>(pMenuCmd->Name());
  289. int iPos = m_MenuLV.InsertItem(&lvi);
  290. ASSERT(iPos >= 0);
  291. // Type and details columns are menu type depedent
  292. CString strType;
  293. LPCWSTR pszDetail = NULL;
  294. switch( pMenuCmd->MenuType() )
  295. {
  296. case MENUTYPE_SHELL:
  297. strType.LoadString(IDS_SHELLCMD);
  298. pszDetail = static_cast<CShellMenuCmd*>(pMenuCmd)->ProgramName();
  299. break;
  300. case MENUTYPE_ACTDIR:
  301. strType.LoadString(IDS_DISPSPEC);
  302. DisplayNameMap* dnMap = DisplayNames::GetClassMap();
  303. if( !dnMap ) return;
  304. if( !m_pClassInfo ) return;
  305. LPCWSTR pszTemp = m_pClassInfo->Name();
  306. if( !pszTemp ) return;
  307. pszDetail = dnMap->GetAttributeDisplayName( pszTemp );
  308. break;
  309. }
  310. // Second column is Type
  311. lvi.mask = LVIF_TEXT;
  312. lvi.iItem = iPos;
  313. lvi.iSubItem = 1;
  314. lvi.pszText = (LPWSTR)(LPCWSTR)strType;
  315. BOOL bStat = m_MenuLV.SetItem(&lvi);
  316. ASSERT(bStat);
  317. // Third column is Details
  318. lvi.iSubItem = 2;
  319. lvi.pszText = (LPWSTR)pszDetail;
  320. bStat = m_MenuLV.SetItem(&lvi);
  321. ASSERT(bStat);
  322. }
  323. LRESULT CMenuWizPage::OnRemoveMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  324. {
  325. if( !m_pClassInfo ) return 0;
  326. menucmd_vector& vMenus = m_pClassInfo->Menus();
  327. LVITEM lvi;
  328. lvi.mask = LVIF_PARAM;
  329. lvi.iSubItem = 0;
  330. int iIndex = -1;
  331. while( (iIndex = m_MenuLV.GetNextItem(iIndex, LVNI_SELECTED)) >= 0 )
  332. {
  333. lvi.iItem = iIndex;
  334. m_MenuLV.GetItem(&lvi);
  335. // Locate menu by its ID
  336. menucmd_vector::iterator itMenu = std::find(vMenus.begin(), vMenus.end(), lvi.lParam);
  337. ASSERT(itMenu != vMenus.end());
  338. if( itMenu == vMenus.end() )
  339. {
  340. return 0;
  341. }
  342. vMenus.erase(itMenu);
  343. m_MenuLV.DeleteItem(iIndex);
  344. iIndex--;
  345. }
  346. EnableDlgItem( m_hWnd, IDC_REMOVEMENU, FALSE );
  347. return 0;
  348. }
  349. LRESULT CMenuWizPage::OnMenuListChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  350. {
  351. EnableDlgItem( m_hWnd, IDC_REMOVEMENU, (m_MenuLV.GetSelectedCount() > 0) );
  352. return TRUE;
  353. }
  354. //////////////////////////////////////////////////////////////////////////////////////////
  355. // CPropertyWizPage
  356. LRESULT CPropertyWizPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  357. {
  358. HWND hwndList = GetDlgItem(IDC_COLUMNLIST);
  359. ASSERT( hwndList );
  360. if( hwndList )
  361. {
  362. m_ColumnLV.SubclassWindow(hwndList);
  363. m_ColumnLV.SetExtendedListViewStyle(LVS_EX_CHECKBOXES);
  364. ConfigSingleColumnListView(hwndList);
  365. }
  366. return 0;
  367. }
  368. void CPropertyWizPage::SetDialogText(LPCTSTR pszClass)
  369. {
  370. // Insert class name in "Select one or more..." text
  371. CString strSelect;
  372. strSelect.Format(IDS_SELECT_PROPERTIES, pszClass);
  373. SetDlgItemText( IDC_SELECT_COLUMNS, strSelect );
  374. }
  375. BOOL CPropertyWizPage::OnSetActive()
  376. {
  377. if( !m_pClassInfo ) return FALSE;
  378. m_ColumnLV.DeleteAllItems();
  379. // Display selection text with current class name
  380. DisplayNameMap* dnMap = DisplayNames::GetClassMap();
  381. if( !dnMap ) return FALSE;
  382. LPCWSTR pszTemp = m_pClassInfo->Name();
  383. if( !pszTemp ) return FALSE;
  384. LPCWSTR pszClass = dnMap->GetAttributeDisplayName( pszTemp );
  385. if( !pszClass ) return FALSE;
  386. SetDialogText(pszClass);
  387. // Get attributes with friendly names for this class
  388. DisplayNameMap* pNameMap = DisplayNames::GetMap( pszTemp );
  389. ASSERT( pNameMap );
  390. if( !pNameMap ) return FALSE;
  391. string_vector vstrColumns;
  392. pNameMap->GetFriendlyNames(&vstrColumns);
  393. // Block change processing when setting checkbox states
  394. m_bLoading = TRUE;
  395. // Add friendly name to list
  396. LV_ITEM lvi;
  397. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  398. lvi.iItem = 0;
  399. lvi.iSubItem = 0;
  400. string_vector::iterator itstrCol;
  401. for( itstrCol = vstrColumns.begin(); itstrCol != vstrColumns.end(); ++itstrCol )
  402. {
  403. lvi.pszText = const_cast<LPWSTR>(pNameMap->GetAttributeDisplayName(itstrCol->c_str()));
  404. lvi.lParam = reinterpret_cast<LPARAM>(itstrCol->c_str());
  405. int iPos = m_ColumnLV.InsertItem(&lvi);
  406. ASSERT(iPos >= 0);
  407. // Enable column if selected in the class info
  408. if( std::find(m_pClassInfo->Columns().begin(), m_pClassInfo->Columns().end(), *itstrCol) != m_pClassInfo->Columns().end() )
  409. m_ColumnLV.SetCheckState(iPos, TRUE);
  410. }
  411. m_bLoading = FALSE;
  412. ::PostMessage( GetParent(), PSM_SETWIZBUTTONS, (WPARAM)0, (LPARAM)(PSWIZB_BACK | PSWIZB_NEXT) );
  413. return TRUE;
  414. }
  415. LRESULT CPropertyWizPage::OnColumnChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  416. {
  417. if( !pNMHDR ) return 0;
  418. if( !m_bLoading )
  419. {
  420. LPNMLISTVIEW pnmv = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  421. // if checked state has changed
  422. if( (pnmv->uChanged & LVIF_STATE) &&
  423. ((pnmv->uNewState ^ pnmv->uOldState) & LVIS_STATEIMAGEMASK) )
  424. {
  425. // if the changed item is currently selected
  426. if( m_ColumnLV.GetItemState(pnmv->iItem, LVIS_SELECTED) & LVIS_SELECTED )
  427. {
  428. // Change the state of all selcted items to match
  429. BOOL bNewState = ((pnmv->uNewState & LVIS_STATEIMAGEMASK) == CHECK_ON);
  430. m_bLoading = TRUE;
  431. int iItem = -1;
  432. while( (iItem = m_ColumnLV.GetNextItem(iItem, LVNI_SELECTED)) >= 0 )
  433. {
  434. m_ColumnLV.SetCheckState(iItem, bNewState);
  435. }
  436. m_bLoading = FALSE;
  437. }
  438. }
  439. }
  440. return TRUE;
  441. }
  442. BOOL CPropertyWizPage::OnKillActive()
  443. {
  444. string_vector vstrNewCols;
  445. int nItems = m_ColumnLV.GetItemCount();
  446. for( int iIndex = 0; iIndex < nItems; iIndex++ )
  447. {
  448. // Save list of enabled columns
  449. if( m_ColumnLV.GetCheckState(iIndex) )
  450. {
  451. LVITEM lvi;
  452. lvi.mask = LVIF_PARAM;
  453. lvi.iItem = iIndex;
  454. lvi.iSubItem = 0;
  455. BOOL bStat = m_ColumnLV.GetItem(&lvi);
  456. ASSERT(bStat);
  457. vstrNewCols.push_back(reinterpret_cast<LPCWSTR>(lvi.lParam));
  458. }
  459. }
  460. if( m_pClassInfo )
  461. {
  462. m_pClassInfo->Columns() = vstrNewCols;
  463. }
  464. return TRUE;
  465. }
  466. /////////////////////////////////////////////////////////////////////////////////////////
  467. // CColumnWizPage
  468. void CColumnWizPage::SetDialogText(LPCTSTR pszClass)
  469. {
  470. // Put class name in "Select one or more..." text
  471. CString strSelect;
  472. strSelect.Format(IDS_SELECT_COLUMNS, pszClass);
  473. SetDlgItemText( IDC_SELECT_COLUMNS, strSelect );
  474. // Change list box label to "Available columns:"
  475. tstring strLabel = StrLoadString(IDS_AVAIL_COLUMNS);
  476. SetDlgItemText( IDC_LIST_LABEL, strLabel.c_str() );
  477. }
  478. //////////////////////////////////////////////////////////////////////////////////////////
  479. // CAddQueryCompletionPage
  480. LRESULT CAddQueryCompletionPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  481. {
  482. if( !m_pWizard ) return 0;
  483. HFONT hfont = m_pWizard->GetWelcomeFont();
  484. if( hfont )
  485. {
  486. SendDlgItemMessage( IDC_COMPLETION, WM_SETFONT, (WPARAM)hfont, (LPARAM)0 );
  487. }
  488. // Remove edge from edit control
  489. HWND hwndSetting = GetDlgItem(IDC_SETTINGS);
  490. if( hwndSetting )
  491. {
  492. ::ModifyStyleEx(hwndSetting, WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);
  493. }
  494. return 0;
  495. }
  496. BOOL CAddQueryCompletionPage::OnSetActive()
  497. {
  498. if( !m_pWizard ) return FALSE;
  499. if( !m_pQueryNode ) return FALSE;
  500. const static TCHAR newline[] = TEXT("\r\n");
  501. ::PostMessage(GetParent(), PSM_SETWIZBUTTONS, (WPARAM)0, (LPARAM)PSWIZB_BACK|PSWIZB_FINISH);
  502. // Create query node nameed: <query name>
  503. CString strOut;
  504. CString strTmp;
  505. strTmp.LoadString(IDS_QUERYFINISH1);
  506. strOut += strTmp;
  507. strOut += static_cast<CAddQueryWizard*>(m_pWizard)->GetQueryName();
  508. strOut += newline;
  509. // Display objects of type: <object class>
  510. tstring strClasses;
  511. GetClassNameList(m_pQueryNode->Objects(), strClasses, L", ");
  512. strTmp.LoadString(IDS_QUERYFINISH2);
  513. strOut += strTmp;
  514. strOut += strClasses.c_str();
  515. strOut += newline;
  516. // From: <query scope>
  517. tstring strDisplay;
  518. tstring strScope = m_pQueryNode->Scope();
  519. GetScopeDisplayString(strScope, strDisplay);
  520. strTmp.LoadString(IDS_QUERYFINISH3);
  521. strOut += strTmp;
  522. strOut += strDisplay.c_str();
  523. strOut += newline;
  524. // Menu items ... available to other query nodes for: <object class>
  525. strTmp.LoadString(IDS_QUERYFINISH4);
  526. strOut += strTmp;
  527. strOut += strClasses.c_str();
  528. SetDlgItemText( IDC_SETTINGS, strOut );
  529. return TRUE;
  530. }
  531. /////////////////////////////////////////////////////////////////////////////////////////
  532. // CWizardBase
  533. HFONT CWizardBase::GetWelcomeFont()
  534. {
  535. if( m_hFontWelcome == 0 )
  536. {
  537. // copied from wiz97.cpp (sample code)
  538. NONCLIENTMETRICS ncm = {0};
  539. ncm.cbSize = sizeof (ncm);
  540. if( SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &ncm, 0) )
  541. {
  542. LOGFONT lf = ncm.lfMessageFont;
  543. // get font name from resource 'Verdana Bold'
  544. WCHAR szFont[32];
  545. ::LoadString( (HINSTANCE)_Module.GetModuleInstance(), IDS_WIZARD97_FONT, szFont, 32 );
  546. lstrcpyn( lf.lfFaceName, szFont, 32);
  547. int FontSize = 12;
  548. lf.lfWeight = FW_BOLD;
  549. HDC hdc = GetDC(NULL);
  550. lf.lfHeight = 0 - (GetDeviceCaps(hdc, LOGPIXELSY) * 12)/72;
  551. ReleaseDC(NULL,hdc);
  552. m_hFontWelcome = CreateFontIndirect (&lf);
  553. }
  554. }
  555. return m_hFontWelcome;
  556. }
  557. void CWizardBase::SetWizardBitmaps(UINT watermarkID, UINT headerID)
  558. {
  559. m_propsheet.m_psh.dwFlags |= PSH_WIZARD|PSH_WIZARD97|
  560. PSH_USEHBMWATERMARK|PSH_WATERMARK|PSH_USEHBMHEADER|PSH_HEADER;
  561. CBitmap bmWatermark;
  562. bmWatermark.LoadBitmap(watermarkID);
  563. m_propsheet.m_psh.hbmWatermark = bmWatermark.Detach();
  564. ASSERT(m_propsheet.m_psh.hbmWatermark != NULL);
  565. CBitmap bmHeader;
  566. bmHeader.LoadBitmap(headerID);
  567. m_propsheet.m_psh.hbmHeader = bmHeader.Detach();
  568. ASSERT(m_propsheet.m_psh.hbmHeader != NULL);
  569. }
  570. /////////////////////////////////////////////////////////////////////////////////////////
  571. // CAddQueryWizard
  572. HRESULT CAddQueryWizard::Run(IPropertySheetProvider* pProvider, HWND hwndParent)
  573. {
  574. SetWizardBitmaps(IDB_ADDQUERY, IDB_ADDQUERY_HDR);
  575. if( !AddPage(m_WelcomePage.Create()) ) return E_FAIL;
  576. if( !AddPage(m_QueryPage.Create()) ) return E_FAIL;
  577. if( !AddPage(m_ObjectPage.Create()) ) return E_FAIL;
  578. if( !AddPage(m_MenuPage.Create()) ) return E_FAIL;
  579. if( !AddPage(m_PropertyPage.Create()) ) return E_FAIL;
  580. if( !AddPage(m_IconPage.Create()) ) return E_FAIL;
  581. if( !AddPage(m_CompletionPage.Create()) ) return E_FAIL;
  582. int iRet = DoModal(hwndParent);
  583. return(iRet == IDOK) ? S_OK : S_FALSE;;
  584. }
  585. int CAddQueryWizard::OnNext(UINT uPageID)
  586. {
  587. int iRet = 0;
  588. switch( uPageID )
  589. {
  590. case IDD_QUERY_WIZ_QUERY:
  591. // Dtermine classes returned by query
  592. SelectClasses();
  593. // if no classes, skip to finish page
  594. if( m_vpClassInfo.size() == 0 )
  595. {
  596. iRet = IDD_SELECTICON_PAGE;
  597. }
  598. else
  599. {
  600. // Pass new classes to object page
  601. m_ObjectPage.SetClassInfo(&m_vpClassInfo);
  602. }
  603. break;
  604. case IDD_QUERY_WIZ_OBJECT:
  605. // if user wants to defer menu and prop selection, skip to finish
  606. if( m_ObjectPage.SkipObjects() )
  607. {
  608. iRet = IDD_SELECTICON_PAGE;
  609. }
  610. else
  611. {
  612. // go to menu page for first class
  613. m_iClassIndex = 0;
  614. m_MenuPage.SetClassInfo(m_vpClassInfo[0]);
  615. }
  616. break;
  617. case IDD_COMMON_WIZ_MENU:
  618. m_PropertyPage.SetClassInfo(m_vpClassInfo[m_iClassIndex]);
  619. break;
  620. case IDD_COMMON_WIZ_PROPERTIES:
  621. // if not on last class, go to menu page for next class
  622. if( ++m_iClassIndex < m_vpClassInfo.size() )
  623. {
  624. m_MenuPage.SetClassInfo(m_vpClassInfo[m_iClassIndex]);
  625. iRet = IDD_COMMON_WIZ_MENU;
  626. }
  627. }
  628. return iRet;
  629. }
  630. int CAddQueryWizard::OnBack(UINT uPageID)
  631. {
  632. int iRet = 0;
  633. switch( uPageID )
  634. {
  635. case IDD_COMMON_WIZ_MENU:
  636. // if not on first class, go to property page for previous class
  637. if( m_iClassIndex > 0 )
  638. {
  639. m_iClassIndex--;
  640. m_PropertyPage.SetClassInfo(m_vpClassInfo[m_iClassIndex]);
  641. iRet = IDD_COMMON_WIZ_PROPERTIES;
  642. }
  643. break;
  644. case IDD_COMMON_WIZ_PROPERTIES:
  645. m_MenuPage.SetClassInfo(m_vpClassInfo[m_iClassIndex]);
  646. break;
  647. case IDD_SELECTICON_PAGE:
  648. // if there are no classes, go back to query page
  649. if( m_vpClassInfo.size() == 0 )
  650. {
  651. iRet = IDD_QUERY_WIZ_QUERY;
  652. }
  653. // if classes skipped, go back to objects page
  654. else if( m_ObjectPage.SkipObjects() )
  655. {
  656. iRet = IDD_QUERY_WIZ_OBJECT;
  657. }
  658. else
  659. {
  660. // go to prop page for the last class
  661. m_iClassIndex = m_vpClassInfo.size() - 1;
  662. m_PropertyPage.SetClassInfo(m_vpClassInfo[m_iClassIndex]);
  663. }
  664. break;
  665. }
  666. return iRet;
  667. }
  668. BOOL CAddQueryWizard::OnCancel()
  669. {
  670. int iRet = DisplayMessageBox(GetActivePage(), IDS_ADDQUERY_WIZ, IDS_QUERYWIZ_CANCEL, MB_YESNO);
  671. return(iRet == IDYES);
  672. }
  673. void CAddQueryWizard::SelectClasses()
  674. {
  675. if( !m_pQueryNode ) return;
  676. // First delete any ClassInfo's the wizard has created that are no longer valid.
  677. // This can happen if the user backs up to the query page and redefines the query
  678. std::vector<CClassInfo*>::iterator itpClass = m_vpClassInfo.begin();
  679. while( itpClass != m_vpClassInfo.end() )
  680. {
  681. QueryObjVector::iterator itObj;
  682. for( itObj = m_pQueryNode->Objects().begin(); itObj != m_pQueryNode->Objects().end(); ++itObj )
  683. {
  684. LPCWSTR pszBuf1 = itObj->Name();
  685. LPCWSTR pszBuf2 = (*itpClass)->Name();
  686. if( pszBuf1 && pszBuf2 && (wcscmp(pszBuf1, pszBuf2) == 0) )
  687. {
  688. break;
  689. }
  690. }
  691. // if class not referenced by query
  692. if( itObj == m_pQueryNode->Objects().end() )
  693. {
  694. // delete the class and remove from vector (vector::erase advances to next item)
  695. delete *itpClass;
  696. itpClass = m_vpClassInfo.erase(itpClass);
  697. }
  698. else
  699. ++itpClass;
  700. }
  701. // Now create new ClassInfo for any classes referenced by the query that have not been created
  702. // by the wizard and are not already defined at the root node
  703. QueryObjVector::iterator itObj;
  704. for( itObj = m_pQueryNode->Objects().begin(); itObj != m_pQueryNode->Objects().end(); ++itObj )
  705. {
  706. for( itpClass = m_vpClassInfo.begin(); itpClass != m_vpClassInfo.end(); ++itpClass )
  707. {
  708. LPCWSTR pszBuf1 = itObj->Name();
  709. LPCWSTR pszBuf2 = (*itpClass)->Name();
  710. if( pszBuf1 && pszBuf2 && (wcscmp(pszBuf1, pszBuf2) == 0) )
  711. {
  712. break;
  713. }
  714. }
  715. if( itpClass == m_vpClassInfo.end() && m_pRootNode->FindClass(itObj->Name()) == NULL )
  716. {
  717. CClassInfo* pClassNew = new CClassInfo(itObj->Name());
  718. ASSERT(pClassNew != NULL);
  719. if( pClassNew )
  720. {
  721. m_vpClassInfo.push_back(pClassNew);
  722. }
  723. }
  724. }
  725. }
  726. /////////////////////////////////////////////////////////////////////////////////////////
  727. // CAddObjectWizard
  728. HRESULT CAddObjectWizard::Run(IPropertySheetProvider* pProvider, HWND hwndParent)
  729. {
  730. SetWizardBitmaps(IDB_ADDOBJECT,IDB_ADDOBJECT_HDR);
  731. if( !AddPage(m_WelcomePage.Create()) ) return E_FAIL;
  732. if( !AddPage(m_ObjSelectPage.Create()) ) return E_FAIL;
  733. if( !AddPage(m_MenuPage.Create()) ) return E_FAIL;
  734. if( !AddPage(m_PropertyPage.Create()) ) return E_FAIL;
  735. if( !AddPage(m_CompletionPage.Create()) ) return E_FAIL;
  736. int iRet = DoModal(hwndParent);
  737. if( iRet != IDOK && m_pClassInfo != NULL )
  738. {
  739. delete m_pClassInfo;
  740. m_pClassInfo = NULL;
  741. }
  742. return(iRet == IDOK) ? S_OK : S_FALSE;
  743. }
  744. int CAddObjectWizard::OnNext(UINT uPageID)
  745. {
  746. switch( uPageID )
  747. {
  748. case IDD_OBJECT_WIZ_SELECT:
  749. {
  750. LPCWSTR pszClass = m_ObjSelectPage.GetSelectedClass();
  751. ASSERT( pszClass );
  752. if( !pszClass ) break;
  753. if( m_pClassInfo == NULL )
  754. {
  755. // if first selection, create a class info
  756. m_pClassInfo = new CClassInfo(pszClass);
  757. }
  758. else if( wcscmp(m_pClassInfo->Name(), pszClass) != 0 )
  759. {
  760. // if class changed, replace the class info
  761. delete m_pClassInfo;
  762. m_pClassInfo = new CClassInfo(pszClass);
  763. }
  764. ASSERT( m_pClassInfo );
  765. if( m_pClassInfo )
  766. {
  767. // Pass class info to menu page
  768. m_MenuPage.SetClassInfo(m_pClassInfo);
  769. }
  770. break;
  771. }
  772. case IDD_COMMON_WIZ_MENU:
  773. {
  774. ASSERT( m_pClassInfo );
  775. if( m_pClassInfo )
  776. {
  777. m_PropertyPage.SetClassInfo(m_pClassInfo);
  778. }
  779. break;
  780. }
  781. case IDD_COMMON_WIZ_PROPERTIES:
  782. {
  783. ASSERT( m_pClassInfo );
  784. if( m_pClassInfo )
  785. {
  786. m_CompletionPage.SetClassInfo(m_pClassInfo);
  787. }
  788. break;
  789. }
  790. }
  791. return 0;
  792. }
  793. BOOL CAddObjectWizard::OnCancel()
  794. {
  795. int iRet = DisplayMessageBox(GetActivePage(), IDS_ADDOBJECT_WIZ, IDS_OBJWIZ_CANCEL, MB_YESNO);
  796. return(iRet == IDYES);
  797. }
  798. //////////////////////////////////////////////////////////////////////////////////////////
  799. // CObjSelectWizPage
  800. LRESULT CObjSelectWizPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  801. {
  802. if( !m_pvstrCurClasses ) return 0;
  803. // Get list of classes with friendly names
  804. DisplayNameMap* pNameMap = DisplayNames::GetClassMap();
  805. if( !pNameMap ) return 0;
  806. string_vector vstrAllObjects;
  807. pNameMap->GetFriendlyNames(&vstrAllObjects);
  808. HWND hwndList = GetDlgItem(IDC_OBJECTLIST);
  809. ASSERT(hwndList != NULL);
  810. if( !hwndList ) return 0;
  811. // Display list of classes that aren't already used (i.e., not in m_vstrCurClasses)
  812. string_vector::iterator itStr;
  813. for( itStr = vstrAllObjects.begin(); itStr != vstrAllObjects.end(); itStr++ )
  814. {
  815. if( std::find(m_pvstrCurClasses->begin(), m_pvstrCurClasses->end(), *itStr) == m_pvstrCurClasses->end() )
  816. {
  817. LPCWSTR pszName = pNameMap ?
  818. pNameMap->GetAttributeDisplayName(itStr->c_str()) : itStr->c_str();
  819. int iPos = ListBox_AddString(hwndList, const_cast<LPWSTR>(pszName));
  820. ASSERT(iPos >= 0);
  821. ListBox_SetItemData(hwndList, iPos, (LPARAM*)itStr->c_str());
  822. }
  823. }
  824. return 0;
  825. }
  826. BOOL CObjSelectWizPage::OnSetActive()
  827. {
  828. UpdateButtons();
  829. return TRUE;
  830. }
  831. LRESULT CObjSelectWizPage::OnObjectSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  832. {
  833. UpdateButtons();
  834. return 0;
  835. }
  836. void CObjSelectWizPage::UpdateButtons()
  837. {
  838. DWORD dwButtons = PSWIZB_BACK;
  839. if( ListBox_GetCurSel(GetDlgItem(IDC_OBJECTLIST)) >= 0 )
  840. dwButtons |= PSWIZB_NEXT;
  841. ::PropSheet_SetWizButtons(GetParent(), dwButtons);
  842. }
  843. LPCWSTR CObjSelectWizPage::GetSelectedClass()
  844. {
  845. HWND hwndList = GetDlgItem(IDC_OBJECTLIST);
  846. ASSERT(hwndList != NULL);
  847. int iSel = ListBox_GetCurSel(hwndList);
  848. ASSERT(iSel >= 0);
  849. LPARAM lParam = ListBox_GetItemData(hwndList, iSel);
  850. ASSERT(lParam != LB_ERR);
  851. return reinterpret_cast<LPCWSTR>(lParam);
  852. }
  853. //////////////////////////////////////////////////////////////////////////////////////////
  854. // CAddObjectWelcomePage
  855. LRESULT CAddObjectWelcomePage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  856. {
  857. if( !m_pWizard ) return 0;
  858. HFONT hfont = m_pWizard->GetWelcomeFont();
  859. if( hfont )
  860. ::SendMessage(GetDlgItem(IDC_WELCOME), WM_SETFONT, (WPARAM)hfont, (LPARAM)0);
  861. return 0;
  862. }
  863. BOOL CAddObjectWelcomePage::OnSetActive()
  864. {
  865. ::PostMessage(GetParent(), PSM_SETTITLE, 0, (LPARAM)IDS_ADDOBJECT_WIZ);
  866. ::PostMessage(GetParent(), PSM_SETWIZBUTTONS, (WPARAM)0, (LPARAM)PSWIZB_NEXT);
  867. return TRUE;
  868. }
  869. //////////////////////////////////////////////////////////////////////////////////////////
  870. // CAddObjectCompletionPage
  871. LRESULT CAddObjectCompletionPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  872. {
  873. if( !m_pWizard ) return 0;
  874. HFONT hfont = m_pWizard->GetWelcomeFont();
  875. if( hfont )
  876. {
  877. ::SendMessage(GetDlgItem(IDC_COMPLETION), WM_SETFONT, (WPARAM)hfont, (LPARAM)0);
  878. }
  879. return 0;
  880. }
  881. BOOL CAddObjectCompletionPage::OnSetActive()
  882. {
  883. if( !m_pClassInfo ) return FALSE;
  884. const static TCHAR newline[] = TEXT("\r\n");
  885. // Get class name table
  886. DisplayNameMap* pNameMap = DisplayNames::GetClassMap();
  887. ASSERT( pNameMap );
  888. if( !pNameMap ) return FALSE;
  889. // "Allow query node to be created for object: <class name>"
  890. CString strOut;
  891. CString strTmp;
  892. strTmp.LoadString(IDS_OBJFINISH1);
  893. strOut += strTmp;
  894. strOut += pNameMap->GetAttributeDisplayName(m_pClassInfo->Name());
  895. strOut += newline;
  896. // if any menu items defined
  897. if( m_pClassInfo->Menus().size() > 0 )
  898. {
  899. // "Enable query nodes to use menu items:"
  900. strTmp.LoadString(IDS_OBJFINISH2);
  901. strOut += strTmp;
  902. strOut += newline;
  903. menucmd_vector& vMenuCmds = m_pClassInfo->Menus();
  904. menucmd_vector::iterator itMenuCmd;
  905. // First add all root menu items that are not yet ref'd by the query node
  906. for( itMenuCmd = vMenuCmds.begin(); itMenuCmd != vMenuCmds.end(); ++itMenuCmd )
  907. {
  908. strOut += " ";
  909. strOut += (*itMenuCmd)->Name();
  910. strOut += newline;
  911. }
  912. }
  913. // if any columns defined
  914. if( m_pClassInfo->Columns().size() > 0 )
  915. {
  916. strTmp.LoadString(IDS_OBJFINISH3);
  917. strOut += strTmp;
  918. strOut += newline;
  919. pNameMap = DisplayNames::GetMap(m_pClassInfo->Name());
  920. ASSERT(pNameMap != NULL);
  921. string_vector& vstrColumns = m_pClassInfo->Columns();
  922. string_vector::iterator itstrCol;
  923. for( itstrCol = vstrColumns.begin(); itstrCol != vstrColumns.end(); ++itstrCol )
  924. {
  925. strOut += " ";
  926. strOut += pNameMap->GetAttributeDisplayName(itstrCol->c_str());
  927. strOut += newline;
  928. }
  929. }
  930. HWND hwndSetting = GetDlgItem(IDC_SETTINGS);
  931. if( !hwndSetting ) return FALSE;
  932. // Initially assume scroll bar is needed
  933. ::ShowScrollBar(hwndSetting, SB_VERT, TRUE);
  934. // display the text
  935. ::SetWindowText(hwndSetting, strOut);
  936. // now hide vertical scroll if we don't need it
  937. SCROLLINFO si = {0};
  938. si.cbSize = sizeof(SCROLLINFO);
  939. si.fMask = SIF_ALL;
  940. ::GetScrollInfo(hwndSetting, SB_VERT, &si);
  941. if( si.nMax < si.nPage )
  942. {
  943. // Remove scroll bar and hide edge
  944. ::ModifyStyleEx( hwndSetting, WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED );
  945. ::ShowScrollBar( hwndSetting, SB_VERT, FALSE );
  946. }
  947. else
  948. {
  949. // if scroll bar needed, display edge too
  950. ::ModifyStyleEx( hwndSetting, 0, WS_EX_CLIENTEDGE, SWP_FRAMECHANGED );
  951. }
  952. EnableDlgItem( m_hWnd, IDC_SETTINGS, FALSE );
  953. EnableDlgItem( m_hWnd, IDC_SETTINGS, TRUE );
  954. ::PostMessage(GetParent(), PSM_SETWIZBUTTONS, (WPARAM)0, (LPARAM)PSWIZB_BACK|PSWIZB_FINISH);
  955. // enable edit field to handle first focus
  956. bFirstFocus = TRUE;
  957. return TRUE;
  958. }
  959. LRESULT CAddObjectCompletionPage::OnSetFocus( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  960. {
  961. // on first focus, cancel the selection so the user doesn't see the entire field inverted
  962. if( bFirstFocus )
  963. {
  964. ::SendMessage(GetDlgItem(IDC_SETTINGS), EM_SETSEL, (WPARAM)0, (LPARAM)0);
  965. bFirstFocus = FALSE;
  966. }
  967. return 0;
  968. }
  969. ///////////////////////////////////////////////////////////////////////////////////////
  970. // Non-member functions
  971. HRESULT GetClassNameList(QueryObjVector& vObjects, tstring& strNames, LPCWSTR pszSeparator)
  972. {
  973. if( vObjects.size() == 0 )
  974. return S_FALSE;
  975. DisplayNameMap* pNameMap = DisplayNames::GetClassMap();
  976. ASSERT( pNameMap );
  977. if( !pNameMap ) return E_FAIL;
  978. QueryObjVector::iterator itQObj = vObjects.begin();
  979. strNames = pNameMap->GetAttributeDisplayName(itQObj->Name());
  980. for( itQObj++; itQObj != vObjects.end(); ++itQObj )
  981. {
  982. strNames += pszSeparator;
  983. strNames += pNameMap->GetAttributeDisplayName(itQObj->Name());
  984. }
  985. return S_OK;
  986. }