⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win32term.cpp

📁 DOS下采用中断接收数据的串口通讯的例子,很难找到的好东西!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        case '\r' :
            m_Position.x = 0 ;
            break;

        case '\n' : 
            if ( m_Position.y++ == ( m_VirtualSize.y - 1 ) )
            {
                for ( int j = 0 ; j < ( m_VirtualSize.y - 1 ) ; j++ ) {
                    m_ScreenText[ j ] = m_ScreenText[ j + 1 ];
                    m_ScreenColor[ j ] = m_ScreenColor[ j + 1 ];
                }
                fill( m_ScreenText.back().begin(),
                      m_ScreenText.back().end(),
                      ' ' );
                fill( m_ScreenColor.back().begin(),
                      m_ScreenColor.back().end(),
                      m_CurrentColor );
                    InvalidateRect( m_hWnd, NULL, FALSE );
                    m_Position.y--;
            }
            break;

        default:
            {
                RECT rect;
                m_ScreenText[ m_Position.y ][ m_Position.x ] = pBuf[ i ];
                m_ScreenColor[ m_Position.y ][ m_Position.x ] = m_CurrentColor;
                rect.left = ( m_Position.x * m_CharSize.x ) - m_Offset.x;
                rect.right = rect.left + m_CharSize.x;
                rect.top = ( m_Position.y * m_CharSize.y ) - m_Offset.y;
                rect.bottom = rect.top + m_CharSize.y;
                ::InvalidateRect( m_hWnd, &rect, FALSE ) ;

                // 
                // Check to see if we wrapped
                //
                if ( m_Position.x < ( m_VirtualSize.x - 1)  )
                    m_Position.x++ ;
                else if ( m_bWrap )
                    Output( "\r\n", 2 ) ;                
                break;
            }
        }
    }
    UpdateCursor();
}

//
// There are a big bunch of possible messages that
// we can get from the scroll bars. All we have to
// do in the handler is determine how far to scroll
// the screen based on the input we receive in the
// form of a message. Note that the total span of
// the scroll bar is stored in m_ScrollRange.
//
void Win32Term::VerticalScroll( WPARAM wParam )
{
    int ScrollCommand = LOWORD( wParam );
    int ScrollPosition = HIWORD( wParam );
    int  nScrollAmt;

    switch (  ScrollCommand )
    {
        case SB_TOP :
            nScrollAmt = -m_Offset.y;
            break;

        case SB_BOTTOM :
            nScrollAmt = m_ScrollRange.y - m_Offset.y;
            break;

        case SB_PAGEUP :
            nScrollAmt = -m_VisibleSize.y;
            break;

        case SB_PAGEDOWN :
            nScrollAmt = m_VisibleSize.y;
            break;

        case SB_LINEUP:
            nScrollAmt = -m_CharSize.y;
            break;

        case SB_LINEDOWN:
            nScrollAmt = m_CharSize.y;
            break;

        case SB_THUMBPOSITION:
            nScrollAmt = ScrollPosition - m_Offset.y;
            break;

        default:
           return;
    }

    if ( ( m_Offset.y + nScrollAmt ) > m_ScrollRange.y )
        nScrollAmt = m_ScrollRange.y - m_Offset.y;
    if ( ( m_Offset.y + nScrollAmt ) < 0 )
        nScrollAmt = -m_Offset.y;
    ::ScrollWindowEx( m_hWnd, 
                      0, 
                      -nScrollAmt, 
                      NULL, 
                      NULL, 
                      NULL, 
                      NULL, 
                      SW_INVALIDATE | SW_ERASE );

    m_Offset.y += nScrollAmt;
    SetScrollPos( m_hWnd, SB_VERT, m_Offset.y, TRUE ) ;
}

