📄 lane_newdlg.cpp
字号:
// 卡重新初始化
void CLane_newDlg::ProcessCaptureWindow(WPARAM wParam,LPARAM lParam)
{
HRESULT hr;
int id;
BOOL bIsConnected = TRUE;
int iCardNumber;
char szDeviceName[MAX_DEVICE_NUM][MAX_DEVICE_NAME_LEN];
const char sz10Moons[] = {"10Moons"};
switch(wParam){
case RESET_CAPTURE: //交班时复位捕获设备
case OVERLAY_CAPTURE: //捕获窗口进入Overlay模式,
// DSStream_DisconnectDevice(0);
// capDriverDisconnect(hWndc);
break;
case POWER_ON_CAPTURE:
//寻找可用的卡,剔除非10Moons卡
hr = DSStream_EnumVideoCaptureDev(szDeviceName, &iCardNumber);
if(FAILED(hr))
{
//AfxMessageBox("枚举失败", MB_OK, 0);
SendMessage(WM_ABNORMAL,0,(LPARAM)"枚举视频卡失败");
return;
}
for(id=0; id<iCardNumber; id++)
{
szDeviceName[id][7] = '\0';
hr = DSStream_IsConnected(id, &bIsConnected);
if(FAILED(hr))
{
bIsConnected = TRUE;
break;
}
if(_stricmp(szDeviceName[id], sz10Moons) != 0)
{
bIsConnected = TRUE;
continue;
}
if(!bIsConnected)
break;
}
int nLineWidth=nScreenX/320;
int nLeft=nScreenX*125/192-nLineWidth;
int nRight=nScreenX*63/64;
int nTop=nScreenY*25/48-2*nLineWidth;
int nButtom=nScreenY*41/48-nLineWidth;
theApp.memDC.Rectangle(nLeft,nTop,nRight,nButtom);
//无可用的卡
if(bIsConnected || id>=iCardNumber)
{
SendMessage(WM_ABNORMAL,0,(LPARAM)"没有可用的视频卡失败");
return;
}
VIDEOSTREAMINFO vsi;
RECT rc;
const BOOL bOverlay2=FALSE;//现在把它设置为捕获方式
hr = DSStream_ConnectDevice(id, bOverlay2);
if(FAILED(hr))
{
SendMessage(WM_ABNORMAL,0,(LPARAM)"连接视频卡失败");
return;
}
hr = DSStream_GetVideoInfo(id, &vsi, PREVIEW);
if(FAILED(hr))
return;
//设置视频制式
DSStream_SetVideoStandard(id,VideoStandard_PAL_D);
//设置视频源
DSStream_RouteInPinToOutPin(id,1, 0);
vsi.subtype = VideoSubType_RGB24;
vsi.bmiHeader.biWidth=352;
vsi.bmiHeader.biHeight=288;
DSStream_SetVideoInfo(id, vsi, PREVIEW);
int width = vsi.bmiHeader.biWidth;
int height = vsi.bmiHeader.biHeight;
hWndc2=capCreateCaptureWindow("",WS_POPUP|WS_VISIBLE,
// 0,0,640,480,m_hWnd,0);
nLeft+2*nLineWidth,nTop+2*nLineWidth,nScreenX/3-nLineWidth,
nScreenY/3-nLineWidth,m_hWnd,0);
DSStream_SetOwnerWnd(id,hWndc2);
rc.left=rc.top=0;
rc.right=width;
rc.bottom=height;
DSStream_SetWindowPos(id, rc);
break;
}
/*int LineWidth,Left,Right,Buttom,Top;
switch(wParam){
case RESET_CAPTURE: //交班时复位捕获设备
case OVERLAY_CAPTURE: //捕获窗口进入Overlay模式,
capDriverDisconnect(hWndc);
break;
case POWER_ON_CAPTURE:
LineWidth=nScreenX/320;
Left=nScreenX*125/192-LineWidth;
Right=nScreenX*63/64;
Top=nScreenY*25/48-2*LineWidth;
Buttom=nScreenY*41/48-LineWidth;
theApp.memDC.Rectangle(Left,Top,Right,Buttom);
hWndc=capCreateCaptureWindow("",WS_POPUP|WS_VISIBLE,
Left+2*LineWidth,Top+2*LineWidth,nScreenX/3-LineWidth,
nScreenY/3-LineWidth,m_hWnd,0);
//在对话框右下脚产生捕获窗口
break;
}
if(hWndc==NULL) return;
capSetCallbackOnError(hWndc,CaptureErrorCallBack);
//设置捕获图象错误回调函数
capDriverConnect(hWndc,0); //连接到捕获卡驱动程序
if(wParam==OVERLAY_CAPTURE){
// 若进入Overlay模式,将捕获设备设置为Overlay工作模式
capOverlay(hWndc,TRUE);
bOverlayMode=TRUE; //视频卡工作在非捕获模式
return;
}
// 否则,需要设置捕获设备的参数
struct {
BITMAPINFOHEADER BmpHead;
RGBQUAD QuadColor[256];
} BitmapInfo;
for(int i=0;i<256;i++){
BitmapInfo.QuadColor[i].rgbBlue=i;
BitmapInfo.QuadColor[i].rgbGreen=i;
BitmapInfo.QuadColor[i].rgbRed=i;
BitmapInfo.QuadColor[i].rgbReserved=i;
}
// 估计因为设备驱动程序或硬件不兼容,本部分设置在WINDOW 2000下无
// 法配置视频卡,视频卡使用了缺省配置:16位彩色、高度288、宽度352
// 现象:启动计算机后必须先调用圆刚公司的演示程序,然后再运行车道
// 软件,否则显示的图象不正确
// 解决办法:1、配置为16位彩色,但尚未找到压缩16位彩色的方法;
// 2、改用NT操作系统;3、用圆刚的二次开发包函数代替标准WINDOWS的
// 视频捕获函数;4、换一台WINDOWS 2000的机子实验一下是否和本机的
// 硬件有关
BitmapInfo.BmpHead.biBitCount=24;
BitmapInfo.BmpHead.biClrImportant=0;
BitmapInfo.BmpHead.biClrUsed=0;
BitmapInfo.BmpHead.biCompression=BI_RGB;
BitmapInfo.BmpHead.biHeight=nScreenY/2;
BitmapInfo.BmpHead.biPlanes=1;
BitmapInfo.BmpHead.biSize=sizeof(BitmapInfo.BmpHead);
BitmapInfo.BmpHead.biSizeImage=0; //对BI_RGB格式,此项可为0
BitmapInfo.BmpHead.biWidth=nScreenX/2;
BitmapInfo.BmpHead.biXPelsPerMeter=0;
BitmapInfo.BmpHead.biYPelsPerMeter=0;
capSetVideoFormat(hWndc,&BitmapInfo,sizeof(BitmapInfo));
CAPTUREPARMS CaptureParms;
capCaptureGetSetup(hWndc,&CaptureParms,sizeof(CAPTUREPARMS));
//获取当前捕获流参数
CaptureParms.dwRequestMicroSecPerFrame=66667;
//15帧/秒 帧速率(帧数/微秒)
CaptureParms.fCaptureAudio=FALSE; //不捕捉音频信号
capCaptureSetSetup(hWndc,&CaptureParms,sizeof (CAPTUREPARMS));
//设置捕获参数
//Preview模式可以捕获图片
capPreviewScale(hWndc,TRUE); //按捕获窗口的大小显示图象
capPreviewRate(hWndc,67); //每秒15帧
capPreview(hWndc,TRUE); //进入预览模式
bOverlayMode=FALSE; //视频卡工作在捕获模式*/
bStartCaptureFlag=FALSE; //捕获标志复位*/
}
// 操作系统将视频图象捕获到内存后自动调用该函数,本函数负责通知车道
// 软件视频图象已经成功地放入内存
void CALLBACK FinishCaptureImage(
HWND hwnd, // handle of destination window
UINT uMsg, // message
DWORD dwData, // application-defined value
LRESULT lResult // result of message processing
){
if((uMsg==WM_CAP_GRAB_FRAME_NOSTOP)&&(lResult!=0)){
SendMessage(theApp.m_pMainWnd->m_hWnd,WM_FINISH_CAPTURE,dwData,0);
}
}
// 抓拍视频图形进内存。如果上一幅图片尚未处理完成,本次不捕获图片;
// 若上幅图片已经处理完成,向操作系统发送视频捕获命令并指定捕获行为
// 完成后应调用的回调函数
void CLane_newDlg::ProcessCapture(WPARAM wParam,LPARAM lParam)
{
DWORD RetValue=1;
//if(bOverlayMode) return; //工作在非捕获模式时不抓拍图像
if(bStartCaptureFlag) return; //上幅图片未捕获完,不再捕获
theApp.muxPicture.Lock();
if(bSavePictureFlag){ //上幅图片未压缩完,不再捕获
theApp.muxPicture.Unlock();
return;
}
theApp.muxPicture.Unlock();
bStartCaptureFlag=TRUE;
/*在这里处理图像抓拍*/
pSize=0;
pData=NULL;
theApp.muxPicture.Lock();
bStartCaptureFlag=TRUE;
theApp.muxPicture.Unlock();
DSStream_GetCurrentDib(0,pData,&pSize);
if(pSize!=0){
pData=new BYTE[pSize];
DSStream_GetCurrentDib(0,pData,&pSize);
if(pData==NULL){
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"捕捉图像进内存失败\n",SMTO_BLOCK,200,&RetValue);
return;
}
}else{
// pData=new BYTE[160000];
// memset(pData,0,160000);
// DSStream_GetCurrentDib(0,pData,&pSize);
// if(pData==NULL){
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"捕捉图像进内存失败\n",SMTO_BLOCK,200,&RetValue);
return;
// }
}
theApp.muxPicture.Lock();
bStartCaptureFlag=FALSE;
theApp.muxPicture.Unlock();
//SendMessageCallback(hWndc,WM_CAP_GRAB_FRAME_NOSTOP,0,0,FinishCaptureImage,wParam);
}
// 将内存中的视频图象拷贝到剪切板成功后调用该回调函数。本函数负责
// 通知车道软件图象已经在剪切板上
/*void CALLBACK FinishSaveImage(
HWND hwnd, // handle of destination window
UINT uMsg, // message
DWORD dwData, // application-defined value
LRESULT lResult // result of message processing
){
if((uMsg==WM_CAP_EDIT_COPY)&&(lResult!=0)){
// 数据已经拷贝到剪贴板上,允许压缩图片
bCaptureSuccessFlag=TRUE;
}
}*/
// 命令操作系统将内存中的视频图象拷贝到剪切板上
void CLane_newDlg::ProcessFinishCapture(WPARAM wParam,LPARAM lParam)
{
//SendMessageCallback(hWndc,WM_CAP_EDIT_COPY,(WPARAM)0,0,FinishSaveImage,wParam);
}
// 需要存储抓拍到的图像文件时调用本函数。本函数根据图像类型设定
// 文件名并将该名称传到图像压缩线程。为了防止两个线程同时调用文
// 件名字符串,使用互斥量保护资源。图像存储类型由wParam指定
void CLane_newDlg::ProcessSavePicture(WPARAM wParam,LPARAM lParam)
{
// 假如剪贴板上无新数据,不存储该帧图片
//if(!bCaptureSuccessFlag) return;
//bCaptureSuccessFlag=FALSE;
char strFileName[PICTURE_NAME_LEN];
memset(strFileName,0,PICTURE_NAME_LEN);
sprintf(strFileName,"%s\\",PICTURE_PATH);
int nLen=strlen(strFileName);
CRecord m_clsRecord;
m_clsRecord.GetPictureName(strFileName+nLen);
theApp.muxPicture.Lock();
bSavePictureFlag=TRUE;
memmove(strPictureName,strFileName,PICTURE_NAME_LEN);
theApp.muxPicture.Unlock();
bStartCaptureFlag=FALSE;
}
// 启动定时器函数。将当前时间和要定时的时长赋给定时器结构,并置定时
// 器激活标志。为了防止冲突,使用互斥量保护资源
void CLane_newDlg::ProcessStartupTimer(WPARAM wParam,LPARAM lParam)
{
struct timeb loc1;
theApp.muxTime.Lock();
ftime(&loc1);
theApp.muxTime.Unlock();
theApp.muxTimerOut.Lock();
if(wParam==ALL_TIMER){
for(int i=0;i<MAX_TIMER_COUNT;i++)
TimerOut[i].StartTime=loc1;
} else {
TimerOut[wParam].Active=1;
TimerOut[wParam].StartTime=loc1;
CLaneInfo m_clsLane;
switch(wParam){
case LEAVE_LOOP_TIMER:
TimerOut[wParam].TimerValue=m_clsLane.LeaveLoopDelays()*1000;
break;
case PICTURE_LOOP_TIMER:
TimerOut[wParam].TimerValue=m_clsLane.PictureLoopDelays()*1000;
break;
case AMBER_LIGHT_TIMER:
TimerOut[wParam].TimerValue=m_clsLane.AmberDelays()*1000;
break;
case ASK_IO_STATUS_TIMER:
TimerOut[wParam].TimerValue=5000;
break;
case SECOND_TIMER:
TimerOut[wParam].TimerValue=1000;
break;
case WORK_WINDOW_TIMER:
TimerOut[wParam].TimerValue=lParam;
break;
case PICTURE_QUERY_TIMER:
// 为了缩短生成图像到图像上传的时间,将30秒查询时间改为12秒
TimerOut[wParam].TimerValue=12000;
break;
case PICTURE_SEND_TIMER:
TimerOut[wParam].TimerValue=2000;
break;
case PICTURE_RESET_TIMER:
TimerOut[wParam].TimerValue=60000;
break;
case TFI_TIMER:
TimerOut[wParam].TimerValue=1500;
break;
case SOUND_TIMER:
TimerOut[wParam].TimerValue=lParam;
break;
case OVERLAY_TIMER:
TimerOut[wParam].TimerValue=lParam;
break;
case INITIAL_TIMER:
TimerOut[wParam].TimerValue=500;
break;
case ALARM_INFO_TIMER:
TimerOut[wParam].TimerValue=lParam;
break;
}
}
theApp.muxTimerOut.Unlock();
}
// 定时器超时后调用本程序,负责将超时消息传送到指定的类
// 根据“多型”的概念,本函数只负责将超时消息送到指定的
// 控制类,至于每个控制类对此消息如何处理和该函数无关
void CLane_newDlg::ProcessTimerOut(WPARAM wParam,LPARAM lParam)
{
m_clsDevice.ProcessTimerOut(wParam);
m_clsStatus.ProcessTimerOut(wParam);
m_clsPicture.ProcessTimerOut(wParam);
}
// 关闭定时器函数,将指定的定时器置为非激活状态
void CLane_newDlg::ProcessCloseTimer(WPARAM wParam,LPARAM lParam)
{
theApp.muxTimerOut.Lock();
if(wParam==ALL_TIMER){
for(int i=0;i<MAX_TIMER_COUNT;i++)
TimerOut[i].Active=0;
} else {
TimerOut[wParam].Active=0;
}
theApp.muxTimerOut.Unlock();
}
// 处理来自输入/输出外设的数据并将该数据传送到指定的类。为了防止
// 冲突,使用互斥量保护资源
void CLane_newDlg::ProcessCXP(WPARAM wParam,LPARAM lParam)
{
char tmpStr[8];
memset(tmpStr,0,8);
// 如果收到的数据长度不合法,说明通讯过程中出现错误,丢弃收到
// 的数据(设备边界类中处理这个错误)
// 上传的输入外设状态共7个字节,请求下传输出外设状态共1个字节
if((wParam==7)||(wParam==1)){
memmove(tmpStr,(char *)lParam,wParam);
} else {
// 指明正在接收数据,但所接收到的数据被丢弃
tmpStr[0]='E';
}
theApp.muxCxpFree.Lock();
bCxpFreeFlag=TRUE;
theApp.muxCxpFree.Unlock();
m_clsDevice.ProcessCxpInput(tmpStr);
}
// 处理来自打印机的数据并将该数据传送到指定的类
void CLane_newDlg::ProcessPrinter(WPARAM wParam,LPARAM lParam)
{
m_clsDevice.ProcessPrinter((char)wParam);
}
// 输入外设的状态发生变化调用该函数,将该消息转发到控制类
// CStatusControl进行处理
void CLane_newDlg::ProcessCxpStatus(WPARAM wParam,LPARAM lParam)
{
m_clsStatus.ProcessCxpStatus(wParam,(char)lParam);
}
// 有图象需要上传时调用本函数,负责通知图象传送类有图象需要传送
void CLane_newDlg::ProcessSendPicture(WPARAM wParam,LPARAM lParam)
{
CLaneInfo m_clsLane;
CRecord m_clsRecord;
char strFileName[PICTURE_NAME_LEN];
memset(strFileName,0,PICTURE_NAME_LEN);
memmove(strFileName,(char *)lParam,strlen((char *)lParam));
if(m_clsLane.RAM_Disk()){
m_clsRecord.RecordP(IMG_INDEX,IMG_TRANS,strFileName);
} else {
m_clsRecord.RecordP(IMG_INDEX_1,IMG_TRANS_1,strFileName);
}
}
// 车道软件收到收费站的下传文件并完成更新时调用本函数,负责将该
// 消息转发给控制类CStatusControl处理
void CLane_newDlg::ProcessUpdate(WPARAM wParam,LPARAM lParam)
{
switch(wParam){
case UPDATE_FILE: //正在更新运行参数文件
m_clsStatus.ProcessUpdate(wParam,"");
break;
case UPDATE_INVOICE: //正在更新发票起、止号
char tmpStr[72]; //7种发票号码
memset(tmpStr,0,72);
memmove(tmpStr,(char *)lParam,70);
m_clsStatus.ProcessUpdate(wParam,tmpStr);
break;
}
}
// 外设有数据输入时调用本函数,负责将该消息转发给控制类
// CStatusControl处理
void CLane_newDlg::ProcessStatusInfo(WPARAM wParam,LPARAM lParam)
{
m_clsStatus.ProcessStatusInfo((char *)lParam);
}
//处理字符叠加消息
/*
void CLane_newDlg::ProcessOverlay(WPARAM wParam,LPARAM lParam)
{
m_clsDevice.ProcessOverlayData((unsigned char)wParam);
}
*/
void CLane_newDlg::OnOK() //重载OnOK()使按回车键程序不退出
{
}
void CLane_newDlg::OnCancel() //重载OnCancel()使按Esc键程序不退出
{
}
// 本定时器只用于程序退出时
void CLane_newDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
PostMessage(WM_NORMAL_QUIT,NORMAL,0);
CDialog::OnTimer(nIDEvent);
}
void CLane_newDlg::WinHelp(DWORD dwData, UINT nCmd)
{
// TODO: Add your specialized code here and/or call the base class
// CDialog::WinHelp(dwData, nCmd);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -