gusucode.com > 精典源码Delphi044:指纹考勤管理系统源码程序 > 精典源码Delphi044:指纹考勤管理系统源码程序/精典源码Delphi044:指纹考勤管理系统/顺发指纹考勤管理系统/指纹考勤系统/1.3cxy/FP/FPCtl.cpp

    // FPCtl.cpp : Implementation of the CFPCtrl ActiveX Control class.

#include "stdafx.h"
#include "FP.h"
#include "FPCtl.h"
#include "FPPpg.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

int g_nWidth, g_nHeight;                //width and height of drawing area
FT_HANDLE g_FtContext;                  //dpFpFns context 
FT_HANDLE g_mcContext;                  //dpMatch context
FT_UI_LINK g_FtUILink;                  //UI link information
FT_DEVICE_INFO g_DevInfo;               //device info
FT_BYTE* g_Features=NULL;				    //features
FT_BYTE* g_VerFeatures=NULL;				    //features
int g_recommendedFtrLen, g_minFtrLen;   //recommended features length and minimum features length
int g_nFingerCount;                     //variable to count down fingers left while registering (4 - 0)
BOOL g_bIsVerifying,g_bCanVerify;       //verifying or register mode, in verifying mode do not show images or fingerprints
CWinThread* g_pRegisterThread = NULL;   //pointer to register thread
CWinThread* g_pVerifyThread = NULL;     //pointer to verify thread
BYTE *g_FPBuffer;                       // Pointer to buffer which holds data portion of bitmap received from sensor.
                                        // This pointer is provided for toolkit in the callback function.
                                        // Toolkit loads image in the buffer and notifies GUI thread that image is ready.
HWND g_hwnd = NULL;                     //HWND of dialog
BOOL g_bIsTimeToDie = FALSE;            //variable used to ensure clean exit from program
CEvent g_event(FALSE, TRUE);            //event used to make sure that program will not exit
                                        //while toolkit is doing something (like waiting for image)
                                        //second argument TRUE for manual CEvent

//Callback functions set up by FT_setupUILink

FT_ACTION getRegisterAction (FT_STATUS_PT pStatus) 
{   
    if(g_bIsTimeToDie)                  //If program wants to exit, then indicate that to toolkit
        return FT_ID_CANCEL;

    switch(pStatus->code) 
    {
        case FT_READY_TO_FILL_BUF:  
//            SendMessage(g_hwnd, MESSAGE_READY_TO_FILL_BUF, 0, 0);
            TRACE("FT_READY_TO_FILL_BUF\n");
            break;

        case FT_BUF_FILLED:       
//            SendMessage(g_hwnd, MESSAGE_IMAGE_RECEIVED, 0, 0);
            TRACE("FT_BUF_FILLED\n");
            break;

        case FT_IMAGE_INFO:         // param1 = FT_IMGQUALITY.  param2 = unused
            SendMessage(g_hwnd, MESSAGE_FT_IMAGE_INFO, 0, (LPARAM)pStatus->param1);
            TRACE("FT_IMAGE_INFO\n");
            break;

        case FT_FEATURES_INFO:
            SendMessage(g_hwnd, MESSAGE_FT_FEATURES_INFO, 0, (LPARAM)pStatus->param1);
            TRACE("FT_FEATURES_INFO\n");
            break;

        case FT_WAITING_FOR_IMAGE:   
            SendMessage(g_hwnd, MESSAGE_FT_WAITING_FOR_IMAGE, 0, 0);
            TRACE("FT_WAITING_FOR_IMAGE\n");
            break;

        default:
            break;
    }
    return FT_ID_CONTINUE;
}

FT_DISPLAY_BUF_PT getRegisterDisplayBuf (FT_FTR_TYPE) 
{
    TRACE("getRegisterDisplayBuf\n");
    return g_FPBuffer;
}

FT_RETCODE releaseRegisterDisplayBuf (FT_DISPLAY_BUF_PT) 
{
    TRACE("releaseRegisterDisplayBuf\n");
    return 0;
}


//Thread functions
UINT DoRegister(LPVOID pParam)          //register thread function
{
    g_nFingerCount = 0;
    FT_RETCODE rc;
    FT_RESULT result;
    g_event.ResetEvent();               //we reset CEvent in nonsignaled state to make sure 
                                        //program will wait until FT_register completes before exiting
	rc = FT_flushFpImages(g_FtContext);
    rc = FT_register(g_FtContext,
                FT_FALSE,                //allowLearning has to be FT_TRUE here because we are planing to 
                                        //use features with database             
                g_recommendedFtrLen,    
                g_Features,
                NULL,
                &result);
    g_event.SetEvent();                 //now we can exit
    ::PostMessage((HWND)pParam, WM_REGISTERTHREADFINISHED, 0, (LPARAM)result);
    return 0;
}

//Thread functions
UINT DoVerify(LPVOID pParam)          //register thread function
{
    FT_IMG_QUALITY qualityImg;
    FT_FTR_QUALITY  qualityFtr;
    FT_RETCODE rc;
    FT_RESULT result;
    g_event.ResetEvent();               //we reset CEvent in nonsignaled state to make sure 
                                        //program will wait until FT_register completes before exiting
	rc = FT_flushFpImages(g_FtContext);
    rc = FT_acquireFeatures(g_FtContext,
		FT_VER_FTR,
        g_recommendedFtrLen,
        g_VerFeatures,
        &qualityImg,
        &qualityFtr,
        &result);
    if(result == FT_SUCCESS) g_bCanVerify=TRUE; else g_bCanVerify=FALSE;
	g_event.SetEvent();                 //now we can exit
    ::PostMessage((HWND)pParam, WM_VERIFYTHREADFINISHED, 0, (LPARAM)result);
    return 0;
}

IMPLEMENT_DYNCREATE(CFPCtrl, COleControl)


/////////////////////////////////////////////////////////////////////////////
// Message map

BEGIN_MESSAGE_MAP(CFPCtrl, COleControl)
	//{{AFX_MSG_MAP(CFPCtrl)
	// NOTE - ClassWizard will add and remove message map entries
	//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG_MAP
	ON_MESSAGE(OCM_COMMAND, OnOcmCommand)
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
	ON_MESSAGE(MESSAGE_FT_IMAGE_INFO, OnImageInfo)
	ON_MESSAGE(MESSAGE_FT_FEATURES_INFO, OnFeaturesInfo)
	ON_MESSAGE(WM_REGISTERTHREADFINISHED, OnRegisterThreadFinished)
	ON_MESSAGE(WM_VERIFYTHREADFINISHED, OnVerifyThreadFinished)
	ON_MESSAGE(MESSAGE_FT_WAITING_FOR_IMAGE, OnWaitingForImage)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// Dispatch map

BEGIN_DISPATCH_MAP(CFPCtrl, COleControl)
	//{{AFX_DISPATCH_MAP(CFPCtrl)
	DISP_PROPERTY(CFPCtrl, "FeatureLength", m_FeatureLength, VT_I2)
	DISP_FUNCTION(CFPCtrl, "FlushImages", FlushImages, VT_BOOL, VTS_NONE)
	DISP_FUNCTION(CFPCtrl, "InitReg", InitReg, VT_BOOL, VTS_NONE)
	DISP_FUNCTION(CFPCtrl, "Regist", Regist, VT_EMPTY, VTS_NONE)
	DISP_FUNCTION(CFPCtrl, "InitVerify", InitVerify, VT_BOOL, VTS_NONE)
	DISP_FUNCTION(CFPCtrl, "GetRegFeatures", GetRegFeatures, VT_BOOL, VTS_I2 VTS_PI2)
	DISP_FUNCTION(CFPCtrl, "SetRegFeatures", SetRegFeatures, VT_BOOL, VTS_I2 VTS_I2)
	DISP_FUNCTION(CFPCtrl, "Verify", Verify, VT_BOOL, VTS_NONE)
	DISP_FUNCTION(CFPCtrl, "KillThread", KillThread, VT_BOOL, VTS_NONE)
	DISP_FUNCTION(CFPCtrl, "GetVerFeature", GetVerFeature, VT_EMPTY, VTS_NONE)
	DISP_FUNCTION(CFPCtrl, "intFeatureByIndex", intFeatureByIndex, VT_I2, VTS_I2)
	//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()


