Code:
	/************************************************************
** CommThread      : Öffnet, schließt und liest den Port,
**                   sendet die Zeiten per PostThreadMessage
**                   an den MonitorThread
************************************************************/
#include <windows.h>
#include <process.h>
#include <stdio.h>
// Prototypes:
DWORD WINAPI ComThread (LPVOID lpParam);
DWORD WINAPI MonitorThread (LPVOID lpParam);
HANDLE StartComThread (DWORD iPortNum, HWND hEdit);
long queryPrecisionTime (void);
long queryPrecisionTimeStamp (void);
// Globals:
HANDLE hCom = INVALID_HANDLE_VALUE;
// global struc contains parameter for threads
typedef struct
{
	volatile BOOL ThreadStoppen;
	volatile int iComPortNum;
	volatile DWORD  dwMonitorThreadId;
} PARAMS, *PPARAMS;
static HANDLE hEvent; 
// Message types
#define MSG_MIN_RANGE      0
// Der Message-Type für PostThreadMessage setzt sich aus
// QS_ALLPOSTMESSAGE (=256) und dem eigenem Message-Type 
// (siehe MSG_xxxxxxx) zusammen.
// Mit MSG_MIN_RANGE können verschiedene Gruppen bei 
// Bedarf gebildet werden.
#define MSG_TIME        MSG_MIN_RANGE + 1000 // vom ComThread
#define MSG_TRIG        MSG_MIN_RANGE + 2000 // reserviert
#define MSG_COMOPEN     MSG_TRIG + 4
#define MSG_COMCLOSE    MSG_TRIG + 5
#define QEVENT     "QueueEvent"
//--------------------------------------------------------------------
// COMThread
//
// erstellt eine Queue, setzt danach den Event ("Queue ist ready").
// Schließt eine geöffneten COM-Port und öffnet den neuen (Nummer ist
// in der Strukur, auf die lpParam zeigt).
// liest die queue aus.
//
// Thread Funktion
// Liest eventgesteuert den Status von CTS, DSR, ... ein und
// sendet in dwEvtMask alle zum Event gehörenden Ereignisse
// zum Monitor-Thread. 
// 
//--------------------------------------------------------------------
DWORD WINAPI ComThread (LPVOID lpParam) 
{
	long lTime;
	volatile PPARAMS pparams;                     // struct-Instanz
	pparams = (PPARAMS) lpParam;                  // Zuweisung zu lpParam
	int iPortNum = pparams->iComPortNum;          // ...
	DWORD dwMonitorThreadId = pparams->dwMonitorThreadId; // ...
	char szPort[15];
	static OVERLAPPED o;
	// Maske für SetCommMask, die bestimmt, welche Ereignisse auftreten können
	DWORD dwEvtMaskIn = EV_CTS | EV_DSR | EV_BREAK | EV_RING | EV_RXCHAR | 
											EV_RLSD | EV_ERR | EV_RXFLAG | EV_TXEMPTY;
	DWORD dwEvtMask = 0;  // Maske, in die WaitCommEvent aktuelle Werte schreibt
	BOOL bRet;
	CloseHandle (hCom);       // "alten" COM-Port schließen
	// Com Port öffnen
  wsprintf (szPort, "COM%d", iPortNum);
	hCom = CreateFile (szPort, 
		GENERIC_READ | GENERIC_WRITE,
    0,    // exclusive access 
    NULL, // no security attributes 
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL);
	if (hCom == INVALID_HANDLE_VALUE)
	{
		LPVOID lpMsgBuf;
		FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL, GetLastError (), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
			(LPTSTR) &lpMsgBuf, 0, NULL);
		MessageBox (NULL, (LPCTSTR)lpMsgBuf, TEXT("ComThread: error: CreateFile()"), 
			MB_OK | MB_ICONINFORMATION);
		LocalFree (lpMsgBuf);
		pparams->ThreadStoppen = TRUE;
	}
	else
	{
		if (!SetCommMask (hCom, dwEvtMaskIn)) 
			MessageBox (NULL, "SetCommMask fehlgeschlagen", "COM Port:", MB_OK | MB_ICONSTOP);
		// Create an event object for use in WaitCommEvent. 
		o.hEvent = CreateEvent (NULL,   // no security attributes 
				FALSE,  // auto reset event 
				FALSE,  // not signaled 
				NULL);  // no name 
	}
  // Setzt die Priorität "RealTime" für das Programm
  DWORD  dwProcessId;  // own process identifier
  HANDLE hProcess;                 // handle to the own process
  DWORD  dwDesiredAccess = PROCESS_SET_INFORMATION;  // access flag
  BOOL   bInheritHandle = TRUE;   // handle inheritance flag
  BOOL   bReturn;           // If the SetPriorityClass succeeds, then nonzero
  DWORD  dwPriorityClass = HIGH_PRIORITY_CLASS;
  dwProcessId = GetCurrentProcessId ();
  hProcess = OpenProcess (dwDesiredAccess, bInheritHandle, dwProcessId);
  bReturn = SetPriorityClass (hProcess, dwPriorityClass);
	printf ("\r\nComThread: %s geöffnet, warte auf Events ...", szPort);
	// eine message zum Monitor-Thread senden:
	bRet = PostThreadMessage (dwMonitorThreadId, (QS_ALLPOSTMESSAGE + MSG_COMOPEN), 
			(WPARAM)iPortNum , (LPARAM)0);
	// Auf Events warten:
	while (!pparams->ThreadStoppen) // solange weitermachen bis TRUE
	{
		WaitCommEvent (hCom, &dwEvtMask, &o);  // EventMask "scharf machen"
		// kommt der Event, ist auch die dwEvtMask geladen und es kann weitergehen
		if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) // warten bis Event
		{
			lTime = queryPrecisionTimeStamp ();  // Zeit holen
			// Message senden. In dwEvtMask können mehrere Ereignisse gesetzt sein
			bRet = PostThreadMessage (dwMonitorThreadId, (QS_ALLPOSTMESSAGE + MSG_TIME), 
					(WPARAM)dwEvtMask , (LPARAM)lTime);
		}    // end of: if (WAIT_OBJECT_0 == ...
	}      // end of: while (...
	CloseHandle (o.hEvent);
	CloseHandle (hCom);          // COM-Port schließen
	printf ("\r\nComThread: %s geschlossen", szPort);
	bRet = PostThreadMessage (dwMonitorThreadId, (QS_ALLPOSTMESSAGE + MSG_COMCLOSE), 
			(WPARAM)iPortNum , (LPARAM)0);
	return (0);
}
//----------------------------------------------------------------------------
// MonitorThread
//
// erstellt eine Queue, setzt danach den Event und liest
// die queue aus
//----------------------------------------------------------------------------
DWORD WINAPI MonitorThread (LPVOID lpParam) 
{ 
	static char szMsg[255] = "";
	static char szMsgTmp[30] = "";
	int i = 0;
	BOOL bRet;
	MSG msg;
	volatile PPARAMS pparams;                     // struct-Instanz
	pparams = (PPARAMS) lpParam;                  // Zuweisung zu lpParam
	DWORD COMStatus;
	// create a queue for the thread
	PeekMessage ((LPMSG)&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
	// sent event after queue creation back to the threads creator
	bRet = SetEvent (hEvent);
	
	printf ("\r\nMonitorThread: warte auf Events ...");
	// get messages by message from threads local queue
	while ((bRet = GetMessage (&msg, NULL, 0, 0)) != 0)
	{
		if (bRet == -1)
		{ // handle the error and possibly exit
			MessageBox (NULL, "MonitorThread: GetMessage error", "COM Port:", MB_OK | MB_ICONSTOP);
			return NULL;  // error!
		}
		else  
		{ // a valid message is received
			switch (msg.message)
			{
			case (QS_ALLPOSTMESSAGE + MSG_COMOPEN):
				printf ("\r\nMonitorThread: MSG_COMOPEN: lParam=0x%08x wParam=0x%08x", 
					msg.lParam, msg.wParam);
				break;
				
			case (QS_ALLPOSTMESSAGE + MSG_COMCLOSE):
				printf ("\r\nMonitorThread: MSG_COMCLOSE: lParam=0x%08x wParam=0x%08x", 
					msg.lParam, msg.wParam);
				break;
				
			case (QS_ALLPOSTMESSAGE + MSG_TIME):
				// Time stamp message: lParam=time, wParam=dwEvtMask
				szMsg[0] = '\0';
				if (DWORD(msg.wParam) & EV_CTS)
				{
					GetCommModemStatus (hCom, &COMStatus);
					if (COMStatus & MS_CTS_ON)
					{ // CTS (Pin8) activated
						wsprintf (szMsgTmp, "\r\nCTS_ON : %lu µs", msg.lParam);
					}
					else
					{ // CTS (Pin8) deactivated
						wsprintf (szMsgTmp, "\r\nCTS_OFF: %lu µs", msg.lParam);
					}
					strcat (szMsg, szMsgTmp);
				}
				if (DWORD(msg.wParam) & EV_DSR)
				{
					GetCommModemStatus (hCom, &COMStatus);
					if (COMStatus & MS_DSR_ON)
					{ // DSR (Pin6) activated
						wsprintf (szMsgTmp, "\r\nDSR_ON : %lu µs", msg.lParam);
					}
					else
					{ // DSR (Pin6) deactivated
						wsprintf (szMsgTmp, "\r\nDSR_OFF: %lu µs", msg.lParam);
					}
					strcat (szMsg, szMsgTmp);
				}
				if (DWORD(msg.wParam) & EV_RLSD)
				{
					GetCommModemStatus (hCom, &COMStatus);
					if (COMStatus & MS_RLSD_ON)
					{ // DCD (Pin1) activated
						wsprintf (szMsgTmp, "\r\nRLSD_ON: %lu µs", msg.lParam);
					}
					else
					{ // DCD (Pin1) deactivated
						wsprintf (szMsgTmp, "\r\nRLSD_OFF: %lu µs ", msg.lParam);
					}
					strcat (szMsg, szMsgTmp);
				}
				if (DWORD(msg.wParam) & EV_RING)
				{
					GetCommModemStatus (hCom, &COMStatus);
					if ((COMStatus & MS_RING_ON))
					{ // RI (Pin9) activated
						wsprintf (szMsgTmp, "\r\nRING_ON: %lu µs", msg.lParam);
					}
					else
					{ // RI (Pin9) deactivated
						wsprintf (szMsgTmp, "\r\nRING_OFF: %lu µs", msg.lParam);
					}
					strcat (szMsg, szMsgTmp);
				}
				printf (szMsg);
				break;
				
			default:
				wsprintf (szMsg, "\r\nMonitorThread: default: lParam=0x%08x wParam=0x%08x message=0x%08x", 
					msg.lParam, msg.wParam, msg.message);
				MessageBox (NULL, (LPCTSTR)szMsg, "COM Port:", MB_OK | MB_ICONSTOP);
				break;
			}  // end of: switch (msg.message)
		}    // end of: if (bRet == -1) else ...
	}      // end of: while((bRet = GetMessage(...
	
	printf ("\r\nMonitorThread: beendet");
	return 0; 
} 
// Globale Variablen
// struct für Zeitmessung
union ut_LargeInteger
{
	LARGE_INTEGER o_WinPart;
	ULONGLONG       l_MyPart;
};
int i_ResetPrecisionTime = 0;
ULONGLONG l_PerfFrequ;
ut_LargeInteger uo_PerfCount;
/************************************************************************
Die Funktion queryPrecisionTimeStamp () liefert die seit dem Start des PC
verstrichene Zeit in Mikrosekunden.
************************************************************************/
long queryPrecisionTimeStamp (void)
{
	if (i_ResetPrecisionTime == 0)
	{
		i_ResetPrecisionTime = 1;
		QueryPerformanceFrequency (&uo_PerfCount.o_WinPart);
		l_PerfFrequ = uo_PerfCount.l_MyPart;
	}
	
	ut_LargeInteger uo_perfCount;
	QueryPerformanceCounter (&uo_perfCount.o_WinPart);
	return (long) (uo_perfCount.l_MyPart * 1000000 / l_PerfFrequ);
}
// *********************************************************************
int main (void)
{
	DWORD  dwMonThreadId;
	DWORD  dwComThreadId;
	HANDLE hMonThread;
	HANDLE hComThread;
	DWORD  dwState;
	PARAMS p;
	// MonitorThread erstellen:
	// Erstellt den Event für die Thread Queue
	hEvent = CreateEvent (NULL, false, true, QEVENT);
	// Thread starten und uMonThreadID für ComThread merken
	hMonThread = CreateThread (      // Handle des Threads
      NULL,                        // no security attributes 
      0,                           // use default stack size  
      MonitorThread,               // thread function 
      &p,                          // argument to thread function 
      0,                           // use default creation flags 
      &dwMonThreadId);             // returns the thread identifier 
	
	if (hMonThread == NULL) 
		printf ("\r\nCreateThread (MonitorThread) fehlgeschlagen");
	p.dwMonitorThreadId = dwMonThreadId;  // merken, für ComThread
	
	// wait for queue completition
	dwState = WaitForSingleObject (hEvent, 100);
	CloseHandle (hEvent);
	// "alten" Thread stoppen  
	p.ThreadStoppen = TRUE;
	CloseHandle (hComThread); // "alten" Thread stoppen
	p.iComPortNum = 1;
	// ComThread: Starten und Parameterstruct übergeben
	p.ThreadStoppen = FALSE;
	hComThread = CreateThread (    // Handle des Threads
    NULL,                        // no security attributes 
    0,                           // use default stack size  
    ComThread,                   // thread function 
    &p,                          // argument to thread function 
    0,                           // use default creation flags 
    &dwComThreadId);             // returns the thread identifier 
	if (hComThread == NULL) 
		printf ("\r\nCreateThread (ComThread) fehlgeschlagen");
	Sleep (30000); // nur so zum Test
	CloseHandle (hMonThread);    // MonitorThread beenden
	CloseHandle (hComThread);    // ComThread beenden
	return (0);
}
 Anpassen an die Borland-Sytax/Notation sollte nicht schwer sein.
Lesezeichen