home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / d / d020_1_4 / 6.ddi / TTY / TTY.C next >
Encoding:
C/C++ Source or Header  |  1990-06-01  |  16.4 KB  |  516 lines

  1. //
  2.  
  3. //    FILE:    TTY.c
  4.  
  5. //    PURPOSE: This sample terminal application demonstrates
  6. //          the basic uses of Windows Communications functions. 
  7. //          It also shows the basic structure for a terminal program.
  8.  
  9. //    FUNCTIONS:
  10. //          WinMain() - Initializes app, calls all other functions.
  11. //          TTYWndProc() - Window procedure for terminal window.
  12. //          About() - Window procedure for About dialog box.
  13. //          AboutInit() - Initialization procedure for About dialog box.
  14. //          SettingDlgProc() - Window procedure for Comm Settings dialog.
  15. //
  16.  
  17. #include <windows.h>
  18. #include <string.h>
  19. #include "wstdio.h"
  20. #include "tty.h"
  21.  
  22.  
  23. //========================================================================\\
  24.  
  25. // Declarations
  26.  
  27. //========================================================================\\
  28.  
  29. #define COM1  "com1"
  30. #define COM2  "com2"
  31. #define CommSettings "com1:96,n,8,1"
  32.  
  33. #define BufMax        160     // Size of line buffer used for displaying text
  34. #define cbInBuf    1024    // Size of receive buffer
  35. #define cbOutBuf   128     // size of transmit buffer
  36.  
  37. DCB CommDCB;               // DCB for comm port
  38. int PortID;                // The comm port id
  39. COMSTAT CommStat;          // COMSTAT info buffer for comm port
  40. char MsgBuff[BufMax + 1];  // Buffer to hold incoming characters
  41. BOOL bConnected;           // Flag to indicate if connected
  42. short nCommErr;            // Storage for communications error data
  43. WORD wCommEvt;             // Storage for communications event data
  44.  
  45. HWND hTTYWnd;              // Handle to application window
  46.  
  47. char sTemp[256];
  48.  
  49. static HANDLE hInst;       // Global instance handle
  50. FARPROC lpprocAbout;       // Pointer to "About" dialog box procedure
  51. FARPROC lpfnOldTTYProc;    // Pointer to TTY proc prior to subclassing
  52.  
  53. long FAR PASCAL TTYWndProc(HWND, unsigned, WORD, LONG);
  54.  
  55.  
  56. //========================================================================\\
  57.  
  58. // FUNCTION: About(HWND, unsigned, WORD, LONG)
  59.  
  60. // PURPOSE:  Processes messages for About dialog box.
  61.  
  62. //========================================================================\\
  63.  
  64. BOOL FAR PASCAL About( hDlg, message, wParam, lParam )
  65. HWND hDlg;
  66. unsigned message;
  67. WORD wParam;
  68. LONG lParam;
  69. {
  70.     if (message == WM_COMMAND
  71.     || message == WM_LBUTTONDOWN) {
  72.  
  73.     // if we click the mouse in the dialog, or press 'Enter', then go away
  74.         EndDialog( hDlg, TRUE );
  75.         return TRUE;
  76.         }
  77.     else if (message == WM_INITDIALOG)
  78.         return TRUE;
  79.     else return FALSE;
  80. }
  81.  
  82.  
  83. //========================================================================\\
  84.  
  85. // FUNCTION: AboutInit(HWND, HANDLE)
  86.  
  87. // PURPOSE:  About box initialization.
  88.  
  89. //========================================================================\\
  90.  
  91. BOOL AboutInit(HWND hWnd, HANDLE hInstance)
  92. {
  93.     HMENU hMenu;
  94.  
  95.     /* Bind callback function with module instance */
  96.     lpprocAbout = MakeProcInstance( (FARPROC)About, hInstance );
  97.  
  98.     return TRUE;
  99. }
  100.  
  101.  
  102. //========================================================================\\
  103.  
  104. // FUNCTION: SettingDlgProc(HWND, unsigned, WORD, LONG)
  105.  
  106. // PURPOSE:  Processes messages for Communications Settings dialog.
  107.  
  108. //========================================================================\\
  109.  
  110. BOOL FAR PASCAL SettingDlgProc( hDlg, message, wParam, lParam )
  111. HWND hDlg;
  112. unsigned message;
  113. WORD wParam;
  114. LONG lParam;
  115. {
  116.    int theButton;
  117.    static DCB dlgDCB;
  118.  
  119.    switch(message) {
  120.       case WM_COMMAND:
  121.  
  122.          // if the Ok button is pressed the new settings are saved
  123.  
  124.          if(wParam == IDOK) {
  125.             // save the new settings
  126.             CommDCB = dlgDCB;
  127.             // close the dialog
  128.             EndDialog( hDlg, TRUE );
  129.  
  130.          } else
  131.  
  132.          // otherwise, the settings are not saved and changes are discarded
  133.             
  134.             if(wParam == IDCANCEL)
  135.                EndDialog(hDlg,FALSE);
  136.             else
  137.                if(HIWORD(lParam) == BN_CLICKED) {
  138.  
  139.                   // if a button is clicked and it is a radiobutton,
  140.                   // then we uncheck the current selection and check
  141.                   // the one that was clicked.
  142.  
  143.                   HWND hStartWnd = GetDlgItem(hDlg,wParam);
  144.  
  145.                   if(LOWORD(GetWindowLong(hStartWnd,GWL_STYLE))
  146.                      == BS_AUTORADIOBUTTON){
  147.                      HWND hCurrWnd = hStartWnd;
  148.                      do{
  149.                         hCurrWnd = GetNextDlgGroupItem(hDlg,hCurrWnd,1);
  150.                         SendMessage(hCurrWnd, BM_SETCHECK, hCurrWnd == hStartWnd, 0L);
  151.                         } while(hCurrWnd != hStartWnd);
  152.                   }
  153.  
  154.             // now we set the appropriate value in the DCB for the
  155.             // button that was clicked
  156.  
  157.             switch (wParam){
  158.                             case RBBAUD_300: dlgDCB.BaudRate = 300; break;
  159.                             case RBBAUD_1200: dlgDCB.BaudRate = 1200; break;
  160.                             case RBBAUD_2400: dlgDCB.BaudRate = 2400; break;
  161.                 case RBBAUD_9600: dlgDCB.BaudRate = 9600; break;
  162.  
  163.                             case RBDBITS_7: dlgDCB.ByteSize = 7; break;
  164.                 case RBDBITS_8: dlgDCB.ByteSize = 8; break;
  165.  
  166.                             case RBPARITY_EVEN: dlgDCB.Parity = EVENPARITY; break;
  167.                             case RBPARITY_ODD: dlgDCB.Parity = ODDPARITY; break;
  168.                 case RBPARITY_NONE: dlgDCB.Parity = NOPARITY; break;
  169.  
  170.                             case RBSBITS_2: dlgDCB.StopBits = TWOSTOPBITS; break;
  171.                 case RBSBITS_1: dlgDCB.StopBits = ONESTOPBIT; break;
  172.  
  173.                 case CBXONXOFF: dlgDCB.fInX = dlgDCB.fInX?0:1; break;
  174.  
  175.                             case RBPORT_COM1: dlgDCB.Id = 1; break;
  176.                             case RBPORT_COM2: dlgDCB.Id = 2; break;
  177.                         }
  178.             } else
  179.                        return FALSE;
  180.  
  181.             break;
  182.  
  183.     case WM_INITDIALOG:
  184.  
  185.         // make a copy of the current DCB
  186.         // we will change this copy, and copy back to the original
  187.         // if we click Ok
  188.  
  189.         dlgDCB = CommDCB;
  190.  
  191.         // set buttons as reflected by the current DCB
  192.  
  193.         // if the current port isn't com2, set com1 button
  194.         theButton = (dlgDCB.Id == 2 ? RBPORT_COM2 : RBPORT_COM1);
  195.         SendDlgItemMessage(hDlg,theButton,BM_SETCHECK,1,0L);
  196.  
  197.         // set baud button
  198.                 switch(dlgDCB.BaudRate){
  199.                     case 300: theButton = RBBAUD_300; break;
  200.                     case 1200: theButton = RBBAUD_1200; break;
  201.                     case 2400: theButton = RBBAUD_2400; break;
  202.                     case 9600: theButton = RBBAUD_9600; break;
  203.                     default: theButton = RBBAUD_300; break;
  204.         }
  205.         SendDlgItemMessage(hDlg,theButton,BM_SETCHECK,1,0L);
  206.  
  207.         // set data bits button. if it's not 8, then it's 7
  208.                 theButton = (dlgDCB.ByteSize == 8 ? RBDBITS_8 : RBDBITS_7);
  209.         SendDlgItemMessage(hDlg,theButton,BM_SETCHECK,1,0L);
  210.  
  211.         // set parity button
  212.                 switch(dlgDCB.Parity){
  213.                     case EVENPARITY: theButton = RBPARITY_EVEN; break;
  214.                     case ODDPARITY: theButton = RBPARITY_ODD; break;
  215.                     case NOPARITY: theButton = RBPARITY_NONE; break;
  216.                     default: theButton = RBPARITY_NONE; break;
  217.                 }
  218.         SendDlgItemMessage(hDlg,theButton,BM_SETCHECK,1,0L);
  219.  
  220.         // set stop bits button. if it's not 2, then it's 1
  221.                 theButton = (dlgDCB.StopBits == TWOSTOPBITS ? RBSBITS_2 : RBSBITS_1);
  222.         SendDlgItemMessage(hDlg,theButton,BM_SETCHECK,1,0L);
  223.  
  224.         // set Xon/Xoff check box to on or off
  225.         SendDlgItemMessage(hDlg,CBXONXOFF,BM_SETCHECK,dlgDCB.fInX,0L);
  226.  
  227.             break;
  228.  
  229.         default:
  230.             return FALSE;
  231.     }
  232.     return TRUE;
  233. }
  234.  
  235.  
  236. //========================================================================\\
  237.  
  238. // FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  239.  
  240. // PURPOSE:  Main procedure of the application.
  241.  
  242. //========================================================================\\
  243.  
  244. int PASCAL WinMain( hInstance, hPrevInstance, lpszCmdLine, cmdShow )
  245. HANDLE hInstance, hPrevInstance;
  246. LPSTR lpszCmdLine;
  247. int cmdShow;
  248. {
  249.     MSG   msg;
  250.     BOOL bMsgAvail;
  251.     short iNumRead,iError;
  252.  
  253.     hInst = hInstance;
  254.  
  255.     // initialize the stdio window library
  256.     if(!hPrevInstance)
  257.         if(!stdioInit(hInstance)) return FALSE;
  258.  
  259.     // create a stdio window
  260.     if(!(hTTYWnd = CreateStdioWindow(
  261.                       "TTY",
  262.                       WS_OVERLAPPEDWINDOW,
  263.                       CW_USEDEFAULT,
  264.                       CW_USEDEFAULT,
  265.                       CW_USEDEFAULT,
  266.                       CW_USEDEFAULT,
  267.                       NULL,
  268.                       hInstance,
  269.                       TRUE)))
  270.         return FALSE;
  271.  
  272.     // subclass the stdio window
  273.      
  274.     lpfnOldTTYProc = (FARPROC) SetWindowLong(hTTYWnd,GWL_WNDPROC,
  275.                                           (DWORD) TTYWndProc);
  276.  
  277.     // add the about box to the system menu
  278.     AboutInit(hTTYWnd,hInstance);
  279.  
  280.     // add the terminal menu
  281.     SetMenu(hTTYWnd,LoadMenu(hInstance, "TTYMENU"));
  282.  
  283.     // set the application icon
  284.     SetClassWord(hTTYWnd, GCW_HICON,
  285.                  LoadIcon( hInstance, MAKEINTRESOURCE(TTYICON) ));
  286.  
  287.     bConnected = FALSE;
  288.  
  289.     // initialize the DCB to default settings
  290.     if(BuildCommDCB(CommSettings,&CommDCB) != 0) {
  291.         MessageBox(GetFocus(),"Error Building DCB!","",MB_OK);
  292.     }
  293.  
  294.     CommDCB.CtsTimeout = 100;           // Set Cts Timeout value
  295.     CommDCB.DsrTimeout = 100;           // Set Dsr Timeout value
  296.     CommDCB.fOutX = 1;               // output Xon/Xoff flow control on
  297.     CommDCB.fInX = 1;               // input Xon/Xoff flow control on
  298.     CommDCB.XonChar = 0x11;           // specify the Xon character
  299.     CommDCB.XoffChar = 0x13;           // specify the Xoff character
  300.     CommDCB.fNull = 1;               // strip null characters
  301.     CommDCB.XonLim = 30;           // distance from queue empty to Xon
  302.     CommDCB.XoffLim = (cbInBuf/2) + 1; // distance from queue full to Xoff
  303.     CommDCB.fBinary = 0;
  304.  
  305.     // show the window
  306.     ShowWindow( hTTYWnd, cmdShow );
  307.     UpdateWindow( hTTYWnd );
  308.  
  309.     // PeekMessage loop to poll the comm port and pull messages from the queue
  310.     // if there is a message available, process it.
  311.     // otherwise, check the port and handle any available characters.
  312.  
  313.     while(TRUE){
  314.         bMsgAvail = PeekMessage(&msg,NULL,0,0,PM_REMOVE);
  315.  
  316.         if(bMsgAvail){
  317.  
  318.             if(msg.message == WM_QUIT) break;
  319.  
  320.             TranslateMessage((LPMSG)&msg);
  321.             DispatchMessage((LPMSG)&msg);
  322.  
  323.         } else {
  324.  
  325.             // check the comm port and process any available
  326.             // characters. you could also use a timer instead, and have
  327.             // the timer case of the wndproc check the port.
  328.             if(bConnected){
  329.  
  330.                 // get the CommStat record and get the # of characters available
  331.         GetCommError(CommDCB.Id,&CommStat);
  332.  
  333.                 // get the number of characters available
  334.                 iNumRead = CommStat.cbInQue;
  335.  
  336.                 if(iNumRead > 0) {
  337.  
  338.                     // get the number of characters rounded to the buffer size
  339.                     if(iNumRead > BufMax) iNumRead = BufMax;
  340.  
  341.                     // read the characters
  342.                     iNumRead = ReadComm(CommDCB.Id,MsgBuff,
  343.                                         iNumRead);
  344.  
  345.                     // check for errors
  346.                     if(iNumRead < 0) {
  347.                         iNumRead = -iNumRead;
  348.                         nCommErr = GetCommError(CommDCB.Id,&CommStat);
  349.                         // clear the event mask
  350.             wCommEvt = GetCommEventMask(CommDCB.Id,0xFFFF);
  351.                         // display what the error was
  352.                         LoadString(hInst, nCommErr, sTemp, 20);
  353.                         MessageBox(GetFocus(), sTemp, "Comm Read Error!",MB_OK);
  354.                     }
  355.  
  356.                     MsgBuff[iNumRead] = '\0';
  357.  
  358.                     // send the characters to the tty window for processing
  359.                     SendMessage(hTTYWnd,COMM_CHARS,
  360.                 iNumRead,(LONG)(LPSTR)MsgBuff);
  361.             //wputs((LPSTR) MsgBuff);    // could just do this instead
  362.                 }
  363.  
  364.  
  365.             }
  366.         }
  367.     }
  368.  
  369. }
  370.  
  371. //========================================================================\\
  372.  
  373. // FUNCTION: TTYWndProc(HWND, unsigned, WORD, LONG)
  374.  
  375. // PURPOSE:  Processes messages for the terminal window.
  376.  
  377. //========================================================================\\
  378.  
  379. long FAR PASCAL TTYWndProc( hWnd, message, wParam, lParam )
  380. HWND hWnd;
  381. unsigned message;
  382. WORD wParam;
  383. LONG lParam;
  384. {
  385.     FARPROC   lpSettingDlgProc;
  386.     char      szErr[22];
  387.     unsigned  nErr;
  388.  
  389.     switch (message)
  390.     {
  391.  
  392.     case WM_DESTROY:
  393.         PostQuitMessage( 0 );
  394.         break;
  395.  
  396.     case WM_ENDSESSION:
  397.     if (wParam && bConnected)
  398.         SendMessage(hWnd, WM_COMMAND, TTYCONNECT, 1L);
  399.     break;
  400.  
  401.     case WM_CLOSE:
  402.         // disconnect if still connected
  403.         if(bConnected)SendMessage(hWnd,WM_COMMAND,TTYCONNECT,0L);
  404.         // go ahead and close down
  405.         return CallWindowProc(lpfnOldTTYProc,hWnd,
  406.                               message,wParam,lParam);
  407.         break;
  408.  
  409.     case WM_COMMAND:
  410.         switch(wParam){
  411.  
  412.         case IDSABOUT:
  413.             DialogBox( hInst, MAKEINTRESOURCE(ABOUTBOX), hWnd, lpprocAbout );
  414.             break;
  415.  
  416.         case TTYEXIT:
  417.             PostMessage(hWnd,WM_CLOSE,0,0L);
  418.             break;
  419.  
  420.         case TTYCONNECT:
  421.             // connect to port if not already connected
  422.             if(!bConnected){
  423.         if((PortID = OpenComm((CommDCB.Id == 2?COM2:COM1),cbInBuf,cbOutBuf)) < 0) {
  424.                     MessageBox(hWnd,"Error Opening Comm Port!","",MB_OK);
  425.                     break;
  426.                 }
  427.  
  428.                 FlushComm(PortID,0);
  429.                 FlushComm(PortID,1);
  430.  
  431.         CommDCB.Id = PortID;
  432.         if(CommDCB.fInX) {
  433.             CommDCB.fOutX = 1;        // enable output Xon/Xoff flow ctl
  434.             CommDCB.fInX = 1;        // enable input Xon/Xoff flow ctl
  435.             CommDCB.fRtsflow = 0;   // disable hardware flow ctl
  436.             CommDCB.fDtrflow = 0;   // disable hardware flow ctl
  437.         } else {
  438.             CommDCB.fOutX = 0;        // disable ouput Xon/Xoff flow ctl
  439.             CommDCB.fInX = 0;        // disable input Xon/Xoff flow ctl
  440.             CommDCB.fRtsflow = 1;   // enable hardware flow ctl
  441.             CommDCB.fDtrflow = 1;   // enable hardware flow ctl
  442.         }
  443.  
  444.  
  445.                 if(SetCommState(&CommDCB) !=0 ){
  446.                     MessageBox(hWnd,"Error Setting CommState!","",MB_OK);
  447.                     break;
  448.                 }
  449.                 bConnected = TRUE;
  450.                 CheckMenuItem(GetMenu(hWnd),TTYCONNECT,MF_CHECKED);
  451.                 EnableMenuItem(GetMenu(hWnd),TTYSETTINGS,MF_DISABLED | MF_GRAYED);
  452.                 MessageBox(hWnd,"Connection was successful.","",MB_OK);
  453.  
  454.             }else{
  455.                 // otherwise disconnect
  456.                 FlushComm(CommDCB.Id,0);
  457.                 FlushComm(CommDCB.Id,1);
  458.                 CloseComm(CommDCB.Id);
  459.         if (!lParam)
  460.                     MessageBox(hWnd,"Connection closed.","",MB_OK);
  461.                 bConnected = FALSE;
  462.                 CheckMenuItem(GetMenu(hWnd),TTYCONNECT,MF_UNCHECKED);
  463.                 EnableMenuItem(GetMenu(hWnd),TTYSETTINGS,MF_ENABLED);
  464.  
  465.             }
  466.             break;
  467.  
  468.         case TTYSETTINGS:
  469.             // settings dialog
  470.             lpSettingDlgProc = MakeProcInstance(SettingDlgProc,hInst);
  471.             DialogBox(hInst,"SETTINGSDLG",hWnd,lpSettingDlgProc);
  472.             FreeProcInstance(lpSettingDlgProc);
  473.             break;
  474.         }
  475.         break;
  476.  
  477.     case WM_CHAR:
  478.     if(!bConnected) break;
  479.  
  480.     // if we're connected, send any keyboard characters to the port
  481.  
  482.         nCommErr = WriteComm(CommDCB.Id,(LPSTR) &wParam,1);
  483.         if(nCommErr != 1) {
  484.         nCommErr = GetCommError(CommDCB.Id,&CommStat);
  485.             if(nCommErr != 0) {
  486.         sTemp[0] = 0;
  487.         for (nErr = 1; nErr != 0; nErr = nErr << 1) {
  488.             if (nErr & nCommErr) {
  489.             LoadString(hInst, nErr, szErr, 20);
  490.             strcat(sTemp, szErr);
  491.             strcat(sTemp, "\n");
  492.             }
  493.         }
  494.         MessageBox(hWnd, sTemp, "Comm Write Error!", MB_OK);
  495.             }
  496.         wCommEvt = GetCommEventMask(CommDCB.Id, 0xFFFF);
  497.         }
  498.         break;
  499.  
  500.     case COMM_CHARS:
  501.     // display available characters
  502.         if(wParam > 0)
  503.             wputs((LPSTR) lParam);
  504.  
  505.         break;
  506.  
  507.     // Pass all other messages to class's window procedure, since window
  508.     // was subclassed
  509.     default:
  510.         return CallWindowProc(lpfnOldTTYProc,hWnd,
  511.                               message,wParam,lParam);
  512.         break;
  513.     }
  514.     return(0L);
  515. }
  516.