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.

1188 lines
34 KiB

  1. // qryprop.cpp - Query Property Page Implementation
  2. #include "stdafx.h"
  3. #include "resource.h"
  4. #include "qryprop.h"
  5. #include "compdata.h"
  6. #include "scopenode.h"
  7. #include "query.h"
  8. #include "cmndlgs.h"
  9. #include "util.h"
  10. #include "namemap.h"
  11. #define SECURITY_WIN32
  12. #include <security.h> // TranslateName
  13. #include <windowsx.h>
  14. #include <algorithm>
  15. #undef SubclassWindow
  16. int GetDateTimeString(FILETIME* pftime, LPWSTR pszBuf, int cBuf);
  17. void LoadObjectCB(CComboBox& ComboBox, QueryObjVector& vObj);
  18. #define CHECK_OFF INDEXTOSTATEIMAGEMASK(1)
  19. #define CHECK_ON INDEXTOSTATEIMAGEMASK(2)
  20. ///////////////////////////////////////////////////////////////////////////////////////////
  21. // CQueryGeneralPage
  22. CQueryGeneralPage::CQueryGeneralPage(CQueryEditObj* pEditObj)
  23. : m_EditObject(*pEditObj)
  24. {
  25. ASSERT(pEditObj != NULL);
  26. m_EditObject.AddRef();
  27. }
  28. CQueryGeneralPage::~CQueryGeneralPage()
  29. {
  30. m_EditObject.Release();
  31. }
  32. LRESULT CQueryGeneralPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  33. {
  34. if( !m_EditObject.m_spQueryNode ) return 0;
  35. // display query node icon
  36. HICON hIcon = ::LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_QUERYNODE));
  37. Static_SetIcon(GetDlgItem(IDC_QUERYICON), hIcon);
  38. // fill dialog fields with query node info
  39. tstring strTempQuery;
  40. m_EditObject.m_spQueryNode->ExpandQuery(strTempQuery);
  41. CQueryNode* pQNode = m_EditObject.m_spQueryNode;
  42. SetDlgItemText( IDC_NAME, m_EditObject.m_spQueryNode->GetName() );
  43. SetDlgItemText( IDC_FILTER, strTempQuery.c_str() );
  44. tstring strComment;
  45. m_EditObject.m_spQueryNode->GetComment(strComment);
  46. SetDlgItemText( IDC_COMMENTS, strComment.c_str() );
  47. Edit_LimitText(GetDlgItem(IDC_COMMENTS), 255);
  48. // set scope source toggle button
  49. UINT uButton = m_EditObject.m_spQueryNode->UseLocalScope() ? IDC_LOCALSCOPE : IDC_QUERYSCOPE;
  50. Button_SetCheck(GetDlgItem(uButton), BST_CHECKED);
  51. tstring strScope = m_EditObject.m_spQueryNode->Scope();
  52. tstring strDisplay;
  53. GetScopeDisplayString(strScope, strDisplay);
  54. SetDlgItemText( IDC_SCOPE, strDisplay.c_str() );
  55. // if using local scope, then set the persisted scope equal to the local scope so that the
  56. // user won't see an obsolete scope that may have been saved when creating the node.
  57. if( m_EditObject.m_spQueryNode->UseLocalScope() )
  58. m_EditObject.m_spQueryNode->SetScope(strScope.c_str());
  59. // if classes known, display comma separated class names
  60. if( m_EditObject.m_vObjInfo.size() != 0 )
  61. {
  62. DisplayNameMap* pNameMap = DisplayNames::GetClassMap();
  63. ASSERT(pNameMap != NULL);
  64. if( pNameMap != NULL )
  65. {
  66. QueryObjVector::iterator itQObj = m_EditObject.m_vObjInfo.begin();
  67. tstring strClasses = pNameMap->GetAttributeDisplayName(itQObj->Name());
  68. for( itQObj++; itQObj != m_EditObject.m_vObjInfo.end(); ++itQObj )
  69. {
  70. strClasses += L", ";
  71. strClasses += pNameMap->GetAttributeDisplayName(itQObj->Name());
  72. }
  73. SetDlgItemText( IDC_OBJCLASS, strClasses.c_str() );
  74. }
  75. }
  76. return TRUE;
  77. }
  78. LRESULT CQueryGeneralPage::OnScopeChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  79. {
  80. if( !m_EditObject.m_spQueryNode ) return 0;
  81. // if user changes scope selection then display the correct scope
  82. tstring strScope;
  83. if( Button_GetCheck(GetDlgItem(IDC_LOCALSCOPE)) == BST_CHECKED )
  84. strScope = GetLocalDomain();
  85. else
  86. strScope = m_EditObject.m_spQueryNode->QueryScope();
  87. tstring strDisplay;
  88. GetScopeDisplayString(strScope, strDisplay);
  89. SetDlgItemText( IDC_SCOPE, strDisplay.c_str() );
  90. SetModified(TRUE);
  91. return 0;
  92. }
  93. LRESULT CQueryGeneralPage::OnChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  94. {
  95. SetModified(TRUE);
  96. return 0;
  97. }
  98. //------------------------------------------------------------------------------------
  99. // CRootGeneralPage::OnClose
  100. //
  101. // This method is invoked when an edit box receives an Esc char. The method converts
  102. // the WM_CLOSE message into a command to close the property sheet. Otherwise the
  103. // WM_CLOSE message has no effect.
  104. //------------------------------------------------------------------------------------
  105. LRESULT CQueryGeneralPage::OnClose( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  106. {
  107. // Simulate press of Cancel button
  108. ::PropSheet_PressButton(GetParent(), PSBTN_CANCEL);
  109. return 0;
  110. }
  111. BOOL CQueryGeneralPage::OnSetActive()
  112. {
  113. m_EditObject.PageActive(m_hWnd);
  114. return TRUE;
  115. }
  116. BOOL CQueryGeneralPage::OnApply()
  117. {
  118. if( !m_EditObject.m_spQueryNode ) return FALSE;
  119. tstring strComment;
  120. GetItemText(GetDlgItem(IDC_COMMENTS), strComment);
  121. m_EditObject.m_spQueryNode->SetComment(strComment.c_str());
  122. bool bLocal = (Button_GetCheck(GetDlgItem(IDC_LOCALSCOPE)) == BST_CHECKED);
  123. m_EditObject.m_spQueryNode->SetLocalScope(bLocal);
  124. return m_EditObject.ApplyChanges(m_hWnd);
  125. }
  126. ///////////////////////////////////////////////////////////////////////////////////////////
  127. // CQueryMenuPage
  128. CQueryMenuPage::CQueryMenuPage(CQueryEditObj* pEditObj)
  129. : m_EditObject(*pEditObj), m_pObjSel(NULL), m_bLoading(FALSE)
  130. {
  131. ASSERT(pEditObj != NULL);
  132. m_EditObject.AddRef();
  133. }
  134. CQueryMenuPage::~CQueryMenuPage()
  135. {
  136. m_ObjectCB.Detach();
  137. m_EditObject.Release();
  138. }
  139. LRESULT CQueryMenuPage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  140. {
  141. HWND hwndList = GetDlgItem(IDC_MENULIST);
  142. ASSERT( hwndList );
  143. if( hwndList )
  144. {
  145. m_MenuLV.SubclassWindow(hwndList);
  146. RECT rc;
  147. BOOL bStat = m_MenuLV.GetClientRect(&rc);
  148. ASSERT(bStat);
  149. int iWidth = (rc.right - rc.left) - GetSystemMetrics(SM_CXVSCROLL);
  150. CString strName;
  151. strName.LoadString(IDS_MENUITEM);
  152. int iCol = m_MenuLV.InsertColumn(0, strName, LVCFMT_LEFT, (iWidth + 1)/2, 0);
  153. ASSERT(iCol == 0);
  154. strName.LoadString(IDS_TYPE);
  155. iCol = m_MenuLV.InsertColumn(1, strName, LVCFMT_LEFT, iWidth/2, 1);
  156. ASSERT(iCol == 1);
  157. m_MenuLV.SetExtendedListViewStyle(LVS_EX_CHECKBOXES|LVS_EX_FULLROWSELECT);
  158. }
  159. HWND hwndCombo = GetDlgItem(IDC_OBJECTLIST);
  160. ASSERT(hwndCombo);
  161. if( hwndCombo )
  162. {
  163. m_ObjectCB.Attach(hwndCombo);
  164. LoadObjectCB(m_ObjectCB, m_EditObject.m_vObjInfo);
  165. if( m_EditObject.m_vObjInfo.size() != 0 )
  166. {
  167. m_ObjectCB.SetCurSel(0);
  168. m_pObjSel = reinterpret_cast<CQueryObjInfo*>(m_ObjectCB.GetItemDataPtr(0));
  169. if( hwndList )
  170. {
  171. DisplayMenus();
  172. }
  173. }
  174. }
  175. return TRUE;
  176. }
  177. void CQueryMenuPage::DisplayMenus()
  178. {
  179. if( m_pObjSel == NULL )
  180. return;
  181. if( !m_EditObject.m_spQueryNode ) return;
  182. m_bLoading = TRUE;
  183. m_MenuLV.DeleteAllItems();
  184. m_DefaultID = 0;
  185. CRootNode* pRootNode = m_EditObject.m_spQueryNode->GetRootNode();
  186. if( !pRootNode ) return;
  187. CClassInfo* pClassInfo = pRootNode->FindClass(m_pObjSel->Name());
  188. if( pClassInfo != NULL )
  189. {
  190. int iIndex = 0;
  191. menuref_vector& vMenuRefs = m_pObjSel->MenuRefs();
  192. menuref_vector::iterator itMenuRef;
  193. menucmd_vector& vMenuCmds = pClassInfo->Menus();
  194. menucmd_vector::iterator itMenuCmd;
  195. // First add all root menu items that are not yet ref'd by the query node
  196. for( itMenuCmd = vMenuCmds.begin(); itMenuCmd != vMenuCmds.end(); ++itMenuCmd )
  197. {
  198. if( std::find(vMenuRefs.begin(), vMenuRefs.end(), (*itMenuCmd)->ID()) != vMenuRefs.end() )
  199. break;
  200. // Add menu to displayed list in an enabled state
  201. DisplayMenuItem(iIndex++, *itMenuCmd, TRUE);
  202. }
  203. // For each query menu reference
  204. for( itMenuRef = vMenuRefs.begin(); itMenuRef != vMenuRefs.end(); ++itMenuRef )
  205. {
  206. // Find the matching root menu cmd
  207. for( itMenuCmd = vMenuCmds.begin(); itMenuCmd != vMenuCmds.end(); ++itMenuCmd )
  208. {
  209. if( (*itMenuCmd)->ID() == itMenuRef->ID() )
  210. break;
  211. }
  212. // if menu was deleted at the root node, then skip it
  213. if( itMenuCmd == vMenuCmds.end() )
  214. continue;
  215. // Display the menu item
  216. DisplayMenuItem(iIndex++, *(itMenuCmd++), itMenuRef->IsEnabled());
  217. // If this is the default menu item save its ID
  218. if( itMenuRef->IsDefault() )
  219. {
  220. ASSERT(m_DefaultID == 0);
  221. m_DefaultID = itMenuRef->ID();
  222. }
  223. // Display any following root items that aren't in the query list
  224. while( itMenuCmd != vMenuCmds.end() &&
  225. std::find(vMenuRefs.begin(), vMenuRefs.end(), (*itMenuCmd)->ID()) == vMenuRefs.end() )
  226. {
  227. DisplayMenuItem(iIndex++, *(itMenuCmd++), TRUE);
  228. }
  229. }
  230. }
  231. // Disable buttons until selection made
  232. EnableDlgItem( m_hWnd, IDC_MOVEUP, FALSE );
  233. EnableDlgItem( m_hWnd, IDC_MOVEDOWN, FALSE );
  234. EnableDlgItem( m_hWnd, IDC_DEFAULTMENU, FALSE );
  235. // Uncheck default button until default item selected
  236. Button_SetCheck(GetDlgItem(IDC_DEFAULTMENU), BST_UNCHECKED);
  237. // Set Property Menu Checkbox
  238. Button_SetCheck(GetDlgItem(IDC_PROPERTYMENU), m_pObjSel->HasPropertyMenu() ? BST_CHECKED : BST_UNCHECKED);
  239. m_bLoading = FALSE;
  240. }
  241. void CQueryMenuPage::DisplayMenuItem(int iIndex, CMenuCmd* pMenuCmd, BOOL bEnabled)
  242. {
  243. if( !pMenuCmd ) return;
  244. static CString strShellCmd;
  245. static CString strADCmd;
  246. LV_ITEM lvi;
  247. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  248. lvi.iItem = iIndex;
  249. lvi.iSubItem = 0;
  250. lvi.pszText = const_cast<LPWSTR>(pMenuCmd->Name());
  251. lvi.lParam = static_cast<LPARAM>(pMenuCmd->ID());
  252. int iPos = m_MenuLV.InsertItem(&lvi);
  253. ASSERT(iPos == iIndex);
  254. lvi.iSubItem = 1;
  255. lvi.mask = LVIF_TEXT;
  256. switch( pMenuCmd->MenuType() )
  257. {
  258. case MENUTYPE_SHELL:
  259. if( strShellCmd.IsEmpty() )
  260. strShellCmd.LoadString(IDS_SHELLCMD);
  261. lvi.pszText = (LPWSTR)(LPCWSTR)strShellCmd;
  262. break;
  263. case MENUTYPE_ACTDIR:
  264. if( strADCmd.IsEmpty() )
  265. strADCmd.LoadString(IDS_DISPSPEC);
  266. lvi.pszText = (LPWSTR)(LPCWSTR)strADCmd;
  267. break;
  268. default:
  269. ASSERT(FALSE);
  270. }
  271. m_MenuLV.SetItem(&lvi);
  272. m_MenuLV.SetCheckState(iIndex, bEnabled);
  273. }
  274. LRESULT CQueryMenuPage::OnObjectSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  275. {
  276. int iItem = m_ObjectCB.GetCurSel();
  277. // Double-clicking an empty combo box can call this with no selection
  278. if( iItem >= 0 )
  279. {
  280. SaveMenuSet();
  281. m_pObjSel = reinterpret_cast<CQueryObjInfo*>(m_ObjectCB.GetItemDataPtr(iItem));
  282. DisplayMenus();
  283. }
  284. return 0;
  285. }
  286. LRESULT CQueryMenuPage::OnMoveUpDown( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  287. {
  288. int iItem = m_MenuLV.GetNextItem(-1, LVNI_SELECTED);
  289. ASSERT(iItem >= 0);
  290. // Get the selected item data
  291. WCHAR szName[100];
  292. LVITEM lvi;
  293. lvi.mask = LVIF_TEXT|LVIF_PARAM|LVIF_STATE;
  294. lvi.stateMask = 0xFFFFFFFF;
  295. lvi.iSubItem = 0;
  296. lvi.iItem = iItem;
  297. lvi.pszText = szName;
  298. lvi.cchTextMax = sizeof(szName);
  299. m_MenuLV.GetItem(&lvi);
  300. WCHAR szType[100];
  301. m_MenuLV.GetItemText(iItem, 1, szType, sizeof(szType));
  302. // Set loading flag to avoid intermediate button enable/disables
  303. m_bLoading = TRUE;
  304. // Delete and insert at new position
  305. m_MenuLV.DeleteItem(iItem);
  306. lvi.iItem += (wID == IDC_MOVEUP) ? -1 : 1;
  307. m_MenuLV.InsertItem(&lvi);
  308. m_MenuLV.SetItemText(lvi.iItem, 1, szType);
  309. // re-establish checked state (insert doesn't retain it)
  310. if( lvi.state & CHECK_ON )
  311. m_MenuLV.SetCheckState(lvi.iItem, TRUE);
  312. m_bLoading = FALSE;
  313. SetModified(TRUE);
  314. // update button states
  315. EnableDlgItem( m_hWnd, IDC_MOVEUP, (lvi.iItem > 0) );
  316. EnableDlgItem( m_hWnd, IDC_MOVEDOWN, (lvi.iItem < (m_MenuLV.GetItemCount() - 1)) );
  317. return 0;
  318. }
  319. LRESULT CQueryMenuPage::OnMenuChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  320. {
  321. if( !pNMHDR ) return 0;
  322. if( !m_bLoading )
  323. {
  324. LPNMLISTVIEW pnmv = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  325. // if state has changed
  326. if( pnmv->uChanged & LVIF_STATE )
  327. {
  328. // if checkbox state change
  329. if( (pnmv->uNewState ^ pnmv->uOldState) & LVIS_STATEIMAGEMASK )
  330. {
  331. // if the changed item is currently selected
  332. if( m_MenuLV.GetItemState(pnmv->iItem, LVIS_SELECTED) & LVIS_SELECTED )
  333. {
  334. // Change the state of all selcted items to match
  335. BOOL bNewState = ((pnmv->uNewState & LVIS_STATEIMAGEMASK) == CHECK_ON);
  336. m_bLoading = TRUE;
  337. int iItem = -1;
  338. while( (iItem = m_MenuLV.GetNextItem(iItem, LVNI_SELECTED)) >= 0 )
  339. {
  340. m_MenuLV.SetCheckState(iItem, bNewState);
  341. }
  342. m_bLoading = FALSE;
  343. }
  344. SetModified(TRUE);
  345. }
  346. if( (pnmv->uNewState ^ pnmv->uOldState) & LVIS_SELECTED )
  347. {
  348. int nItems = m_MenuLV.GetItemCount();
  349. int iItem = m_MenuLV.GetNextItem(-1, LVNI_SELECTED);
  350. int nSelected = m_MenuLV.GetSelectedCount();
  351. BOOL bDefault = (nSelected == 1) && (m_MenuLV.GetItemData(iItem) == m_DefaultID);
  352. Button_SetCheck(GetDlgItem(IDC_DEFAULTMENU), bDefault ? BST_CHECKED : BST_UNCHECKED);
  353. EnableDlgItem( m_hWnd, IDC_MOVEUP, ((iItem > 0) && (nSelected == 1)) );
  354. EnableDlgItem( m_hWnd, IDC_MOVEDOWN, ((iItem >= 0) && (iItem < (nItems - 1)) && (nSelected == 1)) );
  355. EnableDlgItem( m_hWnd, IDC_DEFAULTMENU, (nSelected == 1) );
  356. }
  357. }
  358. }
  359. return TRUE;
  360. }
  361. LRESULT CQueryMenuPage::OnDefaultChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  362. {
  363. // if user checks the default then save currently selected menu ID as default
  364. if( Button_GetCheck(GetDlgItem(IDC_DEFAULTMENU)) == BST_CHECKED )
  365. {
  366. // button should be disabled unless there is one menu item selected
  367. ASSERT(m_MenuLV.GetSelectedCount() == 1);
  368. int iItem = m_MenuLV.GetNextItem(-1, LVNI_SELECTED);
  369. m_DefaultID = m_MenuLV.GetItemData(iItem);
  370. }
  371. else
  372. {
  373. // if user unchecks box there is no default
  374. m_DefaultID = 0;
  375. }
  376. SetModified(TRUE);
  377. return 0;
  378. }
  379. LRESULT CQueryMenuPage::OnPropertyMenuChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  380. {
  381. SetModified(TRUE);
  382. return 0;
  383. }
  384. void CQueryMenuPage::SaveMenuSet()
  385. {
  386. if( m_pObjSel == NULL )
  387. return;
  388. m_pObjSel->m_vMenuRefs.clear();
  389. LVITEM lvi;
  390. lvi.mask = LVIF_PARAM | LVIF_STATE;
  391. lvi.stateMask = LVIS_STATEIMAGEMASK;
  392. lvi.iSubItem = 0;
  393. int nItems = m_MenuLV.GetItemCount();
  394. for( int iIndex = 0; iIndex < nItems; iIndex++ )
  395. {
  396. lvi.iItem = iIndex;
  397. BOOL bStat = m_MenuLV.GetItem(&lvi);
  398. ASSERT(bStat);
  399. CMenuRef menuref;
  400. menuref.m_menuID = static_cast<MenuID>(lvi.lParam);
  401. menuref.SetEnable((lvi.state & LVIS_STATEIMAGEMASK) == CHECK_ON);
  402. menuref.SetDefault(menuref.m_menuID == m_DefaultID);
  403. m_pObjSel->m_vMenuRefs.push_back(menuref);
  404. }
  405. m_pObjSel->SetPropertyMenu( Button_GetCheck(GetDlgItem(IDC_PROPERTYMENU)) == BST_CHECKED );
  406. }
  407. BOOL CQueryMenuPage::OnSetActive()
  408. {
  409. m_EditObject.PageActive(m_hWnd);
  410. return TRUE;
  411. }
  412. BOOL CQueryMenuPage::OnApply()
  413. {
  414. SaveMenuSet();
  415. return m_EditObject.ApplyChanges(m_hWnd);
  416. }
  417. ///////////////////////////////////////////////////////////////////////////////////////////
  418. // CQueryViewPage
  419. CQueryViewPage::CQueryViewPage(CQueryEditObj* pEditObj)
  420. : m_EditObject(*pEditObj), m_bLoading(FALSE), m_pObjSel(NULL)
  421. {
  422. ASSERT(pEditObj != NULL);
  423. m_EditObject.AddRef();
  424. }
  425. CQueryViewPage::~CQueryViewPage()
  426. {
  427. m_ObjectCB.Detach();
  428. m_EditObject.Release();
  429. }
  430. LRESULT CQueryViewPage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  431. {
  432. HWND hwndList = GetDlgItem(IDC_COLUMNLIST);
  433. if( hwndList )
  434. {
  435. m_ColumnLV.SubclassWindow(hwndList);
  436. RECT rc;
  437. BOOL bStat = m_ColumnLV.GetClientRect(&rc);
  438. ASSERT(bStat);
  439. int iCol = m_ColumnLV.InsertColumn(0, NULL, LVCFMT_LEFT, (rc.right - rc.left), 0);
  440. ASSERT(iCol == 0);
  441. m_ColumnLV.SetExtendedListViewStyle(LVS_EX_CHECKBOXES);
  442. }
  443. HWND hwndCombo = GetDlgItem(IDC_OBJECTLIST);
  444. if( hwndCombo )
  445. {
  446. m_ObjectCB.Attach(hwndCombo);
  447. LoadObjectCB(m_ObjectCB, m_EditObject.m_vObjInfo);
  448. if( m_EditObject.m_vObjInfo.size() != 0 )
  449. {
  450. m_ObjectCB.SetCurSel(0);
  451. m_pObjSel = reinterpret_cast<CQueryObjInfo*>(m_ObjectCB.GetItemDataPtr(0));
  452. if( hwndList )
  453. {
  454. DisplayColumns();
  455. }
  456. }
  457. }
  458. return TRUE;
  459. }
  460. LRESULT CQueryViewPage::OnObjectSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  461. {
  462. int iItem = m_ObjectCB.GetCurSel();
  463. // Double-clicking an empty combo box can call this with no selection
  464. if( iItem >= 0 )
  465. {
  466. SaveColumnSet();
  467. m_pObjSel = reinterpret_cast<CQueryObjInfo*>(m_ObjectCB.GetItemDataPtr(iItem));
  468. DisplayColumns();
  469. }
  470. return 0;
  471. }
  472. void CQueryViewPage::DisplayColumns()
  473. {
  474. if( !m_pObjSel ) return;
  475. if( !m_EditObject.m_spQueryNode ) return;
  476. m_bLoading = TRUE;
  477. m_ColumnLV.DeleteAllItems();
  478. LV_ITEM lvi;
  479. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  480. lvi.iItem = 0;
  481. lvi.iSubItem = 0;
  482. CRootNode* pRootNode = m_EditObject.m_spQueryNode->GetRootNode();
  483. if( !pRootNode ) return;
  484. CClassInfo* pClassInfo = pRootNode->FindClass(m_pObjSel->Name());
  485. if( pClassInfo != NULL )
  486. {
  487. DisplayNameMap* pNameMap = DisplayNames::GetMap(m_pObjSel->Name());
  488. ASSERT(pNameMap != NULL);
  489. if( pNameMap == NULL )
  490. return;
  491. string_vector& vDisabledCols = m_pObjSel->DisabledColumns();
  492. string_vector::iterator itstrCol;
  493. for( itstrCol = pClassInfo->Columns().begin(); itstrCol != pClassInfo->Columns().end(); ++itstrCol )
  494. {
  495. lvi.pszText = const_cast<LPWSTR>(pNameMap->GetAttributeDisplayName(itstrCol->c_str()));
  496. lvi.lParam = reinterpret_cast<LPARAM>(itstrCol->c_str());
  497. int iPos = m_ColumnLV.InsertItem(&lvi);
  498. ASSERT(iPos >= 0);
  499. //Enable all columns that aren't excluded by the query node
  500. if( std::find(vDisabledCols.begin(), vDisabledCols.end(), *itstrCol) == vDisabledCols.end() )
  501. m_ColumnLV.SetCheckState(iPos, TRUE);
  502. }
  503. }
  504. m_bLoading = FALSE;
  505. }
  506. LRESULT CQueryViewPage::OnColumnChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  507. {
  508. if( !pNMHDR ) return 0;
  509. if( !m_bLoading )
  510. {
  511. LPNMLISTVIEW pnmv = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  512. // if checked state has changed
  513. if( (pnmv->uChanged & LVIF_STATE) &&
  514. ((pnmv->uNewState ^ pnmv->uOldState) & LVIS_STATEIMAGEMASK) )
  515. {
  516. // if the changed item is currently selected
  517. if( m_ColumnLV.GetItemState(pnmv->iItem, LVIS_SELECTED) & LVIS_SELECTED )
  518. {
  519. // Change the state of all selcted items to match
  520. BOOL bNewState = ((pnmv->uNewState & LVIS_STATEIMAGEMASK) == CHECK_ON);
  521. m_bLoading = TRUE;
  522. int iItem = -1;
  523. while( (iItem = m_ColumnLV.GetNextItem(iItem, LVNI_SELECTED)) >= 0 )
  524. {
  525. m_ColumnLV.SetCheckState(iItem, bNewState);
  526. }
  527. m_bLoading = FALSE;
  528. }
  529. SetModified(TRUE);
  530. }
  531. }
  532. return TRUE;
  533. }
  534. void CQueryViewPage::SaveColumnSet()
  535. {
  536. if( m_pObjSel == NULL )
  537. return;
  538. string_vector vstrNewCols;
  539. int nItems = m_ColumnLV.GetItemCount();
  540. for( int iIndex = 0; iIndex < nItems; iIndex++ )
  541. {
  542. // Save list of disabled columns
  543. if( !m_ColumnLV.GetCheckState(iIndex) )
  544. {
  545. LVITEM lvi;
  546. lvi.mask = LVIF_PARAM;
  547. lvi.iItem = iIndex;
  548. lvi.iSubItem = 0;
  549. BOOL bStat = m_ColumnLV.GetItem(&lvi);
  550. ASSERT(bStat);
  551. vstrNewCols.push_back(reinterpret_cast<LPCWSTR>(lvi.lParam));
  552. }
  553. }
  554. m_pObjSel->m_vstrDisabledColumns = vstrNewCols;
  555. }
  556. typedef struct
  557. {
  558. HWND hwndList;
  559. int iCol;
  560. }
  561. COMPAREPARAM, *LPCOMPAREPARAM;
  562. int CALLBACK ColumnCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  563. {
  564. if( !lParamSort ) return 0;
  565. LPCOMPAREPARAM pcmp = reinterpret_cast<LPCOMPAREPARAM>(lParamSort);
  566. WCHAR sz1[MAX_PATH];
  567. ListView_GetItemText(pcmp->hwndList, lParam1, pcmp->iCol, sz1, MAX_PATH);
  568. WCHAR sz2[MAX_PATH];
  569. ListView_GetItemText(pcmp->hwndList, lParam2, pcmp->iCol, sz2, MAX_PATH);
  570. return wcscmp(sz1,sz2);
  571. }
  572. LRESULT CQueryViewPage::OnColumnClick(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  573. {
  574. if( !pNMHDR ) return 0;
  575. LPNMLISTVIEW pnmv = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  576. COMPAREPARAM cmp;
  577. cmp.hwndList = pnmv->hdr.hwndFrom;
  578. cmp.iCol = pnmv->iSubItem;
  579. ListView_SortItemsEx(pnmv->hdr.hwndFrom, &ColumnCompare, &cmp);
  580. return TRUE;
  581. }
  582. BOOL CQueryViewPage::OnSetActive()
  583. {
  584. DisplayColumns();
  585. m_EditObject.PageActive(m_hWnd);
  586. return TRUE;
  587. }
  588. BOOL CQueryViewPage::OnApply()
  589. {
  590. SaveColumnSet();
  591. return m_EditObject.ApplyChanges(m_hWnd);
  592. }
  593. ///////////////////////////////////////////////////////////////////////////////////////////
  594. // CQueryNodeMenuPage
  595. CQueryNodeMenuPage::CQueryNodeMenuPage(CQueryEditObj* pEditObj)
  596. : m_EditObject(*pEditObj)
  597. {
  598. ASSERT(pEditObj != NULL);
  599. m_EditObject.AddRef();
  600. }
  601. CQueryNodeMenuPage::~CQueryNodeMenuPage()
  602. {
  603. m_MenuLV.Detach();
  604. m_EditObject.Release();
  605. }
  606. LRESULT CQueryNodeMenuPage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  607. {
  608. m_MenuLV.Attach(GetDlgItem(IDC_MENULIST));
  609. ::ConfigSingleColumnListView(GetDlgItem(IDC_MENULIST));
  610. return TRUE;
  611. }
  612. BOOL CQueryNodeMenuPage::OnSetActive()
  613. {
  614. m_EditObject.PageActive(m_hWnd);
  615. DisplayMenus();
  616. return TRUE;
  617. }
  618. void CQueryNodeMenuPage::DisplayMenus()
  619. {
  620. if( !m_EditObject.m_spQueryNode ) return;
  621. HWND hwndLV = GetDlgItem(IDC_MENULIST);
  622. ASSERT(::IsWindow(hwndLV));
  623. ListView_DeleteAllItems(hwndLV);
  624. // make sure menu names have been loaded
  625. CRootNode* pRootNode = m_EditObject.m_spQueryNode->GetRootNode();
  626. if( !pRootNode ) return;
  627. CComponentData* pCompData = pRootNode->GetCompData();
  628. if( !pCompData ) return;
  629. IStringTable* pStringTable = pCompData->GetStringTable();
  630. ASSERT(pStringTable != NULL);
  631. if( !pStringTable ) return;
  632. m_EditObject.LoadStrings(pStringTable);
  633. LV_ITEM lvi;
  634. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  635. lvi.iItem = 0;
  636. lvi.iSubItem = 0;
  637. menucmd_vector::iterator itMenu;
  638. for( itMenu = m_EditObject.Menus().begin(); itMenu != m_EditObject.Menus().end(); ++itMenu )
  639. {
  640. lvi.pszText = const_cast<LPWSTR>((*itMenu)->Name());
  641. lvi.lParam = (*itMenu)->ID();
  642. int iPos = ListView_InsertItem(hwndLV, &lvi);
  643. ASSERT(iPos >= 0);
  644. lvi.iItem++;
  645. }
  646. EnableDlgItem( m_hWnd, IDC_ADDMENU, TRUE );
  647. EnableDlgItem( m_hWnd, IDC_REMOVEMENU, FALSE );
  648. EnableDlgItem( m_hWnd, IDC_EDITMENU, FALSE );
  649. EnableDlgItem( m_hWnd, IDC_MOVEUP, FALSE );
  650. EnableDlgItem( m_hWnd, IDC_MOVEDOWN, FALSE );
  651. }
  652. LRESULT CQueryNodeMenuPage::OnAddMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  653. {
  654. if( !m_EditObject.m_spQueryNode ) return 0;
  655. CAddQNMenuDlg dlg(m_EditObject);
  656. if( dlg.DoModal() == IDOK )
  657. {
  658. CMenuCmd* pMenuNew = dlg.GetMenu();
  659. ASSERT(pMenuNew != NULL);
  660. if( !pMenuNew ) return 0;
  661. // Add new menu to list
  662. HWND hwndList = GetDlgItem(IDC_MENULIST);
  663. // Set name to add it to string table and generate the menu ID
  664. CRootNode* pRootNode = m_EditObject.m_spQueryNode->GetRootNode();
  665. if( !pRootNode ) return 0;
  666. CComponentData* pCompData = pRootNode->GetCompData();
  667. ASSERT( pCompData );
  668. if( !pCompData ) return 0;
  669. IStringTable* pStringTable = pCompData->GetStringTable();
  670. ASSERT( pStringTable );
  671. if( !pStringTable ) return 0;
  672. // Use temp string because string fails an assignement like: strX = strX.c_str()
  673. // (it relases the private buffer first and then assigns the string)
  674. tstring strName = pMenuNew->Name();
  675. pMenuNew->SetName(pStringTable, strName.c_str());
  676. LVITEM lvi;
  677. lvi.mask = LVIF_PARAM | LVIF_TEXT;
  678. lvi.iSubItem = 0;
  679. lvi.iItem = ListView_GetItemCount(hwndList);
  680. lvi.lParam = pMenuNew->ID();
  681. lvi.pszText = const_cast<LPWSTR>(pMenuNew->Name());
  682. ListView_InsertItem(hwndList,&lvi);
  683. // Add to menu vector (note that temp CMenuCmdPtr will delete pMenuNew)
  684. m_EditObject.m_vMenus.push_back(CMenuCmdPtr(pMenuNew));
  685. SetModified(TRUE);
  686. }
  687. return 0;
  688. }
  689. LRESULT CQueryNodeMenuPage::OnEditMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  690. {
  691. if( !m_EditObject.m_spQueryNode ) return 0;
  692. HWND hwndList = GetDlgItem(IDC_MENULIST);
  693. int iIndex = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
  694. ASSERT(iIndex != -1);
  695. LVITEM lvi;
  696. lvi.mask = LVIF_PARAM;
  697. lvi.iSubItem = 0;
  698. lvi.iItem = iIndex;
  699. ListView_GetItem(hwndList, &lvi);
  700. // Locate selected menu by it's ID (lparam)
  701. menucmd_vector& vMenus = m_EditObject.Menus();
  702. menucmd_vector::iterator itMenu;
  703. itMenu = std::find(vMenus.begin(), vMenus.end(), lvi.lParam);
  704. ASSERT(itMenu != vMenus.end());
  705. CMenuCmd* pMenu = *itMenu;
  706. if( !pMenu ) return 0;
  707. CAddQNMenuDlg dlg(m_EditObject, pMenu);
  708. if( dlg.DoModal() == IDOK )
  709. {
  710. CMenuCmd* pMenuNew = dlg.GetMenu();
  711. ASSERT(pMenuNew != NULL);
  712. if( !pMenuNew ) return 0;
  713. // Set the name again in case it was changed
  714. CRootNode* pRootNode = m_EditObject.m_spQueryNode->GetRootNode();
  715. if( !pRootNode ) return 0;
  716. CComponentData* pCompData = pRootNode->GetCompData();
  717. if( !pCompData ) return 0;
  718. IStringTable* pStringTable = pCompData->GetStringTable();
  719. ASSERT(pStringTable != NULL);
  720. if( !pStringTable ) return 0;
  721. // Use temp string because string fails an assignement like: strX = strX.c_str()
  722. // (it relases the private buffer first and then assigns the string)
  723. tstring strName = pMenuNew->Name();
  724. pMenuNew->SetName(pStringTable, strName.c_str());
  725. // locate object again because the vector may have been reallocated
  726. menucmd_vector& vMenusNew = m_EditObject.Menus();
  727. // locate with the old ID because it will be different if the name was changed
  728. itMenu = std::find(vMenusNew.begin(), vMenusNew.end(), pMenu->ID());
  729. ASSERT(itMenu != vMenusNew.end());
  730. // Replace menu with new one
  731. *itMenu = pMenuNew;
  732. // Update the list
  733. lvi.mask = LVIF_PARAM | LVIF_TEXT;
  734. lvi.lParam = pMenuNew->ID();
  735. lvi.pszText = const_cast<LPWSTR>(pMenuNew->Name());
  736. ListView_SetItem(hwndList,&lvi);
  737. SetModified(TRUE);
  738. }
  739. return 0;
  740. }
  741. LRESULT CQueryNodeMenuPage::OnRemoveMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  742. {
  743. HWND hwndList = GetDlgItem(IDC_MENULIST);
  744. UINT uiMsg = (ListView_GetSelectedCount(hwndList) == 1) ? IDS_MENU_REMOVE_ONE : IDS_MENU_REMOVE;
  745. int iRet = DisplayMessageBox(m_hWnd, IDS_MENU_REMOVE_TITLE, uiMsg, MB_YESNO|MB_ICONWARNING);
  746. if( iRet != IDYES )
  747. return 0;
  748. menucmd_vector& vMenus = m_EditObject.Menus();
  749. LVITEM lvi;
  750. lvi.mask = LVIF_PARAM;
  751. lvi.iSubItem = 0;
  752. int iIndex = -1;
  753. while( (iIndex = ListView_GetNextItem(hwndList, iIndex, LVNI_SELECTED)) >= 0 )
  754. {
  755. lvi.iItem = iIndex;
  756. ListView_GetItem(hwndList, &lvi);
  757. // Locate menu by its ID
  758. menucmd_vector::iterator itMenu = std::find(vMenus.begin(), vMenus.end(), lvi.lParam);
  759. ASSERT(itMenu != vMenus.end());
  760. vMenus.erase(itMenu);
  761. ListView_DeleteItem(hwndList, iIndex);
  762. iIndex--;
  763. }
  764. EnableDlgItem( m_hWnd, IDC_REMOVEMENU, FALSE );
  765. EnableDlgItem( m_hWnd, IDC_EDITMENU, FALSE );
  766. EnableDlgItem( m_hWnd, IDC_MOVEUP, FALSE );
  767. EnableDlgItem( m_hWnd, IDC_MOVEDOWN, FALSE );
  768. SetModified(TRUE);
  769. return 0;
  770. }
  771. LRESULT CQueryNodeMenuPage::OnMoveUpDown( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  772. {
  773. HWND hwndList = GetDlgItem(IDC_MENULIST);
  774. int iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
  775. ASSERT(iItem >= 0);
  776. // Determine new position for selected item
  777. if( wID == IDC_MOVEUP )
  778. iItem--;
  779. else
  780. iItem++;
  781. // Now swap the selected item with the item at its new position
  782. // Do it by moving the unselected item to avoid state change notifications
  783. // because they will cause unwanted butten enables/disables.
  784. LVITEM lvi;
  785. lvi.mask = LVIF_PARAM;
  786. lvi.iSubItem = 0;
  787. lvi.iItem = iItem;
  788. ListView_GetItem(hwndList, &lvi);
  789. // Move the menu item in the menu vector
  790. menucmd_vector& vMenus = m_EditObject.Menus();
  791. menucmd_vector::iterator itMenu = std::find(vMenus.begin(), vMenus.end(), lvi.lParam);
  792. ASSERT(itMenu != vMenus.end());
  793. menucmd_vector::iterator itMenuOld = itMenu;
  794. if( wID == IDC_MOVEUP )
  795. itMenu++;
  796. else
  797. itMenu--;
  798. // swap the items
  799. std::iter_swap (itMenuOld, itMenu);
  800. //Now delete and reinsert it in the list view
  801. ListView_DeleteItem(hwndList, lvi.iItem);
  802. if( wID == IDC_MOVEUP )
  803. lvi.iItem++;
  804. else
  805. lvi.iItem--;
  806. lvi.mask = LVIF_PARAM | LVIF_TEXT;
  807. lvi.pszText = const_cast<LPWSTR>((*itMenu)->Name());
  808. ListView_InsertItem(hwndList, &lvi);
  809. // Update Up/Down buttons
  810. EnableDlgItem( m_hWnd, IDC_MOVEUP, (iItem > 0) );
  811. EnableDlgItem( m_hWnd, IDC_MOVEDOWN, (iItem < (ListView_GetItemCount(hwndList) - 1)) );
  812. SetModified(TRUE);
  813. return 0;
  814. }
  815. LRESULT CQueryNodeMenuPage::OnMenuListChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  816. {
  817. HWND hwndList = GetDlgItem(IDC_MENULIST);
  818. int nItemSel = ListView_GetSelectedCount(hwndList);
  819. int iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED);
  820. EnableDlgItem( m_hWnd, IDC_REMOVEMENU, (nItemSel > 0) );
  821. EnableDlgItem( m_hWnd, IDC_EDITMENU, (nItemSel == 1) );
  822. EnableDlgItem( m_hWnd, IDC_MOVEUP, ((nItemSel == 1) && (iItem > 0)) );
  823. EnableDlgItem( m_hWnd, IDC_MOVEDOWN, ((nItemSel == 1) && (iItem < (ListView_GetItemCount(hwndList) - 1))) );
  824. return TRUE;
  825. }
  826. LRESULT CQueryNodeMenuPage::OnMenuListDblClk(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  827. {
  828. if( ListView_GetSelectedCount(GetDlgItem(IDC_MENULIST)) )
  829. ::SendMessage(GetDlgItem(IDC_EDITMENU), BM_CLICK, (WPARAM)0, (LPARAM)0);
  830. return 0;
  831. }
  832. BOOL CQueryNodeMenuPage::OnApply()
  833. {
  834. return m_EditObject.ApplyChanges(m_hWnd);
  835. }
  836. /////////////////////////////////////////////////////////////////////////////////////////////////
  837. // CQueryEditObj
  838. void CQueryEditObj::PageActive(HWND hwndPage)
  839. {
  840. ASSERT(::IsWindow(hwndPage));
  841. // track the highest created page number for ApplyChanges method
  842. int iPage = PropSheet_HwndToIndex(GetParent(hwndPage), hwndPage);
  843. if( iPage > m_iPageMax )
  844. m_iPageMax = iPage;
  845. }
  846. BOOL CQueryEditObj::ApplyChanges(HWND hwndPage)
  847. {
  848. if( !m_spQueryNode ) return FALSE;
  849. ASSERT(::IsWindow(hwndPage));
  850. // Don't apply changes until called from highest activated page
  851. if( PropSheet_HwndToIndex(GetParent(hwndPage), hwndPage) < m_iPageMax )
  852. return TRUE;
  853. // replace original query objects with edited copies
  854. m_spQueryNode->Objects() = m_vObjInfo;
  855. m_spQueryNode->Menus() = m_vMenus;
  856. if( m_spQueryNode )
  857. {
  858. CRootNode* pRootNode = m_spQueryNode->GetRootNode();
  859. if( pRootNode )
  860. {
  861. pRootNode->UpdateModifyTime();
  862. }
  863. }
  864. return TRUE;
  865. }
  866. /////////////////////////////////////////////////////////////////////////////////////////////////
  867. // Helper functions
  868. void LoadObjectCB(CComboBox& ComboBox, QueryObjVector& vObj)
  869. {
  870. ComboBox.ResetContent();
  871. DisplayNameMap* pNameMap = DisplayNames::GetClassMap();
  872. ASSERT(pNameMap != NULL);
  873. if( pNameMap == NULL )
  874. return;
  875. for( QueryObjVector::iterator itObj = vObj.begin(); itObj != vObj.end(); ++itObj )
  876. {
  877. int iIndex = ComboBox.AddString(pNameMap->GetAttributeDisplayName(itObj->Name()));
  878. ASSERT(iIndex >= 0);
  879. ComboBox.SetItemDataPtr(iIndex, &(*itObj));
  880. }
  881. }