/////////////////////////////////////////////////////////////////////////////
// Event map

BEGIN_EVENT_MAP(CFPCtrl, COleControl)
	//{{AFX_EVENT_MAP(CFPCtrl)
	EVENT_CUSTOM("GetVerFeatures", FireGetVerFeatures, VTS_BOOL  VTS_BSTR)
	EVENT_CUSTOM("GetRegFeatures", FireGetRegFeatures, VTS_BOOL  VTS_BSTR)
	EVENT_CUSTOM("Status", FireStatus, VTS_I4  VTS_BSTR)
	//}}AFX_EVENT_MAP
END_EVENT_MAP()


/////////////////////////////////////////////////////////////////////////////
// Property pages

// TODO: Add more property pages as needed.  Remember to increase the count!
BEGIN_PROPPAGEIDS(CFPCtrl, 1)
	PROPPAGEID(CFPPropPage::guid)
END_PROPPAGEIDS(CFPCtrl)


/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid

IMPLEMENT_OLECREATE_EX(CFPCtrl, "FP.FPCtrl.1",
	0xb40bcde9, 0xb949, 0x11d3, 0x98, 0xf0, 0xbd, 0xa0, 0x34, 0x90, 0x69, 0x7a)


/////////////////////////////////////////////////////////////////////////////
// Type library ID and version

IMPLEMENT_OLETYPELIB(CFPCtrl, _tlid, _wVerMajor, _wVerMinor)


/////////////////////////////////////////////////////////////////////////////
// Interface IDs

const IID BASED_CODE IID_DFP =
		{ 0xb40bcde7, 0xb949, 0x11d3, { 0x98, 0xf0, 0xbd, 0xa0, 0x34, 0x90, 0x69, 0x7a } };
const IID BASED_CODE IID_DFPEvents =
		{ 0xb40bcde8, 0xb949, 0x11d3, { 0x98, 0xf0, 0xbd, 0xa0, 0x34, 0x90, 0x69, 0x7a } };


/////////////////////////////////////////////////////////////////////////////
// Control type information

static const DWORD BASED_CODE _dwFPOleMisc =
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST |
	OLEMISC_INSIDEOUT |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CFPCtrl, IDS_FP, _dwFPOleMisc)


/////////////////////////////////////////////////////////////////////////////
// CFPCtrl::CFPCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CFPCtrl

BOOL CFPCtrl::CFPCtrlFactory::UpdateRegistry(BOOL bRegister)
{
	// TODO: Verify that your control follows apartment-model threading rules.
	// Refer to MFC TechNote 64 for more information.
	// If your control does not conform to the apartment-model rules, then
	// you must modify the code below, changing the 6th parameter from
	// afxRegApartmentThreading to 0.

	if (bRegister)
		return AfxOleRegisterControlClass(
			AfxGetInstanceHandle(),
			m_clsid,
			m_lpszProgID,
			IDS_FP,
			IDB_FP,
			afxRegApartmentThreading,
			_dwFPOleMisc,
			_tlid,
			_wVerMajor,
			_wVerMinor);
	else
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}


/////////////////////////////////////////////////////////////////////////////
// CFPCtrl::CFPCtrl - Constructor

CFPCtrl::CFPCtrl()
{
	InitializeIIDs(&IID_DFP, &IID_DFPEvents);

	// TODO: Initialize your control's instance data here.
	SetInitialSize(168,264); 
}


/////////////////////////////////////////////////////////////////////////////
// CFPCtrl::~CFPCtrl - Destructor

CFPCtrl::~CFPCtrl()
{
	// TODO: Cleanup your control's instance data here.
	if (g_FPBuffer != NULL )
	{
		g_bIsTimeToDie = TRUE;
		::WaitForSingleObject(g_event, INFINITE);
		FT_disconnectDevice(g_FtContext);
		FT_closeContext(g_FtContext);
		FT_terminate();
		if (g_VerFeatures !=NULL)
		{
			MC_closeContext(g_mcContext);
			MC_terminate();
			delete [] g_VerFeatures;
		}
		delete [] g_FPBuffer;
		delete [] g_Features;
		delete m_pGray8Dib;
	};
}


/////////////////////////////////////////////////////////////////////////////
// CFPCtrl::OnDraw - Drawing function

void CFPCtrl::OnDraw(
			CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
	DoSuperclassPaint(pdc, rcBounds);
	pdc->Rectangle(rcBounds);
	if (g_FPBuffer!=NULL)
	{
		m_pGray8Dib->UsePalette(pdc, true);
        m_pGray8Dib->Draw(pdc, 1, 1, g_FPBuffer);
	}
}


/////////////////////////////////////////////////////////////////////////////
// CFPCtrl::DoPropExchange - Persistence support

void CFPCtrl::DoPropExchange(CPropExchange* pPX)
{
	ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
	COleControl::DoPropExchange(pPX);

	// TODO: Call PX_ functions for each persistent custom property.

}


/////////////////////////////////////////////////////////////////////////////
// CFPCtrl::OnResetState - Reset control to default state

void CFPCtrl::OnResetState()
{
	COleControl::OnResetState();  // Resets defaults found in DoPropExchange

	// TODO: Reset any other control state here.
}


/////////////////////////////////////////////////////////////////////////////
// CFPCtrl::PreCreateWindow - Modify parameters for CreateWindowEx

BOOL CFPCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
	cs.lpszClass = _T("STATIC");
	return COleControl::PreCreateWindow(cs);
}


/////////////////////////////////////////////////////////////////////////////
// CFPCtrl::IsSubclassedControl - This is a subclassed control

