📄 ttychic.c
字号:
//---------------------------------------------------------------------------
//
// Module: ttychic.c
//
// Purpose:
// This sample application demonstrates the usage of the COMM
// API. It implements the new Win32c API of Windows 95.
//
// This application demonstrates how to read data asynchronously
// using the OVERLAPPED structure.
//
// NOTE: no escape sequences are translated, only
// the necessary control codes (LF, CR, BS, etc.)
//
// Description of functions:
// Descriptions are contained in the function headers.
//
//---------------------------------------------------------------------------
//
// Written by Microsoft Product Support Services, Windows Developer Support.
// Copyright (c) 1991 Microsoft Corporation. All Rights Reserved.
//
//---------------------------------------------------------------------------
#include "tty.h"
HINSTANCE ghInst; //global instance handle, for now.
HWND hTTYWnd ; //global window handle
BOOL bReading;
PTTYINFO pTTYInfo ;
COMMCONFIG cc;
DCB dcb;
COMMTIMEOUTS to;
COMMPROP cp;
HANDLE hComm, hThread;
LPCSTR lpszCommName = "COM2"; //global variable to define the serial
// COM port you will be using
DWORD ReadThread (LPDWORD lpdwParam1);
void locProcessCommError (DWORD dwError);
void locProcessBytes (LPBYTE buf, DWORD dwBytes);
#if !defined(_WIN32)
#include <ver.h>
#endif
// Windows NT defines APIENTRY, but 3.x doesn't
#if !defined (APIENTRY)
#define APIENTRY far pascal
#endif
// Windows 3.x uses a FARPROC for dialogs
#if !defined(_WIN32)
#define DLGPROC FARPROC
#endif
char szDebug[100];
//
// FUNCTION: WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
//
// PURPOSE: calls initialization function, processes message loop
//
// COMMENTS:
//
// Windows recognizes this function by name as the initial entry point
// for the program. This function calls the application initialization
// routine, if no other instance of the program is running, and always
// calls the instance initialization routine. It then executes a
// message retrieval and dispatch loop that is the top-level control
// structure for the remainder of execution. The loop is terminated
// when a WM_QUIT message is received, at which time this function
// exits the application instance by returning the value passed by
// PostQuitMessage().
//
// If this function must abort before entering the message loop, it
// returns the conventional value NULL.
//
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
MSG msg;
DWORD id;
BOOL bOldState = FALSE;
OutputDebugString ("TTY Demo Program\n");
// Other instances of app running?
if (!hPrevInstance) {
// Initialize shared things
if (!InitApplication(hInstance)) {
return (FALSE); // Exits if unable to initialize
}
}
if (NULL == (hTTYWnd = InitInstance( hInstance, nCmdShow )))
return ( FALSE ) ;
ghInst = hInstance;
CreateTTYInfo( hTTYWnd );
if (NULL == (pTTYInfo =
(PTTYINFO) GetWindowLong( hTTYWnd,GWL_PTTYINFO )))
return ( FALSE ) ;
/* open COM port #2 for reading and writing */
if ((hComm=CreateFile (lpszCommName, GENERIC_READ|GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,NULL)) == INVALID_HANDLE_VALUE) {
/* handle error */
MessageBox (NULL, "Error opening COM port","",MB_OK);
return FALSE;
} /* end if (error creating read thread) */
/* get comm properties */
cp.wPacketLength = sizeof(COMMPROP);
GetCommProperties (hComm, &cp);
/* create the thread for reading bytes */
bReading = TRUE;
if ((hThread=CreateThread (NULL /*def security */, 0 /* def stack size */,
(LPTHREAD_START_ROUTINE)ReadThread, NULL /* param to pass to thread */,
0, &id)) == INVALID_HANDLE_VALUE) {
/* handle error */
MessageBox (NULL, "Error creating READ thread","",MB_OK);
CloseHandle (hComm);
return FALSE;
} /* end if (error creating read thread) */
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator (msg.hwnd, ghAccel, &msg)) {
TranslateMessage(&msg);// Translates virtual key codes
DispatchMessage(&msg); // Dispatches message to window
}
} /* end while (not a quit message) */
/* kill the read thread */
bReading = FALSE;
/* in case the thread is not running, resume it now */
ResumeThread (hThread);
/* wait for thread to die... */
while (GetExitCodeThread(hThread, &id)) {
if (id == STILL_ACTIVE)
continue;
else
break;
} /* end while (no error reading thread exit code) */
CloseHandle (hThread);
/* close COM port */
CloseHandle (hComm);
/* clean up */
DestroyTTYInfo( hTTYWnd ) ;
// Returns the value from PostQuitMessage
return (msg.wParam);
// This will prevent 'unused formal parameter' warnings
lpCmdLine;
}
//---------------------------------------------------------------------------
// BOOL NEAR InitApplication( HANDLE hInstance )
//
// Description:
// First time initialization stuff. This registers information
// such as window classes.
//
// Parameters:
// HANDLE hInstance
// Handle to this instance of the application.
//
//---------------------------------------------------------------------------
BOOL NEAR InitApplication( HANDLE hInstance )
{
WNDCLASS wndclass ;
// register tty window class
wndclass.style = 0 ;
wndclass.lpfnWndProc = TTYWndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = sizeof( DWORD ) ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( TTYICON ) );
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;
wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ;
wndclass.lpszMenuName = MAKEINTRESOURCE( TTYMENU ) ;
wndclass.lpszClassName = gszTTYClass ;
return( RegisterClass( &wndclass ) ) ;
} // end of InitApplication()
//---------------------------------------------------------------------------
// HWND NEAR InitInstance( HANDLE hInstance, int nCmdShow )
//
// Description:
// Initializes instance specific information.
//
// Parameters:
// HANDLE hInstance
// Handle to instance
//
// int nCmdShow
// How do we show the window?
//
//---------------------------------------------------------------------------
HWND NEAR InitInstance( HANDLE hInstance, int nCmdShow )
{
HWND hTTYWnd ;
// load accelerators
ghAccel = LoadAccelerators( hInstance, MAKEINTRESOURCE( TTYACCEL ) ) ;
// create the TTY window
hTTYWnd = CreateWindow( gszTTYClass, gszAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL ) ;
if (NULL == hTTYWnd)
return ( NULL ) ;
ShowWindow( hTTYWnd, nCmdShow ) ;
UpdateWindow( hTTYWnd ) ;
return ( hTTYWnd ) ;
} // end of InitInstance()
//---------------------------------------------------------------------------
// LRESULT FAR PASCAL TTYWndProc( HWND hWnd, UINT uMsg,
// WPARAM wParam, LPARAM lParam )
//
// Description:
// This is the TTY Window Proc. This handles ALL messages
// to the tty window.
//
// Parameters:
// As documented for Window procedures.
//
//---------------------------------------------------------------------------
LRESULT FAR PASCAL TTYWndProc( HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam )
{
LONG lrc;
switch (uMsg)
{
case WM_CREATE:
break;
case WM_COMMAND:
{
switch ((DWORD) wParam)
{
case ID_SETTINGS_CONFIGURE:
/* get current port settings */
lrc = sizeof(COMMCONFIG);
GetCommConfig (hComm, &cc, &lrc);
/* display dialog to modify settings */
if (!CommConfigDialog(lpszCommName,hWnd, &cc))
break;
/* write new settings */
if (!SetCommState (hComm, &cc.dcb))
break;
break;
case IDM_ABOUT:
GoModalDialogBoxParam ( GETHINST( hWnd ),
MAKEINTRESOURCE( ABOUTDLGBOX ),
hWnd,
AboutDlgProc, 0 ) ;
break;
case IDM_EXIT:
PostMessage( hWnd, WM_CLOSE, 0, 0L ) ;
break ;
}
}
break ;
case WM_PAINT:
PaintTTY( hWnd ) ;
break ;
case WM_SIZE:
SizeTTY( hWnd, HIWORD( lParam ), LOWORD( lParam ) ) ;
break ;
case WM_HSCROLL:
ScrollTTYHorz( hWnd, (WORD) wParam, LOWORD( lParam ) ) ;
break ;
case WM_VSCROLL:
ScrollTTYVert( hWnd, (WORD) wParam, LOWORD( lParam ) ) ;
break ;
case WM_CHAR:
/* echo to local window if echo turned on */
if (LOCALECHO (pTTYInfo)) {
WriteTTYBlock(hWnd, (LPBYTE)&wParam, 1 );
}
/* write out the character to the COM Port */
if (!WriteFile(hComm, (LPBYTE)&wParam, 1, &lrc, NULL)) {
/* handle error */
locProcessCommError(GetLastError ());
} /* end if (error reading bytes) */
break ;
case WM_SETFOCUS:
SetTTYFocus( hWnd ) ;
break ;
case WM_KILLFOCUS:
KillTTYFocus( hWnd ) ;
break ;
case WM_DESTROY:
PostQuitMessage( 0 ) ;
break ;
case WM_CLOSE:
if (IDOK != MessageBox( hWnd, "OK to close window?", "TTY Sample",
MB_ICONQUESTION | MB_OKCANCEL ))
break ;
// fall through
default:
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
}
return 0L ;
} // end of TTYWndProc()
//---------------------------------------------------------------------------
// DWORD ReadThread(LPDWORD lpdwParam1)
//
// Description:
// Thread dedicated to reading bytes from the COM port
//
//
// Parameters:
// LPDWORD lpdwParam1
// Thread data (not used)
//
//---------------------------------------------------------------------------
/* This is an example of the overlapped, signalled reading of bytes from a COM port */
/*Note the use of FALSE in the last flag to GetOverlappResult, telling the function to return immediately if all the bytes requested have not been read. The alternative code section, which is compiled out with #if 0, has the same flag set TRUE. In t
his case, GetOverlappedResult will not return until all the bytes are read
Also note that use of this code for interactive terminals will produce an annoying
"blockyness" as Windows waits for 10 bytes at a time. This can be fixed by
setting the number of bytes to read to merely 1.
*/
/* THIS CODE REQUIRES THAT THE COM PORT BE OPENED FOR OVERLAPPED I/O */
DWORD ReadThread (LPDWORD lpdwParam1)
{
BYTE inbuff[100];
DWORD nBytesRead, endtime, lrc;
static OVERLAPPED o;
/* the next two lines check to make sure that total timeouts
are supported */
if (!cp.dwProvCapabilities & PCF_TOTALTIMEOUTS)
return 1L;
/* the next four lines set the total timeout interval */
memset (&to, 0, sizeof(to));
to.ReadTotalTimeoutMultiplier = 5;
to.ReadTotalTimeoutConstant = 1000;
SetCommTimeouts (hComm, &to);
/* create a manual-reset event */
o.hEvent = CreateEvent (NULL, /* lpsa */
TRUE, /* manual reset */
FALSE, /* init state non sig */
NULL);
/* read loop */
while (bReading) {
/* try to read 10 bytes */
if (!ReadFile(hComm, inbuff, 10, &nBytesRead, &o)) {
/* if there are not ten bytes waiting in read buffer, then
ERROR_IO_PENDING is returned */
/* if ReadFile failed, the number of returned bytes not
valid, so zero out and wait to get correct number from
GetOverlappedResult */
nBytesRead = 0;
if ((lrc=GetLastError()) == ERROR_IO_PENDING) {
#if 0
if (GetOverlappedResult(hComm, &o, &nBytesRead, TRUE)) {
if (nBytesRead)
locProcessBytes(inbuff, nBytesRead);
} else {
locProcessCommError(GetLastError ());
}
#endif
#if 1
/* wait 1 second for the ten bytes */
endtime = GetTickCount() + 1000;
/* wait for overlapped I/O to complete */
while (!GetOverlappedResult(hComm, &o, &nBytesRead,
FALSE)) {
/* do additional processing here - perhaps get and displatch
messages to keep the menus alive */
/* .... */
/* make sure timeout has not expired */
if (GetTickCount() > endtime) {
break;
}
} /* end while (I/O still pending) */
/* if I/O retrieved some bytes, then process bytes */
if (nBytesRead) {
locProcessBytes(inbuff, nBytesRead);
}
#endif
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -