Jeg har fået lavet et første udkast.
Det virker ligesom et terminal program, du kan skrive en at-kommando (f.ex. AT eller ATZ) og trykke Send (eller enter) så vil det sende beskeden og modtage svar og skrive det ud.
Du skal nok starte med at sende IR
Når det sender putter det CR og LF på, det skal du måske fjerne (andet kald af WriteFile i HandleSend).
#include <windows.h>
#include <commctrl.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#define RX_THREAD_MESSAGE WM_APP
#define REG_KEY "Software\\\\HomeMadeApps\\\\ComPortMon"
class RegistryClass
{
public:
RegistryClass(const char *aKey)
{
if(RegOpenKey(HKEY_CURRENT_USER, aKey, &KeyHandle) != ERROR_SUCCESS)
{
if(RegCreateKeyEx(HKEY_CURRENT_USER, aKey, 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &KeyHandle, 0) != ERROR_SUCCESS)
KeyHandle = 0;
}
}
~RegistryClass()
{
if(KeyHandle)
RegCloseKey(KeyHandle);
}
int GetInt(const char *aKey, int aDefaultValue = 0)
{
if(!KeyHandle)
return aDefaultValue;
DWORD Type = REG_DWORD, Size = sizeof(DWORD);
int Value;
if(RegQueryValueEx(KeyHandle, aKey, 0, &Type, (BYTE *)&Value, &Size) != ERROR_SUCCESS)
return aDefaultValue;
return Value;
}
void WriteInt(const char *aKey, int aValue)
{
if(!KeyHandle)
return;
RegSetValueEx(KeyHandle, aKey, 0, REG_DWORD, (BYTE *)&aValue, sizeof(aValue));
}
char *GetString(const char *aKey, char *aBuffer, int aMaxSize)
{
if(!KeyHandle)
{
*aBuffer = 0;
return aBuffer;
}
DWORD Type = REG_SZ, Size = aMaxSize;
if(RegQueryValueEx(KeyHandle, aKey, 0, &Type, (BYTE *)aBuffer, &Size) != ERROR_SUCCESS)
*aBuffer = 0;
return aBuffer;
}
void WriteString(const char *aKey, const char *aBuffer)
{
if(!KeyHandle)
return;
RegSetValueEx(KeyHandle, aKey, 0, REG_SZ, (BYTE *)aBuffer, strlen(aBuffer));
}
private:
HKEY KeyHandle;
};
static LRESULT CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
void CleanUp(HWND aHwnd, HANDLE aPort);
bool RunRxThread = true;
bool RxThreadDone = false;
enum CtrlIdType
{
ListCtrlId = 1025,
EditCtrlId,
ExitButtonCtrlId,
SendButtonCtrlId = IDOK
};
/* Add a line of text to the list box
** Make sure the line is visible Scroll as requred
** Adjust the horz scrollbar */
void AddListText(HWND aMainWnd, const char *aMsg)
{
static int MaxWidth;
int idx;
HWND List;
HDC dc;
HFONT Font, OldFont;
SIZE TextSize, SizeExtra;
List = GetDlgItem(aMainWnd, ListCtrlId);
idx = SendMessage(List, LB_ADDSTRING, 0, (LPARAM )aMsg);
SendMessage(List, LB_SETCARETINDEX, idx, 0);
dc = GetDC(List);
Font = (HFONT )SendMessage(aMainWnd, WM_GETFONT, 0, 0);
OldFont = (HFONT )SelectObject(dc, Font);
GetTextExtentPoint32(dc, aMsg, strlen(aMsg), &TextSize);
GetTextExtentPoint32(dc, "WWW", 3, &SizeExtra);
TextSize.cx += SizeExtra.cx;
if(TextSize.cx > MaxWidth)
{
MaxWidth = TextSize.cx;
SendMessage(List, LB_SETHORIZONTALEXTENT, MaxWidth, 0);
}
SelectObject(dc, OldFont);
ReleaseDC(List, dc);
}
/* Grab the text from the edit-box and send it on the com-port
** The text is appended to the list-box
*/
void HandleSend(HWND aHWnd, HANDLE ComPort)
{
char buffer[128];
GetDlgItemText(aHWnd, EditCtrlId, buffer, sizeof(buffer));
char Text[130];
sprintf(Text, ">%s", buffer);
AddListText(aHWnd, Text);
DWORD Dummy;
WriteFile(ComPort, buffer, strlen(buffer), &Dummy, 0);
WriteFile(ComPort, "\\r\\n", 2, &Dummy, 0);
SetDlgItemText(aHWnd, EditCtrlId, "");
}
BOOL CALLBACK SetFontProc(HWND aHWnd, LPARAM lParam)
{
SendMessage(aHWnd, WM_SETFONT, lParam, 0);
return TRUE;
}
struct ThreadParamType
{
HWND HWnd;
HANDLE ComPort;
};
DWORD WINAPI RxThreadProc(LPVOID aParam)
{
ThreadParamType *ThreadParam = (ThreadParamType *)aParam;
while(RunRxThread)
{
unsigned char Buffer[128];
DWORD Length, i;
ReadFile(ThreadParam->ComPort, Buffer, 128, &Length, 0);
for(i = 0; i < Length; i++)
{
char *Msg = new char [64];
sprintf(Msg, "%02X %3u %c", Buffer[ i ], Buffer[ i ], isprint(Buffer[ i ]) ? Buffer[ i ] : '.');
PostMessage(ThreadParam->HWnd, RX_THREAD_MESSAGE, (WPARAM )Msg, 0);
}
Sleep(100);
}
RxThreadDone = true;
delete ThreadParam;
return 0;
}
int APIENTRY WinMain(HINSTANCE aHInst, HINSTANCE, LPSTR, int)
{
WNDCLASS wc;
memset(&wc, 0, sizeof(WNDCLASS));
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = DialogFunc;
wc.hInstance = aHInst;
wc.hbrBackground = (HBRUSH )(COLOR_BTNFACE + 1);
wc.lpszClassName = "MainDialogClass";
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
if(!RegisterClass(&wc))
return FALSE;
HWND WindowHandle = CreateWindow("MainDialogClass",
"Whatever", // Caption text
WS_MINIMIZEBOX | WS_VISIBLE | WS_CLIPSIBLINGS | WS_THICKFRAME |
WS_CLIPCHILDREN | WS_MAXIMIZEBOX | WS_CAPTION | WS_BORDER | WS_SYSMENU,
100, 100, 140, 160, // Position
0,
0,
aHInst,
0);
MSG Msg;
while(GetMessage(&Msg, 0, 0, 0xFFFF) > 0)
{
if(!IsDialogMessage(WindowHandle, &Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
return 0;
}
void OnSize(HWND aMainWnd, int aWidth, int aHeight)
{
HWND hwnd;
hwnd = GetDlgItem(aMainWnd, SendButtonCtrlId);
MoveWindow(hwnd, 5, aHeight - 25, 50, 20, TRUE);
hwnd = GetDlgItem(aMainWnd, ExitButtonCtrlId);
MoveWindow(hwnd, 70, aHeight - 25, 50, 20, TRUE);
hwnd = GetDlgItem(aMainWnd, EditCtrlId);
MoveWindow(hwnd, 5, aHeight - 55, aWidth - 10, 25, TRUE);
hwnd = GetDlgItem(aMainWnd, ListCtrlId);
MoveWindow(hwnd, 5, 5, aWidth - 10, aHeight - 65, TRUE);
}
void SetTimeOut(HANDLE Port, int sec)
{
COMMTIMEOUTS commtimeouts;
GetCommTimeouts(Port, &commtimeouts);
commtimeouts.ReadIntervalTimeout = 1000*sec;
commtimeouts.ReadTotalTimeoutMultiplier = 10;
commtimeouts.ReadTotalTimeoutConstant = 1000*sec;
SetCommTimeouts(Port, &commtimeouts);
}
HANDLE SetupComport(HWND aHWnd)
{
DCB dcb;
HANDLE Port = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if(Port == INVALID_HANDLE_VALUE)
{
MessageBox(aHWnd, "Failed to open port", "Whatever", MB_OK);
return 0;
}
GetCommState(Port, &dcb);
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fOutxCtsFlow = 1;
SetCommState(Port, &dcb);
SetTimeOut(Port, 1);
DWORD RxThreadID;
ThreadParamType *ThreadParam = new ThreadParamType;
ThreadParam->ComPort = Port;
ThreadParam->HWnd = aHWnd;
CreateThread(0, 0, RxThreadProc, (LPVOID )ThreadParam, 0, &RxThreadID);
return Port;
}
/*
** This is the main function for the main dialog. It handles all messages.
*/
static LRESULT CALLBACK DialogFunc(HWND aDlg, UINT aMsg, WPARAM wParam, LPARAM lParam)
{
static HANDLE ComPort;
switch(aMsg)
{
case WM_CREATE:
{
CreateWindowEx(WS_EX_CLIENTEDGE,
"LISTBOX",
"",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | WS_HSCROLL | LBS_NOINTEGRALHEIGHT,
5, 5, 100, 100,
aDlg,
(HMENU )ListCtrlId,
0,
0);
CreateWindowEx(WS_EX_CLIENTEDGE,
"Edit",
"",
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
5, 80, 250, 22,
aDlg,
(HMENU )EditCtrlId,
0,
0);
CreateWindow("BUTTON",
"Send",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,
5, 100, 50, 20,
aDlg,
(HMENU )SendButtonCtrlId,
0,
0);
CreateWindow("BUTTON",
"Exit",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
5, 100, 50, 20,
aDlg,
(HMENU )ExitButtonCtrlId,
0,
0);
HWND Edit = GetDlgItem(aDlg, EditCtrlId);
SetFocus(Edit);
RegistryClass Registry(REG_KEY);
RECT R;
R.left = Registry.GetInt("LeftPos", -1);
if(R.left != -1)
{
R.right = Registry.GetInt("RightPos", R.left + 200);
R.top = Registry.GetInt("TopPos", 100);
R.bottom = Registry.GetInt("BottomPos", R.top + 200);
MoveWindow(aDlg, R.left, R.top, R.right - R.left, R.bottom - R.top, TRUE);
}
else
{
GetClientRect(aDlg, &R);
OnSize(aDlg, R.right - R.left, R.bottom - R.top);
}
EnumChildWindows(aDlg, SetFontProc, (LPARAM )GetStockObject(DEFAULT_GUI_FONT));
HFONT Font = CreateFont(12, /* nHeight */
0, /* nWidth */
0, /* nEscapement */
0, /* nOrientation */
FW_NORMAL, /* nWeight */
FALSE, /* bItalic */
FALSE, /* bUnderline */
0, /* cStrikeOut */
ANSI_CHARSET, /* nCharSet */
OUT_DEFAULT_PRECIS, /* nOutPrecision */
CLIP_DEFAULT_PRECIS, /* nClipPrecision */
DEFAULT_QUALITY, /* nQuality */
DEFAULT_PITCH | FF_SWISS, /* nPitchAndFamily */
"Courier"); /* lpszFacename */
SendDlgItemMessage(aDlg, ListCtrlId, WM_SETFONT, (WPARAM )Font, 0);
ComPort = SetupComport(aDlg);
return FALSE;
}
case RX_THREAD_MESSAGE:
{ // Here we receive a message from the thread
char *text = (char *)wParam;
AddListText(aDlg, text);
delete [] text;
}
break;
case WM_GETMINMAXINFO:
{
MINMAXINFO *MinMaxInfo = (MINMAXINFO *)lParam;
MinMaxInfo->ptMinTrackSize.x = 200;
MinMaxInfo->ptMinTrackSize.y = 200;
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ExitButtonCtrlId:
CleanUp(aDlg, ComPort);
PostMessage(aDlg, WM_QUIT, 1, 1);
break;
case SendButtonCtrlId:
HandleSend(aDlg, ComPort);
return 0;
}
break;
case WM_SIZE:
OnSize(aDlg, LOWORD(lParam), HIWORD(lParam));
return 0;
}
return DefWindowProc(aDlg, aMsg, wParam, lParam);
}
void CleanUp(HWND aHwnd, HANDLE aPort)
{
RunRxThread = false;
RegistryClass Registry(REG_KEY);
RECT R;
GetWindowRect(aHwnd, &R);
Registry.WriteInt("LeftPos", R.left);
Registry.WriteInt("RightPos", R.right);
Registry.WriteInt("TopPos", R.top);
Registry.WriteInt("BottomPos", R.bottom);
if(!aPort)
return;
for(int i = 0; !RxThreadDone && i < 20; i++)
Sleep(100);
}
[Redigeret d. 15/08-05 01:25:47 af Bertel Brander]