BOOL CFPCtrl::IsSubclassedControl()
{
	return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// CFPCtrl::OnOcmCommand - Handle command messages

LRESULT CFPCtrl::OnOcmCommand(WPARAM wParam, LPARAM lParam)
{
#ifdef _WIN32
	WORD wNotifyCode = HIWORD(wParam);
#else
	WORD wNotifyCode = HIWORD(lParam);
#endif

	// TODO: Switch on wNotifyCode here.

	return 0;
}

LRESULT CFPCtrl::OnImageInfo(WPARAM wParam, LPARAM lParam)
{
	CString s;
    switch(lParam)
    {
    case FT_GOOD_IMG:
		s.LoadString(IDS_GoodIMG);
        TRACE("FT_GOOD_IMG\n");
        break;
        
    case FT_IMG_TOO_LIGHT:
		s.LoadString(IDS_LightIMG);
        TRACE("FT_IMG_TOO_LIGHT\n");
        break;

    case FT_IMG_TOO_DARK:
		s.LoadString(IDS_DarkIMG);
        TRACE("FT_IMG_TOO_DARK\n");
        break;

    case FT_IMG_TOO_NOISY:
		s.LoadString(IDS_NoisyIMG);
        TRACE("FT_IMG_TOO_NOISY\n");
        break;

    case FT_LOW_CONTRAST:
		s.LoadString(IDS_BadIMG);
        TRACE("FT_LOW_CONTRAST\n");
        break;

    case FT_UNKNOWN_IMG_QUALITY:
		s.LoadString(IDS_BadIMG);
        TRACE("FT_LOW_CONTRAST\n");
        break;
    
    default:
        break;
    }
	FireStatus(lParam,s);
	return 0L;
}

LRESULT CFPCtrl::OnFeaturesInfo(WPARAM wParam, LPARAM lParam)
{
	CString s,s1;
    switch(lParam)
    {
    case FT_GOOD_FTR:
		s1.LoadString(IDS_GoodFTR);
        TRACE("FT_GOOD_FTR\n");
        if(!g_bIsVerifying)
        {
            s.Format(s1, 3 - g_nFingerCount);
            g_nFingerCount++;
        }
        break;
        
    case FT_NOT_ENOUGH_FTR:
		s.LoadString(IDS_NOT_ENOUGH_FTR);
        TRACE("FT_NOT_ENOUGH_FTR\n");
        break;

    case FT_NO_CENTRAL_REGION:
		s.LoadString(IDS_NOT_CENTRAL_FTR);
        TRACE("FT_NO_CENTRAL_REGION\n");
        break;

    case FT_UNKNOWN_FTR_QUALITY:
		s.LoadString(IDS_BADFTR);
        TRACE("FT_UNKNOWN_FTR_QUALITY\n");
        break;
        
    default:
        break;
    }
	InvalidateControl(NULL);
	FireStatus(lParam,s);
	return 0L;
}

LRESULT CFPCtrl::OnWaitingForImage(WPARAM wParam, LPARAM lParam)
{
	CString s;
	s.LoadString(IDS_WaitIMG);
	FireStatus(FT_WAITING_FOR_IMAGE,s);
    TRACE("FT_WAITING_FOR_IMAGE\n");
	return 0L;
}

LRESULT CFPCtrl::OnRegisterThreadFinished(WPARAM wParam, LPARAM lParam)
{
	CString s;
	g_pRegisterThread = NULL;
    if((FT_RESULT)lParam == FT_SUCCESS)
    {
		s.LoadString(IDS_RegSuccess);
		FireGetRegFeatures(TRUE,s);
    }
    else if(!g_bIsTimeToDie)
    {
		s.LoadString(IDS_RegFail);
		FireGetRegFeatures(FALSE,s);
    }
	FireStatus(0,s);
	return 0L;
}

LRESULT CFPCtrl::OnVerifyThreadFinished(WPARAM wParam, LPARAM lParam)
{
	CString s;
	g_pVerifyThread = NULL;
    if(g_bCanVerify)
    {
		s.LoadString(IDS_GetVerSuccess);
    }
    else if(!g_bIsTimeToDie)
    {
		s.LoadString(IDS_GetVerFail);
    }
	FireGetVerFeatures(g_bCanVerify,s);
	return 0L;
}
/////////////////////////////////////////////////////////////////////////////
// CFPCtrl message handlers

BOOL CFPCtrl::FlushImages() 
{
	// TODO: Add your dispatch handler code here
	FT_RETCODE rc;
	rc=FT_flushFpImages(g_FtContext);
	if (rc==FT_OK)	return TRUE; else return FALSE;
}

BOOL CFPCtrl::InitReg() 
{
	// TODO: Add your dispatch handler code here
    g_FPBuffer = NULL;
	GetControlSize(&g_nWidth,&g_nHeight);
    FT_RETCODE rc;
    rc = FT_init();
    rc = FT_createContext(&g_FtContext);
    rc = FT_getDeviceList (1, &g_DevInfo);
    rc = FT_connectDevice (g_FtContext, g_DevInfo.devId, FT_REGULAR_PRIORITY);

    g_FtUILink.getAction = getRegisterAction;
    g_FtUILink.getDisplayBuf = getRegisterDisplayBuf;
    g_FtUILink.releaseDisplayBuf = releaseRegisterDisplayBuf;
    g_FtUILink.numIntensityLevels = 32;
    g_FtUILink.timeout = 2000;
    g_FtUILink.extension = NULL;
    g_FtUILink.displayOrientation = FT_PORTRAIT;
    g_FtUILink.displayBufSize.width = g_nWidth;
    g_FtUILink.displayBufSize.height = g_nHeight;

    rc = FT_setupUIlink(g_FtContext, &g_FtUILink);
    rc =FT_getFeaturesLen(FT_REG_FTR, FT_FALSE, &g_recommendedFtrLen, &g_minFtrLen);
    g_FPBuffer = new BYTE[g_FtUILink.displayBufSize.width * g_FtUILink.displayBufSize.height ];
    g_Features = new FT_BYTE[g_recommendedFtrLen];
	m_FeatureLength=g_recommendedFtrLen;
    ZeroMemory(g_FPBuffer, sizeof(BYTE) * g_nHeight * g_nWidth);
    // CGray8Dib is a class used to create a bitmap from an array of BYTE's and draw it in a specified rectangle
    m_pGray8Dib = new CGray8Dib(CRect(0, 0, g_nWidth, g_nHeight), g_nWidth, g_nHeight);
    g_hwnd = (HWND) GetHwnd();
    g_bIsVerifying = FALSE;
    g_event.SetEvent();
    g_event.SetEvent();
	if (g_FPBuffer!=NULL) return TRUE; else	return FALSE;
}

void CFPCtrl::Regist() 
{
	// TODO: Add your dispatch handler code here
	CString s;
    g_bIsTimeToDie = TRUE;
    ::WaitForSingleObject(g_event, INFINITE);
    g_bIsTimeToDie = FALSE;

    g_bIsVerifying = FALSE;
    ZeroMemory(g_FPBuffer, sizeof(BYTE) * g_nHeight * g_nWidth);
	s.LoadString(IDS_BegReg);
	FireStatus(0,s);
	InvalidateControl(NULL);
    g_pRegisterThread = AfxBeginThread(DoRegister, (HWND)GetHwnd(), THREAD_PRIORITY_NORMAL);
} 

BOOL CFPCtrl::InitVerify() 
{
	// TODO: Add your dispatch handler code here
	if (g_FPBuffer==NULL) InitReg();
    FT_RETCODE rc;
    rc = MC_init();
    rc = MC_createContext(&g_mcContext);
	g_VerFeatures=new FT_BYTE[g_recommendedFtrLen];
	if (rc==FT_OK) return TRUE; else return FALSE;
}


BOOL CFPCtrl::GetRegFeatures(short Index, short FAR* FeatureChar) 
{
	// TODO: Add your dispatch handler code here
	if (Index<0 || Index>=g_recommendedFtrLen) return FALSE;
	*FeatureChar=(short) g_Features[Index];
	return TRUE;
}

BOOL CFPCtrl::SetRegFeatures(short Index, short FeatureChar) 
{
	// TODO: Add your dispatch handler code here
	if (Index<0 || Index>=g_recommendedFtrLen) return FALSE;
	g_Features[Index]=(unsigned char)FeatureChar;
	return TRUE;
}

BOOL CFPCtrl::Verify() 
{
	FT_RETCODE rc;
	FT_BOOL bFeatureChanged,isVerified;
	FT_VER_SCORE sc;
	FT_BYTE* fKey;
	CString s;
	BOOL bResult;
	if (!g_bCanVerify)  return FALSE;
	fKey=new FT_BYTE[FT_KEY_LEN];
	rc=MC_verifyFeatures(g_mcContext,
		g_recommendedFtrLen,
		g_Features,
		g_recommendedFtrLen,
		g_VerFeatures,
		FALSE,
		&bFeatureChanged,
		fKey,
		&sc,
		&isVerified);
	delete [] fKey;
	s.LoadString(IDS_EndVerify);
	FireStatus(rc,s);
	if (rc != FT_OK) bResult =FALSE; else bResult = isVerified;
	return bResult;
}

BOOL CFPCtrl::KillThread() 
{
	g_bIsTimeToDie=TRUE;
	::WaitForSingleObject(g_event, INFINITE);
	return TRUE;
}

void CFPCtrl::GetVerFeature() 
{
	CString s;
    ZeroMemory(g_VerFeatures, sizeof(BYTE) * g_recommendedFtrLen);
    ZeroMemory(g_FPBuffer, sizeof(BYTE) * g_nHeight * g_nWidth);
    InvalidateControl(NULL);
    g_bIsVerifying = TRUE;
	s.LoadString(IDS_BegVerify);
	FireStatus(0,s);
    g_pVerifyThread = AfxBeginThread(DoVerify, (HWND)GetHwnd(), THREAD_PRIORITY_NORMAL);
}

short CFPCtrl::intFeatureByIndex(short Index) 
{
	if (Index<0 || Index>=g_recommendedFtrLen) return -1;
	return (short) g_Features[Index];
}