home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c221 / 7.ddi / MWHC.007 / OB < prev    next >
Encoding:
Text File  |  1991-10-24  |  16.7 KB  |  516 lines

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