www.gusucode.com > 一个VC++ GUI测试程序-源码程序 > 一个VC++ GUI测试程序-源码程序/code/OutputWnd.cpp
//Download by http://www.NewXing.com /* Output Window v1.0 ------------------ (C) 1998/99 Ben Ashley Distribution : You are free to use this code in any program, commercial or otherwise, providing credit is given. Modification : You are also free to modify this code to suit your needs providing credit is still given to the original code, and all changes are documented. You might also consider re-submitting it complete with modifications to http://www.codeguru.com, share your talent with others!! */ #include "stdafx.h" // Precompiled Header #include "OutputWnd.h" // class TOutputWnd #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /* ================================================================= TOutputWnd::TOutputWnd() TOutputWnd::~TOutputWnd() ------------------------- ================================================================= */ TOutputWnd::TOutputWnd() { TRACE0( "CONSTRUCTOR : TOutputWnd()\n" ); m_pFont = NULL; m_BackCol = GetSysColor( COLOR_WINDOW ); m_nHead = -1; m_nLinesDone = 0; m_nDefTextCol = COLOUR_BLACK; m_bWordWrap = true; m_nXOffset = 0; m_nMaxLines = 500; // Maximum of 500 entries ( default ) m_nMaxWidth = 0; // Greatest width done m_nFontHeight = 0; // No Font Height // Temporary... m_ColTable[ COLOUR_WHITE ] = RGB( 255, 255, 255 ); m_ColTable[ COLOUR_BLACK ] = RGB( 0, 0, 0 ); m_ColTable[ COLOUR_BLUE ] = RGB( 0, 0, 128 ); m_ColTable[ COLOUR_GREEN ] = RGB( 0, 128, 0 ); m_ColTable[ COLOUR_LIGHTRED ] = RGB( 255, 0, 0 ); m_ColTable[ COLOUR_BROWN ] = RGB( 128, 0, 0 ); m_ColTable[ COLOUR_PURPLE ] = RGB( 128, 0, 128 ); m_ColTable[ COLOUR_ORANGE ] = RGB( 128, 128, 0 ); m_ColTable[ COLOUR_YELLOW ] = RGB( 255, 255, 0 ); m_ColTable[ COLOUR_LIGHTGREEN ] = RGB( 0, 255, 0 ); m_ColTable[ COLOUR_CYAN ] = RGB( 0, 128, 128 ); m_ColTable[ COLOUR_LIGHTCYAN ] = RGB( 0, 255, 255 ); m_ColTable[ COLOUR_LIGHTBLUE ] = RGB( 0, 0, 255 ); m_ColTable[ COLOUR_PINK ] = RGB( 255, 0, 255 ); m_ColTable[ COLOUR_GREY ] = RGB( 128, 128, 128 ); m_ColTable[ COLOUR_LIGHTGREY ] = RGB( 192, 192, 192 ); // ------------------------------------------------------------- // Load the Cursor: // ------------------------------------------------------------- m_hCursor = AfxGetApp()->LoadStandardCursor( IDC_IBEAM ); } TOutputWnd::~TOutputWnd() { TRACE0( "DESTRUCTOR : ~TOutputWnd()\n" ); // Destroy the font we were using: if( m_pFont != NULL ) delete( m_pFont ); } /* ================================================================================= void TOutputWnd::UpdateHScroll() void TOutputWnd::UpdateVScroll() -------------------------------- Updates scroll-bar information. ================================================================================= */ void TOutputWnd::UpdateHScroll() { if( m_bWordWrap ) return; // No need for word-wrapped output windows CRect clientRc; GetClientRect( &clientRc ); int nMax = m_nMaxWidth - clientRc.Width(); if( nMax <= 0 ) m_nXOffset = 0; SetScrollRange( SB_HORZ, 0, nMax ); //SCROLLINFO si; //si.fMask = SIF_PAGE; //si.nPage = m_nAvgCharWidth; //SetScrollInfo( SB_HORZ, &si ); }; void TOutputWnd::UpdateVScroll() { SetScrollRange( SB_VERT, 0, GetLineCount() - 1 ); //SCROLLINFO si; //si.fMask = SIF_PAGE; //si.nPage = GetMaxViewableLines(); //SetScrollInfo( SB_VERT, &si ); }; /* ================================================================= void TOutputWnd::RenderSingleLine( CString&, CDC*, int&, int& ) --------------------------------------------------------------- Renders a single line at the specified position, and will handle the control codes accordingly. The line passed is expected to fit , as word-wrapping code should already have been applied. ================================================================= */ void TOutputWnd::RenderSingleLine( CString& strLine, CDC* pDC, int nX, int nY ) { CRect clientRc; GetClientRect( &clientRc ); CString strTemp = strLine; CString strToRender; SIZE sz; int nPos; UINT nWidth = 0; do { nPos = strTemp.Find( CONTROL_BYTE ); if( nPos > -1 ) { strToRender = strTemp.Left( nPos ); if( strToRender != "" ) { if( !FLAG( m_lfFont.lfPitchAndFamily, FIXED_PITCH ) ) ::GetTextExtentPoint32( pDC->GetSafeHdc(), strToRender, strToRender.GetLength(), &sz ); else sz.cx = strToRender.GetLength() * m_nAvgCharWidth; pDC->TextOut( nX, nY, strToRender ); nX += sz.cx; nWidth += sz.cx; }; COLOURCODE code; strTemp = strTemp.Mid( nPos ); GetColourCodes( strTemp, &code ); if( code.nFore != -1 ) pDC->SetTextColor( m_ColTable[ code.nFore ] ); if( code.nBack != -1 ) pDC->SetBkColor( m_ColTable[ code.nBack ] ); } else { if( !FLAG( m_lfFont.lfPitchAndFamily, FIXED_PITCH ) ) ::GetTextExtentPoint32( pDC->GetSafeHdc(), strTemp, strTemp.GetLength(), &sz ); else sz.cx = strTemp.GetLength() * m_nAvgCharWidth; nWidth += sz.cx; pDC->TextOut( nX, nY, strTemp ); nX += sz.cx; // Pad out rest of line with solid colour: CRect solidRc( nX, nY, clientRc.right, nY + m_nFontHeight ); pDC->FillSolidRect( &solidRc, m_BackCol ); break; } }while( 1 ); nY += m_nFontHeight; // ------------------------------------------------------------- // Update Horizontal scroll bar for width ( for times when the // word wrap is OFF ) // ------------------------------------------------------------- if( nWidth > m_nMaxWidth && !m_bWordWrap ) { m_nMaxWidth = nWidth; UpdateHScroll(); }; }; /* ================================================================================= int TOutputWnd::GetLineInfo( CString&, LINEINFO* ) -------------------------------------------------- Works out the bounding rectangle of a line, and fills out a LINERECT with the necessary information to render it. This function will automatically strip out control codes for the purpose of measuring. ================================================================================= */ int TOutputWnd::GetLineInfo( CString& strLine, CDC* pDC, int nRight ) { int nLines = 1; // Start of with 1 line // --------------------------------------------------------- // We can very quickly handle empty lines: // --------------------------------------------------------- if( strLine == "" ) return( nLines ); // See, I told u it was easy. // And lets do the rest properly: int nLen = strLine.GetLength(); int nOriginalLength = nLen; char* pTmp = new char[ nOriginalLength + 1 ]; char ch = 0; SIZE sz; memset( pTmp, 0, nOriginalLength ); int nCurrWidth = 0; // Width of current line int nPosInTemp = 0; // Current Position in temp buffer int nPosInString = 0; // Current Position in string int nSpc = 0; HDC hDC = pDC->GetSafeHdc();// Handle to the device context CString strLeftPart; // Left Part CString strRightPart; // Right Part int nLastWrap = -1; // Where we put the last wrap point COLOURCODE code; do { ch = strLine[ nPosInString ]; if( ch != CONTROL_BYTE ) { pTmp[ nPosInTemp ] = ch; if( !FLAG( m_lfFont.lfPitchAndFamily, FIXED_PITCH ) ) ::GetTextExtentPoint32( hDC, pTmp, nPosInTemp + 1, &sz ); else sz.cx = ( nPosInTemp + 1 ) * m_nAvgCharWidth; if( sz.cx >= nRight ) { // Find the previous space for( int nSpc = nPosInString - 1; nSpc >= 0; nSpc -- ) if( strLine[ nSpc ] == ' ' ) break; if( nSpc == 0 ) nSpc = nPosInString; if( nSpc > nLastWrap ) { strLeftPart = strLine.Left( nSpc ); strRightPart = strLine.Mid( nSpc + 1 ); strLine = strLine.Left( nSpc ); nLastWrap = nSpc; strLine += WRAP_BYTE; strLine += strRightPart; nPosInString = nSpc + 1; nLen = strLine.GetLength(); nLines++; // And another line }; memset( pTmp, 0, nOriginalLength ); nPosInTemp = 0; } else { nPosInTemp++; nPosInString++; }; } else { CString strTemp = strLine.Mid( nPosInString ); // Make temp copy. dont want to modify original nPosInString += GetColourCodes( strTemp, &code );// skips correct number of bytes }; }while( nPosInString < nLen ); delete [] pTmp; return( nLines ); }; /* ================================================================= int TOutputWnd::GetColourCodes( CString&, COLOURCODE* ) ------------------------------------------------------- Looks at the data passed ( first character must be the control byte ), and fills in the COLOURCODE structure accordingly. This function returns the number of bytes to skip. ================================================================= */ int TOutputWnd::GetColourCodes( CString& strData, COLOURCODE* pColourCode ) { ASSERT( pColourCode != NULL ); ASSERT( strData.Left( 1 ) == CONTROL_BYTE ); strData = strData.Mid( 1 ); // Truncate control byte int nBytesToSkip = 1; // Jump out of strData is now empty... if( strData == "" ) { pColourCode->nFore = -1; // No foreground colour pColourCode->nBack = -1; // No background colour } else { // Now handle foreground and background colours: int nComma = strData.Find( "," ); // Position of comma. Only present if background colour present if( ( nComma != -1 ) && ( ( nComma == 1 ) || ( nComma == 2 && isdigit( strData[ 1 ] ) ) ) ) { CString strFore = strData.Left( nComma ); nBytesToSkip += strFore.GetLength() + 1; // Includes code and comma pColourCode->nFore = atoi( strFore ); // Get Code strData = strData.Mid( nComma + 1 ); // Truncate string // Now look for backcolour: CString strBack; int nCodeLength = 1; if( strData.GetLength() >= 2 ) { if( isdigit( strData[ 1 ] ) ) nCodeLength++; }; nBytesToSkip+= nCodeLength; strBack = strData.Left( nCodeLength ); strData = strData.Mid( nCodeLength ); pColourCode->nBack = atoi( strBack ); } else { // No background colour present, the delimiter for this code // is the next non-numeric character... CString strFore; int nCodeLength = 1; if( strData.GetLength() >= 2 ) { if( isdigit( strData[ 1 ] ) ) nCodeLength++; }; nBytesToSkip += nCodeLength; strFore = strData.Left( nCodeLength ); strData = strData.Mid( nCodeLength ); pColourCode->nFore = atoi( strFore ); pColourCode->nBack = -1; }; }; // Return number of bytes processed: return( nBytesToSkip ); }; /* ================================================================= void TOutputWnd::SetBuffer( CStringArray& ) bool TOutputWnd::GetBuffer( CStringArray& ) const ------------------------------------------------- Sets or gets the content of the buffer. This facility allows a different part of the application to use multiple buffers with one output window. A typical example of this kind of use is the RAW output window which uses one output window, but allows the user to switch the content. ================================================================= */ void TOutputWnd::SetBuffer( CStringArray& rArray ) { // Copy the buffer across: m_Lines.RemoveAll(); int nLines = rArray.GetUpperBound() + 1; for( int l = 0; l < nLines; l ++ ) m_Lines.Add( rArray.GetAt( l ) ); UpdateVScroll(); // Place the head at the bottom. m_nHead = nLines - 1; // Redraw the view if necessary: if( GetSafeHwnd() ) { Invalidate(); UpdateHScroll(); }; }; bool TOutputWnd::GetBuffer( CStringArray& rArray ) const { rArray.RemoveAll(); // Ensures the passed array is empty // ------------------------------------------------------------- // Add the lines to the buffer that was passed: // ------------------------------------------------------------- int nLines = m_Lines.GetUpperBound() + 1; for( int l = 0; l < nLines; l ++ ) rArray.Add( m_Lines.GetAt( l ) ); return( true ); }; /* ================================================================= void TOutputWnd::ClearBuffer() ------------------------------ Clears the entire buffer of content. ================================================================= */ void TOutputWnd::ClearBuffer() { m_Lines.RemoveAll(); m_nMaxWidth = 0; m_nHead = -1; if( GetSafeHwnd() ) { UpdateHScroll(); UpdateVScroll(); Invalidate(); }; }; /* ================================================================= void TOutputWnd::AddLine( CString& ) ------------------------------------ Adds a line to the output window. ================================================================= */ void TOutputWnd::AddLine( CString& strLine ) { // Add to the buffer, cutting off the first ( top ) line if // necessary. m_Lines.Add( strLine ); if( GetLineCount() > m_nMaxLines ) { m_Lines.RemoveAt( 0 ); m_nHead--; }; // Update the vertical scroll bar: UpdateVScroll(); // Automatically scroll down if the user is already at the // bottom... if( m_nHead == GetLineCount() - 2 || m_nHead == -1 ) { m_nHead++; SetHead( m_nHead ); } else Invalidate(); }; /* ================================================================= void TOutputWnd::SetFont( LOGFONT& ) bool TOutputWnd::GetFont( LOGFONT& ) const ------------------------------------------ Sets or returns the font used to render the output text. ================================================================= */ void TOutputWnd::SetFont( LOGFONT& rFont ) { // Destroy the old font if necessary: if( m_pFont != NULL ) { delete( m_pFont ); m_pFont = NULL; }; // Create the new one: m_pFont = new CFont; m_pFont->CreateFontIndirect( &rFont ); memcpy( &m_lfFont, &rFont, sizeof( LOGFONT ) ); // Get the Average Char Width: TEXTMETRIC tm; CDC* pDC = GetDC(); CFont* pOldFont = pDC->SelectObject( m_pFont ); pDC->GetTextMetrics( &tm ); pDC->SelectObject( pOldFont ); ReleaseDC( pDC ); m_nAvgCharWidth = tm.tmAveCharWidth; m_nFontHeight = tm.tmHeight; // Redraw the display if necessary: if( GetSafeHwnd() ) { UpdateHScroll(); // Page size depends on average char width Invalidate(); }; }; bool TOutputWnd::GetFont( LOGFONT& rFont ) const { if( m_pFont != NULL ) { memcpy( &rFont, &m_lfFont, sizeof( LOGFONT ) ); return( true ); } else return( false ); // Should never happen unless I'm stupid }; /* ================================================================= void TOutputWnd::SetBackColour( COLORREF ) ------------------------------------------ Sets the background colour. ================================================================= */ void TOutputWnd::SetBackColour( COLORREF col ) { m_BackCol = col; // Force a repaint if we are displayed. if( GetSafeHwnd() ) Invalidate(); }; /* ================================================================= void TOutputWnd::SetHead( int ) ------------------------------- Sets the position of the view relative to the first line of the buffer. ================================================================= */ void TOutputWnd::SetHead( int nPos ) { if( nPos < -1 ) nPos = -1; if( nPos > GetLineCount() - 1 ) nPos = GetLineCount() - 1; m_nHead = nPos; if( GetSafeHwnd() ) { SetScrollPos( SB_VERT, m_nHead ); Invalidate(); }; }; /* ================================================================= void TOutputWnd::SetMaxLines( UINT ) ------------------------------------ Sets the maximum amount of lines we can display. ================================================================= */ void TOutputWnd::SetMaxLines( UINT nLines ) { }; /* ================================================================= UINT TOutputWnd::GetMaxViewableLines() const -------------------------------------------- Based on the current font, this function returns the maximum number of lines that can be displayed in the output window, given it's current size. ================================================================= */ UINT TOutputWnd::GetMaxViewableLines() { ASSERT( GetSafeHwnd() != NULL ); // Must have been created CRect clientRc; GetClientRect( &clientRc ); return( clientRc.Height() / m_nFontHeight ); }; /* ================================================================================= void TOutputWnd::SetWordWrap( bool ) ------------------------------------ Sets whether we word-wrap or not. ================================================================================= */ void TOutputWnd::SetWordWrap( bool bWrap ) { m_bWordWrap = bWrap; if( GetSafeHwnd() ) Invalidate(); }; /* ================================================================= void TOutputWnd::Load( const char* ) ------------------------------------ Loads a text file in from disk, and puts it in to the buffer. ================================================================= */ void TOutputWnd::Load( const char* lpFilename ) { CStringArray tmpArray; // Temporary Array CFile file; if( file.Open( lpFilename, CFile::modeRead ) ) { // --------------------------------------------------------- // Read the entire file into memory // --------------------------------------------------------- int nLen = file.GetLength(); char* pBuffer = new char[ nLen + 1 ]; file.Read( pBuffer, nLen ); pBuffer[ nLen ] = 0; CString strTemp = pBuffer; delete [] pBuffer; file.Close(); // --------------------------------------------------------- // Now add it to the buffer, line by line: // --------------------------------------------------------- int nCRLF = -1; do { if( ( nCRLF = strTemp.Find( "\r\n" ) ) != -1 ) { tmpArray.Add( strTemp.Left( nCRLF ) ); strTemp = strTemp.Mid( nCRLF + 2 ); } else { tmpArray.Add( strTemp ); strTemp = ""; }; }while( strTemp != "" ); SetBuffer( tmpArray ); }; }; /* ================================================================= TOutputWnd Message Map: ================================================================= */ BEGIN_MESSAGE_MAP( TOutputWnd, CWnd ) //{{AFX_MSG_MAP(TOutputWnd) ON_WM_CREATE() ON_WM_DESTROY() ON_WM_PAINT() ON_WM_ERASEBKGND() ON_WM_VSCROLL() ON_WM_SIZE() ON_WM_HSCROLL() ON_WM_SETCURSOR() ON_WM_LBUTTONUP() ON_WM_RBUTTONDOWN() //}}AFX_MSG_MAP END_MESSAGE_MAP() /* ================================================================= int TOutputWnd::OnCreate( LPCREATESTRUCT ) ------------------------------------------ Initializes the window members, etc. ================================================================= */ int TOutputWnd::OnCreate( LPCREATESTRUCT lpCreateStruct ) { // ------------------------------------------------------------- // Call base-class implementation: // ------------------------------------------------------------- if( CWnd::OnCreate( lpCreateStruct ) == -1 ) return( -1 ); // ------------------------------------------------------------- // Give ourselves the device's default fixed-width font: // ------------------------------------------------------------- #ifndef _WINNT HFONT hSysFont = ( HFONT )GetStockObject( DEFAULT_GUI_FONT ); #else HFONT hSysFont = ( HFONT )GetStockObject( DEVICE_DEFAULT_FONT ); #endif // !_WINNT LOGFONT lf; CFont* pFont = CFont::FromHandle( hSysFont ); pFont->GetLogFont( &lf ); SetFont( lf ); // Initialize the scroll bars: SetScrollRange( SB_VERT, 0, 0 ); SetScrollPos( SB_VERT, 0 ); SetScrollRange( SB_HORZ, 0, 0 ); SetScrollPos( SB_HORZ, 0 ); return( 0 ); } /* ================================================================= void TOutputWnd::OnDestroy() ---------------------------- Cleans up anything we allocated during the lifetime of this window ( namely fonts, bitmaps and device contexts ) ================================================================= */ void TOutputWnd::OnDestroy() { // Call base-class implementation: CWnd::OnDestroy(); // TOutputWnd-specific destruction: }; /* ================================================================= void TOuputWnd::OnPaint() ------------------------- Simply blits our memory DC to the window's DC. ================================================================= */ void TOutputWnd::OnPaint() { CPaintDC dc( this ); CRect clientRc; GetClientRect( &clientRc ); // Initialize the draw: UINT nMaxLines = GetMaxViewableLines(); // Max number of lines in view m_nLinesDone = 0; // No Lines drawn // Initialize colours and font: CFont* pOldFont = dc.SelectObject( m_pFont ); // Now draw the lines, one by one: UINT nUBound = m_Lines.GetUpperBound(); if( m_nHead != -1 ) { int nRunner = m_nHead; int nX = clientRc.left - m_nXOffset; int nMasterY = clientRc.bottom; int nY = nMasterY; int nPos = -1; CString strTemp; CString strLine; do { // ----------------------------------------------------- // Reset Colours: // ----------------------------------------------------- dc.SetBkColor( m_BackCol ); dc.SetTextColor( m_ColTable[ m_nDefTextCol ] ); // ----------------------------------------------------- // Proceed on to the next line: // ----------------------------------------------------- strTemp = m_Lines[ nRunner ]; if( !m_bWordWrap ) { // Life is easier if no word-wrapping is expected // of us. ( A damn sight quicker too <g> ) nMasterY -= m_nFontHeight; RenderSingleLine( strTemp, &dc, nX, nMasterY ); } else { // Obtain the line info for this line. This // routine will insert word-wrap control byes for // proper wrapping. It returns the number of lines // processed. nMasterY -= GetLineInfo( strTemp, &dc, clientRc.right ) * m_nFontHeight; nY = nMasterY; do { if( ( nPos = strTemp.Find( WRAP_BYTE ) ) != -1 ) { RenderSingleLine( strTemp.Left( nPos ), &dc, nX, nY ); strTemp = strTemp.Mid( nPos + 1 ); } else { RenderSingleLine( strTemp, &dc, nX, nY ); strTemp = ""; }; nY += m_nFontHeight; }while( strTemp != "" ); }; // ----------------------------------------------------- // Go on to the next line. // ----------------------------------------------------- nRunner--; }while( nRunner > -1 && nMasterY >= 0 ); // Pad out any remaining area... if( nMasterY >= 0 ) { CRect solidRc = clientRc; solidRc.bottom = nMasterY; dc.FillSolidRect( &solidRc, m_BackCol ); }; } else dc.FillSolidRect( &clientRc, m_BackCol ); // Clean up: dc.SelectObject( pOldFont ); } /* ================================================================= BOOL TOutputWnd::OnEraseBkgnd( CDC* ) ------------------------------------- Simply returns TRUE as we don't use this function and we don't want a flicker. ================================================================= */ BOOL TOutputWnd::OnEraseBkgnd( CDC* pDC ) { return( TRUE ); } /* ================================================================= void TOutputWnd::OnVScroll( UINT, UINT, CScrollBar* ) ----------------------------------------------------- Occurs when the user scrolls. Our job here is to position the head. ================================================================= */ void TOutputWnd::OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) { int nUBound = GetLineCount() - 1; switch( nSBCode ) { case SB_TOP: SetHead( 0 ); break; case SB_BOTTOM: SetHead( nUBound ); break; case SB_PAGEUP: case SB_LINEUP: if( m_nHead > 0 ) { m_nHead--; SetHead( m_nHead ); } break; case SB_PAGEDOWN: case SB_LINEDOWN: if( m_nHead < nUBound ) { m_nHead++; SetHead( m_nHead ); }; break; case SB_THUMBPOSITION: case SB_THUMBTRACK: SetHead( ( int )nPos ); break; }; CWnd::OnVScroll( nSBCode, nPos, pScrollBar ); } /* ================================================================= void TOutputWnd::OnHScroll( UINT, UINT, CScrollBar* ) ----------------------------------------------------- For Non-Wordwrapped output windows, the horizontal scroll bar can adjust the viewport so the user can see the end of the line. ================================================================= */ void TOutputWnd::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) { CRect clientRc; GetClientRect( &clientRc ); UINT nMax = m_nMaxWidth - clientRc.Width(); switch( nSBCode ) { case SB_TOP: m_nXOffset = 0; break; case SB_BOTTOM: m_nXOffset = nMax; break; case SB_LINEUP: case SB_PAGEUP: { m_nXOffset -= m_nAvgCharWidth; if( m_nXOffset < 0 ) m_nXOffset = 0; break; }; case SB_LINEDOWN: case SB_PAGEDOWN: { m_nXOffset += m_nAvgCharWidth; if( m_nXOffset > nMax ) m_nXOffset = nMax; break; }; case SB_THUMBPOSITION: case SB_THUMBTRACK: m_nXOffset = ( int )nPos; break; }; SetScrollPos( SB_HORZ, m_nXOffset ); Invalidate(); CWnd::OnHScroll( nSBCode, nPos, pScrollBar ); } /* ================================================================================= void TOutputWnd::OnSize( UINT, int, int ) ----------------------------------------- Overidden to update the scroll bars. ================================================================================= */ void TOutputWnd::OnSize(UINT nType, int cx, int cy) { CWnd ::OnSize(nType, cx, cy); if( GetSafeHwnd() ) { UpdateHScroll(); UpdateVScroll(); }; } /* ================================================================= BOOL TOuputWnd::OnSetCursor( CWnd*, UINT, UINT ) ------------------------------------------------ Overidden to set the window cursor. ================================================================= */ BOOL TOutputWnd::OnSetCursor( CWnd* pWnd, UINT nHitTest, UINT message ) { if( nHitTest != HTVSCROLL && nHitTest != HTHSCROLL ) { SetCursor( m_hCursor ); return( TRUE ); } else return( CWnd::OnSetCursor( pWnd, nHitTest, message ) ); } /* ================================================================================= Mouse handlers: ================================================================================= */ void TOutputWnd::OnLButtonUp( UINT nFlags, CPoint point ) { // *** Put code for notifying owner about button up *** CWnd::OnLButtonUp( nFlags, point ); } void TOutputWnd::OnRButtonDown( UINT nFlags, CPoint point ) { // *** Put code for notifying owner about Rbutton down *** CWnd::OnRButtonDown( nFlags, point ); }