// qryprop.cpp - Query Property Page Implementation #include "stdafx.h" #include "resource.h" #include "qryprop.h" #include "compdata.h" #include "scopenode.h" #include "query.h" #include "cmndlgs.h" #include "util.h" #include "namemap.h" #define SECURITY_WIN32 #include // TranslateName #include #include #undef SubclassWindow int GetDateTimeString(FILETIME* pftime, LPWSTR pszBuf, int cBuf); void LoadObjectCB(CComboBox& ComboBox, QueryObjVector& vObj); #define CHECK_OFF INDEXTOSTATEIMAGEMASK(1) #define CHECK_ON INDEXTOSTATEIMAGEMASK(2) /////////////////////////////////////////////////////////////////////////////////////////// // CQueryGeneralPage CQueryGeneralPage::CQueryGeneralPage(CQueryEditObj* pEditObj) : m_EditObject(*pEditObj) { ASSERT(pEditObj != NULL); m_EditObject.AddRef(); } CQueryGeneralPage::~CQueryGeneralPage() { m_EditObject.Release(); } LRESULT CQueryGeneralPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { if( !m_EditObject.m_spQueryNode ) return 0; // display query node icon HICON hIcon = ::LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_QUERYNODE)); Static_SetIcon(GetDlgItem(IDC_QUERYICON), hIcon); // fill dialog fields with query node info tstring strTempQuery; m_EditObject.m_spQueryNode->ExpandQuery(strTempQuery); CQueryNode* pQNode = m_EditObject.m_spQueryNode; SetDlgItemText( IDC_NAME, m_EditObject.m_spQueryNode->GetName() ); SetDlgItemText( IDC_FILTER, strTempQuery.c_str() ); tstring strComment; m_EditObject.m_spQueryNode->GetComment(strComment); SetDlgItemText( IDC_COMMENTS, strComment.c_str() ); Edit_LimitText(GetDlgItem(IDC_COMMENTS), 255); // set scope source toggle button UINT uButton = m_EditObject.m_spQueryNode->UseLocalScope() ? IDC_LOCALSCOPE : IDC_QUERYSCOPE; Button_SetCheck(GetDlgItem(uButton), BST_CHECKED); tstring strScope = m_EditObject.m_spQueryNode->Scope(); tstring strDisplay; GetScopeDisplayString(strScope, strDisplay); SetDlgItemText( IDC_SCOPE, strDisplay.c_str() ); // if using local scope, then set the persisted scope equal to the local scope so that the // user won't see an obsolete scope that may have been saved when creating the node. if( m_EditObject.m_spQueryNode->UseLocalScope() ) m_EditObject.m_spQueryNode->SetScope(strScope.c_str()); // if classes known, display comma separated class names if( m_EditObject.m_vObjInfo.size() != 0 ) { DisplayNameMap* pNameMap = DisplayNames::GetClassMap(); ASSERT(pNameMap != NULL); if( pNameMap != NULL ) { QueryObjVector::iterator itQObj = m_EditObject.m_vObjInfo.begin(); tstring strClasses = pNameMap->GetAttributeDisplayName(itQObj->Name()); for( itQObj++; itQObj != m_EditObject.m_vObjInfo.end(); ++itQObj ) { strClasses += L", "; strClasses += pNameMap->GetAttributeDisplayName(itQObj->Name()); } SetDlgItemText( IDC_OBJCLASS, strClasses.c_str() ); } } return TRUE; } LRESULT CQueryGeneralPage::OnScopeChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { if( !m_EditObject.m_spQueryNode ) return 0; // if user changes scope selection then display the correct scope tstring strScope; if( Button_GetCheck(GetDlgItem(IDC_LOCALSCOPE)) == BST_CHECKED ) strScope = GetLocalDomain(); else strScope = m_EditObject.m_spQueryNode->QueryScope(); tstring strDisplay; GetScopeDisplayString(strScope, strDisplay); SetDlgItemText( IDC_SCOPE, strDisplay.c_str() ); SetModified(TRUE); return 0; } LRESULT CQueryGeneralPage::OnChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { SetModified(TRUE); return 0; } //------------------------------------------------------------------------------------ // CRootGeneralPage::OnClose // // This method is invoked when an edit box receives an Esc char. The method converts // the WM_CLOSE message into a command to close the property sheet. Otherwise the // WM_CLOSE message has no effect. //------------------------------------------------------------------------------------ LRESULT CQueryGeneralPage::OnClose( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { // Simulate press of Cancel button ::PropSheet_PressButton(GetParent(), PSBTN_CANCEL); return 0; } BOOL CQueryGeneralPage::OnSetActive() { m_EditObject.PageActive(m_hWnd); return TRUE; } BOOL CQueryGeneralPage::OnApply() { if( !m_EditObject.m_spQueryNode ) return FALSE; tstring strComment; GetItemText(GetDlgItem(IDC_COMMENTS), strComment); m_EditObject.m_spQueryNode->SetComment(strComment.c_str()); bool bLocal = (Button_GetCheck(GetDlgItem(IDC_LOCALSCOPE)) == BST_CHECKED); m_EditObject.m_spQueryNode->SetLocalScope(bLocal); return m_EditObject.ApplyChanges(m_hWnd); } /////////////////////////////////////////////////////////////////////////////////////////// // CQueryMenuPage CQueryMenuPage::CQueryMenuPage(CQueryEditObj* pEditObj) : m_EditObject(*pEditObj), m_pObjSel(NULL), m_bLoading(FALSE) { ASSERT(pEditObj != NULL); m_EditObject.AddRef(); } CQueryMenuPage::~CQueryMenuPage() { m_ObjectCB.Detach(); m_EditObject.Release(); } LRESULT CQueryMenuPage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { HWND hwndList = GetDlgItem(IDC_MENULIST); ASSERT( hwndList ); if( hwndList ) { m_MenuLV.SubclassWindow(hwndList); RECT rc; BOOL bStat = m_MenuLV.GetClientRect(&rc); ASSERT(bStat); int iWidth = (rc.right - rc.left) - GetSystemMetrics(SM_CXVSCROLL); CString strName; strName.LoadString(IDS_MENUITEM); int iCol = m_MenuLV.InsertColumn(0, strName, LVCFMT_LEFT, (iWidth + 1)/2, 0); ASSERT(iCol == 0); strName.LoadString(IDS_TYPE); iCol = m_MenuLV.InsertColumn(1, strName, LVCFMT_LEFT, iWidth/2, 1); ASSERT(iCol == 1); m_MenuLV.SetExtendedListViewStyle(LVS_EX_CHECKBOXES|LVS_EX_FULLROWSELECT); } HWND hwndCombo = GetDlgItem(IDC_OBJECTLIST); ASSERT(hwndCombo); if( hwndCombo ) { m_ObjectCB.Attach(hwndCombo); LoadObjectCB(m_ObjectCB, m_EditObject.m_vObjInfo); if( m_EditObject.m_vObjInfo.size() != 0 ) { m_ObjectCB.SetCurSel(0); m_pObjSel = reinterpret_cast(m_ObjectCB.GetItemDataPtr(0)); if( hwndList ) { DisplayMenus(); } } } return TRUE; } void CQueryMenuPage::DisplayMenus() { if( m_pObjSel == NULL ) return; if( !m_EditObject.m_spQueryNode ) return; m_bLoading = TRUE; m_MenuLV.DeleteAllItems(); m_DefaultID = 0; CRootNode* pRootNode = m_EditObject.m_spQueryNode->GetRootNode(); if( !pRootNode ) return; CClassInfo* pClassInfo = pRootNode->FindClass(m_pObjSel->Name()); if( pClassInfo != NULL ) { int iIndex = 0; menuref_vector& vMenuRefs = m_pObjSel->MenuRefs(); menuref_vector::iterator itMenuRef; menucmd_vector& vMenuCmds = pClassInfo->Menus(); menucmd_vector::iterator itMenuCmd; // First add all root menu items that are not yet ref'd by the query node for( itMenuCmd = vMenuCmds.begin(); itMenuCmd != vMenuCmds.end(); ++itMenuCmd ) { if( std::find(vMenuRefs.begin(), vMenuRefs.end(), (*itMenuCmd)->ID()) != vMenuRefs.end() ) break; // Add menu to displayed list in an enabled state DisplayMenuItem(iIndex++, *itMenuCmd, TRUE); } // For each query menu reference for( itMenuRef = vMenuRefs.begin(); itMenuRef != vMenuRefs.end(); ++itMenuRef ) { // Find the matching root menu cmd for( itMenuCmd = vMenuCmds.begin(); itMenuCmd != vMenuCmds.end(); ++itMenuCmd ) { if( (*itMenuCmd)->ID() == itMenuRef->ID() ) break; } // if menu was deleted at the root node, then skip it if( itMenuCmd == vMenuCmds.end() ) continue; // Display the menu item DisplayMenuItem(iIndex++, *(itMenuCmd++), itMenuRef->IsEnabled()); // If this is the default menu item save its ID if( itMenuRef->IsDefault() ) { ASSERT(m_DefaultID == 0); m_DefaultID = itMenuRef->ID(); } // Display any following root items that aren't in the query list while( itMenuCmd != vMenuCmds.end() && std::find(vMenuRefs.begin(), vMenuRefs.end(), (*itMenuCmd)->ID()) == vMenuRefs.end() ) { DisplayMenuItem(iIndex++, *(itMenuCmd++), TRUE); } } } // Disable buttons until selection made EnableDlgItem( m_hWnd, IDC_MOVEUP, FALSE ); EnableDlgItem( m_hWnd, IDC_MOVEDOWN, FALSE ); EnableDlgItem( m_hWnd, IDC_DEFAULTMENU, FALSE ); // Uncheck default button until default item selected Button_SetCheck(GetDlgItem(IDC_DEFAULTMENU), BST_UNCHECKED); // Set Property Menu Checkbox Button_SetCheck(GetDlgItem(IDC_PROPERTYMENU), m_pObjSel->HasPropertyMenu() ? BST_CHECKED : BST_UNCHECKED); m_bLoading = FALSE; } void CQueryMenuPage::DisplayMenuItem(int iIndex, CMenuCmd* pMenuCmd, BOOL bEnabled) { if( !pMenuCmd ) return; static CString strShellCmd; static CString strADCmd; LV_ITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = iIndex; lvi.iSubItem = 0; lvi.pszText = const_cast(pMenuCmd->Name()); lvi.lParam = static_cast(pMenuCmd->ID()); int iPos = m_MenuLV.InsertItem(&lvi); ASSERT(iPos == iIndex); lvi.iSubItem = 1; lvi.mask = LVIF_TEXT; switch( pMenuCmd->MenuType() ) { case MENUTYPE_SHELL: if( strShellCmd.IsEmpty() ) strShellCmd.LoadString(IDS_SHELLCMD); lvi.pszText = (LPWSTR)(LPCWSTR)strShellCmd; break; case MENUTYPE_ACTDIR: if( strADCmd.IsEmpty() ) strADCmd.LoadString(IDS_DISPSPEC); lvi.pszText = (LPWSTR)(LPCWSTR)strADCmd; break; default: ASSERT(FALSE); } m_MenuLV.SetItem(&lvi); m_MenuLV.SetCheckState(iIndex, bEnabled); } LRESULT CQueryMenuPage::OnObjectSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { int iItem = m_ObjectCB.GetCurSel(); // Double-clicking an empty combo box can call this with no selection if( iItem >= 0 ) { SaveMenuSet(); m_pObjSel = reinterpret_cast(m_ObjectCB.GetItemDataPtr(iItem)); DisplayMenus(); } return 0; } LRESULT CQueryMenuPage::OnMoveUpDown( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { int iItem = m_MenuLV.GetNextItem(-1, LVNI_SELECTED); ASSERT(iItem >= 0); // Get the selected item data WCHAR szName[100]; LVITEM lvi; lvi.mask = LVIF_TEXT|LVIF_PARAM|LVIF_STATE; lvi.stateMask = 0xFFFFFFFF; lvi.iSubItem = 0; lvi.iItem = iItem; lvi.pszText = szName; lvi.cchTextMax = sizeof(szName); m_MenuLV.GetItem(&lvi); WCHAR szType[100]; m_MenuLV.GetItemText(iItem, 1, szType, sizeof(szType)); // Set loading flag to avoid intermediate button enable/disables m_bLoading = TRUE; // Delete and insert at new position m_MenuLV.DeleteItem(iItem); lvi.iItem += (wID == IDC_MOVEUP) ? -1 : 1; m_MenuLV.InsertItem(&lvi); m_MenuLV.SetItemText(lvi.iItem, 1, szType); // re-establish checked state (insert doesn't retain it) if( lvi.state & CHECK_ON ) m_MenuLV.SetCheckState(lvi.iItem, TRUE); m_bLoading = FALSE; SetModified(TRUE); // update button states EnableDlgItem( m_hWnd, IDC_MOVEUP, (lvi.iItem > 0) ); EnableDlgItem( m_hWnd, IDC_MOVEDOWN, (lvi.iItem < (m_MenuLV.GetItemCount() - 1)) ); return 0; } LRESULT CQueryMenuPage::OnMenuChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled) { if( !pNMHDR ) return 0; if( !m_bLoading ) { LPNMLISTVIEW pnmv = reinterpret_cast(pNMHDR); // if state has changed if( pnmv->uChanged & LVIF_STATE ) { // if checkbox state change if( (pnmv->uNewState ^ pnmv->uOldState) & LVIS_STATEIMAGEMASK ) { // if the changed item is currently selected if( m_MenuLV.GetItemState(pnmv->iItem, LVIS_SELECTED) & LVIS_SELECTED ) { // Change the state of all selcted items to match BOOL bNewState = ((pnmv->uNewState & LVIS_STATEIMAGEMASK) == CHECK_ON); m_bLoading = TRUE; int iItem = -1; while( (iItem = m_MenuLV.GetNextItem(iItem, LVNI_SELECTED)) >= 0 ) { m_MenuLV.SetCheckState(iItem, bNewState); } m_bLoading = FALSE; } SetModified(TRUE); } if( (pnmv->uNewState ^ pnmv->uOldState) & LVIS_SELECTED ) { int nItems = m_MenuLV.GetItemCount(); int iItem = m_MenuLV.GetNextItem(-1, LVNI_SELECTED); int nSelected = m_MenuLV.GetSelectedCount(); BOOL bDefault = (nSelected == 1) && (m_MenuLV.GetItemData(iItem) == m_DefaultID); Button_SetCheck(GetDlgItem(IDC_DEFAULTMENU), bDefault ? BST_CHECKED : BST_UNCHECKED); EnableDlgItem( m_hWnd, IDC_MOVEUP, ((iItem > 0) && (nSelected == 1)) ); EnableDlgItem( m_hWnd, IDC_MOVEDOWN, ((iItem >= 0) && (iItem < (nItems - 1)) && (nSelected == 1)) ); EnableDlgItem( m_hWnd, IDC_DEFAULTMENU, (nSelected == 1) ); } } } return TRUE; } LRESULT CQueryMenuPage::OnDefaultChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { // if user checks the default then save currently selected menu ID as default if( Button_GetCheck(GetDlgItem(IDC_DEFAULTMENU)) == BST_CHECKED ) { // button should be disabled unless there is one menu item selected ASSERT(m_MenuLV.GetSelectedCount() == 1); int iItem = m_MenuLV.GetNextItem(-1, LVNI_SELECTED); m_DefaultID = m_MenuLV.GetItemData(iItem); } else { // if user unchecks box there is no default m_DefaultID = 0; } SetModified(TRUE); return 0; } LRESULT CQueryMenuPage::OnPropertyMenuChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { SetModified(TRUE); return 0; } void CQueryMenuPage::SaveMenuSet() { if( m_pObjSel == NULL ) return; m_pObjSel->m_vMenuRefs.clear(); LVITEM lvi; lvi.mask = LVIF_PARAM | LVIF_STATE; lvi.stateMask = LVIS_STATEIMAGEMASK; lvi.iSubItem = 0; int nItems = m_MenuLV.GetItemCount(); for( int iIndex = 0; iIndex < nItems; iIndex++ ) { lvi.iItem = iIndex; BOOL bStat = m_MenuLV.GetItem(&lvi); ASSERT(bStat); CMenuRef menuref; menuref.m_menuID = static_cast(lvi.lParam); menuref.SetEnable((lvi.state & LVIS_STATEIMAGEMASK) == CHECK_ON); menuref.SetDefault(menuref.m_menuID == m_DefaultID); m_pObjSel->m_vMenuRefs.push_back(menuref); } m_pObjSel->SetPropertyMenu( Button_GetCheck(GetDlgItem(IDC_PROPERTYMENU)) == BST_CHECKED ); } BOOL CQueryMenuPage::OnSetActive() { m_EditObject.PageActive(m_hWnd); return TRUE; } BOOL CQueryMenuPage::OnApply() { SaveMenuSet(); return m_EditObject.ApplyChanges(m_hWnd); } /////////////////////////////////////////////////////////////////////////////////////////// // CQueryViewPage CQueryViewPage::CQueryViewPage(CQueryEditObj* pEditObj) : m_EditObject(*pEditObj), m_bLoading(FALSE), m_pObjSel(NULL) { ASSERT(pEditObj != NULL); m_EditObject.AddRef(); } CQueryViewPage::~CQueryViewPage() { m_ObjectCB.Detach(); m_EditObject.Release(); } LRESULT CQueryViewPage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { HWND hwndList = GetDlgItem(IDC_COLUMNLIST); if( hwndList ) { m_ColumnLV.SubclassWindow(hwndList); RECT rc; BOOL bStat = m_ColumnLV.GetClientRect(&rc); ASSERT(bStat); int iCol = m_ColumnLV.InsertColumn(0, NULL, LVCFMT_LEFT, (rc.right - rc.left), 0); ASSERT(iCol == 0); m_ColumnLV.SetExtendedListViewStyle(LVS_EX_CHECKBOXES); } HWND hwndCombo = GetDlgItem(IDC_OBJECTLIST); if( hwndCombo ) { m_ObjectCB.Attach(hwndCombo); LoadObjectCB(m_ObjectCB, m_EditObject.m_vObjInfo); if( m_EditObject.m_vObjInfo.size() != 0 ) { m_ObjectCB.SetCurSel(0); m_pObjSel = reinterpret_cast(m_ObjectCB.GetItemDataPtr(0)); if( hwndList ) { DisplayColumns(); } } } return TRUE; } LRESULT CQueryViewPage::OnObjectSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { int iItem = m_ObjectCB.GetCurSel(); // Double-clicking an empty combo box can call this with no selection if( iItem >= 0 ) { SaveColumnSet(); m_pObjSel = reinterpret_cast(m_ObjectCB.GetItemDataPtr(iItem)); DisplayColumns(); } return 0; } void CQueryViewPage::DisplayColumns() { if( !m_pObjSel ) return; if( !m_EditObject.m_spQueryNode ) return; m_bLoading = TRUE; m_ColumnLV.DeleteAllItems(); LV_ITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = 0; lvi.iSubItem = 0; CRootNode* pRootNode = m_EditObject.m_spQueryNode->GetRootNode(); if( !pRootNode ) return; CClassInfo* pClassInfo = pRootNode->FindClass(m_pObjSel->Name()); if( pClassInfo != NULL ) { DisplayNameMap* pNameMap = DisplayNames::GetMap(m_pObjSel->Name()); ASSERT(pNameMap != NULL); if( pNameMap == NULL ) return; string_vector& vDisabledCols = m_pObjSel->DisabledColumns(); string_vector::iterator itstrCol; for( itstrCol = pClassInfo->Columns().begin(); itstrCol != pClassInfo->Columns().end(); ++itstrCol ) { lvi.pszText = const_cast(pNameMap->GetAttributeDisplayName(itstrCol->c_str())); lvi.lParam = reinterpret_cast(itstrCol->c_str()); int iPos = m_ColumnLV.InsertItem(&lvi); ASSERT(iPos >= 0); //Enable all columns that aren't excluded by the query node if( std::find(vDisabledCols.begin(), vDisabledCols.end(), *itstrCol) == vDisabledCols.end() ) m_ColumnLV.SetCheckState(iPos, TRUE); } } m_bLoading = FALSE; } LRESULT CQueryViewPage::OnColumnChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled) { if( !pNMHDR ) return 0; if( !m_bLoading ) { LPNMLISTVIEW pnmv = reinterpret_cast(pNMHDR); // if checked state has changed if( (pnmv->uChanged & LVIF_STATE) && ((pnmv->uNewState ^ pnmv->uOldState) & LVIS_STATEIMAGEMASK) ) { // if the changed item is currently selected if( m_ColumnLV.GetItemState(pnmv->iItem, LVIS_SELECTED) & LVIS_SELECTED ) { // Change the state of all selcted items to match BOOL bNewState = ((pnmv->uNewState & LVIS_STATEIMAGEMASK) == CHECK_ON); m_bLoading = TRUE; int iItem = -1; while( (iItem = m_ColumnLV.GetNextItem(iItem, LVNI_SELECTED)) >= 0 ) { m_ColumnLV.SetCheckState(iItem, bNewState); } m_bLoading = FALSE; } SetModified(TRUE); } } return TRUE; } void CQueryViewPage::SaveColumnSet() { if( m_pObjSel == NULL ) return; string_vector vstrNewCols; int nItems = m_ColumnLV.GetItemCount(); for( int iIndex = 0; iIndex < nItems; iIndex++ ) { // Save list of disabled columns if( !m_ColumnLV.GetCheckState(iIndex) ) { LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iItem = iIndex; lvi.iSubItem = 0; BOOL bStat = m_ColumnLV.GetItem(&lvi); ASSERT(bStat); vstrNewCols.push_back(reinterpret_cast(lvi.lParam)); } } m_pObjSel->m_vstrDisabledColumns = vstrNewCols; } typedef struct { HWND hwndList; int iCol; } COMPAREPARAM, *LPCOMPAREPARAM; int CALLBACK ColumnCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { if( !lParamSort ) return 0; LPCOMPAREPARAM pcmp = reinterpret_cast(lParamSort); WCHAR sz1[MAX_PATH]; ListView_GetItemText(pcmp->hwndList, lParam1, pcmp->iCol, sz1, MAX_PATH); WCHAR sz2[MAX_PATH]; ListView_GetItemText(pcmp->hwndList, lParam2, pcmp->iCol, sz2, MAX_PATH); return wcscmp(sz1,sz2); } LRESULT CQueryViewPage::OnColumnClick(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled) { if( !pNMHDR ) return 0; LPNMLISTVIEW pnmv = reinterpret_cast(pNMHDR); COMPAREPARAM cmp; cmp.hwndList = pnmv->hdr.hwndFrom; cmp.iCol = pnmv->iSubItem; ListView_SortItemsEx(pnmv->hdr.hwndFrom, &ColumnCompare, &cmp); return TRUE; } BOOL CQueryViewPage::OnSetActive() { DisplayColumns(); m_EditObject.PageActive(m_hWnd); return TRUE; } BOOL CQueryViewPage::OnApply() { SaveColumnSet(); return m_EditObject.ApplyChanges(m_hWnd); } /////////////////////////////////////////////////////////////////////////////////////////// // CQueryNodeMenuPage CQueryNodeMenuPage::CQueryNodeMenuPage(CQueryEditObj* pEditObj) : m_EditObject(*pEditObj) { ASSERT(pEditObj != NULL); m_EditObject.AddRef(); } CQueryNodeMenuPage::~CQueryNodeMenuPage() { m_MenuLV.Detach(); m_EditObject.Release(); } LRESULT CQueryNodeMenuPage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { m_MenuLV.Attach(GetDlgItem(IDC_MENULIST)); ::ConfigSingleColumnListView(GetDlgItem(IDC_MENULIST)); return TRUE; } BOOL CQueryNodeMenuPage::OnSetActive() { m_EditObject.PageActive(m_hWnd); DisplayMenus(); return TRUE; } void CQueryNodeMenuPage::DisplayMenus() { if( !m_EditObject.m_spQueryNode ) return; HWND hwndLV = GetDlgItem(IDC_MENULIST); ASSERT(::IsWindow(hwndLV)); ListView_DeleteAllItems(hwndLV); // make sure menu names have been loaded CRootNode* pRootNode = m_EditObject.m_spQueryNode->GetRootNode(); if( !pRootNode ) return; CComponentData* pCompData = pRootNode->GetCompData(); if( !pCompData ) return; IStringTable* pStringTable = pCompData->GetStringTable(); ASSERT(pStringTable != NULL); if( !pStringTable ) return; m_EditObject.LoadStrings(pStringTable); LV_ITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = 0; lvi.iSubItem = 0; menucmd_vector::iterator itMenu; for( itMenu = m_EditObject.Menus().begin(); itMenu != m_EditObject.Menus().end(); ++itMenu ) { lvi.pszText = const_cast((*itMenu)->Name()); lvi.lParam = (*itMenu)->ID(); int iPos = ListView_InsertItem(hwndLV, &lvi); ASSERT(iPos >= 0); lvi.iItem++; } EnableDlgItem( m_hWnd, IDC_ADDMENU, TRUE ); EnableDlgItem( m_hWnd, IDC_REMOVEMENU, FALSE ); EnableDlgItem( m_hWnd, IDC_EDITMENU, FALSE ); EnableDlgItem( m_hWnd, IDC_MOVEUP, FALSE ); EnableDlgItem( m_hWnd, IDC_MOVEDOWN, FALSE ); } LRESULT CQueryNodeMenuPage::OnAddMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { if( !m_EditObject.m_spQueryNode ) return 0; CAddQNMenuDlg dlg(m_EditObject); if( dlg.DoModal() == IDOK ) { CMenuCmd* pMenuNew = dlg.GetMenu(); ASSERT(pMenuNew != NULL); if( !pMenuNew ) return 0; // Add new menu to list HWND hwndList = GetDlgItem(IDC_MENULIST); // Set name to add it to string table and generate the menu ID CRootNode* pRootNode = m_EditObject.m_spQueryNode->GetRootNode(); if( !pRootNode ) return 0; CComponentData* pCompData = pRootNode->GetCompData(); ASSERT( pCompData ); if( !pCompData ) return 0; IStringTable* pStringTable = pCompData->GetStringTable(); ASSERT( pStringTable ); if( !pStringTable ) return 0; // Use temp string because string fails an assignement like: strX = strX.c_str() // (it relases the private buffer first and then assigns the string) tstring strName = pMenuNew->Name(); pMenuNew->SetName(pStringTable, strName.c_str()); LVITEM lvi; lvi.mask = LVIF_PARAM | LVIF_TEXT; lvi.iSubItem = 0; lvi.iItem = ListView_GetItemCount(hwndList); lvi.lParam = pMenuNew->ID(); lvi.pszText = const_cast(pMenuNew->Name()); ListView_InsertItem(hwndList,&lvi); // Add to menu vector (note that temp CMenuCmdPtr will delete pMenuNew) m_EditObject.m_vMenus.push_back(CMenuCmdPtr(pMenuNew)); SetModified(TRUE); } return 0; } LRESULT CQueryNodeMenuPage::OnEditMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { if( !m_EditObject.m_spQueryNode ) return 0; HWND hwndList = GetDlgItem(IDC_MENULIST); int iIndex = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED); ASSERT(iIndex != -1); LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iSubItem = 0; lvi.iItem = iIndex; ListView_GetItem(hwndList, &lvi); // Locate selected menu by it's ID (lparam) menucmd_vector& vMenus = m_EditObject.Menus(); menucmd_vector::iterator itMenu; itMenu = std::find(vMenus.begin(), vMenus.end(), lvi.lParam); ASSERT(itMenu != vMenus.end()); CMenuCmd* pMenu = *itMenu; if( !pMenu ) return 0; CAddQNMenuDlg dlg(m_EditObject, pMenu); if( dlg.DoModal() == IDOK ) { CMenuCmd* pMenuNew = dlg.GetMenu(); ASSERT(pMenuNew != NULL); if( !pMenuNew ) return 0; // Set the name again in case it was changed CRootNode* pRootNode = m_EditObject.m_spQueryNode->GetRootNode(); if( !pRootNode ) return 0; CComponentData* pCompData = pRootNode->GetCompData(); if( !pCompData ) return 0; IStringTable* pStringTable = pCompData->GetStringTable(); ASSERT(pStringTable != NULL); if( !pStringTable ) return 0; // Use temp string because string fails an assignement like: strX = strX.c_str() // (it relases the private buffer first and then assigns the string) tstring strName = pMenuNew->Name(); pMenuNew->SetName(pStringTable, strName.c_str()); // locate object again because the vector may have been reallocated menucmd_vector& vMenusNew = m_EditObject.Menus(); // locate with the old ID because it will be different if the name was changed itMenu = std::find(vMenusNew.begin(), vMenusNew.end(), pMenu->ID()); ASSERT(itMenu != vMenusNew.end()); // Replace menu with new one *itMenu = pMenuNew; // Update the list lvi.mask = LVIF_PARAM | LVIF_TEXT; lvi.lParam = pMenuNew->ID(); lvi.pszText = const_cast(pMenuNew->Name()); ListView_SetItem(hwndList,&lvi); SetModified(TRUE); } return 0; } LRESULT CQueryNodeMenuPage::OnRemoveMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { HWND hwndList = GetDlgItem(IDC_MENULIST); UINT uiMsg = (ListView_GetSelectedCount(hwndList) == 1) ? IDS_MENU_REMOVE_ONE : IDS_MENU_REMOVE; int iRet = DisplayMessageBox(m_hWnd, IDS_MENU_REMOVE_TITLE, uiMsg, MB_YESNO|MB_ICONWARNING); if( iRet != IDYES ) return 0; menucmd_vector& vMenus = m_EditObject.Menus(); LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iSubItem = 0; int iIndex = -1; while( (iIndex = ListView_GetNextItem(hwndList, iIndex, LVNI_SELECTED)) >= 0 ) { lvi.iItem = iIndex; ListView_GetItem(hwndList, &lvi); // Locate menu by its ID menucmd_vector::iterator itMenu = std::find(vMenus.begin(), vMenus.end(), lvi.lParam); ASSERT(itMenu != vMenus.end()); vMenus.erase(itMenu); ListView_DeleteItem(hwndList, iIndex); iIndex--; } EnableDlgItem( m_hWnd, IDC_REMOVEMENU, FALSE ); EnableDlgItem( m_hWnd, IDC_EDITMENU, FALSE ); EnableDlgItem( m_hWnd, IDC_MOVEUP, FALSE ); EnableDlgItem( m_hWnd, IDC_MOVEDOWN, FALSE ); SetModified(TRUE); return 0; } LRESULT CQueryNodeMenuPage::OnMoveUpDown( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { HWND hwndList = GetDlgItem(IDC_MENULIST); int iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED); ASSERT(iItem >= 0); // Determine new position for selected item if( wID == IDC_MOVEUP ) iItem--; else iItem++; // Now swap the selected item with the item at its new position // Do it by moving the unselected item to avoid state change notifications // because they will cause unwanted butten enables/disables. LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iSubItem = 0; lvi.iItem = iItem; ListView_GetItem(hwndList, &lvi); // Move the menu item in the menu vector menucmd_vector& vMenus = m_EditObject.Menus(); menucmd_vector::iterator itMenu = std::find(vMenus.begin(), vMenus.end(), lvi.lParam); ASSERT(itMenu != vMenus.end()); menucmd_vector::iterator itMenuOld = itMenu; if( wID == IDC_MOVEUP ) itMenu++; else itMenu--; // swap the items std::iter_swap (itMenuOld, itMenu); //Now delete and reinsert it in the list view ListView_DeleteItem(hwndList, lvi.iItem); if( wID == IDC_MOVEUP ) lvi.iItem++; else lvi.iItem--; lvi.mask = LVIF_PARAM | LVIF_TEXT; lvi.pszText = const_cast((*itMenu)->Name()); ListView_InsertItem(hwndList, &lvi); // Update Up/Down buttons EnableDlgItem( m_hWnd, IDC_MOVEUP, (iItem > 0) ); EnableDlgItem( m_hWnd, IDC_MOVEDOWN, (iItem < (ListView_GetItemCount(hwndList) - 1)) ); SetModified(TRUE); return 0; } LRESULT CQueryNodeMenuPage::OnMenuListChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled) { HWND hwndList = GetDlgItem(IDC_MENULIST); int nItemSel = ListView_GetSelectedCount(hwndList); int iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED); EnableDlgItem( m_hWnd, IDC_REMOVEMENU, (nItemSel > 0) ); EnableDlgItem( m_hWnd, IDC_EDITMENU, (nItemSel == 1) ); EnableDlgItem( m_hWnd, IDC_MOVEUP, ((nItemSel == 1) && (iItem > 0)) ); EnableDlgItem( m_hWnd, IDC_MOVEDOWN, ((nItemSel == 1) && (iItem < (ListView_GetItemCount(hwndList) - 1))) ); return TRUE; } LRESULT CQueryNodeMenuPage::OnMenuListDblClk(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled) { if( ListView_GetSelectedCount(GetDlgItem(IDC_MENULIST)) ) ::SendMessage(GetDlgItem(IDC_EDITMENU), BM_CLICK, (WPARAM)0, (LPARAM)0); return 0; } BOOL CQueryNodeMenuPage::OnApply() { return m_EditObject.ApplyChanges(m_hWnd); } ///////////////////////////////////////////////////////////////////////////////////////////////// // CQueryEditObj void CQueryEditObj::PageActive(HWND hwndPage) { ASSERT(::IsWindow(hwndPage)); // track the highest created page number for ApplyChanges method int iPage = PropSheet_HwndToIndex(GetParent(hwndPage), hwndPage); if( iPage > m_iPageMax ) m_iPageMax = iPage; } BOOL CQueryEditObj::ApplyChanges(HWND hwndPage) { if( !m_spQueryNode ) return FALSE; ASSERT(::IsWindow(hwndPage)); // Don't apply changes until called from highest activated page if( PropSheet_HwndToIndex(GetParent(hwndPage), hwndPage) < m_iPageMax ) return TRUE; // replace original query objects with edited copies m_spQueryNode->Objects() = m_vObjInfo; m_spQueryNode->Menus() = m_vMenus; if( m_spQueryNode ) { CRootNode* pRootNode = m_spQueryNode->GetRootNode(); if( pRootNode ) { pRootNode->UpdateModifyTime(); } } return TRUE; } ///////////////////////////////////////////////////////////////////////////////////////////////// // Helper functions void LoadObjectCB(CComboBox& ComboBox, QueryObjVector& vObj) { ComboBox.ResetContent(); DisplayNameMap* pNameMap = DisplayNames::GetClassMap(); ASSERT(pNameMap != NULL); if( pNameMap == NULL ) return; for( QueryObjVector::iterator itObj = vObj.begin(); itObj != vObj.end(); ++itObj ) { int iIndex = ComboBox.AddString(pNameMap->GetAttributeDisplayName(itObj->Name())); ASSERT(iIndex >= 0); ComboBox.SetItemDataPtr(iIndex, &(*itObj)); } }