LWQ
2025-08-13 12fc574703adc0528a7e905540dbd1ba26015c37
Merge branch 'side_inspection' of https://soft.boounion.cn/r/~liuyang/MiniLED_ADM into side_inspection
已修改21个文件
1158 ■■■■■ 文件已修改
EdgeInspector_App/BICommon.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Define/Global_Define.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Define/StatusMonitor.cpp 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Define/StatusMonitor.h 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Grabber/MulticamControl.cpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Grabber/MulticamControl.h 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Grabber/RadientControl.cpp 678 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Grabber/RadientControl.h 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Grabber/SapControl.cpp 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Grabber/SapControl.h 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Grabber/SapLineGrab.cpp 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Grabber/SapLineGrab.h 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Grabber/SoliosControl.cpp 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Grabber/SoliosControl.h 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/InterfaceManager.cpp 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Process/InspectCamera.cpp 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Recipe/HardwareSettings.cpp 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Recipe/HardwareSettings.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/View/GlassMap.cpp 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/View/ViewMain_HWSetting.cpp 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SDK/BlGrabber/include/GrabberControl.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/BICommon.h
@@ -8,7 +8,7 @@
#include <string>
#include <time.h>
#define OFFLINE_KEY           1   //OFFLINE_KEY:1是离线模式;0是在线模式
#define OFFLINE_KEY           0   //OFFLINE_KEY:1是离线模式;0是在线模式
#define MINI_LED              0   //Mini车间
#define MINI_NOTCH              0   //Mini车间, 是否使用刻槽功能
#define HALCON_VISION_KEY     1   //是否启用HALCON
EdgeInspector_App/Define/Global_Define.h
@@ -80,7 +80,7 @@
    enum    LIGHT_TYPE                    {LIGHT_TYPE_TRANS=0,LIGHT_TYPE_REF,LIGHT_TYPE_NONE};
    enum    LIGHT_MAKER                    {MAKER_LCP=0,MAKER_AKP,MAKER_NONE};
    enum    CAMERA_DIR                    {CAMDIR_TOP=0,CAMDIR_BOTTOM,CAMDIR_NONE};
    enum    CAMERA_DIR                    {CAMDIR_TOP=0,CAMDIR_BOTTOM,CAMDIR_SIDE,CAMDIR_NONE};
    enum    CAMERA_INSPECTION_DIR        {INSPECTDIR_FORWARD=0,INSPECTDIR_BACKWARD,INSPECTDIR_NONE};
    enum    CAMERA_SCANDIR                {SCANGLASS_X=0,SCANGLASS_Y,SCANGLASS_NONE};    
    enum    BOARD_TYPE                    {GRAB_LINK_BOARD=0,RADIENT_BOARD,SOLIOS_BOARD,SAP_BOARD,BOARDTYPE_NONE};
EdgeInspector_App/Define/StatusMonitor.cpp
@@ -1,17 +1,19 @@
#include "StdAfx.h"
#include "StatusMonitor.h"
#define VALID_IDX(i, max)     ((unsigned)(i) < (unsigned)(max))
#define VALID_CAM(c)          VALID_IDX((c), MAX_CAMERA_COUNT)
#define VALID_SCAN(s)         VALID_IDX((s), MAX_SCAN_COUNT)
#define VALID_CAM_SCAN(c, s)  (VALID_CAM(c) && VALID_SCAN(s))
//////////////////////////////////////////////////////////////////////////
CStatusMonitor::CStatusMonitor(void)
{
    m_iScanIdx = -1;
    for(int iCam=0;iCam<MAX_CAMERA_COUNT;iCam++)
    for (int iCam = 0; iCam < MAX_CAMERA_COUNT; iCam++) {
        m_pFrameBuffer[iCam] = NULL;
    InitGlassLoading();
    }
    m_pControlInterface        = NULL;
    m_pLightManager            = NULL;
@@ -21,6 +23,8 @@
    m_pHWSettings            = NULL;
    m_pLanguageControl        = NULL;
    m_pLicenseChecker        = NULL;
    InitGlassLoading();
}
CStatusMonitor::~CStatusMonitor(void)
@@ -29,35 +33,31 @@
void CStatusMonitor::InitGlassLoading()
{    
    for(int i=0;i<MAX_SCAN_COUNT;i++)
    {
        m_nGrabFrame[i] = 0;
        m_bGrabEnd[i] = FALSE;
    ZeroMemory(m_nGrabFrame, sizeof(m_nGrabFrame));
    ZeroMemory(m_bGrabEnd, sizeof(m_bGrabEnd));
}
int    CStatusMonitor::GetGrabFrameCount(int nCamera, int iScan)
{
    if (VALID_CAM_SCAN(nCamera, iScan)) {
        return m_nGrabFrame[nCamera][iScan];
    }
    return 0;
}
void CStatusMonitor::SetGrabEnd(int nCamera, int iScan)
{
    if (VALID_CAM_SCAN(nCamera, iScan)) {
        m_bGrabEnd[nCamera][iScan] = TRUE;
    }
}
int    CStatusMonitor::GetGrabFrameCount(int iScan)
void CStatusMonitor::SetGrabFrametoScan(int nCamera, int iScan,int nFrame)
{
    if(iScan < 0 || iScan >= MAX_SCAN_COUNT)
        return 0;
    return m_nGrabFrame[iScan];
}
void CStatusMonitor::SetGrabEnd(int iScan)
{
    if(iScan < 0 || iScan >= MAX_SCAN_COUNT)
        return;
    m_bGrabEnd[iScan] = TRUE;
}
void CStatusMonitor::SetGrabFrametoScan(int iScan,int nFrame)
{
    if(iScan < 0 || iScan >= MAX_SCAN_COUNT)
        return;
    m_nGrabFrame[iScan] = nFrame;
    if (VALID_CAM_SCAN(nCamera, iScan)) {
        m_nGrabFrame[nCamera][iScan] = nFrame;
    }
}
BOOL CStatusMonitor::DeleteFolder(const CString &strFolder)
EdgeInspector_App/Define/StatusMonitor.h
@@ -36,9 +36,9 @@
    
    void        InitGlassLoading();
    void        SetGrabFrametoScan(int iScan,int nFrame);
    int            GetGrabFrameCount(int iScan);
    void        SetGrabEnd(int iScan);
    void        SetGrabFrametoScan(int nCamera, int iScan, int nFrame);
    int            GetGrabFrameCount(int nCamera, int iScan);
    void        SetGrabEnd(int nCamera, int iScan);
    BOOL        DeleteFolder(const CString &strFolder);
    BOOL        CheckDirectory(const TCHAR szPathName[], BOOL bDelete = FALSE);
@@ -47,8 +47,8 @@
    int            m_iScanIdx;
    CFrameBufferController    *m_pFrameBuffer[MAX_CAMERA_COUNT];
    
    int            m_nGrabFrame[MAX_SCAN_COUNT];
    BOOL        m_bGrabEnd[MAX_SCAN_COUNT];
    int            m_nGrabFrame[MAX_CAMERA_COUNT][MAX_SCAN_COUNT];
    BOOL        m_bGrabEnd[MAX_CAMERA_COUNT][MAX_SCAN_COUNT];
    CControl_Interface*        m_pControlInterface;
    CLightManager*            m_pLightManager;
EdgeInspector_App/Grabber/MulticamControl.cpp
@@ -374,18 +374,19 @@
    m_nEndFrameIdx++;            //Count
    m_nSetBufferIdx++;        //index
    
    if (m_nEndFrameIdx > g_pStatus->GetGrabFrameCount(m_nScanIndex))
    int nCameraIdx = m_Param.nCameraIdx;
    if (m_nEndFrameIdx > g_pStatus->GetGrabFrameCount(nCameraIdx, m_nScanIndex))
    {
        GrabScanStop();        
        g_pStatus->SetGrabEnd(m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Count : Stop Grab[%d][%d] - %d"), m_nBoardID, m_nScanIndex, m_nEndFrameIdx,g_pStatus->GetGrabFrameCount(m_nScanIndex));
        g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Count : Stop Grab[%d][%d] - %d"), m_nBoardID, m_nScanIndex, m_nEndFrameIdx,g_pStatus->GetGrabFrameCount(nCameraIdx, m_nScanIndex));
        return TRUE;
    }
    if (m_nSetBufferIdx > m_pFrameBuffer->GetFrameCount())
    {
        GrabScanStop();        
        g_pStatus->SetGrabEnd(m_nScanIndex);
        g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), m_nBoardID, m_nScanIndex, m_nEndFrameIdx,m_pFrameBuffer->GetFrameCount());
        return TRUE;
    }
EdgeInspector_App/Grabber/MulticamControl.h
@@ -42,8 +42,9 @@
    virtual void    ClearGrabIdx();
    virtual stFrameIndex    GetGrabFrame();
    virtual stFrameIndex    GetGrabFrameNoRemove();
    virtual CFrameBufferController    *GetFrameBuffer(){return m_pFrameBuffer;}
    virtual BOOL    SetTriggerMode( BOOL bExTrigger ){return TRUE;}
    virtual CFrameBufferController    *GetFrameBuffer() { return m_pFrameBuffer; }
    virtual BOOL    SetTriggerMode( BOOL bExTrigger ) { return TRUE; }
    virtual BOOL    DumpBufferAsOneImage(int iScan, LPCTSTR pszPath) { return TRUE; }
public:    
#if OFFLINE_KEY == 0
EdgeInspector_App/Grabber/RadientControl.cpp
@@ -2,8 +2,12 @@
#include "RadientControl.h"
#include "FrameBufferController.h"
MIL_ID        g_MilApplication_Radient    = M_NULL;    /* Application identifier.  */
int            g_nGrabberCount_Radient        = 0;        // grabber count
MIL_ID g_MilApplication_Radient    = M_NULL;    /* Application identifier.  */
int       g_nGrabberCount_Radient    = 0;        // grabber count
// 调试
#define GRAB_DEBUG_ENABLE    0                // 置 0 关闭所有调试输出与转存
#define GRAB_DUMP_DIR        _T("D:\\Dump")  // 输出目录
//==========================================================================================================================================================================
// Grabber Radient
@@ -23,152 +27,161 @@
CGrabberRadient::~CGrabberRadient()
{
    if(m_pFrameBuffer != NULL)
    if (m_pFrameBuffer != NULL) {
        delete m_pFrameBuffer;
    m_pFrameBuffer = NULL;
        m_pFrameBuffer = NULL;
    }
}
BOOL CGrabberRadient::Initialize(void *pParam, int *pErrorCode,int iBoard)
{
    _GRABBER_INIT_PARAM_ *pParameter = (_GRABBER_INIT_PARAM_ *)pParam;
    if(NULL != pParameter)
    {
        m_Param = *pParameter;
    //    return TRUE;
        CString            strDCF;
        strDCF = m_Param.cDCFPath;
        CString strTmp;
        if(g_nGrabberCount_Radient == 0)
        {
            MappAlloc(M_NULL,M_DEFAULT, &g_MilApplication_Radient);
        }
        g_nGrabberCount_Radient++;
        MsysAlloc(M_SYSTEM_RADIENTEVCL, m_Param.nBoardIdx, M_DEFAULT, &m_MilSystem);
        //MsysAlloc(M_DEFAULT, MIL_TEXT("M_DEFAULT"), m_Param.nBoardIdx, M_DEFAULT, &m_MilSystem);
        if(CheckLastError())
            return FALSE;
        MdigAlloc(m_MilSystem  , m_Param.nBoardCh , strDCF, M_DEFAULT, &m_MilDigitizer);
        if(CheckLastError())
            return FALSE;
        for(int j = 0; j < BUFFERING_SIZE_MAX ;j++)
        {
            MbufAlloc2d(m_MilSystem, m_Param.nFrameWidth, m_Param.nFrameHeight, 8+M_UNSIGNED, M_IMAGE+M_GRAB, &m_Milbufgrab[j]);
        }
        if(CheckLastError())
            return FALSE;
        /*
        INT nExposureTimer = m_Param.nExposure*1000;
        INT nExposureTimerDelay = m_Param.nExposureDelay*1000;
        MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_TIME+M_TIMER1,  nExposureTimer);                        //10us
        MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_TIME_DELAY+M_TIMER1,  nExposureTimerDelay);                 //10us
        if(m_Param.nImgFlipX == 1)
            SetImageFlipX(TRUE);
        else
            SetImageFlipX(FALSE);
        */
        //MdigControl(m_MilDigitizer,M_GRAB_MODE   , M_ASYNCHRONOUS);
        MdigControl(m_MilDigitizer,M_GRAB_TIMEOUT, M_INFINITE);
        if(CheckLastError())
            return FALSE;
        m_DigitizerStatus.status = M_STOP;
    }
    else
    if(NULL == pParameter) {
        return FALSE;
    }
    m_Param = *pParameter;
    CString    strDCF;
    strDCF = m_Param.cDCFPath;
    if (g_nGrabberCount_Radient == 0) {
        MappAlloc(M_NULL, M_DEFAULT, &g_MilApplication_Radient);
    }
    g_nGrabberCount_Radient++;
    // 分配系统
    MsysAlloc(M_SYSTEM_RADIENTEVCL, m_Param.nBoardIdx, M_DEFAULT, &m_MilSystem);
    if (CheckLastError()) {
        return FALSE;
    }
    // 分配 digitizer,M_DEV0/M_DEV1 区分 CH0/CH1
    MIL_INT nDev = m_Param.nBoardCh;
    MdigAlloc(m_MilSystem, nDev, strDCF, M_DEFAULT, &m_MilDigitizer);
    if (CheckLastError()) {
        MIL_INT nErrorCode = 0;
        MappGetError(M_GLOBAL, &nErrorCode);
        g_pLog->DisplayMessage(_T("Digitizer Alloc Error | BoardIdx=%d, BoardCh=%d, DCF=\"%s\", MIL_Error=%ld"), m_Param.nBoardIdx, m_Param.nBoardCh, strDCF, nErrorCode);
        return FALSE;
    }
    g_pLog->DisplayMessage(_T("Digitizer Alloc | BoardIdx=%d, BoardCh=%d, DCF=\"%s\""), m_Param.nBoardIdx, m_Param.nBoardCh, strDCF);
    // 查询真实尺寸
    MIL_INT nSizeX = 0, nSizeY = 0, nBands = 1, nType = 0;
    MdigInquire(m_MilDigitizer, M_SIZE_X, &nSizeX);
    MdigInquire(m_MilDigitizer, M_SIZE_Y, &nSizeY);
    MdigInquire(m_MilDigitizer, M_SIZE_BAND, &nBands);
    MdigInquire(m_MilDigitizer, M_TYPE, &nType);
    // 用硬件实际值覆盖配置
    if (m_Param.nFrameWidth != (int)nSizeX || m_Param.nFrameHeight != (int)nSizeY) {
        g_pLog->DisplayMessage(_T("Digitizer Size sync: cfg %dx%d -> hw %dx%d"), m_Param.nFrameWidth, m_Param.nFrameHeight, (int)nSizeX, (int)nSizeY);
        m_Param.nFrameWidth = (int)nSizeX;
        m_Param.nFrameHeight = (int)nSizeY;
    }
    // 分配缓冲
    for (int j = 0; j < BUFFERING_SIZE_MAX; j++) {
        MbufAlloc2d(m_MilSystem, m_Param.nFrameWidth, m_Param.nFrameHeight, (/*nType ? nType : */8 + M_UNSIGNED), M_IMAGE + M_GRAB + M_PROC, &m_Milbufgrab[j]);
    }
    if (CheckLastError()) {
        return FALSE;
    }
    /*
    INT nExposureTimer = m_Param.nExposure*1000;
    INT nExposureTimerDelay = m_Param.nExposureDelay*1000;
    MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_TIME+M_TIMER1,  nExposureTimer);                        //10us
    MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_TIME_DELAY+M_TIMER1,  nExposureTimerDelay);             //10us
    if(m_Param.nImgFlipX == 1)
        SetImageFlipX(TRUE);
    else
        SetImageFlipX(FALSE);
    */
    // 抓取控制
    MdigControl(m_MilDigitizer, M_GRAB_MODE, M_ASYNCHRONOUS);
    MdigControl(m_MilDigitizer, M_GRAB_TIMEOUT, M_INFINITE);
    if (CheckLastError()) {
        return FALSE;
    }
    m_DigitizerStatus.status = M_STOP;
    return TRUE;
}
BOOL CGrabberRadient::SetImageFlipX(BOOL bOn)
{
    if(bOn == TRUE)
    if (bOn == TRUE) {
        MdigControl(m_MilDigitizer, M_GRAB_DIRECTION_X, M_REVERSE);
    else
    }
    else {
        MdigControl(m_MilDigitizer, M_GRAB_DIRECTION_X, M_FORWARD);
    }
    return TRUE;
}
BOOL CGrabberRadient::CheckLastError()
{
    BOOL bReturn = FALSE;
    MIL_INT nErrorCode; 
    CString strMsg;
    if(MappGetError(M_GLOBAL, &nErrorCode))
    {
    if(MappGetError(M_GLOBAL, &nErrorCode)) {
        int    iCam = m_Param.nCameraIdx;    
        int    iScan = m_Param.nCameraScan;
        int    iBoard = m_Param.nBoardIdx;
        int    iBoardCh = m_Param.nBoardCh;
        
        strMsg.Format(_T("[Board:%d,ch %d] [Camera:%d,Scan %d] MIL Error Code : %d"), iBoard,iBoardCh,iCam,iScan, nErrorCode);
        CString strMsg;
        strMsg.Format(_T("[Board=%d,ch=%d] [Camera=%d,Scan=%d] MIL Error Code : %d"), iBoard,iBoardCh,iCam,iScan, nErrorCode);
        g_pLog->DisplayMessage(strMsg);    
        
        bReturn = TRUE;
        return TRUE;
    }    
    else
        bReturn = FALSE;
    return bReturn;
    return FALSE;
}
BOOL CGrabberRadient::InitializeBuffer(void *pParam)
{
    _GRABBER_INIT_PARAM_ *pParameter = (_GRABBER_INIT_PARAM_ *)pParam;
    BOOL        bRet = TRUE;
    if(NULL != pParameter)
    {
        m_Param = *pParameter;
        bRet = CreateGrabBuffer(m_Param.nScanCount,m_Param.nGrabBufCount,m_Param.nFrameWidth,m_Param.nFrameHeight);
    if (NULL == pParameter) {
        g_pLog->DisplayMessage(_T("InitializeBuffer : pParameter is NULL"));
        return FALSE;
    }
    return bRet;
    m_Param = *pParameter;
    return CreateGrabBuffer(m_Param.nScanCount, m_Param.nGrabBufCount, m_Param.nFrameWidth, m_Param.nFrameHeight);
}
BOOL CGrabberRadient::Deinitialize(void)
{    
    if (IsGrabbing())
    if (IsGrabbing()) {
        GrabScanStop();
    }
    g_nGrabberCount_Radient--;
    for(int i = 0; i < BUFFERING_SIZE_MAX ;i++)
    {
    for(int i = 0; i < BUFFERING_SIZE_MAX ;i++) {
        MbufFree(m_Milbufgrab[i]);
    }        
    MdigFree(m_MilDigitizer);
    MdigFree(m_MilDigitizer);
    MsysFree(m_MilSystem);
    if(g_nGrabberCount_Radient == 0)
    if (g_nGrabberCount_Radient == 0) {
        MappFree(g_MilApplication_Radient);
    }
    return TRUE;
}
BOOL CGrabberRadient::GrabLiveStart(int nExposure)
{
    if (IsGrabbing())
    {
    if (IsGrabbing()) {
        g_pLog->DisplayMessage(_T("Start Live Acq : IsGrabbing -> Stop Acq %d"), m_nEndFrameIdx);
        GrabScanStop();
        Sleep(100);                
@@ -179,11 +192,10 @@
    m_nSetBufferIdx = -1;
    m_nScanIndex = 0;    
    if(m_DigitizerStatus.status == M_STOP)
    {
        m_DigitizerStatus.status            = M_FREE_START;
        m_DigitizerStatus.nCount            = 0;
        m_DigitizerStatus.nIndex            = m_Param.nCameraScan;
    if(m_DigitizerStatus.status == M_STOP) {
        m_DigitizerStatus.status = M_FREE_START;
        m_DigitizerStatus.nCount = 0;
        m_DigitizerStatus.nIndex = m_Param.nCameraScan;
        MdigProcess(m_MilDigitizer,&m_Milbufgrab[0],BUFFERING_SIZE_MAX, M_START, M_DEFAULT, (MIL_BUF_HOOK_FUNCTION_PTR)CallbackFreeRunFunction, this);                
    }
@@ -197,9 +209,11 @@
BOOL CGrabberRadient::GrabScanStart(int iScan, BOOL bFreeRun, int nPeriod, int nExposure, BOOL bAuto)
{    
    if (IsGrabbing())
    {
        g_pLog->DisplayMessage(_T("Start Acq : IsGrabbing -> Stop Acq %d"), m_nEndFrameIdx);
    int nCameraIdx = m_Param.nCameraIdx;
    g_pLog->DisplayMessage(_T("%d Start Acq : Camera=%d, Scan=%d, GrabFrameCount=%d, FrameHeight=%d"), m_Param.nBoardIdx, nCameraIdx, iScan, g_pStatus->GetGrabFrameCount(nCameraIdx, iScan), m_Param.nFrameHeight);
    if (IsGrabbing()) {
        g_pLog->DisplayMessage(_T("%d Start Acq : Camera=%d, Scan=%d, IsGrabbing -> Stop Acq %d"), m_Param.nBoardIdx, nCameraIdx, iScan, m_nEndFrameIdx);
        GrabScanStop();
        Sleep(100);
    }
@@ -209,84 +223,73 @@
    m_nSetBufferIdx = -1;
    m_nScanIndex = iScan;
    if(bAuto == TRUE)
    {
    if (bAuto == TRUE) {
        int nDigitizer = 0;
        if(bFreeRun == FALSE)
        {
        if (bFreeRun == FALSE) {
            SetTriggerMode(TRUE);
            /* Start the processing. The processing function is called for every frame grabbed. */
            if(m_DigitizerStatus.status == M_STOP)
            {
                m_DigitizerStatus.status            = M_START;
                m_DigitizerStatus.nCount            = 0;
                m_DigitizerStatus.nIndex            = iScan;
                MdigProcess(m_MilDigitizer,&m_Milbufgrab[0],BUFFERING_SIZE_MAX, M_START, M_DEFAULT, (MIL_BUF_HOOK_FUNCTION_PTR)CallbackHookFunction, this);
            if (m_DigitizerStatus.status == M_STOP) {
                m_DigitizerStatus.status = M_START;
                m_DigitizerStatus.nCount = 0;
                m_DigitizerStatus.nIndex = iScan;
                MdigProcess(m_MilDigitizer, &m_Milbufgrab[0], BUFFERING_SIZE_MAX, M_START, M_DEFAULT, (MIL_BUF_HOOK_FUNCTION_PTR)CallbackHookFunction, this);
            }
        }
        else
        {
            if(m_DigitizerStatus.status == M_STOP)
            {
                m_DigitizerStatus.status            = M_FREE_START;
                m_DigitizerStatus.nCount            = 0;
                m_DigitizerStatus.nIndex            = iScan;
        else {
            if (m_DigitizerStatus.status == M_STOP) {
                m_DigitizerStatus.status = M_FREE_START;
                m_DigitizerStatus.nCount = 0;
                m_DigitizerStatus.nIndex = iScan;
                MdigProcess(m_MilDigitizer,&m_Milbufgrab[0],BUFFERING_SIZE_MAX, M_START, M_DEFAULT, (MIL_BUF_HOOK_FUNCTION_PTR)CallbackFreeRunFunction, this);
                MdigProcess(m_MilDigitizer, &m_Milbufgrab[0], BUFFERING_SIZE_MAX, M_START, M_DEFAULT, (MIL_BUF_HOOK_FUNCTION_PTR)CallbackFreeRunFunction, this);
            }
        }
        m_isGrabbing = TRUE;
        m_isLiveGrab = FALSE;
    }
    else
    {
    else {
        SimulationGrab(iScan);
    }
    g_pLog->DisplayMessage(_T("Start Acq : %d"), iScan);
    }
    return TRUE;
}
void CGrabberRadient::SimulationGrab(int iScan)
{
    if(m_pFrameBuffer == NULL)
    if (m_pFrameBuffer == NULL) {
        return;
    int            nFrameCnt = m_pFrameBuffer->GetFrameCount();
    }
    int    nFrameCnt = m_pFrameBuffer->GetFrameCount();
    m_nEndFrameIdx = nFrameCnt;
    m_nSetBufferIdx = nFrameCnt -1;
    m_nSetBufferIdx = nFrameCnt - 1;
    
    for(int i=0;i<nFrameCnt;i++)
    {
        SetInsertFrame(iScan,i);
    for (int i = 0; i < nFrameCnt; i++) {
        SetInsertFrame(iScan, i);
    }
}
BOOL CGrabberRadient::GrabScanStop(void)
{
    g_pLog->DisplayMessage(_T("%d StopAcq : Scan %d, Grab %d, End %d"), m_Param.nBoardIdx,m_nScanIndex,m_nSetBufferIdx, m_nEndFrameIdx);
    g_pLog->DisplayMessage(_T("%d StopAcq : Camera %d, Scan %d, Grab %d, End %d"), m_Param.nBoardIdx, m_Param.nCameraIdx, m_nScanIndex, m_nSetBufferIdx, m_nEndFrameIdx);
    CString strMsg;
    if( m_DigitizerStatus.status == M_START)
    {
        MdigProcess(m_MilDigitizer,&m_Milbufgrab[0],BUFFERING_SIZE_MAX, M_STOP, M_DEFAULT, (MIL_BUF_HOOK_FUNCTION_PTR)CallbackHookFunction, this);
        m_DigitizerStatus.nIndex    = m_nScanIndex;
        m_DigitizerStatus.status    = M_STOP;
    }
    else if(m_DigitizerStatus.status == M_FREE_START)
    {
        MdigProcess(m_MilDigitizer,&m_Milbufgrab[0],BUFFERING_SIZE_MAX, M_STOP, M_DEFAULT, (MIL_BUF_HOOK_FUNCTION_PTR)CallbackFreeRunFunction, this);
        m_DigitizerStatus.nIndex    = m_nScanIndex;
        m_DigitizerStatus.status    = M_STOP;
    if (m_DigitizerStatus.status == M_START) {
        MdigProcess(m_MilDigitizer, &m_Milbufgrab[0], BUFFERING_SIZE_MAX, M_STOP, M_DEFAULT, (MIL_BUF_HOOK_FUNCTION_PTR)CallbackHookFunction, this);
        m_DigitizerStatus.nIndex = m_nScanIndex;
        m_DigitizerStatus.status = M_STOP;
    }
    else if (m_DigitizerStatus.status == M_FREE_START) {
        MdigProcess(m_MilDigitizer, &m_Milbufgrab[0], BUFFERING_SIZE_MAX, M_STOP, M_DEFAULT, (MIL_BUF_HOOK_FUNCTION_PTR)CallbackFreeRunFunction, this);
        m_DigitizerStatus.nIndex = m_nScanIndex;
        m_DigitizerStatus.status = M_STOP;
    }
    m_isGrabbing = FALSE;
    m_isLiveGrab = FALSE;
@@ -303,57 +306,62 @@
    return m_nSetBufferIdx - nFrameNo;        
}
LPBYTE    CGrabberRadient::GetFrameHeaderLine(int iScan,int nLine, BOOL* bSuccess)
LPBYTE CGrabberRadient::GetFrameHeaderLine(int iScan,int nLine, BOOL* bSuccess)
{    
    if(m_pFrameBuffer == NULL)
    if (m_pFrameBuffer == NULL) {
        return NULL;
    }
    return m_pFrameBuffer->GetFrameHeaderLine(iScan,nLine);
}
LPBYTE CGrabberRadient::GetFrameHeader(int iScan,int nFrameNo, BOOL* bRet)
{        
    if(m_pFrameBuffer == NULL)
    if (m_pFrameBuffer == NULL) {
        return NULL;
    return m_pFrameBuffer->GetFrameBuferHeader(iScan,nFrameNo);
    }
    return m_pFrameBuffer->GetFrameBuferHeader(iScan, nFrameNo);
}
BOOL CGrabberRadient::GetSmallImage(int iScan,LPBYTE lpIn, int nXStart, int nYStart, int nXSize, int nYSize, BOOL bMustMapping)
BOOL CGrabberRadient::GetSmallImage(int iScan, LPBYTE lpIn, int nXStart, int nYStart, int nXSize, int nYSize, BOOL bMustMapping)
{
    int nBufSizeX = m_Param.nFrameWidth;
    int nBufSizeY = m_Param.nFrameHeight;
    if (nXStart < 0 || nYStart < 0)
    if (nXStart < 0 || nYStart < 0) {
        g_pLog->DisplayMessage(_T("GetSmallImage : Invalid Start Position X=%d, Y=%d"), nXStart, nYStart);
        return FALSE;
    if (nXStart + nXSize > nBufSizeX)
    }
    if (nXStart + nXSize > nBufSizeX) {
        g_pLog->DisplayMessage(_T("GetSmallImage : Invalid X Size Start=%d, Size=%d, BufferSizeX=%d"), nXStart, nXSize, nBufSizeX);
        return FALSE;
    if (nYStart + nYSize > nBufSizeY* GetEndFrameIdx())
    }
    if (nYStart + nYSize > nBufSizeY * GetEndFrameIdx()) {
        g_pLog->DisplayMessage(_T("GetSmallImage : Invalid Y Size Start=%d, Size=%d, BufferSizeY=%d"), nYStart, nYSize, nBufSizeY);
        return FALSE;
    }
    
    // 矫累 橇饭烙 锅龋客 场 橇饭烙 锅龋.
    int nStartFrameNo = nYStart / nBufSizeY;
    int nEndFrameNo = (nYStart + nYSize) / nBufSizeY;
    LPBYTE    lpHeadAddr = GetFrameHeader(iScan,nStartFrameNo);
    if (!lpHeadAddr)
    {
    LPBYTE lpHeadAddr = GetFrameHeader(iScan, nStartFrameNo);
    if (!lpHeadAddr) {
        g_pLog->DisplayMessage(_T("GetSmallImage : GetFrameHeader Failed for Scan %d, Frame %d"), iScan, nStartFrameNo);
        return FALSE;
    }
    LPBYTE lpStart = lpHeadAddr + (nYStart % nBufSizeY) * nBufSizeX + nXStart;
    
    int nLine = 0;
    for (int i = 0; i < nYSize; i++)
    {
    for (int i = 0; i < nYSize; i++) {
        memcpy(lpIn + i * nXSize, lpStart + nLine * nBufSizeX, nXSize);
        if (nStartFrameNo <= nEndFrameNo && (nYStart + i + 1) % nBufSizeY  == 0)
        {
            // 捞固瘤甫 蝶郴具窍绰 康开捞 MemFrameNo 版拌俊 吧媚乐绰 版快 贸府.
            lpHeadAddr = GetFrameHeader(iScan,++nStartFrameNo);
        if (nStartFrameNo <= nEndFrameNo && (nYStart + i + 1) % nBufSizeY == 0) {
            lpHeadAddr = GetFrameHeader(iScan, ++nStartFrameNo);
            lpStart = lpHeadAddr + nXStart;
            nLine = 0;
        }
        else
        else {
            nLine++;
        }
    }
    
    return TRUE;
@@ -361,107 +369,201 @@
void CGrabberRadient::SetSimulFrame(int nFrame)
{
//     if(nFrame == 0)
//     {
//         for(int i = 0; i < g_pBase->m_nProcessMargin; i++)
//             SetSimulBuffer(i, m_nScanIndex % 2 == 1);
//     }
//
//     m_nEndFrameIdx = CHKMIN(GetGrabFrameNo(m_nScanIndex), nFrame + g_pBase->m_nProcessMargin + 1);
//     SetSimulBuffer(m_nEndFrameIdx - 1, m_nScanIndex % 2 == 1);
//
//     if(GetParents() != NULL)
//         GetParents()->PostMessage(UM_IMAGE_GRAB, m_nEndFrameIdx - 1,NULL);
    return;
}
BOOL CGrabberRadient::Processing(long HookType, MIL_ID HookId)
{
    if(m_pFrameBuffer == NULL)
    if (m_pFrameBuffer == NULL) {
        return FALSE;
    }
    m_nEndFrameIdx++;    //Count
    m_nSetBufferIdx++;    //index
    int nCameraIdx = m_Param.nCameraIdx;
    if (m_nEndFrameIdx > g_pStatus->GetGrabFrameCount(nCameraIdx, m_nScanIndex)) {
        GrabScanStop();
        g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Count : Stop Grab [Cam:%d][Scan:%d] - EndFrameIdx=%d  FrameCount=%d"), m_Param.nBoardIdx, nCameraIdx, m_nScanIndex, m_nEndFrameIdx, g_pStatus->GetGrabFrameCount(nCameraIdx, m_nScanIndex));
        return TRUE;
    }
    if (m_nSetBufferIdx > m_pFrameBuffer->GetFrameCount()) {
        GrabScanStop();
        g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d BufferIndex Overflow : Stop Grab [Cam:%d][Scan:%d] - FrameIdx=%d  BufferCount=%d"), m_Param.nBoardIdx, nCameraIdx, m_nScanIndex, m_nEndFrameIdx, m_pFrameBuffer->GetFrameCount());
        return TRUE;
    }
    MIL_ID ModifiedImage = 0;
    m_nEndFrameIdx++;            //Count
    m_nSetBufferIdx++;        //index
    if (m_nEndFrameIdx > g_pStatus->GetGrabFrameCount(m_nScanIndex))
    {
        GrabScanStop();
        g_pStatus->SetGrabEnd(m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Count : Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,g_pStatus->GetGrabFrameCount(m_nScanIndex));
    LPBYTE pBuffer = m_pFrameBuffer->GetFrameBuferHeader(m_nScanIndex, m_nSetBufferIdx);
    if (pBuffer == NULL) {
        GrabScanStop();
        g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d BufferPointer NULL : Stop Grab [Cam:%d][Scan:%d] - FrameIdx=%d  BufferCount=%d"), m_Param.nBoardIdx, nCameraIdx, m_nScanIndex, m_nEndFrameIdx, m_pFrameBuffer->GetFrameCount());
        return TRUE;
    }
    if (m_nSetBufferIdx > m_pFrameBuffer->GetFrameCount())
    {
        GrabScanStop();
        g_pStatus->SetGrabEnd(m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,m_pFrameBuffer->GetFrameCount());
        return TRUE;
    MdigGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &ModifiedImage);
    MbufControl(ModifiedImage, M_LOCK, M_DEFAULT);
    MbufGet2d(ModifiedImage, 0, 0, m_Param.nFrameWidth, m_Param.nFrameHeight, pBuffer);
    MbufControl(ModifiedImage, M_UNLOCK, M_DEFAULT);
    SetInsertFrame(m_nScanIndex, m_nSetBufferIdx);
#if GRAB_DEBUG_ENABLE
    // 调试用的详细日志
    g_pLog->DisplayMessage(
        _T("[Grab-Processing] FrameAcquired | Board=%d Cam=%d Scan=%d FrameIdx=%d BufIdx=%d Size=%dx%d BufCount=%d"),
        m_Param.nBoardIdx,
        m_Param.nCameraIdx,
        m_nScanIndex,
        m_nEndFrameIdx,
        m_nSetBufferIdx,
        m_Param.nFrameWidth,
        m_Param.nFrameHeight,
        m_pFrameBuffer->GetFrameCount()
    );
#endif // GRAB_DEBUG_ENABLE
    return TRUE;
}
BOOL CGrabberRadient::DumpCurrentBuffer(LPBYTE pBuffer, LPCTSTR pszDir)
{
    if (!pszDir || !*pszDir) {
        g_pLog->DisplayMessage(_T("Dump invalid dir"));
        return FALSE;
    }
    LPBYTE        pBuffer = m_pFrameBuffer->GetFrameBuferHeader(m_nScanIndex,m_nSetBufferIdx);
    if(pBuffer == NULL)
    {
        GrabScanStop();
        g_pStatus->SetGrabEnd(m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,m_pFrameBuffer->GetFrameCount());
        return TRUE;
    const MIL_INT W = m_Param.nFrameWidth;
    const MIL_INT H = m_Param.nFrameHeight;
    MIL_INT bits = 8;
    if (m_MilDigitizer) {
        MdigInquire(m_MilDigitizer, M_SIZE_BIT, &bits);
    }
    const MIL_INT milType = (bits > 8) ? (16 + M_UNSIGNED) : (8 + M_UNSIGNED);
    if (CreateDirectory(pszDir, nullptr) == 0) {
        DWORD e = GetLastError();
        if (e != ERROR_ALREADY_EXISTS) {
            g_pLog->DisplayMessage(_T("DumpFB CreateDirectory failed (%lu): %s"), e, pszDir);
            return FALSE;
        }
    }
    MdigGetHookInfo(HookId, M_MODIFIED_BUFFER+M_BUFFER_ID, &ModifiedImage);
    MbufControl(ModifiedImage, M_LOCK, M_DEFAULT);
    MbufGet2d(ModifiedImage,0,0,m_Param.nFrameWidth,m_Param.nFrameHeight,pBuffer);
    MbufControl(ModifiedImage, M_UNLOCK, M_DEFAULT);
    MIL_ID img = M_NULL;
    MbufAlloc2d(m_MilSystem, W, H, milType, M_IMAGE + M_PROC, &img);
    if (img == M_NULL) {
        g_pLog->DisplayMessage(_T("DumpFB MbufAlloc2d failed: %dx%dx%dbit"), (int)W, (int)H, (int)bits);
        return FALSE;
    }
    SetInsertFrame(m_nScanIndex,m_nSetBufferIdx);
    static LONG sSeq = 0;
    LONG seq = InterlockedIncrement(&sSeq);
    MbufPut2d(img, 0, 0, W, H, pBuffer);
    CString path;
    path.Format(_T("%s\\Cam%d_Scan%d_seq%06ld.tif"), pszDir, m_Param.nCameraIdx, m_nScanIndex, (long)seq);
    MIL_INT dummy = 0;
    MappGetError(M_GLOBAL, &dummy);
    MbufExport((MIL_CONST_TEXT_PTR)(LPCTSTR)path, M_TIFF, img);
    MIL_INT err = 0;
    if (MappGetError(M_GLOBAL, &err)) {
        g_pLog->DisplayMessage(_T("DumpFB export failed (MIL_ERR=%lld): %s"), err, path);
    }
    MbufFree(img);
    return TRUE;
}
long MFTYPE CGrabberRadient::CallbackHookFunction(long HookType, MIL_ID HookId, void MPTYPE *HookDataPtr)
{
    if(GetThreadPriority(GetCurrentThread()) != THREAD_PRIORITY_HIGHEST)
    if (GetThreadPriority(GetCurrentThread()) != THREAD_PRIORITY_HIGHEST) {
        SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
        g_pLog->DisplayMessage(_T("[Grab] CallbackHookFunction : thread priority set to HIGHEST"));
    }
    MIL_ID nEventDig = M_NULL;
    CGrabberRadient    *pRadient = (CGrabberRadient*)HookDataPtr;
    if (nullptr == pRadient){
        return 0;
    }
    pRadient->Processing(HookType,HookId);
    MdigGetHookInfo(HookId, M_DIGITIZER_ID, &nEventDig);
    if (nEventDig != pRadient->m_MilDigitizer) {
        g_pLog->DisplayMessage(_T("CallbackHookFunction : HookId %lld does not match Digitizer %lld"), HookId, pRadient->m_MilDigitizer);
        return 0;
    }
    return 0;
    return pRadient->Processing(HookType, HookId) ? 0 : 1;
}
long MFTYPE CGrabberRadient::CallbackFreeRunFunction(long HookType, MIL_ID HookId, void MPTYPE *HookDataPtr)
{
    if(GetThreadPriority(GetCurrentThread()) != THREAD_PRIORITY_HIGHEST)
    if (GetThreadPriority(GetCurrentThread()) != THREAD_PRIORITY_HIGHEST) {
        SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
        g_pLog->DisplayMessage(_T("CallbackFreeRunFunction : thread priority set to HIGHEST"));
    }
    MIL_ID nEventDig = M_NULL;
    CGrabberRadient    *pRadient = (CGrabberRadient*)HookDataPtr;
    if (nullptr == pRadient) {
        return 0;
    }
    if(pRadient->m_isLiveGrab == TRUE)        // Live Grab 矫.
    {
    MdigGetHookInfo(HookId, M_DIGITIZER_ID, &nEventDig);
    if (nEventDig != pRadient->m_MilDigitizer) {
        g_pLog->DisplayMessage(_T("CallbackFreeRunFunction : HookId %lld does not match Digitizer %lld"), HookId, pRadient->m_MilDigitizer);
        return 0;
    }
    if(pRadient->m_isLiveGrab == TRUE) {
        pRadient->m_nSetBufferIdx = 0;
        int nCameraIdx = pRadient->m_Param.nCameraIdx;
        LPBYTE        pBuffer = pRadient->m_pFrameBuffer->GetFrameBuferHeader(pRadient->m_nScanIndex,pRadient->m_nSetBufferIdx);
        if(pBuffer == NULL)
        {
        LPBYTE pBuffer = pRadient->m_pFrameBuffer->GetFrameBuferHeader(pRadient->m_nScanIndex, pRadient->m_nSetBufferIdx);
        if(pBuffer == NULL) {
            pRadient->GrabScanStop();        
            g_pStatus->SetGrabEnd(pRadient->m_nScanIndex);
            g_pStatus->SetGrabEnd(nCameraIdx, pRadient->m_nScanIndex);
            g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), pRadient->m_Param.nBoardIdx, pRadient->m_nScanIndex, pRadient->m_nEndFrameIdx,pRadient->m_pFrameBuffer->GetFrameCount());
            return TRUE;
        }
        MIL_ID ModifiedImage = 0;
        MdigGetHookInfo(HookId, M_MODIFIED_BUFFER+M_BUFFER_ID, &ModifiedImage);
        MbufControl(ModifiedImage, M_LOCK, M_DEFAULT);
        MbufGet2d(ModifiedImage,0,0,pRadient->m_Param.nFrameWidth,pRadient->m_Param.nFrameHeight,pBuffer);
        MbufControl(ModifiedImage, M_UNLOCK, M_DEFAULT);
        MdigGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &ModifiedImage);
        MbufControl(ModifiedImage, M_LOCK, M_DEFAULT);
        MbufGet2d(ModifiedImage, 0, 0, pRadient->m_Param.nFrameWidth, pRadient->m_Param.nFrameHeight, pBuffer);
        MbufControl(ModifiedImage, M_UNLOCK, M_DEFAULT);
        
        /*
        int            iGrab = pRadient->m_nSetBufferIdx%pRadient->m_Param.nGrabBufCount;
        int iGrab = pRadient->m_nSetBufferIdx%pRadient->m_Param.nGrabBufCount;
        MbufGet(pRadient->m_MilImageChild[iGrab],pBuffer);
        */
#if GRAB_DEBUG_ENABLE
        // 打印采集详细信息
        g_pLog->DisplayMessage(
            _T("[Grab-FreeRun] FrameAcquired | Board=%d Cam=%d Scan=%d FrameIdx=%d BufIdx=%d Size=%dx%d BufCount=%d"),
            pRadient->m_Param.nBoardIdx,
            pRadient->m_Param.nCameraIdx,
            pRadient->m_nScanIndex,
            pRadient->m_nEndFrameIdx,
            pRadient->m_nSetBufferIdx,
            pRadient->m_Param.nFrameWidth,
            pRadient->m_Param.nFrameHeight,
            pRadient->m_pFrameBuffer->GetFrameCount()
        );
        // 调试用的图像转存
         pRadient->DumpCurrentBuffer(pBuffer, GRAB_DUMP_DIR);
#endif  // GRAB_DEBUG_ENABLE
        return TRUE;
    }    
@@ -471,24 +573,22 @@
BOOL CGrabberRadient::CreateGrabBuffer(int nScanCount,int nBufSize, int nBufSizeX, int nBufSizeY)
{
    SIZE_T tempBufferSize= nBufSize;
    SIZE_T tempFrmCX = nBufSizeX;
    SIZE_T tempFrmCY = nBufSizeY;
    SIZE_T TotalBufferSize= tempBufferSize*tempFrmCX*tempFrmCY;
    SIZE_T nTempBufferSize= nBufSize;
    SIZE_T nTempFrmCX = nBufSizeX;
    SIZE_T nTempFrmCY = nBufSizeY;
    SIZE_T nTotalBufferSize= nTempBufferSize * nTempFrmCX * nTempFrmCY;
    m_nAllocatedGrabBufSize = nBufSize;    
    if(m_pFrameBuffer != NULL)
    if (m_pFrameBuffer != NULL) {
        delete m_pFrameBuffer;
    m_pFrameBuffer = NULL;
        m_pFrameBuffer = NULL;
    }
    m_pFrameBuffer = new CFrameBufferController;
    if(TRUE == m_pFrameBuffer->CreateBuffer(m_Param.nCameraIdx,nBufSizeX ,nBufSizeY,nBufSize, nScanCount))
    {
    if (TRUE == m_pFrameBuffer->CreateBuffer(m_Param.nCameraIdx, nBufSizeX, nBufSizeY, nBufSize, nScanCount)) {
        g_pLog->DisplayMessage(_T("Create Buffer success!:Id[%d],Frame[%d,%d],Cnt[%d]"),m_Param.nCameraIdx,nBufSizeX,nBufSizeY,nBufSize);        
    }
    else
    {
    else {
        g_pLog->DisplayMessage(_T("Create Buffer Fail!:Id[%d],Frame[%d,%d],Cnt[%d]"),m_Param.nCameraIdx,nBufSizeX,nBufSizeY,nBufSize);
        return FALSE;
    }
@@ -498,8 +598,9 @@
void CGrabberRadient::ClearBuffer()
{
    if(m_pFrameBuffer != NULL)
    if (m_pFrameBuffer != NULL) {
        m_pFrameBuffer->ClearBuffer();
    }
}
void CGrabberRadient::ClearGrabIdx()
@@ -525,21 +626,19 @@
    return TRUE;
}
BOOL CGrabberRadient::FindGrabIdx(int iScan,int iFrame)
BOOL CGrabberRadient::FindGrabIdx(int iScan, int iFrame)
{
    CSingleLock MyLock(&m_csIdxLock);
    MyLock.Lock();
    BOOL                bRet = FALSE;
    stFrameIndex        stFrame;
    for(dqGrabIdxIt it=m_dqCallbackFrame.begin();it!=m_dqCallbackFrame.end();it++)
    {
    BOOL bRet = FALSE;
    stFrameIndex stFrame;
    for (dqGrabIdxIt it = m_dqCallbackFrame.begin(); it != m_dqCallbackFrame.end(); it++) {
        stFrame = *it;
        if(stFrame.nScanIdx == iScan)
        {
            if(stFrame.nFrameIdx < iFrame)
        if (stFrame.nScanIdx == iScan) {
            if (stFrame.nFrameIdx < iFrame) {
                bRet = TRUE;
            }
        }
    }
    MyLock.Unlock();
@@ -558,8 +657,7 @@
    CSingleLock MyLock(&m_csIdxLock);
    MyLock.Lock();
    if(IsHasGrabFrame() == FALSE)
    {
    if(IsHasGrabFrame() == FALSE) {
        MyLock.Unlock();
        return stPop;
    }
@@ -574,11 +672,9 @@
stFrameIndex CGrabberRadient::GetGrabFrame()
{
    stFrameIndex stPop(-1, -1);    
    CSingleLock MyLock(&m_csIdxLock);
    MyLock.Lock();
    if(IsHasGrabFrame() == FALSE)
    {
    if(IsHasGrabFrame() == FALSE) {
        MyLock.Unlock();
        return stPop;
    }
@@ -598,29 +694,73 @@
BOOL CGrabberRadient::SetTriggerMode( BOOL bExTrigger )
{    
    INT nExposureTimer = m_Param.nExposure*1000;
    INT nExposureTimerDelay = m_Param.nExposureDelay*1000;
    if(bExTrigger == TRUE)    // Trigger
    {
        /*
        MdigControl(m_MilDigitizer, M_CAMERALINK_CC1_SOURCE, M_GRAB_EXPOSURE+M_TIMER1);
        MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE+M_TIMER1, M_ENABLE);
        //MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_SOURCE+M_TIMER1, nHWPort);
        MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_TIME+M_TIMER1,  nExposureTimer);                        //10us
        MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_TIME_DELAY+M_TIMER1,  nExposureTimerDelay);                 //10us
        */
    }
    else        // Live
    {
        /*
        MdigControl(m_MilDigitizer, M_CAMERALINK_CC1_SOURCE, M_GRAB_EXPOSURE+M_TIMER1);
        MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE+M_TIMER1, M_ENABLE);
        MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_SOURCE+M_TIMER1, M_CONTINUOUS);                      // Periodic 脚龋 牢啊
        MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_TIME+M_TIMER1, nExposureTimer);                        //10000ns
        MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_TIME_DELAY+M_TIMER1,  nExposureTimerDelay);                 //10000ns
        */
    if (m_MilDigitizer == M_NULL) {
        g_pLog->DisplayMessage(_T("SetTriggerMode failed: digitizer is NULL"));
        return FALSE;
    }
    INT nExposureTimer = m_Param.nExposure * 1000;
    INT nExposureTimerDelay = m_Param.nExposureDelay * 1000;
    //MdigControl(m_MilDigitizer, M_CAMERALINK_CC1_SOURCE, M_GRAB_EXPOSURE + M_TIMER1);
    //MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE + M_TIMER1, M_ENABLE);
    //MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_SOURCE + M_TIMER1, bExTrigger ? M_HARDWARE : M_CONTINUOUS);
    //MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_TIME + M_TIMER1, nExposureTimer);
    //MdigControl(m_MilDigitizer, M_GRAB_EXPOSURE_TIME_DELAY + M_TIMER1, nExposureTimerDelay);
    g_pLog->DisplayMessage(_T("TriggerMode=%s, Exp(ns)=%d, Delay(ns)=%d"), bExTrigger ? _T("External") : _T("Live"), nExposureTimer, nExposureTimerDelay);
    return TRUE;
}
BOOL CGrabberRadient::DumpBufferAsOneImage(int iScan, LPCTSTR pszPath)
{
    if (!m_pFrameBuffer) {
        g_pLog->DisplayMessage(_T("Dump m_pFrameBuffer is NULL"));
        return FALSE;
    }
    const int nFramesAlloc = m_pFrameBuffer->GetFrameCount();
    const int nFramesGrab = GetEndFrameIdx();
    const int nFrames = (nFramesGrab > 0 && nFramesGrab <= nFramesAlloc) ? nFramesGrab : nFramesAlloc;
    if (nFrames <= 0) {
        return FALSE;
    }
    const MIL_INT W = m_Param.nFrameWidth;
    const MIL_INT H = m_Param.nFrameHeight;
    // 保持真实位深(8/10/12/16bit -> 8/16bit缓冲)
    MIL_INT bits = 8;
    if (m_MilDigitizer) {
        MdigInquire(m_MilDigitizer, M_SIZE_BIT, &bits);
    }
    const int bpp = (int)((bits + 7) / 8);
    const MIL_INT type = (bpp >= 2) ? (16 + M_UNSIGNED) : (8 + M_UNSIGNED);
    // 拼接成一张长图
    MIL_ID img = M_NULL;
    MbufAlloc2d(m_MilSystem, W, H * nFrames, type, M_IMAGE + M_PROC, &img);
    if (img == M_NULL) {
        return FALSE;
    }
    for (int f = 0; f < nFrames; ++f) {
        LPBYTE src = m_pFrameBuffer->GetFrameBuferHeader(iScan, f);
        if (!src) {
            break;
        }
        MbufPut2d(img, 0, (MIL_INT)f * H, W, H, src);
    }
    MbufExport((MIL_CONST_TEXT_PTR)(LPCTSTR)pszPath, M_TIFF, img);
    MIL_INT err = 0;
    if (MappGetError(M_GLOBAL, &err)) {
        g_pLog->DisplayMessage(_T("DumpBufferAsOneImage Error : %d"), err);
        return FALSE;
    }
    MbufFree(img);
    return TRUE;
}
EdgeInspector_App/Grabber/RadientControl.h
@@ -46,15 +46,17 @@
    virtual stFrameIndex    GetGrabFrameNoRemove();
    virtual CFrameBufferController    *GetFrameBuffer(){return m_pFrameBuffer;}
    virtual BOOL    SetTriggerMode( BOOL bExTrigger );
    virtual BOOL    DumpBufferAsOneImage(int iScan, LPCTSTR pszPath);
    dqGrabIdx        *GetGrabIdx(){return &m_dqCallbackFrame;}    
    BOOL            FindGrabIdx(int iScan,int iFrame);    
    BOOL            SetInsertFrame(int iScan,int iFrame);
        
    BOOL            IsHasGrabFrame();
    BOOL            IsHasGrabFrame();
protected:    
    BOOL            Processing(long HookType, MIL_ID HookId);
    BOOL            DumpCurrentBuffer(LPBYTE pBuffer, LPCTSTR pszDir);
//////////////////////////////////////////////////////////////////////////
// Buffer
public:    
EdgeInspector_App/Grabber/SapControl.cpp
@@ -761,18 +761,19 @@
    pX64->m_nEndFrameIdx++;            //Count
    pX64->m_nSetBufferIdx++;        //index    
    if (pX64->m_nEndFrameIdx > g_pStatus->GetGrabFrameCount(pX64->m_nScanIndex))
    int nCameraIdx = pX64->m_Param.nCameraIdx;
    if (pX64->m_nEndFrameIdx > g_pStatus->GetGrabFrameCount(nCameraIdx, pX64->m_nScanIndex))
    {
        pX64->GrabScanStop();        
        g_pStatus->SetGrabEnd(pX64->m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Count : Stop Grab[%d][%d] - %d"), pX64->m_Param.nBoardIdx, pX64->m_nScanIndex, pX64->m_nEndFrameIdx,g_pStatus->GetGrabFrameCount(pX64->m_nScanIndex));
        g_pStatus->SetGrabEnd(nCameraIdx, pX64->m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Count : Stop Grab[%d][%d] - %d"), pX64->m_Param.nBoardIdx, pX64->m_nScanIndex, pX64->m_nEndFrameIdx,g_pStatus->GetGrabFrameCount(nCameraIdx, pX64->m_nScanIndex));
        return TRUE;
    }
    if (pX64->m_nSetBufferIdx > pX64->m_pFrameBuffer->GetFrameCount())
    {
        pX64->GrabScanStop();        
        g_pStatus->SetGrabEnd(pX64->m_nScanIndex);
        g_pStatus->SetGrabEnd(nCameraIdx, pX64->m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), pX64->m_Param.nBoardIdx, pX64->m_nScanIndex, pX64->m_nEndFrameIdx,pX64->m_pFrameBuffer->GetFrameCount());
        return TRUE;
    }
@@ -781,7 +782,7 @@
    if(pBuffer == NULL)
    {
        pX64->GrabScanStop();        
        g_pStatus->SetGrabEnd(pX64->m_nScanIndex);
        g_pStatus->SetGrabEnd(nCameraIdx, pX64->m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), pX64->m_Param.nBoardIdx, pX64->m_nScanIndex, pX64->m_nEndFrameIdx,pX64->m_pFrameBuffer->GetFrameCount());
        return TRUE;
    }
EdgeInspector_App/Grabber/SapControl.h
@@ -34,8 +34,9 @@
    virtual void    ClearGrabIdx();
    virtual stFrameIndex    GetGrabFrame();
    virtual stFrameIndex    GetGrabFrameNoRemove();
    virtual CFrameBufferController    *GetFrameBuffer(){return m_pFrameBuffer;}
    virtual BOOL    SetTriggerMode( BOOL bExTrigger ){return TRUE;}
    virtual CFrameBufferController    *GetFrameBuffer() { return m_pFrameBuffer; }
    virtual BOOL    SetTriggerMode( BOOL bExTrigger ) { return TRUE; }
    virtual BOOL    DumpBufferAsOneImage(int iScan, LPCTSTR pszPath) { return TRUE; }
    BOOL            FindGrabIdx(int iScan,int iFrame);
protected:
EdgeInspector_App/Grabber/SapLineGrab.cpp
@@ -231,18 +231,19 @@
        if(m_bGrabLive == TRUE)
            m_nSetBufferIdx = 0;
        
        if (m_nEndFrameIdx > g_pStatus->GetGrabFrameCount(m_nScanIndex))
        int nCameraIdx = m_Param.nCameraIdx;
        if (m_nEndFrameIdx > g_pStatus->GetGrabFrameCount(nCameraIdx, m_nScanIndex))
        {
            GrabScanStop();        
            g_pStatus->SetGrabEnd(m_nScanIndex);
            g_pLog->DisplayMessage(_T("%d Over Grab Count : Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,g_pStatus->GetGrabFrameCount(m_nScanIndex));
            g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
            g_pLog->DisplayMessage(_T("%d Over Grab Count : Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,g_pStatus->GetGrabFrameCount(nCameraIdx, m_nScanIndex));
            return;
        }
        if (m_nSetBufferIdx > m_pFrameBuffer->GetFrameCount())
        {
            GrabScanStop();        
            g_pStatus->SetGrabEnd(m_nScanIndex);
            g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
            g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,m_pFrameBuffer->GetFrameCount());
            return;
        }
@@ -251,7 +252,7 @@
        if(pBuffer == NULL)
        {
            GrabScanStop();        
            g_pStatus->SetGrabEnd(m_nScanIndex);
            g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
            g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,m_pFrameBuffer->GetFrameCount());
            return;
        }
EdgeInspector_App/Grabber/SapLineGrab.h
@@ -35,8 +35,9 @@
    virtual void    ClearGrabIdx();
    virtual stFrameIndex    GetGrabFrame();
    virtual stFrameIndex    GetGrabFrameNoRemove();
    virtual CFrameBufferController    *GetFrameBuffer(){return m_pFrameBuffer;}
    virtual BOOL    SetTriggerMode( BOOL bExTrigger ){return TRUE;}
    virtual CFrameBufferController    *GetFrameBuffer() { return m_pFrameBuffer; }
    virtual BOOL    SetTriggerMode( BOOL bExTrigger ) { return TRUE; }
    virtual BOOL    DumpBufferAsOneImage(int iScan, LPCTSTR pszPath) { return TRUE; }
    BOOL            CreateGrabBuffer(int nScanCount,int nBufSize, int nBufSizeX, int nBufSizeY);
    void            SimulationGrab(int iScan);
EdgeInspector_App/Grabber/SoliosControl.cpp
@@ -383,18 +383,19 @@
    m_nEndFrameIdx++;            //Count
    m_nSetBufferIdx++;        //index
    if (m_nEndFrameIdx > g_pStatus->GetGrabFrameCount(m_nScanIndex))
    int nCameraIdx = m_Param.nCameraIdx;
    if (m_nEndFrameIdx > g_pStatus->GetGrabFrameCount(nCameraIdx, m_nScanIndex))
    {
        GrabScanStop();        
        g_pStatus->SetGrabEnd(m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Count : Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,g_pStatus->GetGrabFrameCount(m_nScanIndex));
        g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Count : Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,g_pStatus->GetGrabFrameCount(nCameraIdx, m_nScanIndex));
        return TRUE;
    }
    if (m_nSetBufferIdx > m_pFrameBuffer->GetFrameCount())
    {
        GrabScanStop();        
        g_pStatus->SetGrabEnd(m_nScanIndex);
        g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,m_pFrameBuffer->GetFrameCount());
        return TRUE;
    }
@@ -403,7 +404,7 @@
    if(pBuffer == NULL)
    {
        GrabScanStop();        
        g_pStatus->SetGrabEnd(m_nScanIndex);
        g_pStatus->SetGrabEnd(nCameraIdx, m_nScanIndex);
        g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), m_Param.nBoardIdx, m_nScanIndex, m_nEndFrameIdx,m_pFrameBuffer->GetFrameCount());
        return TRUE;
    }
@@ -438,15 +439,17 @@
    CGrabberSolios    *pRadient = (CGrabberSolios*)HookDataPtr;
    if(pRadient->m_isLiveGrab == TRUE)        // Live Grab 矫.
    {
        pRadient->m_nSetBufferIdx = 0;
        int nCameraIdx = pRadient->m_Param.nCameraIdx;
        LPBYTE        pBuffer = pRadient->m_pFrameBuffer->GetFrameBuferHeader(pRadient->m_nScanIndex,pRadient->m_nSetBufferIdx);
        LPBYTE pBuffer = pRadient->m_pFrameBuffer->GetFrameBuferHeader(pRadient->m_nScanIndex,pRadient->m_nSetBufferIdx);
        if(pBuffer == NULL)
        {
            pRadient->GrabScanStop();        
            g_pStatus->SetGrabEnd(pRadient->m_nScanIndex);
            g_pStatus->SetGrabEnd(nCameraIdx, pRadient->m_nScanIndex);
            g_pLog->DisplayMessage(_T("%d Over Grab Buffer Stop Grab[%d][%d] - %d"), pRadient->m_Param.nBoardIdx, pRadient->m_nScanIndex, pRadient->m_nEndFrameIdx,pRadient->m_pFrameBuffer->GetFrameCount());
            return TRUE;
        }
EdgeInspector_App/Grabber/SoliosControl.h
@@ -44,8 +44,9 @@
    virtual void    ClearGrabIdx();
    virtual stFrameIndex    GetGrabFrame();
    virtual stFrameIndex    GetGrabFrameNoRemove();
    virtual CFrameBufferController    *GetFrameBuffer(){return m_pFrameBuffer;}
    virtual CFrameBufferController    *GetFrameBuffer() { return m_pFrameBuffer; }
    virtual BOOL    SetTriggerMode( BOOL bExTrigger );
    virtual BOOL    DumpBufferAsOneImage(int iScan, LPCTSTR pszPath) { return TRUE; }
    dqGrabIdx        *GetGrabIdx(){return &m_dqCallbackFrame;}    
    BOOL            FindGrabIdx(int iScan,int iFrame);    
EdgeInspector_App/InterfaceManager.cpp
@@ -581,13 +581,13 @@
    DWORD dwTick = GetTickCount();
    g_pLog->DisplayMessage(_T("Full Image Save Start"));
    int                    iCam,iScan;
    CHardwareSettings    *pHard = &m_HardwareRecipe;
    CCameraSettings        *pCamera;
    CGlassRecipe        *pGlsRcp = &m_GlassRecipe;
    CString                strFolder,strFileJpg,strPanelID;
    pINSPECTFULLIMAGE_BUFFER pBuffer;
    int                    nQuality = pHard->m_nSaveImageQuality;
    int    iCam, iScan;
    CHardwareSettings* pHard = &m_HardwareRecipe;
    CCameraSettings* pCamera;
    CGlassRecipe* pGlsRcp = &m_GlassRecipe;
    CString    strFolder, strFileJpg, strPanelID;
    pINSPECTFULLIMAGE_BUFFER pBuffer;
    int    nQuality = pHard->m_nSaveImageQuality;
    if (nQuality < 0 || nQuality > 100) {
        nQuality = 30;
@@ -601,24 +601,24 @@
        strPanelID = _T("TestGlass");
    }
    for(iCam=0;iCam<pHard->GetCameraCount();iCam++) {
        for(iScan=0;iScan<MAX_SCAN_COUNT;iScan++) {
            pCamera = pHard->GetCameraSettings(iCam,iScan);
    for (iCam = 0; iCam < pHard->GetCameraCount(); iCam++) {
        for (iScan = 0; iScan < MAX_SCAN_COUNT; iScan++) {
            pCamera = pHard->GetCameraSettings(iCam, iScan);
            if (pCamera == NULL) {
                continue;
            }
            pBuffer = m_pInspect[iCam]->GetFullImgBuffer(iScan);
            pBuffer = m_pInspect[iCam]->GetFullImgBuffer(iScan);
            if (pBuffer == NULL) {
                continue;
            }
            g_pLog->DisplayMessage(_T("Sava %s iCam=%d, iScan=%d, szImage.cx=%ld, pBuffer->szImage.cy=%ld"), PANEL_SIDE[pCamera->m_eDimension], iCam, iScan, pBuffer->szImage.cx, pBuffer->szImage.cy);
            if(pBuffer->pImage != NULL && pBuffer->szImage.cx > 100 && pBuffer->szImage.cy > 100) {
                strFileJpg.Format(_T("%s\\%s_%s_%s.jpg"),strFolder, strPanelID, PANEL_SIDE[pCamera->m_eDimension],g_pBase->m_strLoadingTime);
            if (pBuffer->pImage != NULL && pBuffer->szImage.cx > 100 && pBuffer->szImage.cy > 100) {
                strFileJpg.Format(_T("%s\\%s_%s_%s.jpg"), strFolder, strPanelID, PANEL_SIDE[pCamera->m_eDimension], g_pBase->m_strLoadingTime);
                SaveFullImageModern(strFileJpg, pBuffer->pImage, pBuffer->szImage.cx, pBuffer->szImage.cy, (int)pCamera->m_eDimension, 0, nQuality);
            }
            }
        }
    }
    g_pLog->DisplayMessage(_T("Full Image Save Completed : Time[%d]"),GetTickCount()-dwTick);
@@ -954,21 +954,19 @@
    int nPeriod = m_HardwareRecipe.m_nFreerunPeriod;
    int nExposureTime = m_HardwareRecipe.m_nFreerunExposureTime;
    CCameraSettings *pCamSettings = m_HardwareRecipe.GetCameraSettings(iCam,g_pStatus->m_iScanIdx);
    g_pStatus->SetGrabFrametoScan(g_pStatus->m_iScanIdx,pCamSettings->m_nGrabFrameCount);
    if(m_pGrabber[iCam] != NULL)
    {
        m_pGrabber[iCam]->GrabScanStart(g_pStatus->m_iScanIdx,bFreerun,nPeriod,nExposureTime);
    CCameraSettings* pCamSettings = m_HardwareRecipe.GetCameraSettings(iCam, g_pStatus->m_iScanIdx);
    g_pStatus->SetGrabFrametoScan(iCam, g_pStatus->m_iScanIdx, pCamSettings->m_nGrabFrameCount);
    if(m_pGrabber[iCam] != NULL) {
        m_pGrabber[iCam]->GrabScanStart(g_pStatus->m_iScanIdx, bFreerun, nPeriod, nExposureTime);
        g_pLog->DisplayMessage(_T("Cam %d Scan %d Grab Start : GrabFrameCount %d"), iCam, g_pStatus->m_iScanIdx, pCamSettings->m_nGrabFrameCount);
        g_pLog->DisplayMessage(_T("Cam %d Scan %d Grab Start : bFreerun %d, nPeriod %d, nExposureTime %d"),iCam, g_pStatus->m_iScanIdx, bFreerun, nPeriod, nExposureTime);
    }
    if(m_pInspect[iCam] != NULL)
    {
    if(m_pInspect[iCam] != NULL) {
        m_pInspect[iCam]->SetSimulation(FALSE);
        m_pInspect[iCam]->SetViewScanHWnd(m_pView->GetViewScanHWnd());
        if(m_pInspect[iCam]->ScanStart(g_pStatus->m_iScanIdx) == FALSE)
        {
        if(m_pInspect[iCam]->ScanStart(g_pStatus->m_iScanIdx) == FALSE) {
            g_pLog->DisplayMessage(_T("Cam %d Scan %d Start Fail"),iCam,g_pStatus->m_iScanIdx);
        }
    }
@@ -1502,8 +1500,7 @@
        Param.nScanCount = g_pBase->m_nScanCount;
        Param.nBoardIdx = g_pBase->m_nBoardID[iCam];
        Param.nBoardCh = g_pBase->m_nBoardCh[iCam];
        Param.nImgFlipX = 0;
        Param.nBoardCh = 0;
        Param.nImgFlipX = 0;
        Param.nCameraIdx = iCam;
        Param.nCameraScan = 0;
@@ -1582,8 +1579,9 @@
            Param.nBoardIdx = nBoardId;
        }
        if(Param.nBoardIdx < 0)
        if (Param.nBoardIdx < 0) {
            Param.nBoardIdx = nBoardId;
        }
        g_pLog->DisplayMessage( _T("Grabber Board ID[%d-%d]-Init"), Param.nBoardIdx, iCam);    
@@ -1899,6 +1897,8 @@
    double dRatio = 1. - tmp;
    dRatio = dRatio - 0.01 < 0.0 ? 1.0 : dRatio;
    g_pLog->DisplayMessage(_T("Save Full Image Start(%s, %s, %d, %d, %d)"), strPath, PANEL_SIDE[iSide], nStartY, nImgHeight, nQuality);
#if 0
    IplImage* pImg = cvCreateImageHeader(cvSize(nImgWidth, nImgHeight), 8, 1);
    IplImage* pImgNew = cvCreateImage(cvSize((int)(nImgWidth * dRatio), (int)(nImgHeight * dRatio)), 8, 1);
EdgeInspector_App/Process/InspectCamera.cpp
@@ -182,38 +182,24 @@
    iScan = m_iScan;
    stFrameIndex stFrame;
    stFrame.nScanIdx = m_iScan;
    if (m_bFindGlassStart[stFrame.nScanIdx] == TRUE)
    if (m_bFindGlassStart[stFrame.nScanIdx] == TRUE) {
        return ERR_FINDGLASSSTART_SUCCESS;
    }
    // 자동일때 프레임 수를 충분히 잡으면 문제가 안되는거 같다만... 프레임 수가 부족하면 여기서 무한으로 걸림.. 그리고 시작선 찾았으면 그냥 넘어가면 되지 않나?
    if (m_pGrabber->GetGrabFrameCount() < 1)
    {
    if (m_pGrabber->GetGrabFrameCount() < 1 || iThread != 0) {
        Sleep(0);
        return ERR_FINDGLASSSTART_FAIL;
    }
    /*
    stFrameIndex stFrame;
    stFrame.nScanIdx = m_iScan;
    if(m_bFindGlassStart[stFrame.nScanIdx] == TRUE)
        return ERR_FINDGLASSSTART_SUCCESS;
    */
    if (iThread != 0)
        return ERR_FINDGLASSSTART_FAIL;
    DimensionDir emDim = GetDimension(stFrame.nScanIdx);
    iScan = stFrame.nScanIdx;
    if (FindGlassStartLine(emDim, stFrame) == TRUE)
    {
        g_pLog->DisplayMessage(_T("Find Start Line Success!"));
    g_pLog->DisplayMessage(_T("%s Is Glass Start Line!"), PANEL_SIDE[emDim]);
    if (FindGlassStartLine(emDim, stFrame) == TRUE) {
        g_pLog->DisplayMessage(_T("%s Find Start Line Success!"), PANEL_SIDE[emDim]);
        ScanRegionSet(stFrame);
        m_bFindGlassStart[stFrame.nScanIdx] = TRUE;
@@ -222,15 +208,15 @@
        m_MsgJob.nDispLine = 0;
        m_MsgJob.nSide = (int)emDim;
        CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
        if (pSideData != NULL)
        if (pSideData != NULL) {
            m_MsgJob.nDispLine = pSideData->m_nGlassStartLine;
        }
        ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS, (WPARAM)&m_MsgJob, (int)emDim);
        return ERR_FINDGLASSSTART_SUCCESS;
    }
    else
    {
    else {
        return ERR_FINDGLASSSTART_FIND_FAIL;
    }
@@ -883,7 +869,7 @@
    CSingleLock myLoc(&m_csThreadEnd);
    myLoc.Lock();
    int        iScan = stFrame.nScanIdx;
    int iScan = stFrame.nScanIdx;
    if (m_iThreadEnd[iScan][iThread] == 1) {
        myLoc.Unlock();
        return FALSE;
@@ -913,6 +899,11 @@
            if (m_pII2S != NULL) {
                m_pII2S->II2S_InspectionEnd(m_iCamera, iScan);
            }
            // Save the image as one image
            //CString strFileName;
            //strFileName.Format(_T("D:\\Dump\\%s.tif"), PANEL_SIDE[emDim]);
            //m_pGrabber->DumpBufferAsOneImage(iScan, strFileName);
        }
    }
@@ -1292,7 +1283,7 @@
    if (pSideData == NULL)
        return FALSE;
    if (g_pStatus->GetGrabFrameCount(stFrame.nScanIdx) - 1 <= stFrame.nFrameIdx)
    if (g_pStatus->GetGrabFrameCount(m_iCamera, stFrame.nScanIdx) - 1 <= stFrame.nFrameIdx)
        return TRUE;
    if (pSideData->m_nPreGlassEndFrame + MAX_THREAD <= stFrame.nFrameIdx)
@@ -1307,8 +1298,6 @@
void CInspectCamera::ScanRegionSet(stFrameIndex stFrame)
{
    g_pLog->DisplayMessage(_T("Scan Region Set"));
    SetGrabEnd(stFrame.nScanIdx);
}
@@ -1798,12 +1787,6 @@
    if (pSideData->m_bTopCorner_Find == TRUE) {
        localLock.Unlock();
        return TRUE;
    }
    BOOL bTopCornerUse = (BOOL)(m_pRecipe->m_SideParam[emDim].m_nTopCornerShape == 0) ? FALSE : TRUE;
    if (bTopCornerUse == FALSE) {
        localLock.Unlock();
        return FALSE;
    }
    double dCornerSizeY_Um = (double)m_pRecipe->m_SideParam[emDim].m_nTopCornerSizeY_um;
@@ -2415,12 +2398,6 @@
    if (pSideData->m_bBotCorner_Find == TRUE) {
        localLock.Unlock();
        return TRUE;
    }
    BOOL bBotCornerUse = (BOOL)(m_pRecipe->m_SideParam[emDim].m_nBottomCornerShape == 0) ? FALSE : TRUE;
    if (bBotCornerUse == FALSE) {
        localLock.Unlock();
        return FALSE;
    }
    double dCornerSizeY_Um = (double)m_pRecipe->m_SideParam[emDim].m_nBottomCornerSizeY_um;
@@ -6446,14 +6423,11 @@
    m_pRecipe = pRecipe;
    m_pHardparm = pHW;
    if (m_pGrabber != NULL)
    {
    if (m_pGrabber != NULL) {
        m_pGrabber->ClearGrabIdx();
        //m_pGrabber->ClearBuffer();
    }
    if (m_pDefectControl != NULL)
    {
    if (m_pDefectControl != NULL) {
        m_pDefectControl->SetHWRecipe(pHW);
        m_pDefectControl->ResetDefectControl();
    }
@@ -6496,33 +6470,30 @@
void CInspectCamera::SetGrabEnd(int iScan)
{
    g_pLog->DisplayMessage(_T("Set Grab End"));
    CCameraSettings* pCamera = m_pHardparm->GetCameraSettings(m_iCamera, iScan);
    if (pCamera == NULL)
    {
    if (pCamera == NULL) {
        g_pLog->DisplayMessage(_T("Camera Setting NULL"));
        return;
    }
    DimensionDir        emDim = pCamera->m_eDimension;
    DimensionDir emDim = pCamera->m_eDimension;
    CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
    if (pSideData == NULL)
    if (pSideData == NULL) {
        return;
    }
    int        nStageNo = g_pBase->m_nStageNo;
    g_pLog->DisplayMessage(_T("%s Set Grab End"), PANEL_SIDE[emDim]);
    if (nStageNo < 0 || nStageNo > 1)
    int nStageNo = g_pBase->m_nStageNo;
    if (nStageNo < 0 || nStageNo > 1) {
        nStageNo = 0;
    }
    int    nGlassSize = (int)(((double)m_pRecipe->m_SideParam[(int)emDim].m_nSidePanelSize_um) / pCamera->m_dScanResolution[nStageNo]);
    pSideData->m_nPreGlassEndLine = pSideData->m_nGlassStartLine + nGlassSize;
    pSideData->m_nPreGlassEndFrame = pSideData->m_nPreGlassEndLine / pCamera->m_FrameSize.cy;
    g_pStatus->SetGrabFrametoScan(iScan, pSideData->m_nPreGlassEndFrame + 5);
    g_pStatus->SetGrabFrametoScan(m_iCamera, iScan, pSideData->m_nPreGlassEndFrame + 5);
    g_pLog->DisplayMessage(_T("%s Scan %d : Set Grab EndFrame - GlassEnd %d, Frame %d, GrabBuf %d"), PANEL_SIDE[emDim], iScan, pSideData->m_nPreGlassEndLine, pSideData->m_nPreGlassEndFrame, pSideData->m_nPreGlassEndFrame + 5);
}
EdgeInspector_App/Recipe/HardwareSettings.cpp
@@ -1826,33 +1826,39 @@
BOOL CHardwareSettings::WriteHardwareSettingsFile(CString strFilePath)
{
    CConfig        BasicInfoFile;
    CString                str;
    int                    iCam,iScan,iLight,iLoop;
    g_pLog->DisplayMessage(_T("HWSettings Start writing hardware settings to file: %s"), strFilePath);
    if(BasicInfoFile.SetRegiConfig(NULL, NULL, (TCHAR*)(LPCTSTR)strFilePath, FileMap_Mode) == FALSE)
    {
    int    iCam, iScan, iLight, iLoop;
    CConfig    BasicInfoFile;
    if(BasicInfoFile.SetRegiConfig(NULL, NULL, (TCHAR*)(LPCTSTR)strFilePath, FileMap_Mode) == FALSE) {
        CFile File;
        if (!File.Open((TCHAR*)(LPCTSTR)strFilePath, CFile::modeCreate))
        {
        if (!File.Open((TCHAR*)(LPCTSTR)strFilePath, CFile::modeCreate)) {
            DWORD dwErr = GetLastError();
            g_pLog->DisplayMessage(_T("HWSettings failed | Path=%s | Error=%lu"), strFilePath, dwErr);
            return FALSE;
        }
        File.Close();
    }
    CString    str;
    str = GetFileString((void *)&m_nCameraCount);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nCameraCount);
    str = GetFileString((void *)&m_nScanCount);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nScanCount);    
    str = GetFileString((void *)&m_nBoardType);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nBoardType);    
    
    //     str = GetFileString((void *)&m_dOneScanTime);
@@ -1861,140 +1867,163 @@
    //     BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_dOneScanTime);    
    str = GetFileString((void *)&m_strMachineName);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,(TCHAR*)(LPCTSTR)m_strMachineName);
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,(TCHAR*)(LPCTSTR)m_strMachineName);
    str = GetFileString((void *)&m_strLineID);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,(TCHAR*)(LPCTSTR)m_strLineID);
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,(TCHAR*)(LPCTSTR)m_strLineID);
    str = GetFileString((void *)&m_nPLCSignalRetry);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nPLCSignalRetry);    
    str = GetFileString((void *)&m_bInsDirReverse);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_bInsDirReverse);
    str = GetFileString((void *)&m_bUseColorVisual);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_bUseColorVisual);
    str = GetFileString((void *)&m_nSaveImageQuality);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nSaveImageQuality);    
    if(m_pCameraSettings != NULL)
    {
    if (m_pCameraSettings != NULL) {
        iLoop = 0;
        for(iCam=0;iCam<m_nCameraCount;iCam++)
        {
            for(iScan=0;iScan<m_nScanCount;iScan++)
            {
                m_pCameraSettings[iLoop].WriteHardwareSettingsFile(&BasicInfoFile);
        for (iCam = 0; iCam < m_nCameraCount; iCam++) {
            for (iScan = 0; iScan < m_nScanCount; iScan++) {
                m_pCameraSettings[iLoop].WriteHardwareSettingsFile(&BasicInfoFile);
                iLoop++;
            }
        }
    }
    str = GetFileString((void *)&m_nLightCount_Trans);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nLightCount_Trans);    
    str = GetFileString((void *)&m_nLightCount_Reflect);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nLightCount_Reflect);
    str = GetFileString((void *)&m_nFolderRemoveDay);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nFolderRemoveDay);
    if(m_pLightSettings != NULL)
    {
        for(iLight=0;iLight<m_nLightCount_Trans+m_nLightCount_Reflect;iLight++)
        {
    if (m_pLightSettings != NULL) {
        for (iLight = 0; iLight < m_nLightCount_Trans + m_nLightCount_Reflect; iLight++) {
            m_pLightSettings[iLight].WriteHardwareSettingsFile(&BasicInfoFile);
        }
        }
    }
    m_PLCSettings.WriteHardwareSettingsFile(&BasicInfoFile);
    m_SoftWareSettings.WriteHardwareSettingsFile(&BasicInfoFile);
    str = GetFileString((void *)&m_bUseFreerun);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,(int) m_bUseFreerun);
    str = GetFileString((void *)&m_nFreerunPeriod);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nFreerunPeriod);
    str = GetFileString((void *)&m_nFreerunExposureTime);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nFreerunExposureTime);
    str = GetFileString((void *)&m_bUse_MvsolTriggerControl);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_bUse_MvsolTriggerControl);
    str = GetFileString((void *)&m_nPort_MvsolTriggerControl);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_nPort_MvsolTriggerControl);
    str = GetFileString((void *)&m_bUse_SaveDebugImage);
    if(str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str,m_bUse_SaveDebugImage);
    // ly,2025.07.10
    str = GetFileString((void*)&m_bSaveResultByHour);
    if (str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str, (int)m_bSaveResultByHour);
    // ly,2025.07.07
    str = GetFileString((void*)&m_bEnableAutoCopy);
    if (str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str, (int)m_bEnableAutoCopy);
    str = GetFileString((void*)&m_strCopyToolExePath);
    if (str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str, m_strCopyToolExePath);
    str = GetFileString((void*)&m_strCopyToolConfigPath);
    if (str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str, m_strCopyToolConfigPath);
    str = GetFileString((void*)&m_bEnableAutoDelete);
    if (str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str, (int)m_bEnableAutoDelete);
    str = GetFileString((void*)&m_strDeleteToolExePath);
    if (str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str, m_strDeleteToolExePath);
    str = GetFileString((void*)&m_strDeleteToolConfigPath);
    if (str.IsEmpty() == TRUE)
    if (str.IsEmpty() == TRUE) {
        return FALSE;
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str, m_strDeleteToolConfigPath);
    }
    BasicInfoFile.SetItemValue((TCHAR*)(LPCTSTR)str, m_strDeleteToolConfigPath);
    BasicInfoFile.WriteToFile();
    g_pLog->DisplayMessage(_T("HWSettings Finished writing hardware settings file: %s"), strFilePath);
    return TRUE;
}
EdgeInspector_App/Recipe/HardwareSettings.h
@@ -3,8 +3,8 @@
#include "Config.h"
#include "Global_Define.h"
#define    HARDWARE_SETTING_PATH                _T("c:\\EdgeInspector_App\\Config\\HardwareSetting.cfg")        // cfg 立辟 版肺汲沥
#define HARDWARE_SETTING_BACKUP_DIR_PATH    _T("c:\\EdgeInspector_App\\Config\\Backup")
#define    HARDWARE_SETTING_PATH                _T("C:\\EdgeInspector_App\\Config\\HardwareSetting.cfg")        // cfg 立辟 版肺汲沥
#define HARDWARE_SETTING_BACKUP_DIR_PATH    _T("C:\\EdgeInspector_App\\Config\\Backup")
#define    KEY_BASIC                            _T("Software\\EdgeInspector_App\\BASIC\\")                        // 饭瘤胶飘府 立辟 版肺汲沥
#define MAX_CNC_COUNT                        6
#define MAX_NCUT_STAGE_COUNT                12
EdgeInspector_App/View/GlassMap.cpp
@@ -2174,6 +2174,9 @@
        {
            if((CAMERA_DIR)pDefect->m_nDir == CAMDIR_BOTTOM)
                continue;
            if ((CAMERA_DIR)pDefect->m_nDir == CAMDIR_SIDE)
                continue;
        }
         if(m_pSelDefect == pDefect)
EdgeInspector_App/View/ViewMain_HWSetting.cpp
@@ -373,7 +373,7 @@
    int            iCam,iScan,i;
    int            iRow,iCol;
    CString        str;        
    const   TCHAR* SET_CAMERA_DIR[] = {_T("Top"),_T("Bottom")};
    const   TCHAR* SET_CAMERA_DIR[] = {_T("Top"),_T("Bottom"),_T("Side") };
    const   TCHAR* SET_INS_DIR[] = {_T("Long"),_T("Short")};    
    const TCHAR* SET_INS_DIMENSION[] = {
        _T("A Top"), _T("B Top"), _T("C Top"), _T("D Top"),
@@ -384,15 +384,16 @@
    CStringArray    arrDir,arrInsDir,arrDimension;
    CGridCellCombo *pCell;        
    
    for(i=0;i<2;i++)
    {
        arrDir.Add(SET_CAMERA_DIR[i]);
        arrInsDir.Add(SET_INS_DIR[i]);
    }
    for(i=0;i<12;i++)
    {
        arrDimension.Add(SET_INS_DIMENSION[i]);
    }
    for (i = 0; i < 3; i++) {
        arrDir.Add(SET_CAMERA_DIR[i]);
    }
    for (i = 0; i < 2; i++) {
        arrInsDir.Add(SET_INS_DIR[i]);
    }
    for (i = 0; i < 12; i++) {
        arrDimension.Add(SET_INS_DIMENSION[i]);
    }
    
    if(bWrite == TRUE)
    {
@@ -422,7 +423,8 @@
                switch(pCamera->m_enCamDir)
                {
                case CAMDIR_TOP: str.Format(_T("%s"),SET_CAMERA_DIR[0]); break;
                case CAMDIR_BOTTOM: str.Format(_T("%s"),SET_CAMERA_DIR[1]); break;
                case CAMDIR_BOTTOM: str.Format(_T("%s"),SET_CAMERA_DIR[1]); break;
                case CAMDIR_SIDE: str.Format(_T("%s"), SET_CAMERA_DIR[2]); break;
                default: str.Format(_T("%s"),_T("No")); break;
                }            
                m_CameraGrid.SetItemText(iRow,iCol,str);    
@@ -669,23 +671,19 @@
void CViewMain_HWSetting::UpdateControlValue(BOOL bWrite)
{
    if(bWrite == TRUE)
    {
    if(bWrite == TRUE) {
        UpdateData(FALSE);
        FillLightGrid(TRUE);
        FillCameraGrid(TRUE);
        ((CComboBox*)(GetDlgItem(IDC_COMBO_BORAD_TYPE)))->SetCurSel((int)m_pDlgHDSettingParm->m_nBoardType);        
    }
    else
    {
    else {
        UpdateData(TRUE);
        FillLightGrid(FALSE);
        FillCameraGrid(FALSE);
        if(m_pHDSetting != NULL)
        {
        if(m_pHDSetting != NULL) {
            m_pDlgHDSettingParm->m_nBoardType = (BOARD_TYPE)((CComboBox*)(GetDlgItem(IDC_COMBO_BORAD_TYPE)))->GetCurSel();
            *m_pHDSetting = *m_pDlgHDSettingParm;
        }
    }
@@ -721,40 +719,30 @@
    CreateDirectory(_T("C:\\EdgeInspector_App\\Config"),NULL);
    CreateDirectory(_T("C:\\EdgeInspector_App\\Config\\Backup"),NULL);
    CTime currentTime = CTime::GetCurrentTime();
    CString    str;
    str.Format(_T("%s\\HardwareSetting_%02d%02d%02d_%02d%02d%02d.cfg"), HARDWARE_SETTING_BACKUP_DIR_PATH
                                                                        , currentTime.GetYear()
                                                                        , currentTime.GetMonth()
                                                                        , currentTime.GetDay()
                                                                        , currentTime.GetHour()
                                                                        , currentTime.GetMinute()
                                                                        , currentTime.GetSecond());
    CTime time = CTime::GetCurrentTime();
    str.Format(_T("%s\\HardwareSetting_%02d%02d%02d_%02d%02d%02d.cfg"), HARDWARE_SETTING_BACKUP_DIR_PATH, time.GetYear(), time.GetMonth(), time.GetDay(), time.GetHour(), time.GetMinute(), time.GetSecond());
    UpdateControlValue(FALSE);    
    if(m_pHDSetting->WriteHardwareSettingsFile(str) == FALSE)
    {
    if(m_pHDSetting->WriteHardwareSettingsFile(str) == FALSE) {
        AfxMessageBox(_T("Save Fail!"));
    }
}
void CViewMain_HWSetting::ClickHWSaveButton()
{
    if(m_pHDSetting == NULL)
    if (m_pHDSetting == NULL) {
        return;
    }
    if (IDYES == AfxMessageBox(_T("Do you want to save? \n Restarting is required to change settings."), MB_YESNO | MB_ICONQUESTION))
    {
    if (IDYES == AfxMessageBox(_T("Do you want to save? \n Restarting is required to change settings."), MB_YESNO | MB_ICONQUESTION)) {
        UpdateControlValue(FALSE);
        if(m_pHDSetting->WriteHardwareSettingsFile(HARDWARE_SETTING_PATH) == FALSE)// if(m_pHDSetting->WriteHardwareSettingsRegistry() == FALSE)
        {
            AfxMessageBox(_T("Save Fail!"));
        g_pLog->DisplayMessage(_T("Saving HW settings file[%s]..."), HARDWARE_SETTING_PATH);
        if (m_pHDSetting->WriteHardwareSettingsFile(HARDWARE_SETTING_PATH) == FALSE) {
            g_pLog->DisplayMessage(_T("Failed to save hardware settings file!"));
            return;
        }
        SaveHardwareFileBackup();
        SaveHardwareFileBackup();
    }
}
SDK/BlGrabber/include/GrabberControl.h
@@ -75,5 +75,6 @@
    virtual stFrameIndex    GetGrabFrameNoRemove() = 0;
    virtual CFrameBufferController    *GetFrameBuffer() = 0;
    virtual BOOL    SetTriggerMode(BOOL bExTrigger) = 0;
    virtual BOOL    DumpBufferAsOneImage(int iScan, LPCTSTR pszPath) = 0;
};