void Win32Term::HorizontalScroll( WPARAM wParam )
{
    int ScrollCommand = LOWORD( wParam );
    int ScrollPosition = HIWORD( wParam );
    int nScrollAmt;

    switch ( ScrollCommand )
    {
        case SB_TOP:
            nScrollAmt = -m_Offset.x;
            break;

        case SB_BOTTOM:
            nScrollAmt = m_ScrollRange.x - m_Offset.x;
            break ;

        case SB_PAGEUP:
            nScrollAmt = -m_VisibleSize.x;
            break;

        case SB_PAGEDOWN:
            nScrollAmt = m_VisibleSize.x;
            break ;

        case SB_LINEUP:
            nScrollAmt = -m_CharSize.x;
            break ;

        case SB_LINEDOWN:
            nScrollAmt = m_CharSize.x;
            break;

        case SB_THUMBPOSITION:
            nScrollAmt = ScrollPosition - m_Offset.x;
            break;

        default:
            return;
    }
    if ( ( m_Offset.x + nScrollAmt ) > m_ScrollRange.x )
        nScrollAmt = m_ScrollRange.x - m_Offset.x;
    if ( ( m_Offset.x + nScrollAmt ) < 0 )
        nScrollAmt = -m_Offset.x;
    ScrollWindowEx( m_hWnd, 
                    -nScrollAmt, 
                    0, 
                    NULL, 
                    NULL, 
                    NULL, 
                    NULL, 
                    SW_INVALIDATE | SW_ERASE );
    m_Offset.x = m_Offset.x + nScrollAmt;
    ::SetScrollPos( m_hWnd, SB_HORZ, m_Offset.x, TRUE );
}

//
// See the text in the book for details on the Size()
// message handler. In principle this routine should
// not be too tricky, but it is complicated by the
// fact that scroll bars can pop up or disappear as
// things change.
//
void Win32Term::Size( int x, int y )
{
    //
    // First, we will try to do everything with no scroll bars.
    // If there are scroll bars, we're going to give their space
    // back, at least temporarily
    //
    long style = ::GetWindowLong( m_hWnd, GWL_STYLE );
    if ( style & WS_VSCROLL )
        x += ::GetSystemMetrics( SM_CXVSCROLL );
    if ( style & WS_HSCROLL )
        y += ::GetSystemMetrics( SM_CYHSCROLL );
    //
    // adjust vertical settings
    //
    m_VisibleSize.y = y;
    m_ScrollRange.y = max( 0, (m_VirtualSize.y * m_CharSize.y ) + m_iCharDescent - m_VisibleSize.y ) ;
    int nScrollAmt = min( m_ScrollRange.y, m_Offset.y ) - m_Offset.y;
    m_Offset.y = m_Offset.y + nScrollAmt;
 
    //
    // adjust horz settings
    //
    m_VisibleSize.x = x;
    m_ScrollRange.x = max( 0, (m_VirtualSize.x *  m_CharSize.x ) - m_VisibleSize.x );
    nScrollAmt = min( m_ScrollRange.x, m_Offset.x ) - m_Offset.x;
    m_Offset.x = m_Offset.x + nScrollAmt;
    //
    // If we created a vertical scrollbar, we need to go back and adjust the horizontal
    //
    if ( m_ScrollRange.y > 0 ) {
        m_VisibleSize.x = x - ::GetSystemMetrics( SM_CXVSCROLL );
        m_ScrollRange.x = max( 0, (m_VirtualSize.x *  m_CharSize.x ) - m_VisibleSize.x );
        nScrollAmt = min( m_ScrollRange.x, m_Offset.x ) - m_Offset.x;
        m_Offset.x = m_Offset.x + nScrollAmt;
    } 
    //
    // If we created a horzontal scrollbar, we need to go back and adjust the vertical
    //
    if ( m_ScrollRange.x > 0 ) {
        m_VisibleSize.y = y - ::GetSystemMetrics( SM_CYHSCROLL );
        m_ScrollRange.y = max( 0, (m_VirtualSize.y * m_CharSize.y ) + m_iCharDescent - m_VisibleSize.y ) ;
        int nScrollAmt = min( m_ScrollRange.y, m_Offset.y ) - m_Offset.y;
        m_Offset.y = m_Offset.y + nScrollAmt;
        //
        // And it's actually still possible that we need to readjust the X scrollbar
        //
        m_VisibleSize.x = x - ::GetSystemMetrics( SM_CXVSCROLL );
        m_ScrollRange.x = max( 0, (m_VirtualSize.x *  m_CharSize.x ) - m_VisibleSize.x );
        nScrollAmt = min( m_ScrollRange.x, m_Offset.x ) - m_Offset.x;
        m_Offset.x = m_Offset.x + nScrollAmt;
    }
    //
    // Now we do the actual scrolling. Note that at this
	// point, the number i m_ScrollRange represents the
	// difference between the pixels needed to display the
	// Virtual screen and the number of pixels in the visible
	// window.
    //
    ScrollWindow( m_hWnd, 0, -nScrollAmt, NULL, NULL );
    SetScrollRange( m_hWnd, SB_VERT, 0, m_ScrollRange.y, TRUE );
    SetScrollPos( m_hWnd, SB_VERT, m_Offset.y, FALSE );
    //
    ScrollWindow( m_hWnd, nScrollAmt, 0, NULL, NULL );
    SetScrollRange( m_hWnd, SB_HORZ, 0, m_ScrollRange.x, FALSE ) ;
    SetScrollPos( m_hWnd, SB_HORZ, m_Offset.x, TRUE ) ;
    
    InvalidateRect( m_hWnd, NULL, FALSE ) ;   // redraw entire window
}

