// DlgObjectBalance.cpp : implementation file // #include "stdafx.h" #include "Balancer.h" #include #include #include "DlgObjectBalance.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 // extern LPCSTR MyLoadStringTempBuffer(UINT uiID); extern void EndDirectoryWithBackSlash(CString & strDir); ///////////////////////////////////////////////////////////////////////////// // CDlgObjectBalance 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 * CDlgObjectBalance::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 * CDlgObjectBalance::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 * CDlgObjectBalance::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 * CDlgObjectBalance::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 CDlgObjectBalance::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 CDlgObjectBalance::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 CDlgObjectBalance::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 CDlgObjectBalance::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 CDlgObjectBalance::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 CDlgObjectBalance::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; } //**************************************************************************************** // // // //**************************************************************************************** CDlgObjectBalance::~CDlgObjectBalance() { if (m_pObjectList) { free(m_pObjectList); } } //**************************************************************************************** // // // //**************************************************************************************** CDlgObjectBalance::CDlgObjectBalance(CWnd* pParent /*=NULL*/) : CDialog(CDlgObjectBalance::IDD, pParent) { //{{AFX_DATA_INIT(CDlgObjectBalance) //}}AFX_DATA_INIT m_pObjectList = NULL; ClearObjectDataSet(); // 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_fShowPageOnly = FALSE; m_eSearchType = eSingleSubdirectory; m_fDirty = FALSE; m_fAllowPresentToChange = TRUE; m_nHorzControlSize = 0; m_nLastControlID = IDC_VARIABLE_VALUE_PLACEHOLDER; } //**************************************************************************************** // // // //**************************************************************************************** int CDlgObjectBalance::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 CDlgObjectBalance::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDlgObjectBalance) DDX_Control(pDX, IDC_DOP_PROPERTIES, m_staticPropertiesGroup); DDX_Control(pDX, ID_DOB_SCROLLBAR, m_sbScrollBarVert); DDX_Control(pDX, ID_DOB_SCROLLBAR2, m_sbScrollBarHorz); //}}AFX_DATA_MAP } //**************************************************************************************** // // // //**************************************************************************************** BEGIN_MESSAGE_MAP(CDlgObjectBalance, CDialog) //{{AFX_MSG_MAP(CDlgObjectBalance) ON_BN_CLICKED(IDC_VALUE_PLUS, OnValuePlus) ON_BN_CLICKED(IDC_VALUE_MULTIPLY, OnValueMultiply) ON_BN_CLICKED(IDC_VALUE_MINUS, OnValueMinus) ON_BN_CLICKED(IDC_VALUE_DIVIDE, OnValueDivide) ON_WM_VSCROLL() ON_WM_HSCROLL() ON_BN_CLICKED(IDC_FILL_ALL_VALUES, OnFillAllValues) ON_BN_CLICKED(IDC_CHECKALL_APPLY_BUTTONS, OnCheckallApplyButtons) //}}AFX_MSG_MAP ON_WM_ERASEBKGND() END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDlgObjectBalance message handlers BOOL CDlgObjectBalance::OnInitDialog() { CDialog::OnInitDialog(); 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(); ClearModifierCells(); UpdateControlData(TRUE); UpdateData(FALSE); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::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_VARIABLE_VALUE_PLACEHOLDER; // // 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 * pControlPlus = GetDlgItem(IDC_VALUE_PLUS); CWnd * pControlPresentPlaceHolder = GetDlgItem(IDC_VARIABLE_PRESENT_PLACEHOLDER); CWnd * pControlValuePlaceHolder = GetDlgItem(IDC_VARIABLE_VALUE_PLACEHOLDER); CWnd * pControlObjectNameHeader = GetDlgItem(IDC_OBJECT_NAME_HEADER); CWnd * pControlApplyChangesPlaceHolder = GetDlgItem(IDC_APPLYCHANGESPLACEHOLDER); CWnd * pControlGroupboxArea = GetDlgItem(IDC_DOP_PROPERTIES); if (!pControlPlus || !pControlPresentPlaceHolder || !pControlValuePlaceHolder) return; // badness has occurred, but no way out of it at this point //CFont * pFontControlPlus = pControlPlus ->GetFont(); CFont * pFontControlPresentPlaceHolder = pControlPresentPlaceHolder->GetFont(); CFont * pFontControlValuePlaceHolder = pControlValuePlaceHolder ->GetFont(); CFont * pFontControlObjectNameHeader = pControlObjectNameHeader ->GetFont(); CRect crRectDlg; CRect crControlPlus; CRect crControlPresentPlaceHolder; CRect crControlValuePlaceHolder; CRect crControlObjectNameHeader; CRect crControlApplyChangesPlaceHolder; CRect crControlGroupboxArea; GetWindowRect(crRectDlg); pControlPlus->GetWindowRect(crControlPlus); pControlPresentPlaceHolder->GetWindowRect(crControlPresentPlaceHolder); pControlValuePlaceHolder->GetWindowRect(crControlValuePlaceHolder); pControlObjectNameHeader->GetWindowRect(crControlObjectNameHeader); pControlApplyChangesPlaceHolder->GetWindowRect(crControlApplyChangesPlaceHolder); pControlGroupboxArea->GetWindowRect(crControlGroupboxArea); pControlApplyChangesPlaceHolder->GetWindowRect(crControlApplyChangesPlaceHolder); // // Offset the rects relative to the dialog // ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlPlus, 2); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlPresentPlaceHolder, 2); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlValuePlaceHolder, 2); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlObjectNameHeader, 2); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlGroupboxArea, 2); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crControlApplyChangesPlaceHolder, 2); // // If the caller wants to override the edit control size then they can. // if (m_nHorzControlSize > 0) { crControlValuePlaceHolder.right = crControlValuePlaceHolder.left + m_nHorzControlSize; } 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. // Next root ID is 1 after this set int nCurrObject = 0; // // For the first pass we create a set of controls on the top to allow the multiple adding/multiplying // factors used for balancing. // // int nCurrX = crControlValuePlaceHolder.left; int nCurrY = crControlPlus.top; const int nYBufferSizeAfterRow = 0; const int nXBufferSizeAfterPresent = 2; const int nXBufferSizeAfterSmallEdit = 1; const char * szStaticText = NULL; // // The ID's for the controls are based on the total number possible per row to make it easier, // 1 for the name of the object and 4 for the 1 present checkbox and 3 edit controls // It starts with the base controls then adds a whole row of values. Then those are applied to the upper row // so the first row of actual values is two rows after the place holder base value. int nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (1) ); const int nXBufferSizeAfterFullEdit = 4; HWND hWndTemp = NULL; while (nCurrentProperty < m_paPropertiesToEdit->nCount) { // Create a property name header 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 : (m_fShowPageOnly ? GetPageNameToPropertyName(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, nCurrX, crControlObjectNameHeader.top, crControlValuePlaceHolder.Width(), crControlObjectNameHeader.Height(), GetSafeHwnd(), // This is now located on the second row of ID's that I am concerned about (HMENU)((int) nCurrID + 1 + ((m_paPropertiesToEdit->nCount * 4) + 1)), theApp.m_hInstance, NULL); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlObjectNameHeader, (LPARAM)FALSE); CDOPVARTYPE eVarType = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType; switch (eVarType) { case eVector3D: hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD, nCurrX, nCurrY, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(), GetSafeHwnd(), (HMENU)(int)(nCurrID+1), theApp.m_hInstance, NULL); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE); nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterSmallEdit; hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD , nCurrX, nCurrY, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(), GetSafeHwnd(), (HMENU)(int)(nCurrID+2), theApp.m_hInstance, NULL); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE); nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterSmallEdit; hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD , nCurrX, nCurrY, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(), GetSafeHwnd(), (HMENU)(int)(nCurrID+3), theApp.m_hInstance, NULL); nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterFullEdit + crControlPresentPlaceHolder.Width() + nXBufferSizeAfterPresent; ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE); break; case efloat: case eint: case eLPSTR: case eBOOL: hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD, nCurrX, nCurrY, crControlValuePlaceHolder.Width(), crControlValuePlaceHolder.Height(), GetSafeHwnd(), (HMENU)(int)(nCurrID+1), theApp.m_hInstance, NULL); nCurrX += crControlValuePlaceHolder.Width() + nXBufferSizeAfterFullEdit + crControlPresentPlaceHolder.Width() + nXBufferSizeAfterPresent; ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE); break; } nCurrID += 4; nCurrentProperty++; } m_nMaxVisibleVert = crControlGroupboxArea.Height()/(crControlValuePlaceHolder.Height() + nYBufferSizeAfterRow); m_nCurScrollPosVert = 0; m_nScrollIncrementVert = (crControlValuePlaceHolder.Height() + nYBufferSizeAfterRow); m_sbScrollBarVert.SetScrollPos(0, FALSE); m_sbScrollBarVert.SetScrollRange(0, max(0, m_pObjectList->nObjectCount - m_nMaxVisibleVert + 2), TRUE); m_nMaxVisibleHorz = (crControlGroupboxArea.Width() - (crControlPresentPlaceHolder.left)) /(crControlValuePlaceHolder.Width() + nXBufferSizeAfterPresent + nXBufferSizeAfterFullEdit + crControlPresentPlaceHolder.Width()); m_nCurScrollPosHorz = 0; m_nScrollIncrementHorz = (crControlValuePlaceHolder.Width() + nXBufferSizeAfterPresent + nXBufferSizeAfterSmallEdit + crControlPresentPlaceHolder.Width()); m_sbScrollBarHorz.SetScrollPos(0, FALSE); m_sbScrollBarHorz.SetScrollRange(0, max(0, m_paPropertiesToEdit->nCount - m_nMaxVisibleHorz + 2), TRUE); // // Set up the static window's children to work as part of the dialog itself. // long wsWindowStyle = ::GetWindowLong(pControlGroupboxArea->GetSafeHwnd(), GWL_EXSTYLE); wsWindowStyle |= WS_EX_CONTROLPARENT; ::SetWindowLong(pControlGroupboxArea->GetSafeHwnd(), GWL_EXSTYLE, wsWindowStyle); // // The ID's for the controls are based on the total number possible per row to make it easier, // 1 for the name of the object and 4 for the 1 present checkbox and 3 edit controls // It starts with the base controls then adds a whole row of values. Then those are applied to the upper row // so the first row of actual values is two rows after the place holder base value. nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrObject + 3) ); nCurrY = crControlValuePlaceHolder.top; while (nCurrObject < m_pObjectList->nObjectCount) { BOOL fReadOnly = m_pObjectList->ppPropertiesArray[nCurrObject]->fReadOnly; UINT uiDisabledFlagIfNecessary = fReadOnly ? WS_DISABLED : 0; nCurrX = crControlPlus.left; szStaticText = m_fShowFullObjectName ? m_pObjectList->ppPropertiesArray[nCurrObject]->szObjectName : GetShortObjectName(m_pObjectList->ppPropertiesArray[nCurrObject]->szObjectName); hWndTemp = ::CreateWindow("STATIC", szStaticText, WS_VISIBLE | SS_LEFT | WS_CHILD, crControlObjectNameHeader.left - crControlGroupboxArea.left + 2, nCurrY - crControlGroupboxArea.top, crControlObjectNameHeader.Width(), crControlValuePlaceHolder.Height(), pControlGroupboxArea->GetSafeHwnd(), (HMENU)IDC_STATIC, theApp.m_hInstance, NULL); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlObjectNameHeader, (LPARAM)FALSE); HWND hWndTemp = NULL; nCurrentProperty = 0; // reset for use in the next pass nCurrX = crControlPresentPlaceHolder.left; // // Create the check boxes that allow you to control which weapons are effected by a given change. // // Since the CurrID is the present button, and represents the beginning of data storage, nCurrID -1 will be the apply checkbox nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrObject + 3)); hWndTemp = ::CreateWindow("BUTTON", "", WS_VISIBLE | BS_CHECKBOX | WS_CHILD | BS_AUTOCHECKBOX | uiDisabledFlagIfNecessary, crControlApplyChangesPlaceHolder.left - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlApplyChangesPlaceHolder.Width(), crControlApplyChangesPlaceHolder.Height(), pControlGroupboxArea->GetSafeHwnd(), (HMENU)(int)(nCurrID-1), theApp.m_hInstance, NULL); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPresentPlaceHolder, (LPARAM)FALSE); if (fReadOnly) { ::SendMessage(hWndTemp, BM_SETCHECK, BST_UNCHECKED, 0); } // Start the ID count for the controls at the set above 0, to skip the place holders // It could be made tighter than this but isn't necessary. while (nCurrentProperty < m_paPropertiesToEdit->nCount) { nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrObject + 3) + (nCurrentProperty * 4)); hWndTemp = ::CreateWindow("BUTTON", "", WS_VISIBLE | BS_CHECKBOX | WS_CHILD | BS_AUTOCHECKBOX | uiDisabledFlagIfNecessary | (m_fAllowPresentToChange ? 0 : WS_DISABLED), nCurrX - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlPresentPlaceHolder.Width(), crControlPresentPlaceHolder.Height(), pControlGroupboxArea->GetSafeHwnd(), (HMENU)(int)(nCurrID+0), theApp.m_hInstance, NULL); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlPresentPlaceHolder, (LPARAM)FALSE); nCurrX += crControlPresentPlaceHolder.Width() + nXBufferSizeAfterPresent; CDOPVARTYPE eVarType = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType; switch (eVarType) { case eVector3D: hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD | uiDisabledFlagIfNecessary, nCurrX - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(), pControlGroupboxArea->GetSafeHwnd(), (HMENU)(int)(nCurrID+1), theApp.m_hInstance, NULL); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE); nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterSmallEdit; hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD | uiDisabledFlagIfNecessary, nCurrX - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(), pControlGroupboxArea->GetSafeHwnd(), (HMENU)(int)(nCurrID+2), theApp.m_hInstance, NULL); ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE); nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterSmallEdit; hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD | uiDisabledFlagIfNecessary, nCurrX - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlValuePlaceHolder.Width()/3, crControlValuePlaceHolder.Height(), pControlGroupboxArea->GetSafeHwnd(), (HMENU)(int)(nCurrID+3), theApp.m_hInstance, NULL); nCurrX += crControlValuePlaceHolder.Width()/3 + nXBufferSizeAfterFullEdit; ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE); break; case efloat: case eint: case eLPSTR: case eBOOL: hWndTemp = ::CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY, "EDIT", "", WS_VISIBLE | WS_BORDER | ES_LEFT | WS_CHILD | uiDisabledFlagIfNecessary, nCurrX - crControlGroupboxArea.left, nCurrY - crControlGroupboxArea.top, crControlValuePlaceHolder.Width(), crControlValuePlaceHolder.Height(), pControlGroupboxArea->GetSafeHwnd(), (HMENU)(int)(nCurrID+1), theApp.m_hInstance, NULL); nCurrX += crControlValuePlaceHolder.Width() + nXBufferSizeAfterFullEdit; ::SendMessage(hWndTemp, WM_SETFONT, (WPARAM)(HFONT)*pFontControlValuePlaceHolder, (LPARAM)FALSE); break; } // switch on property type nCurrID += 4; nCurrentProperty++; } // while currentproperty nCurrY += crControlValuePlaceHolder.Height() + nYBufferSizeAfterRow; nCurrObject++; } // while nCurrentObject m_nLastControlID = nCurrID; } // end of CreateSubControlsForProperties() //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::OnOK() { // // Validate the data and save any changes made since the last sel change // UpdateControlData(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 CDlgObjectBalance::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 CDlgObjectBalance::SetObjectFilesDirectory(LPCSTR lpszDirectoryPath) { m_strObjectFilesRootDirectory = lpszDirectoryPath; EndDirectoryWithBackSlash(m_strObjectFilesRootDirectory ); return TRUE; } //**************************************************************************************** // // Sets the root file name type to search for like "*.data" // //**************************************************************************************** BOOL CDlgObjectBalance::SetFileNameToSearchSubdirectoriesFor(LPCSTR lpszFileSearchString) { m_strFileNameToSearchSubdirectoriesFor = lpszFileSearchString; return TRUE; } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::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 CDlgObjectBalance::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 CDlgObjectBalance::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 CDlgObjectBalance::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 CDlgObjectBalance::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; } //**************************************************************************************** // //**************************************************************************************** LPCSTR CDlgObjectBalance::GetShortObjectName(LPCSTR szObjectName) { // // CString is used to remove the directory info To the weapons name. Find the last \ // CString strObjectNameOnly(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 } return (szObjectName + nPos); } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::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 } 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 CDlgObjectBalance::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... // put in default values for each type 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; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::DisableAllControls() { for (UINT i = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (2) ) ; i < m_nLastControlID ; i++) { CWnd * pWnd = GetDescendantWindow(i); if (pWnd) pWnd->EnableWindow(FALSE); } return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::GetBOOLFromButton(UINT uiID, BOOL * pfDest) { CButton * pWnd = (CButton *)GetDescendantWindow(uiID); if (!pWnd) return FALSE; *pfDest = pWnd->GetCheck(); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::GetBOOLFromControl(UINT uiID, BOOL * pfDest) { CWnd * pWnd = GetDescendantWindow(uiID); if (!pWnd) return FALSE; char szTemp[256]; pWnd->GetWindowText(szTemp, 255); *pfDest = FALSE; if (!stricmp(szTemp, "true") || !stricmp(szTemp, "yes") || !stricmp(szTemp, "1")) { *pfDest = TRUE; } return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::GetfloatFromControl(UINT uiID, float * pfltDest) { CWnd * pWnd = GetDescendantWindow(uiID); if (!pWnd) return FALSE; char szTemp[256]; pWnd->GetWindowText(szTemp, 255); *pfltDest = (float)atof(szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::GetLPSTRFromControl(UINT uiID, LPSTR pszDest) { CWnd * pWnd = GetDescendantWindow(uiID); if (!pWnd) return FALSE; char szTemp[256]; pWnd->GetWindowText(szTemp, 255); szTemp[255] = 0; strcpy(pszDest, szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::GetintFromControl(UINT uiID, int * pnDest) { CWnd * pWnd = GetDescendantWindow(uiID); if (!pWnd) return FALSE; char szTemp[256]; pWnd->GetWindowText(szTemp, 255); *pnDest = atoi(szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::GetVector3DFromControl(UINT uiID, float * pfltx, float * pflty, float * pfltz) { CWnd * pWnd = GetDescendantWindow(uiID); if (!pWnd) return FALSE; char szTemp[256]; pWnd->GetWindowText(szTemp, 255); *pfltx = (float)atof(szTemp); pWnd = GetDescendantWindow(uiID +1); if (!pWnd) return FALSE; pWnd->GetWindowText(szTemp, 255); *pflty = (float)atof(szTemp); pWnd = GetDescendantWindow(uiID +2); if (!pWnd) return FALSE; pWnd->GetWindowText(szTemp, 255); *pfltz = (float)atof(szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::SetBOOLToButton(UINT uiID, BOOL fDest) { CButton * pWnd = (CButton *)GetDescendantWindow(uiID); if (!pWnd) return FALSE; pWnd->SetCheck(fDest); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::SetBOOLToControl(UINT uiID, BOOL fSrc) { CWnd * pWnd = GetDescendantWindow(uiID); if (!pWnd) return FALSE; char szTemp[256]; sprintf(szTemp, fSrc ? "true" : "false"); pWnd->SetWindowText(szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::SetfloatToControl(UINT uiID, float fltSrc) { CWnd * pWnd = GetDescendantWindow(uiID); if (!pWnd) return FALSE; char szTemp[256]; sprintf(szTemp, "%f", (double) fltSrc); pWnd->SetWindowText(szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::SetLPSTRToControl(UINT uiID, LPSTR pszSrc) { CWnd * pWnd = GetDescendantWindow(uiID); if (!pWnd) return FALSE; pWnd->SetWindowText(pszSrc); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::SetintToControl(UINT uiID, int nSrc) { CWnd * pWnd = GetDescendantWindow(uiID); if (!pWnd) return FALSE; char szTemp[256]; sprintf(szTemp, "%d", nSrc); pWnd->SetWindowText(szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::SetVector3DToControl(UINT uiID, float fltx, float flty, float fltz) { CWnd * pWnd = GetDescendantWindow(uiID); if (!pWnd) return FALSE; char szTemp[256]; sprintf(szTemp, "%f", (double) fltx); pWnd->SetWindowText(szTemp); sprintf(szTemp, "%f", (double) flty); pWnd->SetWindowText(szTemp); sprintf(szTemp, "%f", (double) fltz); pWnd->SetWindowText(szTemp); return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::UpdateControlData(BOOL fToControls) { CDOPPROPERTIES_OBJECT_PROPERTIES * pObjectProperties = NULL; if (!fToControls) { pObjectProperties = Allocate_CDOPPROPERTIES_OBJECT_PROPERTIES(m_paPropertiesToEdit->nCount); } for (int nCurrentObject = 0; nCurrentObject < m_pObjectList->nObjectCount; nCurrentObject++) { // // UINT uiFirst = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrentObject+3) ); for (int nCurrentProperty = 0; nCurrentProperty < m_paPropertiesToEdit->nCount; nCurrentProperty++) { // First is the first ID of the controls for this property. End is the first control of the next // property. UINT uCurrID = uiFirst + (nCurrentProperty*4); if (!fToControls) { Copy_CDOPPROPERTIES_OBJECT_PROPERTIES(pObjectProperties, m_pObjectList->ppPropertiesArray[nCurrentObject]); GetBOOLFromButton(uCurrID,&(pObjectProperties->ppObjectProperties[nCurrentProperty]->fPresent) ); switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType) { case efloat: GetfloatFromControl(uCurrID + 1,&(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.fltValue)); break; case eint: GetintFromControl(uCurrID + 1,&(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.nValue)); break; case eLPSTR: GetLPSTRFromControl(uCurrID + 1,(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.szValue)); break; case eBOOL: GetBOOLFromControl(uCurrID + 1,&(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.fValue)); break; case eVector3D: GetVector3DFromControl(uCurrID + 1,&(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.x), &(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.y), &(pObjectProperties->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.z)); break; } // switch on property type BOOL fDirty = !IsEqual_CDOPPROPERTIES_OBJECT_PROPERTIES(m_pObjectList->ppPropertiesArray[nCurrentObject], pObjectProperties); // if( fDirty && !m_pObjectList->ppPropertiesArray[nCurrentObject]->fReadOnly) { m_fDirty = TRUE; Copy_CDOPPROPERTIES_OBJECT_PROPERTIES(m_pObjectList->ppPropertiesArray[nCurrentObject], pObjectProperties); m_pObjectList->ppPropertiesArray[nCurrentObject]->fDirty = TRUE; } } // if !fFromControls else { SetBOOLToButton(uCurrID,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->fPresent) ); switch (m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType) { case efloat: SetfloatToControl(uCurrID + 1,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.fltValue)); break; case eint: SetintToControl(uCurrID + 1,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.nValue)); break; case eLPSTR: SetLPSTRToControl(uCurrID + 1,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.szValue)); break; case eBOOL: SetBOOLToControl(uCurrID + 1,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.fValue)); break; case eVector3D: SetVector3DToControl(uCurrID + 1,(m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.x), (m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.y), (m_pObjectList->ppPropertiesArray[nCurrentObject]->ppObjectProperties[nCurrentProperty]->uPropValue.v3dValues.z)); break; } // switch on property type } } // for loop for property list } // nCurrentObject loop free(pObjectProperties); return TRUE; } #define TooSmall(M_fltTemp) ((M_fltTemp >= -0.00001f) && (M_fltTemp <= 0.00001f)) //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::AlterAllProperties(CDOPMATHTYPE eMathType) { // // Run through the list of properties, and read in the value from the controls at the top // if the control value is non-zero, call the function for altering all the object values // for that property. // float fltTemp; int nTemp; float fltTempArray[3]; UINT uiFirst = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (1)); for (int nCurrentProperty = 0; nCurrentProperty < m_paPropertiesToEdit->nCount; nCurrentProperty++) { CDOPVARTYPE eVarType = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType; switch (eVarType) { case efloat: fltTemp = 0.0f; GetfloatFromControl(uiFirst + (nCurrentProperty*4 + 1), &fltTemp); if (TooSmall(fltTemp)) { continue; } AlterProperty(nCurrentProperty, (void *)&fltTemp, eMathType); break; case eint: GetintFromControl(uiFirst + (nCurrentProperty*4 + 1), &nTemp); nTemp = 0;; if (nTemp == 0) { continue; } AlterProperty(nCurrentProperty, (void *)&nTemp, eMathType); break; case eVector3D: fltTempArray[0] = 0.0f; fltTempArray[1] = 0.0f; fltTempArray[2] = 0.0f; if (TooSmall(fltTempArray[0]) && TooSmall(fltTempArray[1]) && TooSmall(fltTempArray[2])) { continue; } GetVector3DFromControl(uiFirst + (nCurrentProperty*4 + 1), &(fltTempArray[0]), &(fltTempArray[1]), &(fltTempArray[2])); AlterProperty(nCurrentProperty, (void *)&(fltTempArray[0]), eMathType); break; } } } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::DoTheMath(float * pValue, float * pModifier, CDOPMATHTYPE eMath) { if (TooSmall(*pModifier)) { return; } switch (eMath) { case ePlus: *pValue = *pValue + *pModifier; break; case eMinus: *pValue = *pValue - *pModifier; break; case eMultiply: *pValue = *pValue * *pModifier; break; case eDivide: *pValue = *pValue / *pModifier; break; } } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::DoTheMath(int * pValue, int * pModifier, CDOPMATHTYPE eMath) { if (!*pModifier) { return; } switch (eMath) { case ePlus: *pValue = *pValue + *pModifier; break; case eMinus: *pValue = *pValue - *pModifier; break; case eMultiply: *pValue = *pValue * *pModifier; break; case eDivide: *pValue = *pValue / *pModifier; break; } } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::AlterProperty(int nProperty, void * pValueToAlterWith, CDOPMATHTYPE eMath) { // // // for (int nCurrentObject = 0; nCurrentObject < m_pObjectList->nObjectCount; nCurrentObject++) { // // UINT uiOfControl = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrentObject+3) ) ; CButton * pWnd = (CButton *)GetDescendantWindow(uiOfControl - 1); uiOfControl += 1 + (nProperty*4); // // If the apply button isn't checked this object should be skipped // if (pWnd && !pWnd->GetCheck()) continue; CDOPVARTYPE eVarType = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nProperty]->ePropertyType; switch (eVarType) { case efloat: { float fltValue; GetfloatFromControl(uiOfControl, &fltValue); DoTheMath(&fltValue, (float *)pValueToAlterWith, eMath); SetfloatToControl(uiOfControl, fltValue); } break; case eint: { int nValue; GetintFromControl(uiOfControl, &nValue); DoTheMath(&nValue, (int *)pValueToAlterWith, eMath); SetintToControl(uiOfControl, nValue); } break; case eVector3D: { for (int i = 0; i<3; i++) { float fltValue; GetfloatFromControl(uiOfControl + i, &fltValue); DoTheMath(&fltValue, (float *)&(((float *)pValueToAlterWith)[i]), eMath); SetfloatToControl(uiOfControl + i, fltValue); } } break; } } } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::OnValuePlus() { AlterAllProperties(ePlus); ClearModifierCells(); } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::OnValueMultiply() { AlterAllProperties(eMultiply); ClearModifierCells(); } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::OnValueMinus() { AlterAllProperties(eMinus); ClearModifierCells(); } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::OnValueDivide() { AlterAllProperties(eDivide); ClearModifierCells(); } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::ClearModifierCells() { // // Since the cells have been used to do math already we want to clear the values to make // sure we don't do an operation twice when not wanting it. // UINT uiFirst = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (1)); for (int nCurrentProperty = 0; nCurrentProperty < m_paPropertiesToEdit->nCount; nCurrentProperty++) { CDOPVARTYPE eVarType = m_paPropertiesToEdit->ppProperties_To_Edit_Entry[nCurrentProperty]->ePropertyType; switch (eVarType) { case efloat: SetfloatToControl(uiFirst + (nCurrentProperty*4 + 1), 0.0f); break; case eint: SetintToControl(uiFirst + (nCurrentProperty*4 + 1), 0); break; case eVector3D: SetVector3DToControl(uiFirst + (nCurrentProperty*4 + 1), 0.0f, 0.0f, 0.0f); break; } // switch eVarType } // for properties loop } // end of ClearModifierCells //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { int nCurPos = m_nCurScrollPosVert; switch(nSBCode) { case SB_BOTTOM: m_nCurScrollPosVert = m_pObjectList->nObjectCount - m_nMaxVisibleVert + 2; break; case SB_ENDSCROLL: m_nCurScrollPosVert = pScrollBar->GetScrollPos(); break; case SB_LINEDOWN: m_nCurScrollPosVert ++; break; case SB_LINEUP: m_nCurScrollPosVert --; break; case SB_PAGEDOWN: m_nCurScrollPosVert += m_nMaxVisibleVert; break; case SB_PAGEUP: m_nCurScrollPosVert -= m_nMaxVisibleVert; break; case SB_THUMBPOSITION: m_nCurScrollPosVert = nPos; break; case SB_THUMBTRACK: m_nCurScrollPosVert = nPos; break; case SB_TOP: m_nCurScrollPosVert = 0; break; } m_nCurScrollPosVert = max(0, m_nCurScrollPosVert); m_nCurScrollPosVert = min(m_nCurScrollPosVert, m_pObjectList->nObjectCount - m_nMaxVisibleVert + 2); pScrollBar->SetScrollPos(m_nCurScrollPosVert, TRUE); CWnd * pControlGroupboxArea = GetDescendantWindow(IDC_DOP_PROPERTIES); int nMoveAmount = m_nScrollIncrementVert * (nCurPos - m_nCurScrollPosVert); CWnd * pChildWindow = pControlGroupboxArea->GetWindow(GW_CHILD); //CRect crControlGroupboxArea; //pControlGroupboxArea->GetWindowRect(crControlGroupboxArea); CRect crWindowRect; while (pChildWindow) { pChildWindow->GetWindowRect(crWindowRect); ::MapWindowPoints(NULL, pControlGroupboxArea->GetSafeHwnd(), (LPPOINT) (LPRECT)crWindowRect, 2); // pControlGroupboxArea->InvalidateRect(crWindowRect, TRUE); // pChildWindow->InvalidateRect(NULL, TRUE); crWindowRect.OffsetRect(0, nMoveAmount); // pControlGroupboxArea->InvalidateRect(crWindowRect, TRUE); pChildWindow->SetWindowPos(NULL, crWindowRect.left, crWindowRect.top, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSIZE | SWP_NOZORDER ); // pChildWindow->InvalidateRect(NULL, TRUE); pChildWindow = pChildWindow->GetWindow(GW_HWNDNEXT); } /* pControlGroupboxArea->ScrollWindow(0, m_nScrollIncrementVert * (m_nCurScrollPosVert - nCurPos), NULL, NULL); */ CDialog::OnVScroll(nSBCode, nPos, pScrollBar); CRect crGroupboxRect; pControlGroupboxArea->GetWindowRect(crGroupboxRect); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crGroupboxRect, 2); // InvalidateRect(crGroupboxRect, TRUE); crGroupboxRect.OffsetRect(-crGroupboxRect.left, -crGroupboxRect.top); // pControlGroupboxArea->InvalidateRect(crGroupboxRect, TRUE); pControlGroupboxArea->InvalidateRect(NULL, TRUE); pControlGroupboxArea->UpdateWindow(); // UpdateWindow(); } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { int nCurPos = m_nCurScrollPosHorz; switch(nSBCode) { case SB_BOTTOM: m_nCurScrollPosHorz = m_paPropertiesToEdit->nCount - m_nMaxVisibleVert + 2; break; case SB_ENDSCROLL: m_nCurScrollPosHorz = pScrollBar->GetScrollPos(); break; case SB_LINEDOWN: m_nCurScrollPosHorz ++; break; case SB_LINEUP: m_nCurScrollPosHorz --; break; case SB_PAGEDOWN: m_nCurScrollPosHorz += m_nMaxVisibleHorz; break; case SB_PAGEUP: m_nCurScrollPosHorz -= m_nMaxVisibleHorz; break; case SB_THUMBPOSITION: m_nCurScrollPosHorz = nPos; break; case SB_THUMBTRACK: m_nCurScrollPosHorz = nPos; break; case SB_TOP: m_nCurScrollPosHorz = 0; break; } m_nCurScrollPosHorz = max(0, m_nCurScrollPosHorz); m_nCurScrollPosHorz = min(m_nCurScrollPosHorz, m_paPropertiesToEdit->nCount - m_nMaxVisibleHorz + 2); pScrollBar->SetScrollPos(m_nCurScrollPosHorz, TRUE); CWnd * pControlGroupboxArea = GetDescendantWindow(IDC_DOP_PROPERTIES); int nMoveAmount = m_nScrollIncrementHorz * (nCurPos - m_nCurScrollPosHorz); CRect crDisplayableArea; pControlGroupboxArea->GetClientRect(crDisplayableArea); CRect crWindowRect; CWnd * pControlValuePlaceHolder = GetDescendantWindow(IDC_VARIABLE_PRESENT_PLACEHOLDER, FALSE); pControlValuePlaceHolder->GetWindowRect(crWindowRect); // // Set the displayable area to the left of the first "present" check box // ::MapWindowPoints(NULL, pControlGroupboxArea->GetSafeHwnd(), (LPPOINT) (LPRECT)crWindowRect, 2); crDisplayableArea.left = crWindowRect.left - 1; CWnd * pChildWindow = pControlGroupboxArea->GetWindow(GW_CHILD); while (pChildWindow) { if (IsHorizontallyScrollable(pChildWindow)) { pChildWindow->GetWindowRect(crWindowRect); ::MapWindowPoints(NULL, pControlGroupboxArea->GetSafeHwnd(), (LPPOINT) (LPRECT)crWindowRect, 2); crWindowRect.OffsetRect(nMoveAmount, 0); pChildWindow->SetWindowPos(NULL, crWindowRect.left, crWindowRect.top, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSIZE | SWP_NOZORDER ); pChildWindow->ShowWindow(IsRectTotallyWithinHorizontally(crWindowRect, crDisplayableArea) ? SW_SHOW : SW_HIDE); } pChildWindow = pChildWindow->GetWindow(GW_HWNDNEXT); } // // Scroll the text headers and property edit windows at the top. // int nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * 1; for (int nCurrProperty = 0; nCurrProperty < m_paPropertiesToEdit->nCount; nCurrProperty++) { for (int nCurControl = 1; nCurControl < 4; nCurControl++) { for (int nRowMultiplier = 0; nRowMultiplier < 2; nRowMultiplier ++) { pChildWindow = GetDescendantWindow(nCurrID + nCurrProperty * 4 + nCurControl + (((m_paPropertiesToEdit->nCount * 4) + 1) * nRowMultiplier), FALSE); if (pChildWindow) { if (IsHorizontallyScrollable(pChildWindow)) { CRect crTestRect; pChildWindow->GetWindowRect(crWindowRect); crTestRect = crWindowRect;// can't actually move this window relative to a non-parent window ::MapWindowPoints(NULL, pControlGroupboxArea->GetSafeHwnd(), (LPPOINT) (LPRECT)crTestRect, 2); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crWindowRect, 2); InvalidateRect(crWindowRect, TRUE); crWindowRect.OffsetRect(nMoveAmount, 0); InvalidateRect(crWindowRect, TRUE); crTestRect.OffsetRect(nMoveAmount, 0); pChildWindow->SetWindowPos(NULL, crWindowRect.left, crWindowRect.top, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSIZE | SWP_NOZORDER ); pChildWindow->ShowWindow(IsRectTotallyWithinHorizontally(crWindowRect, crDisplayableArea) ? SW_SHOW : SW_HIDE); } } } } } CDialog::OnVScroll(nSBCode, nPos, pScrollBar); CRect crGroupboxRect; pControlGroupboxArea->GetWindowRect(crGroupboxRect); ::MapWindowPoints(NULL, GetSafeHwnd(), (LPPOINT) (LPRECT)crGroupboxRect, 2); crGroupboxRect.OffsetRect(-crGroupboxRect.left, -crGroupboxRect.top); pControlGroupboxArea->InvalidateRect(NULL, TRUE); pControlGroupboxArea->UpdateWindow(); } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::IsRectTotallyWithinHorizontally(LPRECT pRectToTest, LPRECT pOuterRect) // used for scrolling { // we are going to clip the rectangles to a rectangle bordering the first present box on the left, and the // client area of the static control for the other three sides // they intersect so lets see if the one rect is totally contained if ((min(pRectToTest->left, pOuterRect->left) == pOuterRect->left) && (max(pRectToTest->right, pOuterRect->right) == pOuterRect->right)) { return TRUE; } return FALSE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::IsHorizontallyScrollable(CWnd * pChildWindow) { int nID = pChildWindow->GetDlgCtrlID(); // // Don't move the name of the object // if (nID == IDC_STATIC) return FALSE; // // If the id is an even multiplier of 4 off of the base then it is a present control // int nFirstButton = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * 1; int nRowThisButtonWouldBeOn = (nID - nFirstButton) / ((m_paPropertiesToEdit->nCount * 4) + 1); if (nID < nFirstButton) return FALSE; if (nID > IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * (m_pObjectList->nObjectCount+3)) return FALSE; // // Don't move the apply button either // The apply button cheats and would actually be told it's one row below the current one by the math above nRowThisButtonWouldBeOn--; int nFirstButtonOnThisRow = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * (nRowThisButtonWouldBeOn+3); if ( nID == (nFirstButtonOnThisRow - 1)) return FALSE; return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::OnEraseBkgnd( CDC* pDC ) { return CDialog::OnEraseBkgnd(pDC); } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { if (IsCreatedControl(wParam)) { // // // OnNotifyCreatedControl(wParam, lParam, pResult); } return CDialog::OnNotify(wParam, lParam, pResult); } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::IsCreatedControl(int uID) { int nMinControl = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (2) ); return (uID >= nMinControl && uID <= m_nLastControlID); } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::OnNotifyCreatedControl(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { if (IsCreatedPresentButton(wParam)) { // // Figure out the correct items to enable/disable // for (int i = wParam + 1; i < wParam + 4; i++) { CButton * pButton = (CButton *)GetDescendantWindow(i, FALSE); BOOL fChecked = pButton->GetCheck() == 1; CWnd * pWnd = GetDescendantWindow(i, FALSE); if (pButton && pWnd) { pWnd->EnableWindow(fChecked); } } } return TRUE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::IsCreatedPresentButton(int uID) { // // If the id is an even multiplier of 4 off of the base then it is a present control // int nFirstButton = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * 2; int nRowThisButtonWouldBeOn = (uID - nFirstButton) / ((m_paPropertiesToEdit->nCount * 4) + 1); int nFirstButtonOnThisRow = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * (nRowThisButtonWouldBeOn+3); if ( ((uID - nFirstButtonOnThisRow) % 4 ) == 0) return TRUE; return FALSE; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::OnCommand(WPARAM wParam, LPARAM lParam) { if (IsCreatedControl(LOWORD(wParam))) { // // // OnCommandCreatedControl(wParam, lParam); } return CDialog::OnCommand(wParam, lParam); } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::OnCommandCreatedControl(WPARAM wParam, LPARAM lParam) { if (IsCreatedPresentButton(LOWORD(wParam)) && HIWORD(wParam) == BN_CLICKED) { // // Figure out the correct items to enable/disable // CButton * pButton = (CButton *)GetDescendantWindow(LOWORD(wParam), FALSE); if (pButton) { BOOL fChecked = pButton->GetCheck() == 1; for (int i = LOWORD(wParam) + 1; i < LOWORD(wParam) + 4; i++) { CWnd * pWnd = GetDescendantWindow(i, FALSE); if (pWnd) { pWnd->EnableWindow(fChecked); } } } } else if (IsCreatedApplyButton(LOWORD(wParam)) && HIWORD(wParam) == BN_CLICKED) { // // Get the state we should set the apply all button to // int nStateForAllButton = GetStateForApplyAllButton(); CButton * pButton = (CButton *) GetDescendantWindow(IDC_CHECKALL_APPLY_BUTTONS, FALSE); if (pButton) { pButton->SetCheck(nStateForAllButton); } } return TRUE; } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::OnFillAllValues() { // // Run through the row of values and copy the first element into all the rest // // All of our current uses for this dialog use floats or vector3d's so I currently // don't worry about having ints/bools/strings in the row // float flt[3] = {0.0f, 0.0f, 0.0f}; // // Scroll the text headers and property edit windows at the top. // int nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * 1; int nCurrProperty = 0; // has to start at 0 to get our fill values int nCurControl; for (nCurControl = 1; nCurControl < 4; nCurControl++) { if (!GetfloatFromControl(nCurrID + nCurrProperty * 4 + nCurControl, &(flt[nCurControl -1]))) { flt[nCurControl - 1] = 0.0f; } } // // Start loop at one since we got the data from the first one. // for (nCurrProperty = 1; nCurrProperty < m_paPropertiesToEdit->nCount; nCurrProperty++) { for (nCurControl = 1; nCurControl < 4; nCurControl++) { if (!SetfloatToControl(nCurrID + nCurrProperty * 4 + nCurControl, flt[nCurControl -1])) { flt[nCurControl - 1] = 0.0f; } } } } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::OnCheckallApplyButtons() { // // If our current state is off, turn all buttons on including this one // If our current state is on, turn all buttons off including this one // If our current state is other, turn all buttons off including this one // // This button state must be updated whenever any of the apply buttons are checked. CButton * pButton = (CButton *) GetDescendantWindow(IDC_CHECKALL_APPLY_BUTTONS, FALSE); if (pButton) { int nStateOfCheck = pButton->GetCheck(); if (nStateOfCheck == 2) // don't act it's not set to anything in particular { return; } SetAllApplyButtons(nStateOfCheck); } } //**************************************************************************************** // //**************************************************************************************** int CDlgObjectBalance::GetStateForApplyAllButton() { // Iterate through all the apply buttons // Then if we have two that don't match we can return indeterminate. Otherwise we return the state // of the buttons int nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (3) ); CButton * pButton = NULL; pButton = (CButton * ) GetDescendantWindow(nCurrID - 1); if (!pButton) { return 2; } int nButtonStates = pButton->GetCheck(); // start at 1 since we already got one for (int nCurrentObject = 1; nCurrentObject < m_pObjectList->nObjectCount; nCurrentObject++) { nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrentObject + 3) ); pButton = (CButton * ) GetDescendantWindow(nCurrID - 1); if (!pButton) { return 2; } if (pButton->IsWindowEnabled()) { if (pButton->GetCheck() != nButtonStates) // something isn't the same { return 2; } } } return nButtonStates; } //**************************************************************************************** // //**************************************************************************************** void CDlgObjectBalance::SetAllApplyButtons(int nState) { // Iterate through all the apply buttons // Then if we have two that don't match we can return indeterminate. Otherwise we return the state // of the buttons CButton * pButton = NULL; int nCurrID = IDC_STATIC; for (int nCurrentObject = 0; nCurrentObject < m_pObjectList->nObjectCount; nCurrentObject++) { nCurrID = IDC_VARIABLE_PRESENT_PLACEHOLDER + (((m_paPropertiesToEdit->nCount * 4) + 1) * (nCurrentObject + 3) ); pButton = (CButton * ) GetDescendantWindow(nCurrID - 1); if (!pButton) { continue; // shouldn't really hit this though } if (pButton->IsWindowEnabled()) pButton->SetCheck(nState); } return; } //**************************************************************************************** // //**************************************************************************************** BOOL CDlgObjectBalance::IsCreatedApplyButton(int uID) { // // If the id is an even multiplier of 4 off of the base then it is a present control // int nFirstButton = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * 2; int nRowThisButtonWouldBeOn = (uID - nFirstButton) / ((m_paPropertiesToEdit->nCount * 4) + 1); // // The apply button actually resides on the row below this one, so these calculations are one off // nRowThisButtonWouldBeOn ++; int nFirstButtonOnThisRow = IDC_VARIABLE_PRESENT_PLACEHOLDER + ((m_paPropertiesToEdit->nCount * 4) + 1) * (nRowThisButtonWouldBeOn+3); if ( uID == (nFirstButtonOnThisRow - 1)) return TRUE; return FALSE; }