// DlgObjectProperties.cpp : implementation file // #include "stdafx.h" #include "Balancer.h" #include #include #include "DlgObjectProperties.h" using namespace Stuff; const int c_Max_Objects_Supported = 100; extern CBalancerApp theApp; // // User passes in an array of data to the dialog at startup. // this array type is...CDOPPROPERTIES_TO_EDIT_ARRAY // LPCSTR MyLoadStringTempBuffer(UINT uiID); // // This function needs to be moved somewhere more generic // // LPCSTR MyLoadStringTempBuffer(UINT uiID) { static TCHAR strings[10][1024]; static nNext = 0; nNext = (nNext + 1) % 10; ::LoadString(NULL, uiID, strings[nNext], 1023); return strings[nNext]; } // puts a backslash as the last char unless it's an empty string, ends in a slash already, or ends with a ':' void EndDirectoryWithBackSlash(CString & strDir) { int nLen = strDir.GetLength(); if (!nLen) return; if (strDir.GetAt(nLen-1) == '\\' || strDir.GetAt(nLen -1) == ':') return; strDir += '\\'; } ///////////////////////////////////////////////////////////////////////////// // CDlgObjectProperties dialog // // Rather than have the calling function have to fill in the structure manually they can call this // function with all the propeties they want to edit. Then they just pass this in to the appropriate // function to specify what properties to get. They will have to clear up the memory with free though // CDOPPROPERTIES_TO_EDIT_ARRAY * CDlgObjectProperties::CreatePropertiesToEditArray(int nCount, ...) { va_list marker; CDOPPROPERTIES_TO_EDIT_ARRAY * pRet = Allocate_CDOPPROPERTIES_TO_EDIT_ARRAY(nCount); va_start( marker, nCount ); /* Initialize variable arguments. */ pRet->nCount = nCount; for (int i = 0 ; i < nCount; i++) { pRet->ppProperties_To_Edit_Entry[i]->ePropertyType = va_arg(marker, CDOPVARTYPE); strcpy(pRet->ppProperties_To_Edit_Entry[i]->szPropertyTag, va_arg(marker, char *)); strcpy(pRet->ppProperties_To_Edit_Entry[i]->szPropertyTagForDisplay, va_arg(marker, char *)); pRet->ppProperties_To_Edit_Entry[i]->uiReserved1_CTRLID = 0; } va_end( marker ); /* Reset variable arguments. */ return pRet; } // // Since I am using a pointer to represent an array the structure has to be allocated with enough size to // store the array. In addition the internal pointer variable must be directed to within // the allocation itself. This way I can use array notation To then on. // CDOPPROPERTIES_TO_EDIT_ARRAY * CDlgObjectProperties::Allocate_CDOPPROPERTIES_TO_EDIT_ARRAY(int nPropertyCount, CDOPPROPERTIES_TO_EDIT_ARRAY * * ppCDOPPROPERTIES_TO_EDIT_ARRAY) { CDOPPROPERTIES_TO_EDIT_ARRAY * pNew = (CDOPPROPERTIES_TO_EDIT_ARRAY *) malloc(sizeof(CDOPPROPERTIES_TO_EDIT_ARRAY) + (nPropertyCount) * sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY *) + (nPropertyCount) * sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY)); // we could - 1 from the count since one is allocated as part of the structure, but // I'm electing to have the 4 byte buffer instead of worrying about nPropertyCount == 0 for (int i = 0; i < nPropertyCount; i++) { pNew->ppProperties_To_Edit_Entry[i] = (CDOPPROPERTIES_TO_EDIT_ENTRY *)(void *)(((DWORD)&(pNew->ppProperties_To_Edit_Entry)) + sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY *) * (nPropertyCount) + i * sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY)); } if (ppCDOPPROPERTIES_TO_EDIT_ARRAY) *ppCDOPPROPERTIES_TO_EDIT_ARRAY = pNew; return pNew; } // // Since I am using a pointer to represent an array the structure has to be allocated with enough size to // store the array. In addition the internal pointer variable must be directed to within // the allocation itself. This way I can use array notation To then on. // CDOPPROPERTIES_OBJECT_PROPERTIES * CDlgObjectProperties::Allocate_CDOPPROPERTIES_OBJECT_PROPERTIES(int nPropertyCount, CDOPPROPERTIES_OBJECT_PROPERTIES * * ppCDOPPROPERTIES_OBJECT_PROPERTIES) { CDOPPROPERTIES_OBJECT_PROPERTIES * pNew = (CDOPPROPERTIES_OBJECT_PROPERTIES *) malloc (sizeof(CDOPPROPERTIES_OBJECT_PROPERTIES) + nPropertyCount * sizeof(CDOPPROPERTYVALUE *) + nPropertyCount * sizeof(CDOPPROPERTYVALUE)); for (int i = 0 ; i < nPropertyCount; i++) { pNew->ppObjectProperties[i] = (CDOPPROPERTYVALUE * )(void *)(((DWORD)&(pNew->ppObjectProperties)) + sizeof(CDOPPROPERTYVALUE *) * nPropertyCount + sizeof(CDOPPROPERTYVALUE) * i); } if (ppCDOPPROPERTIES_OBJECT_PROPERTIES) *ppCDOPPROPERTIES_OBJECT_PROPERTIES = pNew; return pNew; } // // Since I am using a pointer to represent an array the structure has to be allocated with enough size to // store the array. In addition the internal pointer variable must be directed to within // the allocation itself. This way I can use array notation To then on. // CDOPPROPERTIES_OBJECT_LIST * CDlgObjectProperties::Allocate_CDOPPROPERTIES_OBJECT_LIST(int nObjectCount, int nPropertyCount, CDOPPROPERTIES_OBJECT_LIST ** ppCDOPPROPERTIES_OBJECT_LIST ) { // This one is the most complex since it has to allocate enough room for all the objects, to have all the properties and have // all the data for those properties CDOPPROPERTIES_OBJECT_LIST * pNew = (CDOPPROPERTIES_OBJECT_LIST *) malloc(sizeof(CDOPPROPERTIES_OBJECT_LIST) + nObjectCount * sizeof(CDOPPROPERTIES_OBJECT_PROPERTIES *) +(nObjectCount * (sizeof(CDOPPROPERTIES_OBJECT_PROPERTIES) + nPropertyCount * sizeof(CDOPPROPERTYVALUE *))) +(nObjectCount * (nPropertyCount * sizeof(CDOPPROPERTYVALUE))) ); for (int i = 0; i < nObjectCount; i++) { // For the object array set up the pointers to each properties array pNew->ppPropertiesArray[i] = (CDOPPROPERTIES_OBJECT_PROPERTIES * )(void *)(((DWORD)&(pNew->ppPropertiesArray)) +sizeof(CDOPPROPERTIES_OBJECT_PROPERTIES * ) * nObjectCount + i * (sizeof(CDOPPROPERTIES_OBJECT_PROPERTIES) + nPropertyCount * (sizeof(CDOPPROPERTYVALUE *)) +nPropertyCount * sizeof(CDOPPROPERTYVALUE))); // For each object set up the pointer list for the properties array for (int j = 0; j < nPropertyCount; j++) { pNew->ppPropertiesArray[i]->ppObjectProperties[j] = (CDOPPROPERTYVALUE *)(void *)(((DWORD)&(pNew->ppPropertiesArray[i]->ppObjectProperties)) + nPropertyCount * sizeof(CDOPPROPERTYVALUE *) + j * sizeof(CDOPPROPERTYVALUE)); } } if (ppCDOPPROPERTIES_OBJECT_LIST) *ppCDOPPROPERTIES_OBJECT_LIST = pNew; return pNew; } //**************************************************************************************** // // // //**************************************************************************************** BOOL CDlgObjectProperties::Copy_CDOPPROPERTIES_TO_EDIT_ARRAY(CDOPPROPERTIES_TO_EDIT_ARRAY * pCDOPPROPERTIES_TO_EDIT_ARRAY_DEST, CDOPPROPERTIES_TO_EDIT_ARRAY * pCDOPPROPERTIES_TO_EDIT_ARRAY_SRC) { pCDOPPROPERTIES_TO_EDIT_ARRAY_DEST->nCount = pCDOPPROPERTIES_TO_EDIT_ARRAY_SRC->nCount; for (int i = 0; i < pCDOPPROPERTIES_TO_EDIT_ARRAY_SRC->nCount; i++) { memcpy(pCDOPPROPERTIES_TO_EDIT_ARRAY_DEST->ppProperties_To_Edit_Entry[i], pCDOPPROPERTIES_TO_EDIT_ARRAY_SRC->ppProperties_To_Edit_Entry[i], sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY)); } return TRUE; } //**************************************************************************************** // // // //**************************************************************************************** BOOL CDlgObjectProperties::Copy_CDOPPROPERTIES_OBJECT_PROPERTIES(CDOPPROPERTIES_OBJECT_PROPERTIES * pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST, CDOPPROPERTIES_OBJECT_PROPERTIES * pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC) { pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->fDirty = pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC->fDirty; pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->fReadOnly = pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC->fReadOnly; pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->nProperties = pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC->nProperties; memcpy(pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->szObjectName, pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC->szObjectName, sizeof(pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->szObjectName)); for (int i = 0 ; i < pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->nProperties; i++) { memcpy(pCDOPPROPERTIES_OBJECT_PROPERTIES_DEST->ppObjectProperties[i], pCDOPPROPERTIES_OBJECT_PROPERTIES_SRC->ppObjectProperties[i], sizeof(CDOPPROPERTYVALUE)); } return TRUE; } //**************************************************************************************** // // // //**************************************************************************************** BOOL CDlgObjectProperties::Copy_CDOPPROPERTIES_OBJECT_LIST(CDOPPROPERTIES_OBJECT_LIST * pCDOPPROPERTIES_OBJECT_LIST_DEST, CDOPPROPERTIES_OBJECT_LIST * pCDOPPROPERTIES_OBJECT_LIST_SRC) { pCDOPPROPERTIES_OBJECT_LIST_DEST->nObjectCount = pCDOPPROPERTIES_OBJECT_LIST_SRC->nObjectCount; for (int i = 0; i < pCDOPPROPERTIES_OBJECT_LIST_DEST->nObjectCount; i++) { Copy_CDOPPROPERTIES_OBJECT_PROPERTIES(pCDOPPROPERTIES_OBJECT_LIST_DEST->ppPropertiesArray[i], pCDOPPROPERTIES_OBJECT_LIST_SRC->ppPropertiesArray[i]); } return TRUE; } //**************************************************************************************** // // // //**************************************************************************************** BOOL CDlgObjectProperties::IsEqual_CDOPPROPERTIES_TO_EDIT_ARRAY(CDOPPROPERTIES_TO_EDIT_ARRAY * pCDOPPROPERTIES_TO_EDIT_ARRAY1, CDOPPROPERTIES_TO_EDIT_ARRAY * pCDOPPROPERTIES_TO_EDIT_ARRAY2) { if (pCDOPPROPERTIES_TO_EDIT_ARRAY1->nCount != pCDOPPROPERTIES_TO_EDIT_ARRAY2->nCount) return FALSE; for (int i = 0; i < pCDOPPROPERTIES_TO_EDIT_ARRAY1->nCount; i++) { if (memcmp(pCDOPPROPERTIES_TO_EDIT_ARRAY1->ppProperties_To_Edit_Entry[i], pCDOPPROPERTIES_TO_EDIT_ARRAY2->ppProperties_To_Edit_Entry[i], sizeof(CDOPPROPERTIES_TO_EDIT_ENTRY))) return FALSE; } return TRUE; } //**************************************************************************************** // // // //**************************************************************************************** BOOL CDlgObjectProperties::IsEqual_CDOPPROPERTIES_OBJECT_PROPERTIES(CDOPPROPERTIES_OBJECT_PROPERTIES * pCDOPPROPERTIES_OBJECT_PROPERTIES1, CDOPPROPERTIES_OBJECT_PROPERTIES * pCDOPPROPERTIES_OBJECT_PROPERTIES2) { if (pCDOPPROPERTIES_OBJECT_PROPERTIES1->nProperties != pCDOPPROPERTIES_OBJECT_PROPERTIES2->nProperties || pCDOPPROPERTIES_OBJECT_PROPERTIES1->fDirty != pCDOPPROPERTIES_OBJECT_PROPERTIES2->fDirty || pCDOPPROPERTIES_OBJECT_PROPERTIES1->fReadOnly != pCDOPPROPERTIES_OBJECT_PROPERTIES2->fReadOnly || memcmp(pCDOPPROPERTIES_OBJECT_PROPERTIES1->szObjectName, pCDOPPROPERTIES_OBJECT_PROPERTIES2->szObjectName, sizeof(pCDOPPROPERTIES_OBJECT_PROPERTIES2->szObjectName))) return FALSE; for (int i = 0 ; i < pCDOPPROPERTIES_OBJECT_PROPERTIES2->nProperties; i++) { if (memcmp(pCDOPPROPERTIES_OBJECT_PROPERTIES1->ppObjectProperties[i], pCDOPPROPERTIES_OBJECT_PROPERTIES2->ppObjectProperties[i], sizeof(CDOPPROPERTYVALUE))) { return FALSE; } } return TRUE; } //**************************************************************************************** // // // //**************************************************************************************** BOOL CDlgObjectProperties::IsEqual_CDOPPROPERTIES_OBJECT_LIST(CDOPPROPERTIES_OBJECT_LIST * pCDOPPROPERTIES_OBJECT_LIST1, CDOPPROPERTIES_OBJECT_LIST * pCDOPPROPERTIES_OBJECT_LIST2) { if (pCDOPPROPERTIES_OBJECT_LIST1->nObjectCount != pCDOPPROPERTIES_OBJECT_LIST2->nObjectCount) return FALSE; for (int i = 0 ; i < pCDOPPROPERTIES_OBJECT_LIST2->nObjectCount; i++) { if (!IsEqual_CDOPPROPERTIES_OBJECT_PROPERTIES(pCDOPPROPERTIES_OBJECT_LIST1->ppPropertiesArray[i], pCDOPPROPERTIES_OBJECT_LIST2->ppPropertiesArray[i])) return FALSE; } return TRUE; } //**************************************************************************************** // // // //**************************************************************************************** CDlgObjectProperties::~CDlgObjectProperties() { if (m_pObjectList) { free(m_pObjectList); } } //**************************************************************************************** // // // //**************************************************************************************** CDlgObjectProperties::CDlgObjectProperties(CWnd* pParent /*=NULL*/) : CDialog(CDlgObjectProperties::IDD, pParent) { //{{AFX_DATA_INIT(CDlgObjectProperties) //}}AFX_DATA_INIT m_pObjectList = NULL; ClearObjectDataSet(); m_nCurSel = LB_ERR; // nothing selected, important to start here since we have no data loaded in the dialog yet // This will be passed in later with a list of properties to edit m_paPropertiesToEdit = NULL; m_fnFilterFunction = NULL; m_fShowFullObjectName = FALSE; m_fShowFullPropertyName = FALSE; m_eSearchType = eSingleSubdirectory; m_popCurObjectPropertiesArray = NULL; m_fDirty = FALSE; m_nLastControlID = IDC_DOP_PROPNAME; } //**************************************************************************************** // // // //**************************************************************************************** int CDlgObjectProperties::DoModal() { // // Check to make sure we have all the data set that we need // if ( m_strFileNameToSearchSubdirectoriesFor.IsEmpty() || m_strObjectFilesRootDirectory.IsEmpty() || m_paPropertiesToEdit == NULL || !m_paPropertiesToEdit->nCount // have to have at least one property ) { return IDABORT; } return CDialog::DoModal(); } //**************************************************************************************** // // // //**************************************************************************************** void CDlgObjectProperties::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDlgObjectProperties) DDX_Control(pDX, IDC_OBJECTLIST, m_lbObjectList); //}}AFX_DATA_MAP } //**************************************************************************************** // // // //**************************************************************************************** BEGIN_MESSAGE_MAP(CDlgObjectProperties, CDialog) //{{AFX_MSG_MAP(CDlgObjectProperties) ON_LBN_SELCHANGE(IDC_OBJECTLIST, OnSelchangeObjectlist) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDlgObjectProperties message handlers BOOL CDlgObjectProperties::OnInitDialog() { CDialog::OnInitDialog(); m_nCurSel = LB_ERR; m_fDirty = FALSE; ClearObjectDataSet(); // // For now we just have a fixed size data set maximum. Otherwise we would have to // iterate all the files once or create a link list of objects instead of an array. // Any of these can be done, the array was simply created to save time getting this // code up to speed. // if (m_pObjectList) free(m_pObjectList); m_pObjectList = Allocate_CDOPPROPERTIES_OBJECT_LIST(c_Max_Objects_Supported, m_paPropertiesToEdit->nCount); m_pObjectList->nObjectCount = 0; // this many being used currently // // Search for the weapons subsytem files // LoadObjectData(m_strObjectFilesRootDirectory, m_eSearchType); // // Create all the sub-controls that represent the data that we are going to be editting in the // dialog // Note: We are not allowed to get here if we don't have a properties list since DoModal should kick // us out, and this dialog is not meant to be modeless. CreateSubControlsForProperties(); UpdateData(FALSE); m_lbObjectList.SetCurSel(0); // get the ball rolling by showing the first weapon in the list OnSelchangeObjectlist(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectProperties::CreateSubControlsForProperties() { // // Go through the list of properties we are editting and place all the controls. // Use the reserved value in the property array passed in to store the starting ID // of each properties control set. Offsets To there are based on the type of variable // that is being used. m_nLastControlID = IDC_DOP_PROPNAME; // // The following hidden objects have been added to the resource dialog in order to // make formatting fully adjustable without having to modify constants in the code // We get the base size, and position for all controls To these // IDC_DOP_PROPNAME, IDC_DOP_PROPPRESENT, IDC_DOP_PROPEDIT1, IDC_DOP_PROPEDIT2, IDC_DOP_PROPEDIT3 // // Use the dummy hidden controls to place our new ones, unhide the dummy controls // for the first property, and then build the rest CWnd * pControlPropName = GetDlgItem(IDC_DOP_PROPNAME); CWnd * pControlPropPresent = GetDlgItem(IDC_DOP_PROPPRESENT); CWnd * pControlPropEdit1 = GetDlgItem(IDC_DOP_PROPEDIT1); CWnd * pControlPropEdit2 = GetDlgItem(IDC_DOP_PROPEDIT2); CWnd * pControlPropEdit3 = GetDlgItem(IDC_DOP_PROPEDIT3); if (!pControlPropName || !pControlPropPresent || !pControlPropEdit1 || !pControlPropEdit2 || !pControlPropEdit3) return; // badness has occurred, but no way out of it at this point CFont * pFontControlPropName = pControlPropName->GetFont(); CFont * pFontControlPropPresent = pControlPropPresent->GetFont(); CFont * pFontControlPropEdit1 = pControlPropEdit1->GetFont(); CFont * pFontControlPropEdit2 = pControlPropEdit2->GetFont(); CFont * pFontControlPropEdit3 = pControlPropEdit3->GetFont(); CRect crRectDlg; CRect crRectPropName; CRect crRectPropPresent; CRect crRectPropEdit1; CRect crRectPropEdit2; CRect crRectPropEdit3; GetWindowRect(crRectDlg); pControlPropName->GetWindowRect(crRectPropName); pControlPropPresent->GetWindowRect(crRectPropPresent); pControlPropEdit1->GetWindowRect(crRectPropEdit1); pControlPropEdit2->GetWindowRect(crRectPropEdit2); pControlPropEdit3->GetWindowRect(crRectPropEdit3); // // Offset the rects relative to the dialog // ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crRectPropName, 2); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crRectPropPresent, 2); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crRectPropEdit1, 2); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crRectPropEdit2, 2); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crRectPropEdit3, 2); // crRectPropName.OffsetRect(-crRectDlg.left, -crRectDlg.top); // crRectPropPresent.OffsetRect(-crRectDlg.left, -crRectDlg.top); // crRectPropEdit1.OffsetRect(-crRectDlg.left, -crRectDlg.top); // crRectPropEdit2.OffsetRect(-crRectDlg.left, -crRectDlg.top); // crRectPropEdit3.OffsetRect(-crRectDlg.left, -crRectDlg.top); // for the first property we just unhide the appropriate boxes and set the property name int nCurrentProperty = 0; // if we didn't have at least one item in the property list DoModal() should have kicked us out // so it should be safe to reference this without checking here. pControlPropName->ShowWindow(SW_SHOW); const char * szStaticText = NULL; if (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->szPropertyTagForDisplay[0]) { szStaticText = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->szPropertyTagForDisplay; } else { szStaticText = m_fShowFullPropertyName ? m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->szPropertyTag : GetEntryNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->szPropertyTag ); } pControlPropName->SetWindowText(szStaticText); pControlPropPresent->ShowWindow(SW_SHOW); pControlPropEdit1->ShowWindow(SW_SHOW); // Next root ID is 1 after this set int nCurrID = IDC_DOP_PROPNAME + 3; // now see if we need to add the others if (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->ePropertyType == eVector3D) { pControlPropEdit2->ShowWindow(SW_SHOW); pControlPropEdit3->ShowWindow(SW_SHOW); } else { pControlPropEdit2->ShowWindow(SW_HIDE); pControlPropEdit3->ShowWindow(SW_HIDE); } nCurrID += 2; // this has to be incremented no matter what since the controls are actually there. m_paPropertiesToEdit->ppProperties_To_Edit_Entry[0]->uiReserved1_CTRLID = IDC_DOP_PROPNAME; int nDiffY = crRectPropEdit1.Height() + 5; // constant used for vertical padding (use largest control type, edit box) HWND hWndTemp = NULL; while (++nCurrentProperty < m_paPropertiesToEdit->nCount) { CWnd wndControlPropName ; CWnd wndControlPropPresent ; CWnd wndControlPropEdit1 ; CWnd wndControlPropEdit2 ; CWnd wndControlPropEdit3 ; // BOOL fIsNumberOnly = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType != eLPSTR; // we have to store off the ID for these properties m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->uiReserved1_CTRLID = nCurrID; crRectPropName.OffsetRect( 0, nDiffY); crRectPropPresent.OffsetRect(0, nDiffY); crRectPropEdit1.OffsetRect( 0, nDiffY); crRectPropEdit2.OffsetRect( 0, nDiffY); crRectPropEdit3.OffsetRect( 0, nDiffY); if (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->szPropertyTagForDisplay[0]) { szStaticText = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->szPropertyTagForDisplay; } else { szStaticText = m_fShowFullPropertyName ? m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->szPropertyTag : GetEntryNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->szPropertyTag ); } hWndTemp = ::CreateWindow("STATIC", szStaticText, WS_VISIBLE | SS_LEFT | WS_CHILD, crRectPropName.left, crRectPropName.top, crRectPropName.Width(), crRectPropName.Height(), GetSafeHwnd(), (HMENU)nCurrID, theApp.m_hInstance, NULL); // ::SetWindowLong(hWndTemp, nCurrID, GWL_ID); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPropName, (LPARAM)FALSE); /* wndControlPropName.Create("STATIC", szStaticText, WS_VISIBLE | SS_LEFT | WS_CHILD, crRectPropName, this, nCurrID, NULL); wndControlPropName.Detach(); */ nCurrID++; hWndTemp = ::CreateWindow("BUTTON", "", WS_VISIBLE | BS_CHECKBOX | WS_CHILD | BS_AUTOCHECKBOX, crRectPropPresent.left, crRectPropPresent.top, crRectPropPresent.Width(), crRectPropPresent.Height(), GetSafeHwnd(), (HMENU)nCurrID, theApp.m_hInstance, NULL); // ::SetWindowLong(hWndTemp, nCurrID, GWL_ID); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPropPresent, (LPARAM)FALSE); /* wndControlPropPresent.Create("BUTTON", _T(""), WS_VISIBLE | BS_CHECKBOX | WS_CHILD, crRectPropPresent, this, nCurrID, NULL); wndControlPropPresent.Detach(); */ nCurrID++; hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD , crRectPropEdit1.left, crRectPropEdit1.top, crRectPropEdit1.Width(), crRectPropEdit1.Height(), GetSafeHwnd(), (HMENU)nCurrID, theApp.m_hInstance, NULL); // ::SetWindowLong(hWndTemp, nCurrID, GWL_ID); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPropEdit1, (LPARAM)FALSE); /* wndControlPropEdit1.Create("EDIT", _T(""), WS_VISIBLE | ES_LEFT | WS_CHILD | (fIsNumberOnly ? ES_NUMBER : 0), // keep them To entering wrong info crRectPropEdit1, this, nCurrID, NULL); wndControlPropEdit1.Detach(); */ nCurrID++; if (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType == eVector3D) { hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD, crRectPropEdit2.left, crRectPropEdit2.top, crRectPropEdit2.Width(), crRectPropEdit2.Height(), GetSafeHwnd(), (HMENU)nCurrID, theApp.m_hInstance, NULL); // ::SetWindowLong(hWndTemp, nCurrID, GWL_ID); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPropEdit2, (LPARAM)FALSE); /* wndControlPropEdit2.Create("EDIT", _T(""), WS_VISIBLE | ES_LEFT | WS_CHILD | ES_NUMBER, // keep them To entering wrong info crRectPropEdit2, this, nCurrID, NULL); wndControlPropEdit2.Detach(); */ nCurrID++; hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD, crRectPropEdit3.left, crRectPropEdit3.top, crRectPropEdit3.Width(), crRectPropEdit3.Height(), GetSafeHwnd(), (HMENU)nCurrID, theApp.m_hInstance, NULL); // ::SetWindowLong(hWndTemp, nCurrID, GWL_ID); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPropEdit3, (LPARAM)FALSE); /* wndControlPropEdit3.Create("EDIT", _T(""), WS_VISIBLE | ES_LEFT | WS_CHILD | ES_NUMBER, // keep them To entering wrong info crRectPropEdit3, this, nCurrID, NULL); wndControlPropEdit3.Detach(); */ nCurrID++; } // if we are entering a eVector3D property here } // while we are iterating through the properties m_nLastControlID = nCurrID; } // end of CreateSubControlsForProperties() //**************************************************************************************** // //**************************************************************************************** void CDlgObjectProperties::OnOK() { // // Validate the data and save any changes made since the last sel change // MoveCurSelDataToOrFromControls(FALSE); // // Ask them if they want to commit the changes? Or should pressing OK be enough? Should there be a // safety net? // if (m_fDirty) { int ret = MessageBox( MyLoadStringTempBuffer(IDS_SAVE_WEAPONS_CHANGES), MyLoadStringTempBuffer(IDS_SAVE_WEAPONS_CHANGES_CAPTION), MB_YESNO); if (ret != IDYES) { return; } // // save the changes, exit if failed without ending the dialog // if (!SaveObjectData()) { MessageBox(MyLoadStringTempBuffer(IDS_SAVE_WEAPONS_FAILED), MyLoadStringTempBuffer(IDS_ERROR_CAPTION), MB_OK | MB_ICONEXCLAMATION); } } // // If we got here, everything should be saved // CDialog::OnOK(); } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectProperties::OnCancel() { // // It's safe to exit, as long as all the notation files are closed out, which should be the case // CDialog::OnCancel(); } //**************************************************************************************** // // Sets the root directory to search under. Only goes one level deep currently // //**************************************************************************************** BOOL CDlgObjectProperties::SetObjectFilesDirectory(LPCSTR lpszDirectoryPath) { m_strObjectFilesRootDirectory = lpszDirectoryPath; EndDirectoryWithBackSlash(m_strObjectFilesRootDirectory ); return TRUE; } //**************************************************************************************** // // Sets the root file name type to search for like "*.data" // //**************************************************************************************** BOOL CDlgObjectProperties::SetFileNameToSearchSubdirectoriesFor(LPCSTR lpszFileSearchString) { m_strFileNameToSearchSubdirectoriesFor = lpszFileSearchString; return TRUE; } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectProperties::ClearObjectDataSet() { // // If you didn't allocate this structure as a whole you have to walk the tree and kill the internal // pointer memory before you do this, but if you used the allocate_... function provided above it was // all allocated as one huge chunk instead of in parts. // if (m_pObjectList) { free(m_pObjectList); m_pObjectList = NULL; } } //**************************************************************************************** // // //**************************************************************************************** LPCSTR CDlgObjectProperties::GetPageNameToPropertyName(LPCSTR szPropertyName) { static char s_szPageNameBuffer[128]; // get everything up to the first \ in the string const char * pTempSrc = szPropertyName; char * pTempDest = s_szPageNameBuffer; while (*pTempSrc && *pTempSrc != '\\') *(pTempDest++) = *(pTempSrc++); *pTempDest = '\0'; return s_szPageNameBuffer; } //**************************************************************************************** // // //**************************************************************************************** LPCSTR CDlgObjectProperties::GetEntryNameToPropertyName(LPCSTR szPropertyName) { static char s_szEntryNameBuffer[128]; // get everything after the last \ in the string const char * pTempSrc = szPropertyName; const char * pLastBackSlash = szPropertyName; while (*pTempSrc) { if (*pTempSrc == '\\') pLastBackSlash = pTempSrc; pTempSrc++; } if (*pLastBackSlash == '\\') pLastBackSlash++; strcpy(s_szEntryNameBuffer, pLastBackSlash); return s_szEntryNameBuffer; } //**************************************************************************************** // // Save weapons data will save all the information back to the appropriate notation files. It only saves // out the weapons that are changed. // //**************************************************************************************** BOOL CDlgObjectProperties::SaveObjectData() { int nFailures = 0; for (int i = 0; i< m_pObjectList->nObjectCount;i++) { if (!m_pObjectList->ppPropertiesArray[i]->fDirty) // not an error condition, just a shortcut continue; // don't worry about saving this one if it hasn't changed. if (!m_pObjectList->ppPropertiesArray[i]->szObjectName[0]) { nFailures++; continue; } if (m_pObjectList->ppPropertiesArray[i]->fReadOnly) // shouldn't have been allowed to change this { nFailures++; continue; } // // Loop through all the properties and save them // Page * page = NULL; char szCurrentPageName[128] = ""; // used to prevent repetitively searching for the same page NotationFile outfile((LPCSTR)m_pObjectList->ppPropertiesArray[i]->szObjectName, NotationFile::Raw); for (int j=0; j < m_pObjectList->ppPropertiesArray[i]->nProperties; j++) { const char * szPageName = GetPageNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->szPropertyTag); if (!page || strcmp(szCurrentPageName, szPageName)) { strcpy(szCurrentPageName, szPageName); page = outfile.FindPage(szPageName); if (!page) // if for some reason we can't find the page, jump out continue; } const char * szEntryName = GetEntryNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->szPropertyTag); // // For each item in the data list, if it shouldn't be there, delete it. If it supposed to be there set it // Assumption is made that there are not two of any particular value key // if (!m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->fPresent) { page->DeleteNote(szEntryName); } else { page->DeleteNote(szEntryName); // temporary kludge to force the dirty bit. This can be removed // after we decide if it is safe to make "SetEntry" set the dirty bit itself switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->ePropertyType) { case efloat: page->SetEntry(szEntryName, m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.fltValue); break; case eint: page->SetEntry(szEntryName, m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.nValue); break; case eLPSTR: page->SetEntry(szEntryName, m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.szValue); break; case eBOOL: page->SetEntry(szEntryName, m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.fValue); break; case eVector3D: { Vector3D v3D(m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.v3dValues.x, m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.v3dValues.y, m_pObjectList->ppPropertiesArray[i]->ppObjectProperties[j]->uPropValue.v3dValues.z); page->SetEntry(szEntryName, (Vector3D)v3D); break; } } // switch for property type } // else, we are setting a property instead of removing one (ie.. fPresent true) } // for loop iterating properties outfile.Save(); } // for loop iterating objects return (!nFailures); } //**************************************************************************************** // LoadObjectData() // // This routine will search the content\weaponsubsystems directory for subdirectories containing .data files // It will then open those .data files to read in weapon data. It is a simplistic algorithm that should be replaced // by either searching through resources.build or some other weapons reference file if they are made to be fully up // to date with their references to the weapons. // // Recursive function so watch what kind of initializations you do, or how you effect // global variables. // // Directory passed in must end in a backslash //**************************************************************************************** BOOL CDlgObjectProperties::LoadObjectData(LPCSTR szDirectoryToSearchFor, DIRECTORYSEARCHTYPE eSearchType) { CString strRootDirSearchString = szDirectoryToSearchFor; strRootDirSearchString += "*.*"; CString strFullSubdirectoryName ; BOOL fRet = TRUE; // // If we are only supposed to seach in the root directory pass this to the next function that finds // the actual files // if (eSearchType == eRootOnly) { fRet = LoadDataFilesFromSubdirectory(szDirectoryToSearchFor); return fRet; // return so we don't do any more searching } // // If we are doing all directories then we should search in the root as well, then // proceed down to the next level. // if (eSearchType == eAllSubdirectories) { fRet = LoadDataFilesFromSubdirectory(szDirectoryToSearchFor); } // // If we got an error, exit now, we don't continue searching the subdirectories // if (!fRet) return fRet; // // If we got here we need to search for subdirectories of the current one // Then call this function recursively on each of those directories // // // Now we iterate through the current directory looking for subdirectories. // // WIN32_FIND_DATA wfdFindFileData; HANDLE hFileSearch = FindFirstFile((LPCSTR)strRootDirSearchString , &wfdFindFileData); if (hFileSearch == INVALID_HANDLE_VALUE) { // strOutput.Format("\r\nError : Didn't find any files in the source dir to copy."); // OutputString(strOutput); return TRUE; } if (wfdFindFileData.cFileName[0] == '\0') { // strOutput.Format("\r\nError : Didn't find any files in the source dir to copy."); // OutputString(strOutput); FindClose(hFileSearch); return TRUE; } while (wfdFindFileData.cFileName[0]) { if (!stricmp(wfdFindFileData.cFileName, ".") || !stricmp(wfdFindFileData.cFileName, "..")) { goto NextFile; } if (!(wfdFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { goto NextFile; } strFullSubdirectoryName = szDirectoryToSearchFor; strFullSubdirectoryName += wfdFindFileData.cFileName; EndDirectoryWithBackSlash(strFullSubdirectoryName); if (eSearchType == eAllSubdirectories) { LoadObjectData(strFullSubdirectoryName, eAllSubdirectories); } else // since eRootOnly was already weeded out above, this means "eSingleSubdirectory" { LoadObjectData(strFullSubdirectoryName, eRootOnly); } NextFile: if (!FindNextFile(hFileSearch, &wfdFindFileData)) { break; } } // while FindClose(hFileSearch); fRet = TRUE; // // Now the list box should be updated. We need a default selection, and then that will trigger the // the fields to update correctly on the dialog box. // return fRet; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::LoadDataFilesFromSubdirectory(CString strSubdirectory) { EndDirectoryWithBackSlash(strSubdirectory); CString strFullFilename ; CString strRootDirSearchString = strSubdirectory; strRootDirSearchString += m_strFileNameToSearchSubdirectoriesFor; // // Now we iterate through the subdirectory looking for files // // WIN32_FIND_DATA wfdFindFileData; HANDLE hFileSearch = FindFirstFile((LPCSTR)strRootDirSearchString , &wfdFindFileData); if (hFileSearch == INVALID_HANDLE_VALUE) { // strOutput.Format("\r\nError : Didn't find any files in the source dir to copy."); // OutputString(strOutput); return TRUE; } if (wfdFindFileData.cFileName[0] == '\0') { // strOutput.Format("\r\nError : Didn't find any files in the source dir to copy."); // OutputString(strOutput); FindClose(hFileSearch); return TRUE; } while (wfdFindFileData.cFileName[0]) { if (!stricmp(wfdFindFileData.cFileName, ".") || !stricmp(wfdFindFileData.cFileName, "..")) { goto NextFile; } if (wfdFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { goto NextFile; } strFullFilename = strSubdirectory; strFullFilename += wfdFindFileData.cFileName; // // See if there is an additional filter function to call, and if so, call it // if (m_fnFilterFunction && !m_fnFilterFunction((LPCSTR)strFullFilename)) { goto NextFile; } // // We have a .data file, so see if it is appropriately setup and load into a data structure and // add to the list box. We need to know if it is read only so we know whether or not we can // alter the data // The data structure will also have to store a variable to know if the data has been altered. // if (LoadObjectDataFromFile(strFullFilename , (wfdFindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY))) { // // If we successfully loaded the weapon, add it to the list box // // Alias some of the data for readability of the code int nCurrObject = m_pObjectList->nObjectCount; CDOPPROPERTIES_OBJECT_PROPERTIES * pObjectPropertiesArray = (m_pObjectList->ppPropertiesArray[nCurrObject]); // // CString is used to remove the directory info To the weapons name. Find the last \ // CString strObjectNameOnly(pObjectPropertiesArray->szObjectName); int nPos = 0; if (!m_fShowFullObjectName) { nPos = strObjectNameOnly.ReverseFind('\\'); nPos ++; // goes to 0 if not found, otherwise the character after the \ or the null terminator if that's last } int nSel = m_lbObjectList.AddString((pObjectPropertiesArray->szObjectName + nPos)); m_lbObjectList.SetItemData(nSel, (DWORD) pObjectPropertiesArray); m_pObjectList->nObjectCount++; // only increment on success since we don't want the index off in the list } NextFile: if (!FindNextFile(hFileSearch, &wfdFindFileData)) { break; } } // while FindClose(hFileSearch); return TRUE; } //**************************************************************************************** // // // // // //**************************************************************************************** BOOL CDlgObjectProperties::LoadObjectDataFromFile(CString strFullObjectFilename, BOOL fReadOnly ) { // CString strOutput; NotationFile infile(strFullObjectFilename, NotationFile::Raw); // // Alias some of the data for readability of the code int nCurrObject = m_pObjectList->nObjectCount; CDOPPROPERTIES_OBJECT_PROPERTIES * pObjectPropertiesArray = (m_pObjectList->ppPropertiesArray[nCurrObject]); int nTotalProperties = m_paPropertiesToEdit->nCount; // // allocate the memory for the properties for this object // pObjectPropertiesArray->fDirty = FALSE; pObjectPropertiesArray->fReadOnly = fReadOnly; pObjectPropertiesArray->nProperties = nTotalProperties; strcpy(pObjectPropertiesArray->szObjectName, (LPCSTR)strFullObjectFilename); // already allocated // pObjectPropertiesArray->ppObjectProperties = Allocate_CDOPPROPERTIES_OBJECT_PROPERTIES(nTotalProperties); // // Now go through and for each item in the properties list we need to get the page and entry // we will cache the page name so we don't keep getting the same one if it repeats // Page * page = NULL; char szCurrentPageName[128] = ""; // used to prevent repetitively searching for the same page for (int j=0; j < nTotalProperties; j++) { pObjectPropertiesArray->ppObjectProperties[j]->fPresent = FALSE; // by default... switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->ePropertyType) { case efloat: pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.fltValue = 0.0f; break; case eint: pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.nValue = 0; break; case eLPSTR: pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.szValue[0] = 0; break; case eBOOL: pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.fValue = FALSE; break; case eVector3D: pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.x = 0.0f; pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.y = 0.0f; pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.z = 0.0f; break; } // switch for property type const char * szPageName = GetPageNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->szPropertyTag); if (!page || strcmp(szCurrentPageName, szPageName)) { strcpy(szCurrentPageName, szPageName); page = infile.FindPage(szPageName); if (!page) // if for some reason we can't find the page, jump out continue; } const char * szEntryName = GetEntryNameToPropertyName(m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->szPropertyTag); // // For each item in the data list, if it shouldn't be there, delete it. If it supposed to be there set it // Assumption is made that there are not two of any particular value key // switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[j]->ePropertyType) { case efloat: if (page->GetEntry(szEntryName, &(pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.fltValue))) { pObjectPropertiesArray->ppObjectProperties[j]->fPresent = TRUE; } break; case eint: if (page->GetEntry(szEntryName, &(pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.nValue))) { pObjectPropertiesArray->ppObjectProperties[j]->fPresent = TRUE; } break; case eLPSTR: { const char * szTemp; if (page->GetEntry(szEntryName, &szTemp)) { strcpy(pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.szValue, szTemp) ; pObjectPropertiesArray->ppObjectProperties[j]->fPresent = TRUE; } } break; case eBOOL: if (page->GetEntry(szEntryName, &(pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.fValue))) { pObjectPropertiesArray->ppObjectProperties[j]->fPresent = TRUE; } break; case eVector3D: { Vector3D v3D(0.0f, 0.0f, 0.0f); if (page->GetEntry(szEntryName, (Vector3D *)&v3D)) { pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.x = v3D.x; pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.y = v3D.y; pObjectPropertiesArray->ppObjectProperties[j]->uPropValue.v3dValues.z = v3D.z; pObjectPropertiesArray->ppObjectProperties[j]->fPresent = TRUE; } break; } } // switch for property type } // for loop iterating properties // // This is a good place to make any known automated updates to the data. If we have just made them all // add a new variable, or we removed a line, or we changed the type of data stored, we can do it at load // time, then mark the dirty flag. Beware to honor the readonly flag here though. We don't want the read only // and the dirty bit set at the same time. // // // Note that we don't increment the weapon count here as we have to make sure we added to the list box // since they are kept in sync by the index in the list box. // return TRUE; } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectProperties::OnSelchangeObjectlist() { // // First check what the old focus was, see if the data has changed, and if it has then we can // update the weapons data structure and move to the next selection // // Load the current data into the variables, then copy that data to a weaponinfo structure MoveCurSelDataToOrFromControls(FALSE); // // If we have selected something then we need to update info to the controls // m_nCurSel = m_lbObjectList.GetCurSel(); if(m_nCurSel!=-1) { m_popCurObjectPropertiesArray = (CDOPPROPERTIES_OBJECT_PROPERTIES * )(void *)m_lbObjectList.GetItemData(m_nCurSel); MoveCurSelDataToOrFromControls(TRUE); EnableControlsForCurrentSelection(); } } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::DisableAllControls() { for (UINT i = IDC_DOP_PROPNAME; i < m_nLastControlID ; i++) { CWnd * pWnd = GetDlgItem(i); if (pWnd) pWnd->EnableWindow(FALSE); } return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::EnableControlsForCurrentSelection() { // In addition to enabling disabling the various controls... // We also have to set the read only text properly when we are done // // if there is not a current selection then disable all and move on if (m_popCurObjectPropertiesArray == NULL) { DisableAllControls(); SetDlgItemText(IDC_READONLY, MyLoadStringTempBuffer(IDS_READONLY)); return FALSE; } BOOL fReadOnly = m_popCurObjectPropertiesArray->fReadOnly; // // If we got here then we have a selected item and need to enable/disable the controls properly // based on the data object info structures // for (int i = 0; i < m_paPropertiesToEdit->nCount; i++) { // First is the first ID of the controls for this property. End is the first control of the next // property. UINT uiFirst = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[i]->uiReserved1_CTRLID; CWnd * pWnd = GetDlgItem(uiFirst); BOOL fPresent = m_popCurObjectPropertiesArray->ppObjectProperties[i]->fPresent; if (pWnd) { pWnd->EnableWindow(!fReadOnly); } pWnd = GetDlgItem(uiFirst+1); if (pWnd) { pWnd->EnableWindow(!fReadOnly); } pWnd = GetDlgItem(uiFirst+2); if (pWnd) { pWnd->EnableWindow(!fReadOnly && fPresent); } if (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[i]->ePropertyType == eVector3D) { pWnd = GetDlgItem(uiFirst+3); if (pWnd) { pWnd->EnableWindow(!fReadOnly && fPresent); } pWnd = GetDlgItem(uiFirst+4); if (pWnd) { pWnd->EnableWindow(!fReadOnly && fPresent); } } // if for vector3d property type } // for loop for property list SetDlgItemText(IDC_READONLY, (fReadOnly ? MyLoadStringTempBuffer(IDS_READONLY) : _T(""))); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::MoveCurSelDataToOrFromControls(BOOL fToControls) { // if there is not a current selection then disable all and move on if (m_popCurObjectPropertiesArray == NULL) { DisableAllControls(); SetDlgItemText(IDC_READONLY, MyLoadStringTempBuffer(IDS_READONLY)); return FALSE; } // // If we are retrieving To the controls we need to save off what we have and // see if it changed. // CDOPPROPERTIES_OBJECT_PROPERTIES * pPropertyArray = NULL; if (!fToControls) { pPropertyArray = Allocate_CDOPPROPERTIES_OBJECT_PROPERTIES( m_paPropertiesToEdit->nCount); Copy_CDOPPROPERTIES_OBJECT_PROPERTIES(pPropertyArray, m_popCurObjectPropertiesArray); } UpdateControlData(fToControls); // put the data in the controls based on the current data pointer // // See if the data changed if we are reading To the controls // if (!fToControls) { if (!IsEqual_CDOPPROPERTIES_OBJECT_PROPERTIES(pPropertyArray, m_popCurObjectPropertiesArray)) { m_popCurObjectPropertiesArray->fDirty = TRUE; // it changed m_fDirty = TRUE; // at least one object has changed. } free(pPropertyArray); } return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::GetBOOLFromButton(UINT uiID, BOOL * pfDest) { CButton * pWnd = (CButton *)GetDlgItem(uiID); if (!pWnd) return FALSE; *pfDest = pWnd->GetCheck(); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::GetBOOLFromControl(UINT uiID, BOOL * pfDest) { CWnd * pWnd = GetDlgItem(uiID); if (!pWnd) return FALSE; char szTemp[256]; GetDlgItemText(uiID, szTemp, 255); *pfDest = FALSE; if (!stricmp(szTemp, "true") || !stricmp(szTemp, "yes") || !stricmp(szTemp, "1")) { *pfDest = TRUE; } return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::GetfloatFromControl(UINT uiID, float * pfltDest) { CWnd * pWnd = GetDlgItem(uiID); if (!pWnd) return FALSE; char szTemp[256]; GetDlgItemText(uiID, szTemp, 255); *pfltDest = (float)atof(szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::GetLPSTRFromControl(UINT uiID, LPSTR pszDest) { CWnd * pWnd = GetDlgItem(uiID); if (!pWnd) return FALSE; char szTemp[256]; GetDlgItemText(uiID, szTemp, 255); szTemp[255] = 0; strcpy(pszDest, szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::GetintFromControl(UINT uiID, int * pnDest) { CWnd * pWnd = GetDlgItem(uiID); if (!pWnd) return FALSE; char szTemp[256]; GetDlgItemText(uiID, szTemp, 255); *pnDest = atoi(szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::GetVector3DFromControl(UINT uiID, float * pfltx, float * pflty, float * pfltz) { CWnd * pWnd = GetDlgItem(uiID); if (!pWnd) return FALSE; char szTemp[256]; GetDlgItemText(uiID, szTemp, 255); *pfltx = (float)atof(szTemp); pWnd = GetDlgItem(uiID +1); if (!pWnd) return FALSE; GetDlgItemText(uiID+1, szTemp, 255); *pflty = (float)atof(szTemp); pWnd = GetDlgItem(uiID +2); if (!pWnd) return FALSE; GetDlgItemText(uiID+2, szTemp, 255); *pfltz = (float)atof(szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::SetBOOLToButton(UINT uiID, BOOL fDest) { CButton * pWnd = (CButton *)GetDlgItem(uiID); if (!pWnd) return FALSE; pWnd->SetCheck(fDest); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::SetBOOLToControl(UINT uiID, BOOL fSrc) { CWnd * pWnd = GetDlgItem(uiID); if (!pWnd) return FALSE; char szTemp[256]; sprintf(szTemp, fSrc ? "true" : "false"); SetDlgItemText(uiID, szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::SetfloatToControl(UINT uiID, float fltSrc) { CWnd * pWnd = GetDlgItem(uiID); if (!pWnd) return FALSE; char szTemp[256]; sprintf(szTemp, "%f", (double) fltSrc); SetDlgItemText(uiID, szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::SetLPSTRToControl(UINT uiID, LPSTR pszSrc) { CWnd * pWnd = GetDlgItem(uiID); if (!pWnd) return FALSE; SetDlgItemText(uiID, pszSrc); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::SetintToControl(UINT uiID, int nSrc) { CWnd * pWnd = GetDlgItem(uiID); if (!pWnd) return FALSE; char szTemp[256]; sprintf(szTemp, "%d", nSrc); SetDlgItemText(uiID, szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::SetVector3DToControl(UINT uiID, float fltx, float flty, float fltz) { CWnd * pWnd = GetDlgItem(uiID); if (!pWnd) return FALSE; char szTemp[256]; sprintf(szTemp, "%f", (double) fltx); SetDlgItemText(uiID, szTemp); sprintf(szTemp, "%f", (double) flty); SetDlgItemText(uiID + 1, szTemp); sprintf(szTemp, "%f", (double) fltz); SetDlgItemText(uiID + 2, szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectProperties::UpdateControlData(BOOL fToControls) { if (!m_popCurObjectPropertiesArray) return FALSE; BOOL fReadOnly = m_popCurObjectPropertiesArray->fReadOnly; if (fReadOnly && !fToControls) return FALSE; // don't bother reading if we don't have to // // for (int i = 0; i < m_paPropertiesToEdit->nCount; i++) { // First is the first ID of the controls for this property. End is the first control of the next // property. UINT uiFirst = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[i]->uiReserved1_CTRLID; if (!fToControls) { GetBOOLFromButton(uiFirst + 1,&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->fPresent) ); switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[i]->ePropertyType) { case efloat: GetfloatFromControl(uiFirst + 2,&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.fltValue)); break; case eint: GetintFromControl(uiFirst + 2,&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.nValue)); break; case eLPSTR: GetLPSTRFromControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.szValue)); break; case eBOOL: GetBOOLFromControl(uiFirst + 2,&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.fValue)); break; case eVector3D: GetVector3DFromControl(uiFirst + 2,&(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.x), &(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.y), &(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.z)); break; } // switch on property type } // if !fFromControls else { SetBOOLToButton(uiFirst + 1,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->fPresent) ); switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[i]->ePropertyType) { case efloat: SetfloatToControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.fltValue)); break; case eint: SetintToControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.nValue)); break; case eLPSTR: SetLPSTRToControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.szValue)); break; case eBOOL: SetBOOLToControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.fValue)); break; case eVector3D: SetVector3DToControl(uiFirst + 2,(m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.x), (m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.y), (m_popCurObjectPropertiesArray->ppObjectProperties[i]->uPropValue.v3dValues.z)); break; } // switch on property type } } // for loop for property list return TRUE; }