//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1999 // // File: tracedlg.cpp // // Contents: Implementation of the debug trace code // // History: 15-Jul-99 VivekJ Created // //-------------------------------------------------------------------------- #include "stdafx.h" #include "resource.h" #include "tracedlg.h" #ifdef DBG //############################################################################ //############################################################################ // // Implementation of class CTraceDialog // //############################################################################ //############################################################################ /*+-------------------------------------------------------------------------* * * CTraceDialog::RecalcCheckboxes * * PURPOSE: Recomputes the settings of the check boxes. This is in response to * a trace tag selection change. * * RETURNS: * void * *+-------------------------------------------------------------------------*/ void CTraceDialog::RecalcCheckboxes() { DWORD dwMask = TRACE_ALL; //initialize with all ones bool bAtLeastOneItem = false; int iItem = m_listCtrl.GetNextItem(-1, LVNI_SELECTED); while(iItem != -1) { CTraceTag *pTag = reinterpret_cast(m_listCtrl.GetItemData(iItem)); ASSERT(pTag != NULL); if(pTag == NULL) return; bAtLeastOneItem = true; dwMask &= pTag->GetFlag(TRACE_ALL); // AND all the selected item's bits. iItem = m_listCtrl.GetNextItem(iItem, LVNI_SELECTED); } // disable the checkbox if no item selected. ::EnableWindow(GetDlgItem(IDC_TRACE_TO_COM2), bAtLeastOneItem); ::EnableWindow(GetDlgItem(IDC_TRACE_OUTPUTDEBUGSTRING),bAtLeastOneItem); ::EnableWindow(GetDlgItem(IDC_TRACE_TO_FILE), bAtLeastOneItem); ::EnableWindow(GetDlgItem(IDC_TRACE_DEBUG_BREAK), bAtLeastOneItem); ::EnableWindow(GetDlgItem(IDC_TRACE_DUMP_STACK), bAtLeastOneItem); if(!bAtLeastOneItem) return; CheckDlgButton(IDC_TRACE_TO_COM2, dwMask & TRACE_COM2 ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(IDC_TRACE_OUTPUTDEBUGSTRING, dwMask & TRACE_OUTPUTDEBUGSTRING ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(IDC_TRACE_TO_FILE, dwMask & TRACE_FILE ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(IDC_TRACE_DEBUG_BREAK, dwMask & TRACE_DEBUG_BREAK ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(IDC_TRACE_DUMP_STACK, dwMask & TRACE_DUMP_STACK ? BST_CHECKED : BST_UNCHECKED); } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnSelChanged * * PURPOSE: Handles a selection change notification. * * PARAMETERS: * int idCtrl : * LPNMHDR pnmh : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnSelChanged(int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) { RecalcCheckboxes(); return 0; } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnColumnClick * * PURPOSE: Handles the column click notification - causes a sort by the * specified column. * * PARAMETERS: * int idCtrl : * LPNMHDR pnmh : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnColumnClick(int idCtrl, LPNMHDR pnmh, BOOL& bHandled ) { NM_LISTVIEW *pnmlv = (NM_LISTVIEW *) pnmh; m_dwSortData = pnmlv->iSubItem; // iSubItem is the column clicked on. Cache this value for later DoSort(); return 0; } /*+-------------------------------------------------------------------------* * * CTraceDialog::SetMaskFromCheckbox * * PURPOSE: Sets the trace tag flag from the state of the specified check box. * * PARAMETERS: * UINT idControl : The check box control * DWORD dwMask : The bit(s) to enable/disable depending on the state * of the control. * * RETURNS: * void * *+-------------------------------------------------------------------------*/ void CTraceDialog::SetMaskFromCheckbox(UINT idControl, DWORD dwMask) { bool bEnabled = IsDlgButtonChecked(idControl) == BST_CHECKED; int iItem = m_listCtrl.GetNextItem(-1, LVNI_SELECTED); ASSERT(iItem != -1); while(iItem != -1) { CTraceTag *pTag = reinterpret_cast(m_listCtrl.GetItemData(iItem)); ASSERT(pTag != NULL); if(pTag == NULL) return; if(bEnabled) pTag->SetFlag(dwMask); else pTag->ClearFlag(dwMask); // update the UI m_listCtrl.SetItemText(iItem, COLUMN_ENABLED, pTag->FAnyTemp() ? TEXT("X") : TEXT("")); iItem = m_listCtrl.GetNextItem(iItem, LVNI_SELECTED); } // sort the items again DoSort(); } /*+-------------------------------------------------------------------------* * * CTraceDialog::DoSort * * PURPOSE: Perform a sort of the items in the dialog * * RETURNS: * void * *+-------------------------------------------------------------------------*/ void CTraceDialog::DoSort() { m_listCtrl.SortItems(CompareItems, m_dwSortData); } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnOutputToCOM2 * * PURPOSE: Handles checking/unchecking the "output to Com2" button. * * PARAMETERS: * WORD wNotifyCode : * WORD wID : * HWND hWndCtl : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnOutputToCOM2(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { SetMaskFromCheckbox(IDC_TRACE_TO_COM2, TRACE_COM2); return 0; } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnOutputDebugString * * PURPOSE: Handles checking/unchecking the "OutputDebugString" button. * * PARAMETERS: * WORD wNotifyCode : * WORD wID : * HWND hWndCtl : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnOutputDebugString(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { SetMaskFromCheckbox(IDC_TRACE_OUTPUTDEBUGSTRING, TRACE_OUTPUTDEBUGSTRING); return 0; } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnOutputToFile * * PURPOSE: Handles checking/unchecking the "output to File" button. * * PARAMETERS: * WORD wNotifyCode : * WORD wID : * HWND hWndCtl : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnOutputToFile(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { SetMaskFromCheckbox(IDC_TRACE_TO_FILE, TRACE_FILE); return 0; } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnDebugBreak * * PURPOSE: Handles checking/unchecking the "DebugBreak" button. * * PARAMETERS: * WORD wNotifyCode : * WORD wID : * HWND hWndCtl : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnDebugBreak(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { SetMaskFromCheckbox(IDC_TRACE_DEBUG_BREAK, TRACE_DEBUG_BREAK); return 0; } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnDumpStack * * PURPOSE: Handles checking/unchecking the "Stack Dump" button. * * PARAMETERS: * WORD wNotifyCode : * WORD wID : * HWND hWndCtl : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnDumpStack(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { SetMaskFromCheckbox(IDC_TRACE_DUMP_STACK, TRACE_DUMP_STACK); return 0; } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnRestoreDefaults * * PURPOSE: Restores the default (canned) settings of all trace tags. * * PARAMETERS: * WORD wNotifyCode : * WORD wID : * HWND hWndCtl : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnRestoreDefaults(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { CTraceTags::iterator iter; CTraceTags * pTraceTags = GetTraceTags(); if(NULL == pTraceTags) goto Error; for(iter = pTraceTags->begin(); iter != pTraceTags->end(); iter++) { (*iter)->RestoreDefaults(); } RecalcCheckboxes(); Cleanup: return 0; Error: goto Cleanup; } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnSelectAll * * PURPOSE: Selects all trace tags. * * PARAMETERS: * WORD wNotifyCode : * WORD wID : * HWND hWndCtl : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnSelectAll(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { int cItems = m_listCtrl.GetItemCount(); for(int i=0; i< cItems; i++) { m_listCtrl.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); } RecalcCheckboxes(); return 0; } /*+-------------------------------------------------------------------------* * * CTraceDialog::CompareItems * * PURPOSE: The callback routine to compare two items in the list control. * * PARAMETERS: * LPARAM lp1 : * LPARAM lp2 : * LPARAM lpSortData : * * RETURNS: * int CALLBACK * *+-------------------------------------------------------------------------*/ int CALLBACK CTraceDialog::CompareItems(LPARAM lp1, LPARAM lp2, LPARAM lpSortData) { CTraceTag *pTag1 = reinterpret_cast(lp1); CTraceTag *pTag2 = reinterpret_cast(lp2); if(!pTag1 && !pTag2) { ASSERT(0 && "Should not come here."); return 0; } switch(lpSortData) { default: ASSERT(0 && "Should not come here."); return 0; case COLUMN_CATEGORY: return _tcscmp(pTag1->GetCategory(), pTag2->GetCategory()); break; case COLUMN_NAME: return _tcscmp(pTag1->GetName(), pTag2->GetName()); break; case COLUMN_ENABLED: { BOOL b1 = (pTag1->FAnyTemp()) ? 0 : 1; BOOL b2 = (pTag2->FAnyTemp()) ? 0 : 1; return b1 - b2; } break; } } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnInitDialog * * PURPOSE: Initializes the dialog - adds columns, sets the file name * and inserts all rows. * * PARAMETERS: * UINT uMsg : * WPARAM wParam : * LPARAM lParam : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { m_listCtrl.Attach(GetDlgItem(IDC_TRACE_LIST)); m_editStackLevels.Attach(GetDlgItem(IDC_TRACE_STACKLEVELS)); m_editStackLevels.LimitText(1); // one character only. // insert the columns - no need to localize since debug only. m_listCtrl.InsertColumn(COLUMN_CATEGORY, TEXT("Category") ,LVCFMT_LEFT, 150, 0); m_listCtrl.InsertColumn(COLUMN_NAME, TEXT("Name" ) ,LVCFMT_LEFT, 150, 0); m_listCtrl.InsertColumn(COLUMN_ENABLED, TEXT("Enabled" ) ,LVCFMT_LEFT, 80, 0); // set the full row select style. m_listCtrl.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); m_listCtrl.SortItems(CompareItems, COLUMN_CATEGORY); // the default sort. // Set the file name. SetDlgItemText(IDC_TRACE_FILENAME, CTraceTag::GetFilename()); //Set the stack level SetDlgItemInt(IDC_TRACE_STACKLEVELS, CTraceTag::GetStackLevels()); CTraceTags * pTraceTags = GetTraceTags(); if(NULL == pTraceTags) return 0; int i = 0; for(CTraceTags::iterator iter = pTraceTags->begin(); iter != pTraceTags->end(); iter++, i++) { int iItem = m_listCtrl.InsertItem(LVIF_PARAM | LVIF_TEXT, i, (*iter)->GetCategory(), 0, 0, 0, (LPARAM) (*iter)); m_listCtrl.SetItemText(iItem, COLUMN_NAME, (*iter)->GetName()); m_listCtrl.SetItemText(iItem, COLUMN_ENABLED, (*iter)->FAny() ? TEXT("X") : TEXT("")); // set up the tag for a temporary change. (*iter)->SetTempState(); } RecalcCheckboxes(); return 0; } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnCancel * * PURPOSE: Handles the Cancel button. Exits without committing changes. * * PARAMETERS: * WORD wNotifyCode : * WORD wID : * HWND hWndCtl : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { m_listCtrl.Detach(); EndDialog (false); return 0; } /*+-------------------------------------------------------------------------* * * CTraceDialog::OnOK * * PURPOSE: Exits and commits changes. * * PARAMETERS: * WORD wNotifyCode : * WORD wID : * HWND hWndCtl : * BOOL& bHandled : * * RETURNS: * LRESULT * *+-------------------------------------------------------------------------*/ LRESULT CTraceDialog::OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { // Set the file name from the edit control TCHAR szFilename[OFS_MAXPATHNAME]; GetDlgItemText(IDC_TRACE_FILENAME, (LPTSTR)szFilename, OFS_MAXPATHNAME); CTraceTag::GetFilename() = szFilename; // Set the stack levels TCHAR szStackLevels[2]; GetDlgItemText(IDC_TRACE_STACKLEVELS, (LPTSTR)szStackLevels, 2); int nLevels = szStackLevels[0] - TEXT('0'); // convert to integer. CTraceTag::GetStackLevels() = nLevels; CTraceTags::iterator iter; CTraceTags * pTraceTags = GetTraceTags(); if(NULL == pTraceTags) goto Error; // save all the trace tags out to the .ini file for(iter = pTraceTags->begin(); iter != pTraceTags->end(); iter++) { CStr str; CTraceTag *pTag = *iter; if(!pTag) goto Error; pTag->Commit(); // write out the trace tag ONLY if the setting is not the same as the default. Avoids clutter. str.Format(TEXT("%d"), pTag->GetAll()); ::WritePrivateProfileString(pTag->GetCategory(), pTag->GetName(), (LPCTSTR)str, szTraceIniFile); } m_listCtrl.Detach(); // write out the values into the ini file. ::WritePrivateProfileString(TEXT("Trace File"), TEXT("Trace File"), (LPCTSTR)szFilename, szTraceIniFile); ::WritePrivateProfileString(TEXT("Stack Levels"), TEXT("Stack Levels"), (LPCTSTR)szStackLevels, szTraceIniFile); Cleanup: EndDialog (true); return 1; Error: goto Cleanup; } /*+-------------------------------------------------------------------------* * * DoDebugTraceDialog * * PURPOSE: Exported routine (DEBUG build only) to bring up the trace dialog. * * RETURNS: * MMCBASE_API void * *+-------------------------------------------------------------------------*/ MMCBASE_API void DoDebugTraceDialog() { CTraceDialog dlg; dlg.DoModal(); } #endif // DBG