📄 wincom.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 + -