//
// This is the dispatcher for messages coming into
// this window. This is the C++ equivaelnt of a 
// WinProc, and in fact is called by the WinProc
// for this window class.
//

LRESULT Win32Term::Dispatch( HWND hWnd, 
                             UINT uMsg, 
                             WPARAM wParam, 
                             LPARAM lParam )
{
    switch( uMsg ) {
        case WM_VSCROLL:
            VerticalScroll( wParam );
            break;

        case WM_HSCROLL:
            HorizontalScroll( wParam );
            break ;

        case WM_SIZE:
            Size( LOWORD( lParam ), HIWORD( lParam ) );
            break;

        case WM_PAINT:
            Paint();
            break;

        case WM_CHAR:
            Output( (char) wParam );
            break;

        case WM_SETFOCUS:
            SetFocus();
            break ;

        case WM_KILLFOCUS:
            KillFocus();
            break;

        case WM_MOUSEACTIVATE:
            ::SetFocus( hWnd );
            return MA_ACTIVATE;
            break;

        case WM_DESTROY :
            SetWindowLong( hWnd, 0, 0 );
			m_hWnd = 0;
            break;
        default:
            return DefWindowProc( hWnd, uMsg, wParam, lParam );
    }
    return 0L;
}

//
// The WinProc for this class is what Windows
// will call when any messages are to be dispatched.
// The only time we actually do anything in this 
// routine is when the window is first created, 
// because then we get a special pointer to the
// C++ object passed in. We extract that pointer
// and store it in a window long word so that all
// subsequent calls to ths routine can get a pointer
// to the C++ object. Thus, all subseuqent calls can
// also be handled by the C++ member function 
// Dispatch().
//
// Why am I so eager to have commands handled by a
// C++ member function? Most importantly, it gives
// me the opportunity to derive new classes from
// Win32Term, and let them write their own versions
// of Dispatch, allowing them to override some or
// all of the behavior of the class. This is how the
// Chapter 13 example works.
//
LRESULT CALLBACK Win32Term::WindowProc( HWND hWnd, 
                                        UINT uMsg, 
                                        WPARAM wParam, 
                                        LPARAM lParam )
{
    Win32Term *p = (Win32Term *) ::GetWindowLong( hWnd, 0 );
    if ( p )
        return p->Dispatch( hWnd, uMsg, wParam, lParam );
    //
    // If we haven't defined the window yet, I want to make sure I don't do 
    // anything that requires the pointer to the object
    //
    if ( uMsg == WM_CREATE ) 
    {
        CreateData UNALIGNED *pData = (CreateData UNALIGNED *) ((LPCREATESTRUCT) lParam)->lpCreateParams;
        pData->pTerm->m_hParent = ::GetParent( hWnd );
        pData->pTerm->m_hWnd = hWnd;
        SetWindowLong( hWnd, 0, (LONG) pData->pTerm );
    } 
    return DefWindowProc( hWnd, uMsg, wParam, lParam );
}

