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

📄 chapt13.cpp

📁 DOS下采用中断接收数据的串口通讯的例子,很难找到的好东西!
💻 CPP
字号:
//
//  CHAPT13.CPP
//
//  Source code from:
//
//  Serial Communications: A C++ Developer's Guide, 2nd Edition
//  by Mark Nelson, IDG Books, 1999
//
//  Please see the book for information on usage.
//
// This file contains the source code for the Chapter 13
// demo program. To build this file, use the Visual C++
// project file included in the same directory as the 
// sample code.
//

#include <windows.h>

#include "AnsiWinTerm.h"
#include "resource.h"


LRESULT CALLBACK WinProc( HWND hwnd, 
                          UINT message, 
                          WPARAM wParam, 
                          LPARAM lParam );

//
// The WinMain() function for this program looks
// very generic. It has to register the class we
// will create for this demo program, being sure
// to include our menu and WinProc. Once the class
// is registered, we can just create the window and
// let it do all the rest of the work. From that
// point on, all we have to do in this routine is
// run the message loop until somebody decides it's
// time to exit.
//

int WINAPI WinMain( HINSTANCE hInstance, 
                    HINSTANCE /* hPrevInstance */, 
                    LPSTR     /* lpCmdLine */, 
                    int       nShowCmd )
{
    //
    // Note that we store enough space extra in our class
    // to hold a single pointer. We keep a pointer to our
    // child window in that extra space, allowing us to
    // avoid the bad taste associated with global variables.
    //
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc      = WinProc;
    wc.hInstance        = hInstance;
    wc.lpszMenuName     = MAKEINTRESOURCE( IDR_MENU );
    wc.hbrBackground    = (HBRUSH) ( COLOR_WINDOW + 1 );
    wc.lpszClassName    = "Chapter13Class";
    wc.cbWndExtra       = sizeof( Win32Term * );
    if ( !RegisterClass( &wc ) ) {
        MessageBox( NULL, "Could not register Chapter 13 class!", NULL, MB_OK );
        return 0;
    }
    HWND hwnd = CreateWindow( "Chapter13Class", 
                              "Chapter 13 Test Program",
                              WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                              CW_USEDEFAULT, 
                              CW_USEDEFAULT,
                              647, // hand picked size to fit exactly 25 x 80
                              347,
                              NULL, 
                              NULL, 
                              hInstance, 
                              NULL );

    if ( hwnd == NULL ) {
        MessageBox( NULL, "Chapter13.exe couldn't start!", NULL, MB_OK );
        return 0;
    }
    ShowWindow( hwnd, nShowCmd );
    UpdateWindow( hwnd );

    MSG msg;
    while ( GetMessage( &msg, NULL, 0, 0 ) ) 
    {
        TranslateMessage( &msg ) ;
        DispatchMessage( &msg ) ;
    }
    return 1;
}

//
// Each time I open or close the port I have to
// change the enabled status of five menu items.
// Namely, the four Open COMx entries and the one
// Close Port entry. This routine does the work,
// and does it properly regardless of whether we
// just opened or just closed a port.
//
void UpdateMenu( HWND hwnd, bool port_open )
{
    HMENU menu = ::GetMenu( hwnd );
    if ( menu ) {
        ::EnableMenuItem( menu, ID_PORT_OPEN_COM1, port_open ? MF_GRAYED  : MF_ENABLED );
        ::EnableMenuItem( menu, ID_PORT_OPEN_COM2, port_open ? MF_GRAYED  : MF_ENABLED );
        ::EnableMenuItem( menu, ID_PORT_OPEN_COM3, port_open ? MF_GRAYED  : MF_ENABLED );
        ::EnableMenuItem( menu, ID_PORT_OPEN_COM4, port_open ? MF_GRAYED  : MF_ENABLED );
        ::EnableMenuItem( menu, ID_PORT_CLOSE,     port_open ? MF_ENABLED : MF_GRAYED  );
    }
}

//
// This is the WinProc for the sample program. Fortunately for
// the sake of clarity, all of the things that have to do with
// terminal emulation are being handled by the Window Procedures
// in the terminal emulation window. All we have to handle in 
// this procedure are menu commands and a few administrative
// details. 
//
// Note that the pointer to the Terminal Emulation window is
// stored as a Window Long word. Each time I enter the loop,
// I extract that pointer for use in all the various message
// handlers in this routine. 
//

LRESULT CALLBACK WinProc( HWND hWnd, 
                          UINT message, 
                          WPARAM wParam, 
                          LPARAM lParam )
{
    //
    // The custom color array is here so that I can support
    // the custom colors in my ChooseColor dialog.
    //
    static COLORREF custom_colors[ 16 ] = { 0 };
    AnsiWinTerm *pTerm = (AnsiWinTerm *) ::GetWindowLong( hWnd, 0 );
    switch ( message ) 
    {
        //
        // When my window is first created, I immediately
        // create the terminal window as a child window. I
        // get the pointer to the C++ object and store it as
        // a window long word, giving me access to it whenever
        // I need it without using a global variable. 
        //
        case WM_CREATE:
            pTerm = new AnsiWinTerm( hWnd, "AnsiTerm Window", 25, 80 );
            SetWindowLong( hWnd, 0, (LONG) pTerm );
            if ( pTerm->m_hWnd == NULL )
                MessageBox( hWnd, "Can't open child window", "Chapter 13", MB_OK );
            SetFocus( hWnd );
            break;
        //
        // When I am being destroyed, I take it upon myself to
        // destroy the terminal object as well. Note that simply
        // calling the C++ destructor like I'm doing here isn't
        // necessarily enough to destory the window itself, but 
        // since it is a child window the O/S will do that in
        // good time.
        //
        case WM_DESTROY: 
            delete pTerm;
            pTerm = 0;
            PostQuitMessage( 0 );
            break;
        //
        // Just for the sake of esthetics, I respond to this message
        // with a minimum size large enough to prevent somebody from
        // resizing me down to the point of ridiculousness.
        //
        case WM_GETMINMAXINFO:
            {
                LPMINMAXINFO lp = (LPMINMAXINFO) lParam;
                POINT ptTemp = { 
                    lp->ptMinTrackSize.x,
                    GetSystemMetrics( SM_CYMENU )        + 
                       GetSystemMetrics( SM_CYCAPTION )  +
                       2 * GetSystemMetrics( SM_CYFRAME )
                };
                lp->ptMinTrackSize = ptTemp;
            }        
            break;

        //
        // When the frame window is resized, I immediately 
        // resize the terminal window. Size the terminal window
        // is supposed to completely fill my client area, I
        // can figure out what size it is supposed to be by
        // simply getting the size of my client rect. When
        // the terminal window processes this command it will
        // potentially add scroll bars and offset the display.
        //
        case WM_SIZE:
            {
                RECT rc;
                ::GetClientRect( hWnd, &rc );
                if ( lParam != 0 )
                ::MoveWindow( pTerm->m_hWnd, 
                              0, 0, 
                              rc.right - rc.left + 1,
                              rc.bottom - rc.top + 1,
                              TRUE );
            }
            break;
        //
        // I don't want the framing window to get the focus,
        // so whenever I get it, I immediately foist it upon
        // the terminal window.
        //
        case WM_SETFOCUS :
            SetFocus( pTerm->m_hWnd );
            return 0;
        //
        // The rest of the code in the message loop 
        // is the set of command handlers for menu
        // items.
        //
        case WM_COMMAND:       
            switch ( LOWORD( wParam ) ) {
            //
            // Clearing the temrinal window is simply a
            // matter of calling one member function 
            //
            case ID_TERMINAL_CLEAR :
                pTerm->Clear();
                break;
            //
            // Telling a window to close itself is a fast way 
            // of shutting the program down.
            //
            case ID_FILE_EXIT :
                PostMessage( hWnd, WM_CLOSE, 0, 0 );
                break;
            //
            // The four Open COMx routines all do essentially
            // the same thing: attempt to open the port, and
            // if succesful, modify the menu a bit. Note that
            // the port is actually being opened inside the 
            // terminal object, we're calling a wrapper routine
            // here.
            //
            case ID_PORT_OPEN_COM1 :
                if ( pTerm->OpenPort( "COM1" ) )
                    UpdateMenu( hWnd, true );
                break;
            case ID_PORT_OPEN_COM2 :
                if ( pTerm->OpenPort( "COM2" ) )
                    UpdateMenu( hWnd, true );
                break;
            case ID_PORT_OPEN_COM3 :
                if ( pTerm->OpenPort( "COM3" ) )
                    UpdateMenu( hWnd, true );
                break;
            case ID_PORT_OPEN_COM4 :
                if ( pTerm->OpenPort( "COM4" ) )
                    UpdateMenu( hWnd, true );
                break;
            //
            // Closing the port is another one of those one
            // line of code things. Note that we assume that
            // we will never get this command unless the port
            // is already open. We believe that is the case
            // because we never enable the Close item on the
            // menu while the port is closed.
            //
            case ID_PORT_CLOSE :
                pTerm->ClosePort();
                UpdateMenu( hWnd, false );
                break;
            //
            // The Set Font command is really pretty simple, it's
            // just a little longer because it has to do a bit of
            // setup work to call the ChooseFont() dialog. You can 
            // see in this routine that if the person presses the
            // OK button in the font dialog, the SetFont() member
            // of the terminal emulator will be called with a copy
            // of the new LOGFONT settings.
            //
            case ID_TERMINAL_SET_FONT:
                {
                    CHOOSEFONT cf = {0};
                    LOGFONT lf = pTerm->GetLogFont();
                    cf.lStructSize = sizeof( CHOOSEFONT );
                    cf.hwndOwner = hWnd;
                    cf.lpLogFont = &lf;
                    cf.Flags = CF_INITTOLOGFONTSTRUCT |
                               CF_SCREENFONTS         |
                               CF_FIXEDPITCHONLY;
                    if ( !ChooseFont( &cf ) )
                        break;
                    pTerm->SetFont( lf );
                    break;
                }
            //
            // The three remaining routines are all pretty
            // much the same. They choose a color, then pass
            // it to the terminal emulator via a function call.
            // Note that the two text routines won't have an
            // immediate noticeable effect, that doesn't happen
            // until more text arrives. Setting the border color
            // on the other hand, will cause an immediate change
            // to appear.
            //
            case ID_TERMINAL_SET_TEXT_COLOR :
                {
                    CHOOSECOLOR cc = { 0 };
                    cc.lStructSize = sizeof( CHOOSECOLOR );
                    cc.hwndOwner = hWnd;
                    cc.rgbResult = pTerm->GetForegroundColor();
                    cc.Flags = CC_ANYCOLOR | CC_RGBINIT;
                    cc.lpCustColors = custom_colors;
                    if ( ChooseColor( &cc ) )
                        pTerm->SetForegroundColor( cc.rgbResult );
                }
                break;
            case ID_TERMINAL_SET_BACKGROUND_COLOR :
                {
                    CHOOSECOLOR cc = { 0 };
                    cc.lStructSize = sizeof( CHOOSECOLOR );
                    cc.hwndOwner = hWnd;
                    cc.rgbResult = pTerm->GetBackgroundColor();
                    cc.Flags = CC_ANYCOLOR | CC_RGBINIT;
                    cc.lpCustColors = custom_colors;
                    if ( ChooseColor( &cc ) )
                        pTerm->SetBackgroundColor( cc.rgbResult );
                }
                break;
            case ID_TERMINAL_SET_BORDER_COLOR :
                {
                    CHOOSECOLOR cc = { 0 };
                    cc.lStructSize = sizeof( CHOOSECOLOR );
                    cc.hwndOwner = hWnd;
                    cc.rgbResult = pTerm->GetBorderColor();
                    cc.Flags = CC_ANYCOLOR | CC_RGBINIT;
                    cc.lpCustColors = custom_colors;
                    if ( ChooseColor( &cc ) ) 
                        pTerm->SetBorderColor( cc.rgbResult );
                }
                break;
            }

        default:
            return DefWindowProc( hWnd, message, wParam, lParam );
    }
    return 0L;
}

// End of CHAPT13.CPP

⌨️ 快捷键说明

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