|
|
// rootprop.cpp - Root Property Page Implementation
#include "stdafx.h"
#include "resource.h"
#include "rootprop.h"
#include "compdata.h"
#include "scopenode.h"
#include "wizards.h"
#include "query.h"
#include "cmndlgs.h"
#include "util.h"
#include "namemap.h"
#include <windowsx.h>
#include <algorithm>
int GetDateTimeString(FILETIME* pftime, LPWSTR pszBuf, int cBuf); void LoadObjectCB(CComboBox& ComboBox, CEditObjList& ObjList);
///////////////////////////////////////////////////////////////////////////////////////////
// CRootGeneralPage
LRESULT CRootGeneralPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { CRootNode* pRootNode = m_ObjList.RootNode(); ASSERT(pRootNode != NULL); if( !pRootNode ) return 0;
Edit_LimitText(GetDlgItem(IDC_COMMENTS),255);
SetDlgItemText( IDC_NAME, pRootNode->GetName() );
tstring strComment; pRootNode->GetComment(strComment); SetDlgItemText( IDC_COMMENTS, strComment.c_str() );
FILETIME ftime; WCHAR szDateTime[32];
pRootNode->GetCreateTime(&ftime); if( GetDateTimeString(&ftime, szDateTime, lengthof(szDateTime)) ) { SetDlgItemText( IDC_CREATED, szDateTime ); }
pRootNode->GetModifyTime(&ftime); if( GetDateTimeString(&ftime, szDateTime, lengthof(szDateTime)) ) { SetDlgItemText( IDC_MODIFIED, szDateTime ); }
m_bChgComment = FALSE;
return TRUE; }
LRESULT CRootGeneralPage::OnChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { SetModified(TRUE); m_bChgComment = TRUE;
return 0; }
//------------------------------------------------------------------------------------
// CRootGeneralPage::OnClose
//
// This method is invoked when the 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 CRootGeneralPage::OnClose( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { // Simulate press of Cancel button
::PropSheet_PressButton(GetParent(), PSBTN_CANCEL);
return 0; }
BOOL CRootGeneralPage::OnSetActive() { m_ObjList.PageActive(m_hWnd); return TRUE; }
BOOL CRootGeneralPage::OnApply() { if (m_bChgComment) { CRootNode* pRootNode = m_ObjList.RootNode(); ASSERT(pRootNode); if( !pRootNode ) return FALSE;
int cLen = ::GetWindowTextLength(GetDlgItem(IDC_COMMENTS)); LPWSTR szTemp = new WCHAR[(cLen+1)]; if( !szTemp ) return FALSE;
int cLen1 = ::GetWindowText(GetDlgItem(IDC_COMMENTS), szTemp, cLen+1); ASSERT(cLen == cLen1);
pRootNode->SetComment(szTemp); pRootNode->UpdateModifyTime();
m_bChgComment = FALSE;
delete [] szTemp; }
return m_ObjList.ApplyChanges(m_hWnd); }
///////////////////////////////////////////////////////////////////////////////////////////
// CRootMenuPage
CRootMenuPage::~CRootMenuPage() { m_ObjectCB.Detach(); m_MenuLV.Detach();
m_ObjList.Release(); }
LRESULT CRootMenuPage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { m_ObjectCB.Attach(GetDlgItem(IDC_OBJECTLIST)); m_MenuLV.Attach(GetDlgItem(IDC_MENULIST));
m_itObjSelect = NULL;
::ConfigSingleColumnListView(GetDlgItem(IDC_MENULIST)); return TRUE; }
BOOL CRootMenuPage::OnSetActive() { m_ObjList.PageActive(m_hWnd);
LoadObjectCB(m_ObjectCB, m_ObjList);
// if object was previously selected
if (m_itObjSelect != NULL) { // find the edit object by name because it may have been moved or deleted
// while another page was active
m_itObjSelect = m_ObjList.FindObject(m_strObjSelect.c_str());
if (m_itObjSelect != NULL && m_itObjSelect->IsDeleted()) m_itObjSelect = NULL; }
// if object still around, reselect it in the combo box
if (m_itObjSelect != NULL) { DisplayNameMap* pNameMap = DisplayNames::GetClassMap(); ASSERT( pNameMap ); if( !pNameMap ) return FALSE;
int iSel = m_ObjectCB.FindStringExact(-1, pNameMap->GetAttributeDisplayName(m_strObjSelect.c_str())); ASSERT(iSel != CB_ERR);
m_ObjectCB.SetCurSel(iSel); } else if (m_ObjectCB.GetCount() > 0) { // default to the first object and update the columns
m_ObjectCB.SetCurSel(0);
void* pv = m_ObjectCB.GetItemDataPtr(0); m_itObjSelect = *(EditObjIter*)&pv;
m_strObjSelect = m_itObjSelect->Name(); DisplayMenus(); } else { DisplayMenus(); } return TRUE; }
LRESULT CRootMenuPage::OnObjectSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { int iItem = m_ObjectCB.GetCurSel();
// Double-clicking an empty combo box will call this with no selection
if (iItem >= 0) { void* pv = m_ObjectCB.GetItemDataPtr(iItem); m_itObjSelect = *(EditObjIter*)&pv; m_strObjSelect = m_itObjSelect->Name();
DisplayMenus(); }
return 0;
}
void CRootMenuPage::DisplayMenus() { HWND hwndLV = GetDlgItem(IDC_MENULIST); if( !hwndLV || !::IsWindow(hwndLV) ) return;
ListView_DeleteAllItems(hwndLV);
if (m_itObjSelect != NULL) { CClassInfo& classInfo = m_itObjSelect->GetObject();
// make sure menu names have been loaded
IStringTable* pStringTable = m_ObjList.RootNode()->GetCompData()->GetStringTable(); ASSERT(pStringTable != NULL); classInfo.LoadStrings(pStringTable);
LV_ITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = 0; lvi.iSubItem = 0; menucmd_vector::iterator itMenu; for (itMenu = classInfo.Menus().begin(); itMenu != classInfo.Menus().end(); ++itMenu) { lvi.pszText = const_cast<LPWSTR>((*itMenu)->Name()); lvi.lParam = (*itMenu)->ID();
int iPos = ListView_InsertItem(hwndLV, &lvi); ASSERT(iPos >= 0);
lvi.iItem++; }
// if items are added, select the first
if (ListView_GetItemCount(hwndLV) > 0) { ListView_SetItemState(hwndLV, 0, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); } }
EnableDlgItem( m_hWnd, IDC_ADDMENU, (m_itObjSelect != NULL) ); 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 CRootMenuPage::OnAddMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { // if object is selected
if (m_itObjSelect == NULL) return 0;
CAddMenuDlg dlg(m_itObjSelect->GetObject());
if (dlg.DoModal() == IDOK) { CClassInfo* pClassInfo = m_itObjSelect->GetModifiedObject(); if( !pClassInfo ) return 0;
CMenuCmd* pMenuNew = dlg.GetMenu(); ASSERT(pMenuNew != NULL);
if( pMenuNew ) { // Add new menu to list
HWND hwndList = GetDlgItem(IDC_MENULIST); // Set name to add it to string table and generate the menu ID
IStringTable* pStringTable = m_ObjList.RootNode()->GetCompData()->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<LPWSTR>(pMenuNew->Name()); ListView_InsertItem(hwndList,&lvi);
// if first item is added, select it
if (ListView_GetItemCount(hwndList) == 1) { ListView_SetItemState(hwndList, 0, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); } // Add to menu vector (note that temp CMenuCmdPtr will delete pMenuNew)
pClassInfo->Menus().push_back(CMenuCmdPtr(pMenuNew));
SetModified(TRUE); } }
return 0; }
LRESULT CRootMenuPage::OnEditMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { HWND hwndList = GetDlgItem(IDC_MENULIST); if( !hwndList || !::IsWindow(hwndList) ) return 0;
int iIndex = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED); ASSERT(iIndex != -1); if( iIndex == -1 ) return 0;
LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iSubItem = 0; lvi.iItem = iIndex;
ListView_GetItem(hwndList, &lvi);
// Locate selected menu by it's ID (lparam)
CClassInfo& classInfo = m_itObjSelect->GetObject(); menucmd_vector& vMenus = classInfo.Menus();
menucmd_vector::iterator itMenu; itMenu = std::find(vMenus.begin(), vMenus.end(), lvi.lParam); ASSERT(itMenu != vMenus.end()); if( itMenu == vMenus.end() ) return 0;
CMenuCmd* pMenu = *itMenu; if( !pMenu ) return 0;
CAddMenuDlg dlg(m_itObjSelect->GetObject(), pMenu);
if (dlg.DoModal() == IDOK) { CMenuCmd* pMenuNew = dlg.GetMenu(); ASSERT( pMenuNew ); if( !pMenuNew ) return 0;
// Set the name again in case it was changed
IStringTable* pStringTable = m_ObjList.RootNode()->GetCompData()->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());
// locate object again because the vector may have been reallocated
CClassInfo* pClassInfoNew = m_itObjSelect->GetModifiedObject(); if( !pClassInfoNew ) return 0;
menucmd_vector& vMenusNew = pClassInfoNew->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()); if( itMenu == vMenusNew.end() ) return 0;
// Replace menu with new one
*itMenu = pMenuNew;
// Update the list
lvi.mask = LVIF_PARAM | LVIF_TEXT; lvi.lParam = pMenuNew->ID(); lvi.pszText = const_cast<LPWSTR>(pMenuNew->Name()); ListView_SetItem(hwndList,&lvi); SetModified(TRUE); } return 0; }
LRESULT CRootMenuPage::OnRemoveMenu( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { if (m_itObjSelect == NULL) return 0;
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;
CClassInfo* pClassInfo = m_itObjSelect->GetModifiedObject(); if( !pClassInfo ) return 0; menucmd_vector& vMenus = pClassInfo->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 CRootMenuPage::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
CClassInfo* pClassInfo = m_itObjSelect->GetModifiedObject(); if( !pClassInfo ) return 0; menucmd_vector& vMenus = pClassInfo->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<LPWSTR>((*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 CRootMenuPage::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 CRootMenuPage::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 CRootMenuPage::OnApply() { return m_ObjList.ApplyChanges(m_hWnd); }
///////////////////////////////////////////////////////////////////////////////////////////
// CRootObjectPage
LRESULT CRootObjectPage::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { HWND hwndList = GetDlgItem(IDC_OBJECTLIST);
ConfigSingleColumnListView(hwndList);
return TRUE; }
LRESULT CRootObjectPage::OnAddObject(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { HRESULT hr; do { // Pass list of current classes, so wizard won't add one twice
string_vector vstrClasses; for (EditObjIter itObj = m_ObjList.begin(); itObj != m_ObjList.end(); ++itObj) { if (!itObj->IsDeleted()) vstrClasses.push_back(itObj->Name()); }
CAddObjectWizard objWiz; objWiz.Initialize(&vstrClasses, m_ObjList.RootNode()->GetCompData()->GetStringTable()); // Run the wizard
IPropertySheetProviderPtr spProvider = m_ObjList.RootNode()->GetCompData()->GetConsole(); if( spProvider == NULL ) return E_NOINTERFACE; hr = objWiz.Run(spProvider, m_hWnd); if (hr == S_OK) { ASSERT(objWiz.GetNewObject() != NULL); if( !(objWiz.GetNewObject()) ) return E_FAIL;
EditObjIter itObj = m_ObjList.AddObject(objWiz.GetNewObject()); ASSERT(itObj != NULL); if( itObj == NULL ) return E_FAIL;
LV_ITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = 0; lvi.iSubItem = 0;
lvi.pszText = const_cast<LPWSTR>(DisplayNames::GetClassMap()->GetAttributeDisplayName(itObj->Name())); lvi.lParam = *(LPARAM*)&itObj; // NEED BETTER CONVERSION
int iPos = ListView_InsertItem(GetDlgItem(IDC_OBJECTLIST), &lvi); ASSERT(iPos >= 0);
// if first item is added, select it
if (ListView_GetItemCount(GetDlgItem(IDC_OBJECTLIST)) == 1) { ListView_SetItemState(GetDlgItem(IDC_OBJECTLIST), 0, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); } SetModified(TRUE); } } while (FALSE);
return hr; }
LRESULT CRootObjectPage::OnRemoveObject( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { HWND hwndList = GetDlgItem(IDC_OBJECTLIST);
BOOL bFirst = TRUE; int iIndex = -1; while ((iIndex = ListView_GetNextItem(hwndList, iIndex, LVNI_SELECTED)) != -1) { LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iItem = iIndex; lvi.iSubItem = 0;
BOOL bStat = ListView_GetItem(hwndList, &lvi); ASSERT(bStat);
EditObjIter itObj = *(EditObjIter*)&lvi.lParam;
// get confirmation before deleting first object
if (bFirst) { bFirst = FALSE;
CString strTitle; strTitle.LoadString(IDS_DELETEOBJ_TITLE); CString strMsgFmt; if (ListView_GetSelectedCount(hwndList) == 1) strMsgFmt.LoadString(IDS_DELETEOBJ); else strMsgFmt.LoadString(IDS_DELETEOBJS); WCHAR szName[MAX_PATH]; ListView_GetItemText(hwndList, iIndex, 0, szName, sizeof(szName));
CString strMsg; strMsg.Format(strMsgFmt, szName);
if (::MessageBox(m_hWnd, strMsg, strTitle, MB_YESNO|MB_ICONWARNING) != IDYES) return 0; }
m_ObjList.DeleteObject(itObj);
ListView_DeleteItem(hwndList, iIndex);
// backup index because it now points to the next item
iIndex--;
SetModified(TRUE); }
EnableDlgItem( m_hWnd, IDC_REMOVEOBJECT, FALSE ); return 0; }
LRESULT CRootObjectPage::OnObjListChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled) { EnableDlgItem( m_hWnd, IDC_REMOVEOBJECT, ListView_GetSelectedCount(GetDlgItem(IDC_OBJECTLIST)) );
return TRUE; }
BOOL CRootObjectPage::OnSetActive() { HWND hwndList = GetDlgItem(IDC_OBJECTLIST);
ListView_DeleteAllItems(hwndList);
LV_ITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = 0; lvi.iSubItem = 0;
DisplayNameMap* pNameMap = DisplayNames::GetClassMap(); ASSERT(pNameMap != NULL); if (pNameMap == NULL) return TRUE;
for (EditObjIter itObj = m_ObjList.begin(); itObj != m_ObjList.end(); ++itObj) { if (!itObj->IsDeleted()) { lvi.pszText = const_cast<LPWSTR>(pNameMap->GetAttributeDisplayName(itObj->Name())); lvi.lParam = *(LPARAM*)&itObj; // NEED BETTER CONVERSION
int iPos = ListView_InsertItem(hwndList, &lvi); ASSERT(iPos >= 0); } }
// if items are added, select the first
if (ListView_GetItemCount(hwndList) > 0) { ListView_SetItemState(hwndList, 0, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); }
EnableDlgItem( m_hWnd, IDC_REMOVEOBJECT, FALSE );
m_ObjList.PageActive(m_hWnd); return TRUE; }
BOOL CRootObjectPage::OnApply() { return m_ObjList.ApplyChanges(m_hWnd); }
///////////////////////////////////////////////////////////////////////////////////////////
// CRootViewPage
CRootViewPage::~CRootViewPage() { m_ObjectCB.Detach(); m_ColumnLV.Detach();
m_ObjList.Release(); }
LRESULT CRootViewPage::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { m_ObjectCB.Attach(GetDlgItem(IDC_OBJECTLIST)); m_ColumnLV.Attach(GetDlgItem(IDC_COLUMNLIST));
m_itObjSelect = NULL;
::ConfigSingleColumnListView(GetDlgItem(IDC_COLUMNLIST)); return TRUE; }
LRESULT CRootViewPage::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) { void* pv = m_ObjectCB.GetItemDataPtr(iItem); m_itObjSelect = *(EditObjIter*)&pv; m_strObjSelect = m_itObjSelect->Name();
DisplayColumns(); }
return 0; }
LRESULT CRootViewPage::OnColumnListChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled) { EnableDlgItem( m_hWnd, IDC_REMOVECOLUMN, ListView_GetSelectedCount(GetDlgItem(IDC_COLUMNLIST)) );
return TRUE; }
void CRootViewPage::DisplayColumns() { HWND hwndLV = GetDlgItem(IDC_COLUMNLIST); ASSERT(::IsWindow(hwndLV));
ListView_DeleteAllItems(hwndLV);
if (m_itObjSelect != NULL) { CClassInfo& classInfo = m_itObjSelect->GetObject();
DisplayNameMap* pNameMap = DisplayNames::GetMap(classInfo.Name()); if( !pNameMap ) return;
LV_ITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = 0; lvi.iSubItem = 0; string_vector::iterator itStr; for (itStr = classInfo.Columns().begin(); itStr != classInfo.Columns().end(); ++itStr) { lvi.pszText = const_cast<LPWSTR>(pNameMap->GetAttributeDisplayName(itStr->c_str())); lvi.lParam = reinterpret_cast<LPARAM>(itStr->c_str());
int iPos = ListView_InsertItem(hwndLV, &lvi); ASSERT(iPos >= 0); }
// if items are added, select the first
if (ListView_GetItemCount(hwndLV) > 0) { ListView_SetItemState(hwndLV, 0, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); } }
EnableDlgItem( m_hWnd, IDC_ADDCOLUMN, (m_itObjSelect != NULL) ); EnableDlgItem( m_hWnd, IDC_REMOVECOLUMN, FALSE ); }
LRESULT CRootViewPage::OnAddColumn( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { // if object is selected
if (m_itObjSelect == NULL) return 0;
CAddColumnDlg dlg(m_itObjSelect->Name());
if (dlg.DoModal() == IDOK) { BOOL bModified = FALSE;
CClassInfo* pClassInfo = m_itObjSelect->GetModifiedObject(); if( !pClassInfo ) return 0;
HWND hwndList = GetDlgItem(IDC_COLUMNLIST); ASSERT(hwndList != NULL);
string_vector::iterator itStr = dlg.GetColumns().begin(); while (itStr != dlg.GetColumns().end()) { if (std::find(pClassInfo->Columns().begin(), pClassInfo->Columns().end(), *itStr) == pClassInfo->Columns().end()) { pClassInfo->Columns().push_back(*itStr); bModified = TRUE; } ++itStr; }
if (bModified) { SetModified(TRUE); DisplayColumns(); } }
return 0; }
LRESULT CRootViewPage::OnRemoveColumn( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { if (m_itObjSelect == NULL) return 0;
HWND hwndList = GetDlgItem(IDC_COLUMNLIST); ASSERT(hwndList != NULL);
UINT uiMsg = (ListView_GetSelectedCount(hwndList) == 1) ? IDS_PROP_REMOVE_ONE : IDS_PROP_REMOVE; int iRet = DisplayMessageBox(m_hWnd, IDS_PROP_REMOVE_TITLE, uiMsg, MB_YESNO|MB_ICONWARNING); if (iRet != IDYES) return 0;
CClassInfo* pClassInfo = m_itObjSelect->GetModifiedObject(); if( !pClassInfo ) return 0;
string_vector vstrTmp = pClassInfo->Columns();
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); LPCWSTR pszName = reinterpret_cast<LPCWSTR>(lvi.lParam);
string_vector::iterator itStr; itStr = std::find(vstrTmp.begin(), vstrTmp.end(), pszName); ASSERT(itStr != vstrTmp.end()); if( itStr != vstrTmp.end() ) { vstrTmp.erase(itStr); } }
pClassInfo->Columns() = vstrTmp;
DisplayColumns();
SetModified(TRUE);
return 0; }
BOOL CRootViewPage::OnSetActive() { m_ObjList.PageActive(m_hWnd);
LoadObjectCB(m_ObjectCB, m_ObjList);
// if object was previously selected
if (m_itObjSelect != NULL) { // find the edit object by name because it may have been moved or deleted
// while another page was active
m_itObjSelect = m_ObjList.FindObject(m_strObjSelect.c_str());
if (m_itObjSelect != NULL && m_itObjSelect->IsDeleted()) m_itObjSelect = NULL; }
// if object still around, reselect it in the combo box
if (m_itObjSelect != NULL) { DisplayNameMap* pNameMap = DisplayNames::GetClassMap(); ASSERT(pNameMap != NULL);
int iSel = m_ObjectCB.FindStringExact(-1, pNameMap->GetAttributeDisplayName(m_strObjSelect.c_str())); ASSERT(iSel != CB_ERR);
m_ObjectCB.SetCurSel(iSel); } else if (m_ObjectCB.GetCount() > 0) { // default to the first object and update the columns
m_ObjectCB.SetCurSel(0);
void* pv = m_ObjectCB.GetItemDataPtr(0); m_itObjSelect = *(EditObjIter*)&pv;
m_strObjSelect = m_itObjSelect->Name(); DisplayColumns(); } else { DisplayColumns(); } return TRUE; }
BOOL CRootViewPage::OnApply() { return m_ObjList.ApplyChanges(m_hWnd); }
/////////////////////////////////////////////////////////////////////////////////////////////////
// CEditObjList
HRESULT CEditObjList::Initialize(CRootNode* pRootNode, classInfo_vector& vClasses, LONG_PTR lNotifyHandle) { ASSERT(pRootNode != NULL); ASSERT(lNotifyHandle != NULL);
m_spRootNode = pRootNode;
classInfo_vector::iterator itClass = vClasses.begin(); while(itClass != vClasses.end()) { CEditObject* pObj = new CEditObject(); if( !pObj ) { break; } EditObjIter iter = m_ObjectList.insert(end(), *pObj); iter->m_strName = itClass->Name(); iter->m_itObjOriginal = itClass;
++itClass; }
m_pvClasses = &vClasses;
m_iPageMax = -1;
m_lNotifyHandle = lNotifyHandle;
return S_OK; }
BOOL CEditObjList::ApplyChanges(HWND hwndPage) { ASSERT(::IsWindow(hwndPage));
// Don't apply changes until called from highest activated page
if (PropSheet_HwndToIndex(GetParent(hwndPage), hwndPage) < m_iPageMax) return TRUE;
// Build a vector of the modified classes
string_vector* pvstrModified = new string_vector; if( !pvstrModified ) return FALSE;
// Apply changes in reverse order so deletions won't invalidate stored iterators
std::list<CEditObject>::reverse_iterator itObj = m_ObjectList.rbegin(); while (itObj != m_ObjectList.rend()) { // if object is modified, replace the original
if (itObj->m_itObjOriginal != NULL) { if (itObj->m_pObjModified != NULL) { *(itObj->m_itObjOriginal) = *(itObj->m_pObjModified); pvstrModified->push_back(itObj->m_pObjModified->Name()); } else if (itObj->IsDeleted()) { m_pvClasses->erase(itObj->m_itObjOriginal); pvstrModified->push_back(itObj->m_itObjOriginal->Name()); } } ++itObj; }
// Now go through list again to add any new objects
// This must be done separately because it can invalidate all stored iterators
itObj = m_ObjectList.rbegin(); while(itObj != m_ObjectList.rend()) { if (itObj->m_itObjOriginal == NULL && itObj->m_pObjModified != NULL) { m_pvClasses->push_back(*(itObj->m_pObjModified)); pvstrModified->push_back(itObj->m_pObjModified->Name()); }
++itObj; }
// clear the edit list and re-initialize it
m_ObjectList.clear();
Initialize(m_spRootNode, *m_pvClasses, m_lNotifyHandle);
// Send change notification to root node, so it can update affected child nodes
// Use MMC method to send from prop page thread to main thread
if (pvstrModified->size() != 0) { // create prop change info struct with root node's data interface
// and list of changed classes
PropChangeInfo* pChg = new PropChangeInfo; if( !pChg ) { delete pvstrModified; return FALSE; }
pChg->pDataObject = static_cast<IDataObject*>(m_spRootNode.p); pChg->lNotifyParam = (LPARAM)pvstrModified;
MMCPropertyChangeNotify(m_lNotifyHandle, (LPARAM)pChg); } else delete pvstrModified;
return TRUE; }
void CEditObjList::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; }
EditObjIter CEditObjList::FindObject(LPCWSTR pszName) { if( !pszName ) return NULL;
EditObjIter iter = begin(); while (iter != end()) { // look for class object with matching name
if (wcscmp(iter->Name(), pszName) == 0) { // If the object hasn't been modified (copied) yet, then load any
// string table strings before returning the object
if (iter->m_itObjOriginal != NULL && iter->m_pObjModified == NULL) { ASSERT(m_spRootNode != NULL); if( !m_spRootNode ) return NULL;
IStringTable* pStringTable = m_spRootNode->GetCompData()->GetStringTable(); ASSERT(pStringTable != NULL); if( !pStringTable ) return NULL;
HRESULT hr = iter->m_itObjOriginal->LoadStrings(pStringTable); } return iter; } ++iter; }
return NULL; }
EditObjIter CEditObjList::AddObject(CClassInfo* pClassInfo) { if( !pClassInfo ) return NULL;
EditObjIter iter = begin(); while (iter != end()) { // Check for exiting edit object (can be there if object was deleted)
if (wcscmp(iter->Name(), pClassInfo->Name()) == 0) { ASSERT(iter->m_bDeleted && iter->m_pObjModified == NULL); iter->m_bDeleted = FALSE; iter->m_pObjModified = pClassInfo;
return iter; } ++iter; }
// if not found, create new edit object and store new class info as the modified object
CEditObject* pObj = new CEditObject(); if( !pObj ) return iter;
iter = m_ObjectList.insert(end(), *pObj);
iter->m_strName = pClassInfo->Name(); iter->m_pObjModified = pClassInfo;
return iter; }
void CEditObjList::DeleteObject(EditObjIter itObj) { ASSERT(itObj != NULL);
if (itObj->m_itObjOriginal == NULL) { m_ObjectList.erase(itObj); } else { if (itObj->m_pObjModified != NULL) { delete itObj->m_pObjModified; itObj->m_pObjModified = NULL; }
itObj->m_bDeleted = TRUE; } }
/////////////////////////////////////////////////////////////////////////////////////////////////
//
void LoadObjectCB(CComboBox& ComboBox, CEditObjList& ObjList) {
ComboBox.ResetContent();
DisplayNameMap* pNameMap = DisplayNames::GetClassMap(); ASSERT(pNameMap != NULL); if (pNameMap == NULL) return;
for (EditObjIter itObj = ObjList.begin(); itObj != ObjList.end(); ++itObj) { if (!itObj->IsDeleted()) { int iIndex = ComboBox.AddString(pNameMap->GetAttributeDisplayName(itObj->Name())); ASSERT(iIndex >= 0); ComboBox.SetItemDataPtr(iIndex, *(LPVOID*)&itObj); } } }
int GetDateTimeString(FILETIME* pftime, LPWSTR pszBuf, int cBuf) { if( !pftime || !pszBuf || !cBuf ) return 0;
FILETIME ftimeLocal; BOOL bStat = FileTimeToLocalFileTime(pftime, &ftimeLocal); ASSERT(bStat);
SYSTEMTIME systime; bStat = FileTimeToSystemTime(&ftimeLocal, &systime); ASSERT(bStat);
// get date string
int cDate = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, NULL, pszBuf, cBuf); if (cDate == 0 || cDate > cBuf - 2) return 0;
// replace teminating null with ", "
pszBuf[cDate-1] = ','; pszBuf[cDate] = ' ';
// append time string
int cTime = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &systime, NULL, pszBuf + (cDate + 1), cBuf - (cDate + 1));
if (cTime == 0) return 0;
// return total string length excluding terminating null
return (cDate + cTime - 2); }
|