/***********************************************************************/ /* Copyright (C) 2002 Definitive Solutions, Inc. All Rights Reserved. */ /* THIS COMPUTER PROGRAM IS PROPRIETARY AND CONFIDENTIAL TO DEFINITIVE */ /* SOLUTIONS, INC. AND ITS LICENSORS AND CONTAINS TRADE SECRETS OF */ /* DEFINITIVE SOLUTIONS, INC. THAT ARE PROVIDED PURSUANT TO A WRITTEN */ /* AGREEMENT CONTAINING RESTRICTIONS ON USE AND DISCLOSURE. ANY USE, */ /* REPRODUCTION, OR TRANSFER EXCEPT AS PROVIDED IN SUCH AGREEMENT */ /* IS STRICTLY PROHIBITED. */ /***********************************************************************/ ///////////////////////////////////////////////////////////////////////////// // How to add this class to your application. // // Add MyLog.cpp, MyLog.h, MyLogResource.h, and MyLog.rc2 to your project in // the usual folders. // // Add this line to the top of your RC2 file: // #include "MyLogResource.h" // MyLog resources. // // Add this line to the end of your RC2 file: // #include "MyLog.rc2" // MyLog resources. // // Optionally, add these lines to your menu resource in your RC file (the // #defines for these items can't be included in the RC file, because the // "MyLogResource.h" file cannot be included in the RC file. So, we just use // the literal values: // MENUITEM SEPARATOR // MENUITEM "&Enable Logging...", 10000 // MENUITEM "&View Log...", 10001 // MENUITEM SEPARATOR // // Optionally, and by hand, map a method in CMainFrame for one or both of // these menu items: // /* // FOR THE HEADER FILE - MUST NOT BE INSIDE THE WIZARD "AFX_MSG" AREA! // MyLog commands. afx_msg void OnEnablelogging(); afx_msg void OnViewlog(); // FOR THE CPP FILE #include "MyLogResource.h" #include "Generic.h" #include "MyApp.h" // MyLog commands. ON_COMMAND(ID_ENABLELOGGING, OnEnablelogging) ON_COMMAND(ID_VIEWLOG, OnViewlog) // ID_ENABLE_LOGGING void CMainFrame::OnEnablelogging() { VALIDATE; static_cast (AfxGetApp())->TheLog.EnableLoggingDlg(this, / * sRegPlacementsKey * / CString("Software\\YourCompanyName\\") + AfxGetAppName() + "\\Placements"); } // ID_VIEWLOG. void CMainFrame::OnViewlog() { VALIDATE; static_cast (AfxGetApp())->TheLog.ViewLog(); } */ // Optionally, add these lines to the top of InitInstance(): // // // Logging is always enabled for this application. // TheLog.SetLevel(MyLog::Warns); // DEBUG_ONLY(TheLog.SetLevel(MyLog::Trace)); // // Add, if needed, the MyApp, MyRegistry, MyButton, MyStatic, MyDialog, and // Generic classes to the project. Be sure to check each of these classes' // *.H file for instructions on how to include them in your project. // // In your app object's constructor, add the following initializer: // // : MyApp("_"YOUR_APP_NAME_HERE".log") // // Note that you can send the log file argument in two formats: // // // Creates the log in the current directory. // : MyApp("_YourApp.log") // // // Creates log at specific path. // : MyApp("\\Network\DirOne\DirTwo\DirN\YourApp.log") // ///////////////////////////////////////////////////////////////////////////// #ifndef MYLOGH_2B77F211_2C61_11d6_8ACD_00B0D0529ED2_INCLUDEDH_ #define MYLOGH_2B77F211_2C61_11d6_8ACD_00B0D0529ED2_INCLUDEDH_ #pragma once #ifndef _FSTREAM_ #include using namespace std; #endif #include "MyDialog.h" #include "MyButton.h" #include "MyStatic.h" ///////////////////////////////////////////////////////////////////////////// // String table defines - see MyLog.rc2 #include "MyLogResource.h" ///////////////////////////////////////////////////////////////////////////// // Macros - Here is how you log messages. // // A word on levels, which are in order of severity: Audit, Error, // Warns, Trace, and Debug. // // Load the format from the string table; logs at "Error" level. // Call like this: DOMYLOGST(API_FAILURE), "Zeke()", nRC, "Error Message"); #define DOMYLOGST(uiStringTableId) \ ((MyApp*) AfxGetApp())->TheLog.Header(__FILE__, __LINE__, \ MyLog::Error); \ CString sFormatString; \ \ if (! sFormatString.LoadString(uiStringTableId)) { \ _ASSERTE(! "LoadString() failed in DOMYLOGST!"); \ sFormatString = "LoadString() failed in DOMYLOGST!"; \ } \ \ ((MyApp*) AfxGetApp())->TheLog.Log(sFormatString + "\n" // Log at Audit level: DOMYLOGA ("This is test %d: %s\n", 328, "Zoë!"); #define DOMYLOGA ((MyApp*) AfxGetApp())->TheLog.Header(__FILE__, __LINE__, MyLog::Audit); \ ((MyApp*) AfxGetApp())->TheLog.Log // Log at Error level: DOMYLOGE ("This is test %d: %s\n", 328, "Zeke!"); #define DOMYLOGE ((MyApp*) AfxGetApp())->TheLog.Header(__FILE__, __LINE__, MyLog::Error); \ ((MyApp*) AfxGetApp())->TheLog.Log // Log at Warns level: DOMYLOGW ("This is test %d: %s\n", 328, "Zoë!"); #define DOMYLOGW ((MyApp*) AfxGetApp())->TheLog.Header(__FILE__, __LINE__, MyLog::Warns); \ ((MyApp*) AfxGetApp())->TheLog.Log // Log at Trace level: DOMYLOGT ("This is test %d: %s\n", 328, "Zeke!"); #define DOMYLOGT ((MyApp*) AfxGetApp())->TheLog.Header(__FILE__, __LINE__, MyLog::Trace); \ ((MyApp*) AfxGetApp())->TheLog.Log // Log at Debug level: DOMYLOGD ("This is test %d: %s\n", 328, "Zoë!"); #define DOMYLOGD ((MyApp*) AfxGetApp())->TheLog.Header(__FILE__, __LINE__, MyLog::Debug); \ ((MyApp*) AfxGetApp())->TheLog.Log // This macro is deprecated and should no longer be used. Use the "DOMYLOGx" // family of macros instead. This macro has been changed to emit Audit level. // // This macro just makes for less typing. If you need finer control, you can // still call the methods manually, but usually you would use this. (Note the // clever use of a space to allow this macro to take variable arguments.) // // Call like this: DOMYLOG ("This is test %d: %s\n", 328, "Zoë!"); // // DO NOT USE - PROVIDED FOR BACKWARD COMPABILITY ONLY! #define DOMYLOG ((MyApp*) AfxGetApp())->TheLog.Header(__FILE__, __LINE__, MyLog::Audit); \ ((MyApp*) AfxGetApp())->TheLog.Log // Easy way to get the last logged message. #define MYLOGLAST ((MyApp*) AfxGetApp())->TheLog.GetLastOutput() ///////////////////////////////////////////////////////////////////////////// // MyLog // Declare the class depending on this file is in an EXE project or a DLL one. class #ifdef _WINDLL AFX_EXT_CLASS #endif MyLog { // Construction. public: MyLog(const TCHAR* pszFileName); virtual ~MyLog(); enum Level { Debug = 0, Trace, Warns, Error, Audit, Nolog }; // Operations. public: void Header(const CString& sFile, int nLine, Level eLevel); void Log(const TCHAR* pszFormatString, ...); MyLog& operator <<(int nVal); MyLog& operator <<(long lVal); MyLog& operator <<(unsigned int unVal); MyLog& operator <<(unsigned long ulVal); MyLog& operator <<(double dVal); MyLog& operator <<(const TCHAR* psz); MyLog& operator <<(TCHAR tch); CString GetLastOutput(); void SetLevel(Level eLevel); bool IsEnabled() const; void SetBaseDirectory(const CString& sDir); void SetStatusBarHwnd(HWND hwndStatusBar); void ViewLog() const; CString GetLogPath() const; Level EnableLoggingDlg(CWnd* pwndParent, const CString& sRegPlacementsKey); // Implementation. protected: void PrintCurTimeAndLevel(bool bTrace = true); void Output(const TCHAR* pszData, bool bTrace = true); // Data. protected: CString m_sPath; // The pathname of the log file. ofstream* m_pOutFile; // The file object. CString m_sLastOutput; // Most recent string output. CString m_sBaseDirectory; // The folder others descend from. HWND m_hwndStatusBar; // MainFrame's status bar. Level m_eLevelApp; // Application's logging level. Level m_eLevelCurrent; // Current message's logging level. }; ///////////////////////////////////////////////////////////////////////////// // MyLogDlg dialog - the dialog that lets the user set the logging level. // Declare the class depending on this file is in an EXE project or a DLL one. class #ifdef _WINDLL AFX_EXT_CLASS #endif MyLogDlg : public MyDialog { friend class MyLog; // Construction. public: MyLogDlg(CWnd* pParent, const CString& sRegPlacementsKey); //{{AFX_DATA(MyLogDlg) enum { IDD = IDD_MYLOG }; MyButton m_buttonOk; MyButton m_buttonCancel; MyStatic m_staticWarns; MyStatic m_staticTrace; MyStatic m_staticNolog; MyStatic m_staticError; MyStatic m_staticDebug; MyStatic m_staticAudit; CSliderCtrl m_slider; MyStatic m_staticDesc; //}}AFX_DATA //{{AFX_VIRTUAL(MyLogDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); //}}AFX_VIRTUAL // Implementation. protected: void UpdateLabels(); //{{AFX_MSG(MyLogDlg) virtual BOOL OnInitDialog(); afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); //}}AFX_MSG virtual void OnOK(); DECLARE_MESSAGE_MAP() // Data. private: MyLog::Level m_eLevel; // Level selected by user. }; #endif // MYLOGH_2B77F211_2C61_11d6_8ACD_00B0D0529ED2_INCLUDEDH_