求助纠错无须独占串口的VC的DEMO转BCB
早前在本论坛发帖问过如何不独占串口监控串口数据,大家都知道要用API,可没人真正玩出来。有个作者jfyes做出了CommMonitor串口监视精灵,该软件可以监控串口数据,无需独占串口,在工作中起了很大的作用。
4.0版的有二次开发SDK接口 DEMO,是DLL,更可惜只有delphi和VC的,因为对VC连入门级都算不上,踉踉跄跄地凑合成了bcb,可是搞得被监控的串口程序(尤其是BCB编制的程序)运行得不是很稳定了,常弹内存警告,请高人指点。
CommMonitor串口监视精灵DEMO界面:
http://www.ceiwei.com/upfile/2010123155902469.jpg
代码下载(内有详细接口说明):
http://www.skycn.com/soft/64411.html
http://www.crsky.com/soft/19798.html
有段源码是借用妖哥的minispy。
头文件:
#ifndef Unit1H
#define Unit1H
//---------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <ExtCtrls.hpp>
#include <Graphics.hpp>
#define IDC_START 1002
//---------------------------------------
class TForm1 : public TForm
{
__published:// IDE-managed Components
TComboBox *ComboBox1;
TComboBox *ComboBox2;
TLabel *Label3;
TLabel *Label4;
TCheckBox *CheckBox1;
TStatusBar *StatusBar1;
TButton *Button3;
TButton *Button4;
TImage *ImageDrag;
TTimer *Timer1;
TRichEdit *RichEdit1;
void __fastcall ImageDragMouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y);
void __fastcall ImageDragMouseMove(TObject *Sender,
TShiftState Shift, int X, int Y);
void __fastcall ImageDragMouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall Button3Click(TObject *Sender);
void __fastcall Timer1Timer(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button4Click(TObject *Sender);
private:// User declarations
public:// User declarations
__fastcall TForm1(TComponent* Owner);
void OnStartMonitor(HWND hDlg);
void FindItem(LPCSTR AStr, HWND hComBox);
};
//---------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------
#endif
.cpp
#include <vcl.h>
#pragma hdrstop
#include <windows.h>
#include "commctrl.h"
#include <RICHEDIT.h>
#include <commdlg.h>
#include <shellapi.h>
#include <stdio.h>
#include <tlhelp32.h>
#include "Unit1.h"
//---------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#define MAX_LOADSTRING 100
#define COMM_OPEN 1
#define COMM_CLOSE 2
#define COMM_READ 3
#define COMM_WRITE 4
#pragma pack(push)
#pragma pack(1) //设置为1字节对齐
typedef struct _HookData
{
BYTE ComPort; //串口号
BYTE CommState; //串口状态
HFILE FileHandle; //被打开的文件句柄 长整型无符号
int DataSize; //数据大小 长整型有符号
char Data [8192] ; //串口数据
} THookData, *PHookData;
#pragma pack(pop)
//DLL 实例句柄
HINSTANCE gPMonitorComm = NULL;
typedef LONG(CALLBACK *TOnData)(LONG lParam);
typedef BOOL(CALLBACK *TMonitorComm)(DWORD Pid, DWORD ComIndex, TOnData lpCallFunc);
typedef BOOL(CALLBACK *TUnMonitorComm)(void);
typedef void(CALLBACK *TGetAllProcess)(HWND hComBox);
TMonitorComm MonitorComm; //启动串口监视
TUnMonitorComm UnMonitorComm; //关闭串口监视, 返BOOL类型
TGetAllProcess GetAllProcess; //取得全部进程ID
//////////////////////////////
LONG ReadTotal = 0;
LONG WriteTotal = 0;
HWND hMemo = NULL;
HWND hHex = NULL;
//是否是启动监视
BOOL bActive = FALSE;
HINSTANCE HInst;
BOOL MouseLButtonDown = FALSE;
bool bMouseDown; // 鼠标按下的标志
bool bScrollFlag; // 窗体上卷的标志
const int crMy = 1;
HANDLE hWindow, hOldWindow; // 取得的窗口句柄
TRect ClassRect, OldClassRect;
TForm1 *Form1;
//---------------------------------------
__fastcall TForm1::TForm1(TComponent *Owner)
: TForm(Owner)
{
}
[解决办法]
//---------------------------------------
int FormatHex(HWND hHex, char *d, int len, LPSTR lpOutText)
{
char hex[4] = {0};
char h = 0;
if (SendMessage(hHex, BM_GETCHECK, 0, 0) != BST_CHECKED)
{
lstrcat(lpOutText, d);
return len;
}
for (int i = 0; i < len; i++)
{
//因为是无符号,所以要这右移4位
int j = (d[i] >> 4) & 0xF;
if (j <= 9) h = j + '0';
else h = j + 'A' - 10;
memset(hex, 0, sizeof(hex));
sprintf(hex, "%C", h);
lstrcat(lpOutText, hex);
j = d[i] & 0xF;
if (j <= 9) h = j + '0';
else h = j + 'A' - 10;
sprintf(hex, "%C ", h);
lstrcat(lpOutText, hex);
}
return lstrlen(lpOutText);
}
DWORD GetPid(LPCSTR lpText)
{
int len;
char buf[6];
len = lstrlen(lpText);
for (int i = 0; i < len; i++)
{
if (lpText[i] == 32)
{
buf[i] = 0x00;
break;
}
else
buf[i] = lpText[i];
}
return DWORD(atol(buf));
}
void FindItem(LPCSTR AStr, HWND hComBox)
{
int i;
char buf[24];
char line[24];
//首先更新ComBox
int iCount = SendMessage(hComBox, CB_GETCOUNT, 0, 0);
for (i = 0; i < iCount; i++)
{
int Len = SendMessage(hComBox, CB_GETLBTEXTLEN, i, 0);
if (Len != CB_ERR)
{
memset(line , 0, sizeof(line));
if (SendMessage(hComBox, CB_GETLBTEXT, i, LONG(&line)) == 0)
continue;
memset(buf, 0, sizeof(buf));
lstrcpyn(buf, line, lstrlen(AStr) + 1);
if (lstrcmp(buf, AStr) == 0)
{
SendMessage(hComBox, CB_SETCURSEL, i, 0);
break;
}
}
}
}
void GetFromWindowPid(HWND hComBox)
{
tagPOINT Pt;
DWORD PID;
HWND H;
char Buf[24] = {0};
//if ActiveCapture then Exit;
if (!GetCursorPos(&Pt)) return;
H = WindowFromPoint(Pt);
if (H > 0)
{
GetWindowThreadProcessId(H, &PID);
if (PID < 5) return;
memset(Buf, 0, sizeof(Buf));
sprintf(Buf, "%-8d ", PID);
FindItem(Buf, hComBox);
}
}
/*以下三段代码引用自妖哥的minispy开源程序*/
void __fastcall TForm1::ImageDragMouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
if(Button == mbLeft)
{
hWindow = NULL;
hOldWindow = NULL;
::SetCursor(LoadCursor(HInstance, "MyCur"));
bMouseDown = true;
ImageDrag->Hide();
}
}
//---------------------------------------
void __fastcall TForm1::ImageDragMouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
POINT MousePoint, p1, p2;
char bufClassName[255], bufClassCaption[255];
int TextLength;
if(bMouseDown)
{
GetCursorPos(&MousePoint);
hWindow = WindowFromPoint(MousePoint);
// 所取得的对象句柄必须不属于本程序
if(hWindow != NULL && hWindow != Handle
&& !PtInRect(BoundsRect, MousePoint) && hWindow != hOldWindow)
{
if(hOldWindow != NULL)
{
Canvas->Handle = GetWindowDC(hOldWindow);
Canvas->Pen->Width = 4;
Canvas->Pen->Mode = pmNotXor;
Canvas->Brush->Style = bsClear;
Canvas->Rectangle(0, 0, OldClassRect.Width(), OldClassRect.Height());
}
GetWindowRect(hWindow, &ClassRect);
if(hWindow != NULL)
{
Canvas->Handle = GetWindowDC(hWindow);
Canvas->Pen->Width = 4;
Canvas->Pen->Color = clRed;
Canvas->Pen->Mode = pmNotXor;
Canvas->Brush->Style = bsClear;
Canvas->Rectangle(0, 0, ClassRect.Width(), ClassRect.Height());
}
OldClassRect = ClassRect;
hOldWindow = hWindow;
GetClassName(hWindow, bufClassName, 255);
TextLength = SendMessage(hWindow, WM_GETTEXTLENGTH, 0, 0);
if(TextLength>256)
TextLength = 255;
}
GetFromWindowPid(ComboBox1->Handle);
}
}
//---------------------------------------
void __fastcall TForm1::ImageDragMouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
if(bMouseDown)
{
if(hOldWindow != NULL)
{
Canvas->Handle = GetWindowDC(hOldWindow);
Canvas->Pen->Width = 4;
Canvas->Pen->Mode = pmNotXor;
Canvas->Brush->Style = bsClear;
Canvas->Rectangle(0, 0, OldClassRect.Width(), OldClassRect.Height());
}
::SetCursor(LoadCursor(NULL, IDC_ARROW));
ImageDrag->Cursor = crHandPoint;
bMouseDown = false;
ImageDrag->Show();
}
}
int GetMemoCount(HWND hMemo)
{
int Result = SendMessage(hMemo, EM_GETLINECOUNT, 0, 0);
if(SendMessage(hMemo,
EM_LINELENGTH,
SendMessage(hMemo, EM_LINEINDEX, Result - 1, 0),
0) == 0)
Result--;
return Result;
}
void MemoPut(HWND hMemo, int Index, char *data)
{
SendMessage(hMemo, EM_SETSEL, 666536+Index, 666536);
SendMessage(hMemo, EM_REPLACESEL, true, (LPARAM)data);
}
LONG CALLBACK AOnData(LONG lParam) //THookData* p
{
PHookData p = NULL;
p = PHookData(lParam);
if (p)
{
char buf[255] = {0};
char data[8912*3+64] = {0};
if (p->CommState == COMM_OPEN)
{
sprintf(buf, "打开 COM%d \r\n", p->ComPort);
}
else if (p->CommState == COMM_CLOSE)
{
sprintf(buf, "关闭 COM%d \r\n", p->ComPort);
}
else if ((p->CommState == COMM_READ)
[解决办法]
(p->CommState == COMM_WRITE))
{
if (p->CommState == COMM_READ)
{
sprintf(buf, "COM%d, Read: %d(Bytes) ", p->ComPort, p->DataSize);
ReadTotal += p->DataSize;
}
else
{
sprintf(buf, "COM%u, Write: %d(Bytes) ", p->ComPort, p->DataSize);
WriteTotal += p->DataSize;
}
lstrcat(data, buf);
FormatHex(hHex, p->Data, p->DataSize, data);
lstrcat(data, "\r\n");
MemoPut(hMemo, GetMemoCount(hMemo) + 1, data);
return IDOK;
}
MemoPut(hMemo, GetMemoCount(hMemo) + 1, buf);
}
return IDOK;
}
[解决办法]
void TForm1::OnStartMonitor(HWND hDlg)
{
if (!bActive)
{
char buf[255] = {0};
StrCopy(buf,ComboBox1->Text.c_str() );
DWORD Pid = GetPid(buf);
DWORD ComID = SendMessage(ComboBox2->Handle, CB_GETCURSEL, 0, 0);
if (Pid < 5)
{
memset(buf, 0, sizeof(buf));
sprintf(buf, "无效的进程ID: %d", Pid);
MessageBox(hDlg, buf, "提示", MB_OK
[解决办法]
MB_ICONERROR);
return;
}
bActive = MonitorComm(Pid, ComID, (TOnData)AOnData);
if (bActive)
{
Button3->Caption ="停止监视";
char p[64] = {0};
memset(buf, 0, sizeof(buf));
SendMessage(ComboBox1->Handle, CB_GETLBTEXT, 0, (LPARAM)p);
sprintf(buf, "打开监视成功, %s\r\n", p);
StatusBar1->Panels->Items[0]->Text=buf;
}
}
else
{
UnMonitorComm();
bActive = FALSE;
MemoPut(hMemo, GetMemoCount(hMemo) + 1, "成功关闭监视\r\n");
Button3->Caption ="启动监视";
}
ComboBox1->Enabled=bActive;
return;
}
void TForm1::FindItem(LPCSTR AStr, HWND hComBox)
{
int i;
char buf[24];
char line[24];
//首先更新ComBox
int iCount = SendMessage(hComBox, CB_GETCOUNT, 0, 0);
for (i = 0; i < iCount; i++)
{
int Len = SendMessage(hComBox, CB_GETLBTEXTLEN, i, 0);
if (Len != CB_ERR)
{
memset(line , 0, sizeof(line));
if (SendMessage(hComBox, CB_GETLBTEXT, i, LONG(&line)) == 0)
continue;
memset(buf, 0, sizeof(buf));
lstrcpyn(buf, line, lstrlen(AStr) + 1);
if (lstrcmp(buf, AStr) == 0)
{
SendMessage(hComBox, CB_SETCURSEL, i, 0);
break;
}
}
}
}
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
if (MessageBox(Handle, "确定要退出吗?", "提示", MB_OKCANCEL
[解决办法]
MB_ICONINFORMATION) != IDOK)
return;
if (bActive) OnStartMonitor(Handle);
//释放DLL库
FreeLibrary(gPMonitorComm);
}
//---------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
OnStartMonitor(Handle);
}
//---------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
GetAllProcess(ComboBox1->Handle);
if (bActive)
if (SendMessage(ComboBox1->Handle, CB_GETCURSEL, 0, 0) < 0)
PostMessage(ComboBox1->Handle, WM_COMMAND, IDC_START, 0);
}
//---------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
hMemo= RichEdit1->Handle;
hHex = CheckBox1->Handle;
Button4->Caption ="清空";
CheckBox1->Caption="HEX/ASC";
SendMessage(hHex, BM_SETCHECK, 1, 0);
gPMonitorComm = LoadLibrary("PMonitorComm4.dll");
if (!gPMonitorComm)
{
MessageBox(GetForegroundWindow(), "加载PMonitorComm.dll失败,请检察该DLL是否存在。", "提示", MB_OK
[解决办法]
MB_ICONERROR);
return;
}
//取得func地址
MonitorComm = (TMonitorComm)GetProcAddress(gPMonitorComm, "MonitorComm");
UnMonitorComm = (TUnMonitorComm)GetProcAddress(gPMonitorComm, "UnMonitorComm");
GetAllProcess = (TGetAllProcess)GetProcAddress(gPMonitorComm, "GetAllProcess");
if (!MonitorComm)
{
MessageBox(0, "MonitorComm function address无效。", "提示", MB_OK
[解决办法]
MB_ICONERROR);
return;
}
if (!UnMonitorComm)
{
MessageBox(0, "UnMonitorComm function address无效。", "提示", MB_OK