#include "stdafx.h" #include "Com.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif TCom *Me; TCom::TCom(void) { InTime = new CWnd; HMODULE Instance; char* ClassAtom; WNDCLASS WC; HWND Window; Instance = GetModuleHandle(NULL); WC.style = 0; WC.lpfnWndProc = &DefWindowProc; WC.cbClsExtra = 0; WC.cbWndExtra = 0; WC.hInstance = Instance; WC.hIcon = LoadIcon(0, IDI_WINLOGO); WC.hCursor = LoadCursor(0, IDC_ARROW); WC.hbrBackground = 0; WC.lpszMenuName = NULL; WC.lpszClassName = "CommoTimerWindowClass"; ClassAtom = (char*)(ULONG(RegisterClass(&WC))); Window = CreateWindowEx(0, ClassAtom, "CommoTimer", WS_POPUP, 0, 0, 128, 32, 0, 0, WC.hInstance, NULL); InTime->Attach(Window); /* InTime needs to become a non-NULL hWnd, so it can be used as a timer to call InTimeTimer char Buf[200]; HWND H; H = CreateWindow("BUTTON", "InTime", 0, 0, 0, 10, 10, GetDesktopWindow(), NULL, NULL, NULL); itoa((int)H, Buf, 10); MessageBox(NULL, Buf, "Debug", 0); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, Buf, 200, NULL); MessageBox(NULL, Buf, "Debug", 0); InTime->Attach(H); //*/ Me = this; Connected = FALSE; hCom = INVALID_HANDLE_VALUE; } TCom::~TCom() { if (Connected) InTime->KillTimer(ITE); InTime->Detach(); delete(InTime); //Release the memory used by the read/write events if (osReader.hEvent) CloseHandle(osReader.hEvent); if (osWriter.hEvent) CloseHandle(osWriter.hEvent); //Release the COM port if (hCom != INVALID_HANDLE_VALUE) CloseHandle(hCom); } BOOL TCom::OpenCom(BYTE Port) { COMMTIMEOUTS Tim; CString ComStr; BOOL Result = FALSE; if (Connected) return(Result); ComStr.Format("\\\\.\\COM%i", Port); //asynchronous hCom = CreateFile((LPCTSTR) ComStr, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (hCom == INVALID_HANDLE_VALUE) //If failed to open COM port return(Result); //Else we can use the port, so let's set up communications SetupComm(hCom, 1026, 255); //In buffer = 1026 bytes, out buffer = 255 bytes Tim.ReadIntervalTimeout = 5; Tim.ReadTotalTimeoutConstant = 0; //No read total timeout, we want to get all the data that comes our way Tim.ReadTotalTimeoutMultiplier = 0; Tim.WriteTotalTimeoutConstant = 0; //No write timeout. Tim.WriteTotalTimeoutMultiplier = 0; SetCommTimeouts(hCom, &Tim); GetCommState(hCom, &ComDCB); //Fill ComDCB with current data ComDCB.BaudRate = 9600; ComDCB.ByteSize = 7; ComDCB.Parity = EVENPARITY; ComDCB.StopBits = ONESTOPBIT; SetCommState(hCom, &ComDCB); if (!(Result = StartRead())) CloseCom(); return(Result); } void TCom::SetBaud(DWORD Baud) { if (!Connected) return; ComDCB.BaudRate = Baud; /* ComDCB.ByteSize = 7; ComDCB.Parity = EVENPARITY; ComDCB.StopBits = ONESTOPBIT; */ SetCommState(hCom, &ComDCB); } void TCom::CloseCom(void) { if (!Connected) return; if (Connected) { InTime->KillTimer(ITE); Connected = FALSE; } //Release the COM port CloseHandle(hCom); hCom = INVALID_HANDLE_VALUE; } DWORD TCom::WriteCom(const char *Data) { CString Buf; DWORD ILen; DWORD Result = 0; BOOL Ret = 0; if (!Connected) return(Result); Buf = "\r"; Buf = Data + Buf; ILen = Buf.GetLength(); Ret = WriteFile(hCom, (LPCTSTR) Buf, ILen, &Result, &osWriter); Ret = GetOverlappedResult(hCom, &osWriter, &Result, true); return(Result); } void CALLBACK EXPORT InTimeTimer(HWND DumHandle, UINT DumMessage, UINT DumEvent, DWORD DumTime) { static BOOL Parsing = FALSE; DWORD I; if (!GetOverlappedResult(Me->hCom, &Me->osReader, &Me->BytesRead, FALSE)) { if (Parsing) return; Parsing = TRUE; try { if (Me->InLin.GetLength()) { I = Me->InLin.Find(13); while (~I) { if (Me->OnReadCom) Me->OnReadCom((LPCTSTR) Me->InLin.Left(I)); Me->InLin = Me->InLin.Mid(I+1); I = Me->InLin.Find(13); } } Parsing = FALSE; } catch(...) { Parsing = FALSE; } } else { Me->InBuf[Me->BytesRead] = 0; //Note the length of the incoming string Me->InLin += Me->InBuf; Me->StartRead(); } } BOOL TCom::StartRead(void) { static BOOL FirstRead = TRUE; BOOL Result; if (Connected) { InTime->KillTimer(ITE); Connected = FALSE; } if (FirstRead) //Handle creation of the asynchronous structures and read event { osWriter.Internal = 0; osWriter.InternalHigh = 0; osWriter.Offset = 0; osWriter.OffsetHigh = 0; osWriter.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);; osReader.Internal = 0; osReader.InternalHigh = 0; osReader.Offset = 0; osReader.OffsetHigh = 0; osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); FirstRead = FALSE; } Result = FALSE; do { if (ReadFile(hCom, &InBuf[0], 255, &BytesRead, &osReader)) //if read completed immediately { InBuf[BytesRead] = 0; //Note the length of the incoming string InLin += InBuf; } else if (GetLastError() == ERROR_IO_PENDING) //elseif the problem was that we'll have to wait, good - setup reading Result = TRUE; else return(Result); } while (!Result); ITE = InTime->SetTimer(1, 25, &InTimeTimer); Connected = TRUE; return(Result); }