//
// Normally clearing the screen is very simple. We
// just fill the screen with blanks of a certain color.
// However, sometimes it is nice to have calibration data
// on the screen so that we can do some experimentation.
// By changing the "#if 1" to "#if 0", we can turn that
// code on. It isn't pretty, but sometimes it is very 
// handy.
//
void Win32Term::Clear()
{
#if 1	
    for ( int row = 0 ; row < m_VirtualSize.y ; row++ ) {
        fill( m_ScreenText[ row ].begin(),
              m_ScreenText[ row ].end(),
              ' ' );
        fill( m_ScreenColor[ row ].begin(),
              m_ScreenColor[ row ].end(),
              m_CurrentColor );
    }
#else
    TextColor bars[ 2 ] = {
		TextColor( RGB(   0,   0,   0 ), RGB( 224, 224, 224 ) ),
		TextColor( RGB( 255, 255, 255 ), RGB( 0,   0,   0 ) )
	};
	bool temp_wrap = m_bWrap;
	m_bWrap = false;
	int temp_row; 
	int temp_col;
	GetCursorPosition( temp_row, temp_col );
    for ( int row = 0 ; row < m_VirtualSize.y ; row++ ) {
        fill( m_ScreenText[ row ].begin(),
              m_ScreenText[ row ].end(),
              ' ' );
        fill( m_ScreenColor[ row ].begin(),
              m_ScreenColor[ row ].end(),
              bars[ row & 1 ] );
		SetForegroundColor( bars[ row & 1 ].m_Foreground );
		SetBackgroundColor( bars[ row & 1 ].m_Background );
		ostringstream s1;
		ostringstream s2;
		s1 << "*** Row " << setw( 2 ) << row;
		s2 << "Row " << setw( 2 ) << row << " ***";
		SetCursorPosition( row, 0 );
		Output( s1.str().c_str() );
		SetCursorPosition( row, m_VirtualSize.x - s2.str().size() );
		Output( s2.str().c_str() );
    }
	m_bWrap = temp_wrap;
	SetCursorPosition( temp_row, temp_col );
#endif
    ::InvalidateRect( m_hWnd, NULL, TRUE );
}

//
// The border color is truly just the background
// color for the window. When we get a new
// color in for the background, we just create
// a brush for that color and stuff it into the
// class data for this window. The rest of it
// is automatic, we never have to actually draw
// the border, it's done automatically as part
// of the paint process.
//
void Win32Term::SetBorderColor( COLORREF color )
{
    HBRUSH brush = (HBRUSH) ::GetClassLong( m_hWnd, GCL_HBRBACKGROUND );
    if ( brush )
        DeleteObject( brush );
    brush = ::CreateSolidBrush( color );
    ::SetClassLong( m_hWnd, GCL_HBRBACKGROUND, (LONG) brush );
    m_BorderColor = color;
    ::InvalidateRect( m_hWnd, NULL, TRUE );
}

//
// Done just like you might think, with a bit
// of error checking
//
int Win32Term::SetCursorPosition( int row, int col )
{
    if ( row < 0 || col < 0 )
        return 0;
    if ( row >= m_VirtualSize.y )
        return 0;
    if ( col >= m_VirtualSize.x )
        return 0;
    m_Position.x = col;
    m_Position.y = row;
    UpdateCursor();
    return 1;
}

void Win32Term::GetCursorPosition( int &row, int &col )
{
    row = m_Position.y;
    col = m_Position.x;
}

//EOF Win32Term.cpp

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -