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

📄 wincom.c

📁 使用xmodem进行串口通讯的程序
💻 C
字号:
/////////////////////////////////////////////////////////////////////////////
//
//  Sample Windows Communications Program for Doctor Dobb's Journal
//
//	WINCOM.C	- Written by Mike Sax for Dr. Dobb's Journal
//
//	This file contains a small communications program and uses the terminal
//	window control and xmodem file transfer functions.
//
////////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include "wincom.h"
#include "terminal.h"
#include "comm.h"
#include "xmodem.h"

// Global variables:
HWND static ghMainWindow;			// The handle of our main window
HANDLE static ghInstance;			// The instance handle of our application
HICON static ghIcon;				// The handle of the main icon
char static *gszClass = "wincom";	// The class name of our main window
int static gnPortID;				// The current port ID (<0 if none)
int static gnPortNum;				// The current port number (1=COM1)
static char gszFilename[81];		// Used for XModem transfers
struct								// Used to fill in the combo-boxes
	{
	WORD wID;						// ID of the combo box
	char *szText;					// String that we should add
	} static gaInitTable[] =
	{
	IDD_COMBOPORT,          "COM1:",    IDD_COMBOPORT,          "COM2:",
	IDD_COMBOPORT,          "COM3:",    IDD_COMBOPORT,          "COM4:",
	IDD_COMBOBAUD,          "300",      IDD_COMBOBAUD,          "1200",
	IDD_COMBOBAUD,          "2400",     IDD_COMBOBAUD,          "4800",
	IDD_COMBOBAUD,          "9600",     IDD_COMBOBAUD,          "19200",
	IDD_COMBOSETTINGS,      "N-8-1",    IDD_COMBOSETTINGS,      "E-7-1",
	IDD_COMBOSETTINGS,      "O-7-1",    IDD_COMBOSETTINGS,      "M-7-1",
	IDD_COMBOSETTINGS,      "S-7-1",    IDD_COMBOHANDSHAKING,   "None",
	IDD_COMBOHANDSHAKING,   "XOn/XOff", IDD_COMBOHANDSHAKING,   "Hardware",
	0,                      NULL
	};
int static ganBaud[] = { 300, 1200, 2400, 4800, 9600, 19200 };

// Static functions:
static void Status(char *szText);
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine,
				   int nCmdShow);
static BOOL InitInstance(int nCmdShow);
static BOOL InitModule(void);
static BOOL DoEvents(void);

// Exported functions:
BOOL FAR PASCAL _export InputDlgProc(HANDLE hDlg, WORD wMessage, WORD wParam,
						 DWORD lParam);
BOOL FAR PASCAL _export MainDlgProc(HANDLE hDlg, WORD wMessage, WORD wParam,
						 DWORD lParam);

// DoEvents is a function in our program that processes all messages
// in the message queue and returns FALSE if a WM_QUIT message was
// received.  It also handles dialog box messages for our main window.
static BOOL DoEvents(void)
	{
	MSG msg;

	// Process messages until the message queue is empty or we we have
	// to quit
	while(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
		{
		if (msg.message == WM_QUIT)
			{
			PostQuitMessage(msg.wParam);
			return FALSE;
			}
		// IsDialogMessage processes the message if it was meant for
		// our main window (which is a modeless dialog box).
		if (!IsDialogMessage(ghMainWindow, &msg))
			{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			}
		}
	return TRUE;
	}

// InitApplication is called only once, even if multiple instances of our
// program are running.  Returns TRUE if succes, FALSE if failure
static BOOL InitModule(void)
	{
	WNDCLASS wc;

	wc.style = 0;
	wc.lpfnWndProc = DefDlgProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = DLGWINDOWEXTRA;
	wc.hInstance = ghInstance;
	wc.hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(1));
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = "DDJCOM";
	return RegisterClass(&wc);
	}

// InitInstance is called once for every instance of our applications.  It
// creates the main window.  Returns TRUE if succes, FALSE if failure
static BOOL InitInstance(int nCmdShow)
	{
	if (!InitTerminal(ghInstance))
		return FALSE;
	ghMainWindow = CreateDialog(ghInstance, MAKEINTRESOURCE(1), NULL,
						MakeProcInstance((FARPROC)MainDlgProc, ghInstance));
	if (!ghMainWindow)
		return FALSE;
	ShowWindow(ghMainWindow, nCmdShow);
	ghIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(1));
	return TRUE;
	}

// WinMain is the first C function that is called in our program.  It's
// the equivalent of main() in non-windows C programs.
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine,
				   int nCmdShow)
	{
	ghInstance = hInstance;

	if( !hPrevInstance )
		if (!InitModule())
			return 0;
	if (!InitInstance(nCmdShow))
		return 0;
	gnPortNum = 1;
	gnPortID = OpenComPort(gnPortNum);
	if (gnPortID < 0)
		Status("ERROR:  Cannot open port COM1:");
	else
		SetComPortParameters(gnPortID, 2400, 'N', 8, 1, FALSE, FALSE);

	// This is our main message loop.  The DoEvents function processes
	// messages and gives control to other windows.  If we have nothing
	// else to do, we process character from the current comm. port.
	while(DoEvents())
		{
		int nChar;

		nChar = ComReadChar(gnPortID);
		while(nChar >= 0)
			{
			SendDlgItemMessage(ghMainWindow, IDD_TERMINAL, TW_SENDCHAR,
							   nChar, 0l);
			nChar = ComReadChar(gnPortID);
			}
		}
	if (gnPortID >= 0)
		CloseComPort(gnPortID);
	return 0;
	}

// This is the dialog-function of our main window.	The main window is a
// modeless dialog box with its own class.
BOOL FAR PASCAL _export MainDlgProc(HANDLE hDlg, WORD wMessage, WORD wParam,
						 DWORD lParam)
	{
	switch(wMessage)
		{
		case WM_INITDIALOG:
			{
			int i;

			// Fill in the combo boxes in our main window
			for(i = 0 ; gaInitTable[i].wID ; ++i)
				SendDlgItemMessage(hDlg, gaInitTable[i].wID, CB_ADDSTRING, 0,
								   (long)(LPSTR)gaInitTable[i].szText);
			SendDlgItemMessage(hDlg, IDD_COMBOPORT, CB_SETCURSEL, 0, 0l);
			SendDlgItemMessage(hDlg, IDD_COMBOBAUD, CB_SETCURSEL, 2, 0l);
			SendDlgItemMessage(hDlg, IDD_COMBOSETTINGS, CB_SETCURSEL, 0, 0l);
			SendDlgItemMessage(hDlg, IDD_COMBOHANDSHAKING, CB_SETCURSEL, 0,
							0l);
			return TRUE;
			}
		case WM_SIZE:
			{
			RECT rectTerminal, rectStatus, rectDialog;
			int cyStatus, cxDialog, cyDialog;
			POINT ptClientOrigin;

			GetWindowRect(GetDlgItem(hDlg, IDD_TERMINAL), &rectTerminal);
			GetWindowRect(GetDlgItem(hDlg, IDD_TEXTSTATUS), &rectStatus);
			GetClientRect(hDlg, &rectDialog);
			// Make all rectangles relative to the dialog window
			ptClientOrigin.x = ptClientOrigin.y = 0;
			ClientToScreen(hDlg, &ptClientOrigin);
			OffsetRect(&rectTerminal, -ptClientOrigin.x, -ptClientOrigin.y);
			OffsetRect(&rectStatus, -ptClientOrigin.x, -ptClientOrigin.y);
			cyStatus = rectStatus.bottom - rectStatus.top;
			cxDialog = rectDialog.right - rectDialog.left;
			cyDialog = rectDialog.bottom - rectDialog.top;
			MoveWindow(GetDlgItem(hDlg, IDD_TERMINAL), 0, rectTerminal.top,
					   cxDialog, cyDialog - rectTerminal.top - cyStatus, TRUE);
			MoveWindow(GetDlgItem(hDlg, IDD_TEXTSTATUS), 0,
					   cyDialog - cyStatus, cxDialog, cyStatus, TRUE);
			}
			break;
		case WM_COMMAND:
			switch(wParam)
				{
				case IDOK:          // User pressed Enter
				case IDCANCEL:      // User pressed Escape
					SetFocus(GetDlgItem(hDlg, IDD_TERMINAL));
					break;
				case IDM_CLEAR:
					// Clear screen by sending a clear screen to the terminal
					SendDlgItemMessage(hDlg, IDD_TERMINAL, TW_SENDCHAR,
							   12, 0l);
					break;
				case IDM_DOWNLOAD:
				case IDM_UPLOAD:
					{
					FARPROC lpInputProc;
					int bSuccess = FALSE;

					if ((lpInputProc = MakeProcInstance((FARPROC)InputDlgProc,
								ghInstance)) != (FARPROC) NULL)
						{
						if (DialogBox(ghInstance, MAKEINTRESOURCE(2), hDlg,
							lpInputProc))
							{
							bSuccess = (wParam == IDM_DOWNLOAD) ?
							  DownloadXModem(hDlg, gnPortID, gszFilename) :
							  UploadXModem(hDlg, gnPortID, gszFilename);
							}
						FreeProcInstance(lpInputProc);
						}
					Status (bSuccess ? "File transfer successful." :
									   "File transfer aborted.");
					}
					break;
				case IDD_COMBOPORT:
					{
					int nNewPort = (int)SendDlgItemMessage(hDlg,
									IDD_COMBOPORT, CB_GETCURSEL, 0, 0l) + 1;
					if (HIWORD(lParam) != CBN_SELCHANGE)
						break;

					if (nNewPort != gnPortNum)
						{
						// Close the old port if it was opened
						if (gnPortID >= 0)
							CloseComPort(gnPortID);
						gnPortNum = nNewPort;
						gnPortID = OpenComPort(nNewPort);
						Status((gnPortID >= 0) ? "Port opened" :
							   "Error: Cannot open communcations port.");
						}
					SetFocus(GetDlgItem(hDlg, IDD_TERMINAL));
					}
					break;
				case IDD_COMBOBAUD:
				case IDD_COMBOSETTINGS:
				case IDD_COMBOHANDSHAKING:
					{
					char szScrap[10];
					int nBaud;
					int nHandShaking;

					if (HIWORD(lParam) != CBN_SELCHANGE)
						break;
					nBaud = ganBaud[SendDlgItemMessage(hDlg, IDD_COMBOBAUD,
									 CB_GETCURSEL, 0, 0l)];
					nHandShaking = SendDlgItemMessage(hDlg,
								  IDD_COMBOHANDSHAKING, CB_GETCURSEL, 0, 0l);
					SendDlgItemMessage(hDlg, IDD_COMBOSETTINGS, CB_GETLBTEXT,
								   (int)SendDlgItemMessage(hDlg,
								   IDD_COMBOSETTINGS, CB_GETCURSEL, 0, 0l),
								   (long)(LPSTR)szScrap);
					Status((SetComPortParameters(gnPortID, nBaud, szScrap[0],
						  szScrap[2] - '0', szScrap[4] - '0',
						  nHandShaking == 1, nHandShaking == 2)) ? "" :
						  "ERROR: Cannot set communications parameters");
					SetFocus(GetDlgItem(hDlg, IDD_TERMINAL));
					}
					break;
				case IDD_TERMINAL:
					SendDlgItemMessage(ghMainWindow, IDD_TERMINAL,
						 TW_SENDCHAR, HIWORD(lParam), 0l);
					ComWriteChar(gnPortID, HIWORD(lParam));
					break;
				case IDM_EXIT:
					PostMessage(hDlg, WM_CLOSE, 0, 0l);
					break;
				default:
					return FALSE;
				}
			break;
		case WM_CLOSE:
			DestroyWindow(hDlg);
			PostQuitMessage(0);
			break;
		default:
			// We didn't process this message, so let Windows do it
			return FALSE;
		}
	return TRUE;    // Don't process the message: we already did
	}

// Show a message in the status bar
static void Status(char *szText)
	{
	SetDlgItemText(ghMainWindow, IDD_TEXTSTATUS, szText);
	}

// This is the dialog box function of the dialog box that is used to get
// the filename to transfer
BOOL FAR PASCAL _export InputDlgProc(HANDLE hDlg, WORD wMessage, WORD wParam,
						 DWORD lParam)
	{
	switch(wMessage)
		{
		case WM_COMMAND:
			if ((wParam == IDOK) || (wParam == IDCANCEL))
				{
				GetDlgItemText(hDlg, IDD_FILENAME, gszFilename,
							   sizeof(gszFilename) - 1);
				EndDialog(hDlg, wParam == IDOK);
				return TRUE;
				}
			break;
		}
	return FALSE;
	}

⌨️ 快捷键说明

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