Loading and Saving Annotations Using Databases (C++ 5.0 and later)
To start a project and add code that demonstrates adding annotation objects to or deleting annotation objects from the BLOB field of a database file:
First create a database file (in this case, named D:\TEMP\DB1.MDB) with one table named Images and with the fields listed below:
Field Name |
Type |
Image |
Binary |
Size |
Number |
|
Start a new project as follows: |
|
1. |
Run Microsoft Visual Studio 2005, select the File à New à Project, and do the following: |
|
|
a. |
Expand Visual C++ tree, if it is not already expanded. |
|
b. |
Select MFC from the sub tree. |
|
c. |
Select MFC Application from the right window. |
|
d. |
In the Project name text box, specify AnnBlob. |
|
e. |
In the Location text box, specify the path of the project. |
|
f. |
Click the OK button. |
2. |
In the overview window Just click Next. |
|
3. |
In the Application Type step dialog box, do the following: |
|
|
a. |
Select Dialog based. |
|
b. |
Use MFC in a shared DLL |
|
c. |
Click the Next button. |
4. |
In the Step 2 of 4 dialog box, do the following: |
|
|
a. |
Ensure that About Box is selected. |
|
b. |
Ensure that System Menu is selected. |
|
c. |
Click the Next button. |
5. |
In the Step 3 of 4 dialog box, just click Finish: |
|
6. |
Add #include statements to your program so you can access the LEAD C++ Class Library constants and classes: |
|
|
a. |
In the Project Workspace, click the Solution Explorer tab. |
|
b. |
Double-click the AnnBlob Project folder to open it. |
|
c. |
Double-click the Header Files folder to open it. |
|
d. |
Double-click the StdAfx.h file to edit it. |
|
Add the following lines to the end of the file (keep in mind, you may have to change the path to where the header files reside): |
#include "..\..\..\..\..\include\ClassLib\ltWrappr.h"
7. |
Add a Button control to the main window as follows: |
|
|
a. |
In the Project Workspace, click the ResourceView tab. |
|
b. |
Double-click the AnnBlob.rc folder to open it. |
|
c. |
Double-click the Dialog folder to open it. |
|
d. |
Double-click IDD_IMAGEBLOB_DIALOG to design the form. |
|
e. |
Select the TODO... text control; then press the Delete key to delete it. |
|
f. |
Click the Static Text control icon, add a control to the dialog, then size and position the control as you want it to appear at run time. |
8. |
Add #import statements to your program so you can access the Microsoft ActiveX Data Object 2.6 Library: |
|
|
a. |
In the Project Workspace, click the Solution Explorer tab. |
|
b. |
Double-click the AnnBlob folder to open it. |
|
c. |
Double-click the Header Files folder to open it. |
|
d. |
Double-click the StdAfx.h file to edit it. |
|
Add the following lines to the end of the file (keep in mind, you may have to change the path to where the .tlb files reside): |
#import <C:\\Windows\\system32\\msado26.tlb> rename("EOF", "ADOEOF")
using namespace ADODB;
9. |
Click the Resrouce View tab. On the View menu, select ToolBox, and then add six command buttons to your form and name them as follows: |
|
|
ID |
Caption |
|
IDC_CONNECT |
&Connect To Database |
|
IDC_DISCONNECT |
&Disconnect From Database |
|
IDC_ADDRECORD |
&Add Record |
|
IDC_DELETERECORD |
D&elete Record |
|
IDC_MOVENEXT |
Move &Next |
|
IDC_MOVEPREVIOUS |
Move &Previous |
|
Save the resource file. |
10. |
Do the following to add m_btnAddRecord to the CAnnBlobDlg class and link the variable to the CButton control using dynamic data exchange: |
|
|
a. |
Open AnnBlob.rc and Double-click on IDD_IMAGEBLOB_DIALOG. |
|
b. |
Right-click on the Add Record button, and choose Add Variable. |
|
c. |
Specify m_btnAddRecord as the variable name, and Control as the category. |
|
d. |
Click Finish to close the dialog box. |
11. |
Repeat step 11 for the other buttons, using the following variable names: |
|
|
ID |
Member Variable Name |
|
IDC_MOVEPREVIOUS |
m_btnMovePrevious |
|
IDC_MOVENEXT |
m_btnMoveNext |
|
IDC_DISCONNECT |
m_btnDisconnect |
|
IDC_DELETERECORD |
m_btnDeleteRecord |
|
IDC_CONNECT |
m_btnConnect |
12. |
Add the following Member Variables to the CAnnBlobDlg class: |
|
|
_ConnectionPtr |
m_pConnection; |
|
_RecordsetPtr |
m_pRecordset; |
|
LAnnotationWindow |
m_LAnnoWnd; |
13. |
Go to the OnInitDialog() function as follows: |
|
|
a. |
From view menu, select Class view. |
|
b. |
In the Project Workspace, click the ClassView tab. |
|
c. |
Double-click the AnnBlob folder to open it. |
|
d. |
Click on the CAnnBlobDlg class. |
|
e. |
Double-click the OnInitDialog()function in the lower window to edit it. |
14. |
Edit the OnInitDialog() function to add the following code after the line that says //TODO: Add extra initialization here: |
LBase::LoadLibraries(LT_KRN);
LBase::LoadLibraries(LT_DIS);
LBase::LoadLibraries(LT_FIL);
LBase::LoadLibraries(LT_ANN);
LSettings::UnlockSupport(L_SUPPORT_DOCUMENT, L_KEY_DOCUMENT);
RECT rc;
GetDlgItem(IDC_STATIC)->GetWindowRect(&rc);
ScreenToClient(&rc);
HWND hWnd = m_LAnnoWnd.CreateWnd(this->GetSafeHwnd(),0,
WS_VISIBLE|L_BS_CENTER|
L_BS_PROCESSKEYBOARD,
rc.left ,rc.top ,rc.right ,rc.bottom );
if (!m_LAnnoWnd.GetToolBar().IsCreated())
m_LAnnoWnd.GetToolBar().Create(hWnd, NULL, ANNTOOLALIGN_RIGHT | ANNTOOLALIGN_TOP, TRUE, NULL, NULL);
m_LAnnoWnd.EnableAutoScroll(TRUE);
m_LAnnoWnd.SetFileName (TEXT("C:\\Program Files\\LEAD
Technologies\\LEADTOOLS 16\\Images\\Image1.cmp"));
int nRet = m_LAnnoWnd.Load (0,ORDER_BGR, 1);
HRESULT hr;
CoInitialize(NULL);
hr = m_pConnection.CreateInstance(__uuidof( Connection) );
m_pRecordset.CreateInstance(__uuidof(Recordset));
m_btnMoveNext.EnableWindow(FALSE);
m_btnMovePrevious.EnableWindow(FALSE);
m_btnAddRecord.EnableWindow(FALSE);
m_btnDeleteRecord.EnableWindow(FALSE);
15. |
Do the following to add an event handler to the Connect To Database button: |
|
|
a. |
Open AnnBlob.rc and Double-click on IDD_IMAGEBLOB_DIALOG. |
|
b. |
Right-click on the Connect To Database button, and choose Add Event Handler. |
|
c. |
From the Message Type List, choose BN_CLICKED. |
|
d. |
Click the Add and Edit button to close the dialog box, then enter the following code: |
HRESULT hr;
_bstr_t bstrConnection("Provider=Microsoft.Jet.OLEDB.4.0;
Data Source=d:\\temp\\DB1.mdb;");
_bstr_t bstrQuery("SELECT * FROM Images");
_variant_t vNull;
vNull.vt = VT_ERROR ;
vNull.scode = DISP_E_PARAMNOTFOUND ;
if (m_pConnection->State == adStateClosed)
{
hr = m_pConnection->Open( bstrConnection,
_bstr_t(L""), _bstr_t(L""), adModeUnknown ) ;
}
if (SUCCEEDED(hr))
{
m_pRecordset->PutRefActiveConnection(m_pConnection);
hr = m_pRecordset->Open(_variant_t(bstrQuery), vNull, adOpenKeyset, adLockOptimistic, adCmdText );
if (SUCCEEDED(hr))
{
if(!m_pRecordset->GetBOF())
{
m_pRecordset->MoveFirst();
}
if (!m_pRecordset->GetADOEOF())
{
m_btnMoveNext.EnableWindow(TRUE);
m_btnMovePrevious.EnableWindow(TRUE);
m_btnDeleteRecord.EnableWindow(TRUE);
}
m_btnAddRecord.EnableWindow(TRUE);
}
}
16. |
Do the following to add an event handler to the Disconnect From Data Base button: |
|
|
a. |
Open AnnBlob.rc and Double-click on IDD_IMAGEBLOB_DIALOG. |
|
b. |
Right-click on the Disconnect From Data Base button, and choose Add Event Handler. |
|
c. |
From the Message Type List, choose BN_CLICKED. |
|
d. |
Click the Add and Edit button to close the dialog box, then enter the following code: |
if (m_pConnection->State == adStateOpen)
{
m_pConnection->Close();
}
if (m_pRecordset->State == adStateOpen )
{
m_pRecordset->Close();
}
m_btnMoveNext.EnableWindow(FALSE);
m_btnMovePrevious.EnableWindow(FALSE);
m_btnAddRecord.EnableWindow(FALSE);
m_btnDeleteRecord.EnableWindow(FALSE);
17. |
Do the following to add an event handler to the Add Record button: |
|
|
a. |
Open AnnBlob.rc and Double-click on IDD_IMAGEBLOB_DIALOG. |
|
b. |
Right-click on the Add Record button, and choose Add Event Handler. |
|
c. |
From the Message Type List, choose BN_CLICKED. |
|
d. |
Click the Add and Edit button to close the dialog box, then enter the following code: |
L_SIZE_T nSize;
int nRet;
LMemoryFile LeadMemFile ;
LBuffer LeadMemBuffer ;
if (m_pConnection->State == adStateClosed )
{
MessageBox (TEXT("Connection closed"));
return;
}
LeadMemFile.SetBitmap((LBitmapBase *) &m_LAnnoWnd);
nRet = LeadMemFile.Save(&LeadMemBuffer,FILE_LEAD,24,QS);
nSize = LeadMemBuffer.GetSize();
BYTE * pData = (BYTE *)LeadMemBuffer.Lock();
VARIANT varBLOB;
BlobToVariant(varBLOB, pData, (LONG)nSize);
LeadMemBuffer.Unlock();
LeadMemBuffer.Free();
m_pRecordset->AddNew();
m_pRecordset->Fields->Item[0L]->AppendChunk(varBLOB);
m_pRecordset->Fields->Item[1L]->PutValue((LONG)nSize);
m_pRecordset->Update();
VariantClear(&varBLOB);
if(m_pRecordset->RecordCount >= 0)
{
m_btnMoveNext.EnableWindow(TRUE);
m_btnMovePrevious.EnableWindow(TRUE);
m_btnDeleteRecord.EnableWindow(TRUE);
}
18. |
Do the following to add an event handler to the Delete Record button: |
|
|
a. |
Open AnnBlob.rc and Double-click on IDD_IMAGEBLOB_DIALOG. |
|
b. |
Right-click on the Delete Record button, and choose Add Event Handler. |
|
c. |
From the Message Type List, choose BN_CLICKED. |
|
d. |
Click the Add and Edit button to close the dialog box, then enter the following code: |
if (m_pConnection->State == adStateClosed )
{
MessageBox (TEXT("Connection closed"));
return;
}
if (!m_pRecordset->GetBOF() || !m_pRecordset->GetADOEOF())
{
m_pRecordset->MoveLast();
m_pRecordset->Delete(adAffectCurrent);
m_pRecordset->Update();
if(m_pRecordset->RecordCount <= 0)
{
m_btnMoveNext.EnableWindow(FALSE);
m_btnMovePrevious.EnableWindow(FALSE);
m_btnDeleteRecord.EnableWindow(FALSE);
}
}
19. |
Do the following to add an event handler to the Move Next button: |
|
|
a. |
Open AnnBlob.rc and Double-click on IDD_IMAGEBLOB_DIALOG. |
|
b. |
Right-click on the Move Next button, and choose Add Event Handler. |
|
c. |
From the Message Type List, choose BN_CLICKED. |
|
d. |
Click the Add and Edit button to close the dialog box, then enter the following code: |
if (m_pConnection->State == adStateClosed )
{
MessageBox (TEXT("Connection closed"));
return;
}
if (!m_pRecordset->GetADOEOF())
{
m_pRecordset->MoveNext();
}
if (m_pRecordset->GetADOEOF())
{
MessageBox(TEXT("Unable to get the Image from db"));
m_pRecordset->MovePrevious();
}
else
{
ReadImage();
}
20. |
Do the following to add an event handler to the Move Previous button: |
|
|
a. |
Open AnnBlob.rc and Double-click on IDD_IMAGEBLOB_DIALOG. |
|
b. |
Right-click on the Move Previous button, and choose Add Event Handler. |
|
c. |
From the Message Type List, choose BN_CLICKED. |
|
d. |
Click the Add and Edit button to close the dialog box, then enter the following code: |
if (m_pConnection->State == adStateClosed )
{
MessageBox (TEXT("Connection closed"));
return;
}
if (!m_pRecordset->GetBOF())
{
m_pRecordset->MovePrevious();
}
if (m_pRecordset->GetBOF())
{
MessageBox(TEXT("Unable to get the Image from db"));
m_pRecordset->MoveNext();
}
else
{
ReadImage();
}
21. |
Go to AnnBlobDlg.h file then add the following function declarations: |
afx_msg void OnClose();
void BlobToVariant(VARIANT &varArray, BYTE* pData, LONG lSize);
void ReadImage();
22. |
Go to AnnBlobDlg.cpp file then add the following line between the BEGIN_MESSAGE_MAP and END_MESSAGE_MAP: ON_WM_CLOSE() |
23. |
Add the following functions to AnnBlobDlg.cpp: |
void CAnnBlobDlg::OnClose()
{
if (m_LAnnoWnd.IsAllocated())
{
m_LAnnoWnd.Free();
}
LBase::UnloadLibraries(LT_KRN);
LBase::UnloadLibraries(LT_DIS);
LBase::UnloadLibraries(LT_FIL);
LBase::UnloadLibraries(LT_ANN);
CoInitialize(NULL);
CDialog::OnClose();
}
void CAnnBlobDlg::BlobToVariant(VARIANT &varArray, BYTE* pData, LONG lSize)
{
BYTE *pByte;
SAFEARRAY FAR* psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = lSize;
// create a single dimensional byte array
psa = SafeArrayCreate(VT_I1, 1, rgsabound);
// set the data of the array with data in the edit box
if(SafeArrayAccessData(psa,(void **)&pByte) == NOERROR)
memcpy((LPVOID)pByte, (LPVOID)pData, lSize);
SafeArrayUnaccessData(psa);
varArray.vt = VT_ARRAY | VT_UI1;
varArray.parray = psa;
}
void CAnnBlobDlg::ReadImage()
{
LONG nSize;
BYTE * pData = NULL;
LMemoryFile LeadMemFile;
int nRet;
_variant_t varSize;
varSize = m_pRecordset->Fields->Item[1L]->Value;
nSize = varSize.intVal;
//free old image
m_LAnnoWnd.Free();
MessageBox(TEXT("old image freed"));
if(nSize)
{
_variant_t varBLOB;
VariantInit(&varBLOB);
// get the chunk of data
varBLOB = m_pRecordset->Fields->Item[0L]->GetChunk(nSize);
pData =(BYTE *) malloc(nSize);
memset(pData,0,nSize);
if(varBLOB.vt == (VT_ARRAY | VT_UI1))
{
BYTE *pBuf = NULL;
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
LeadMemFile.SetBitmap((LBitmapBase *)& m_LAnnoWnd);
LBuffer LeadMemBuffer (pBuf,nSize);
nRet = LeadMemFile.Load(LeadMemBuffer,24,ORDER_BGR, NULL);
SafeArrayUnaccessData(varBLOB.parray);
}
}
}
24. |
Create a new file called Imports.cpp in place it beside your project files. |
|
|
a. |
In the Project Workspace, click the Solution Explorer tab. |
|
b. |
Double-click the AnnBlob folder to open it. |
|
c. |
Right-click the Source files folder and select Add à New item. |
|
d. |
Right-click on the Source file |
|
e. |
Expand Visual C++ tree, if it is not already expanded. |
|
f. |
Select Code from the sub tree. |
|
g. |
Select C++ File (.cpp) from the right window. |
|
h. |
In the name text box, specify Imports. |
|
i. |
Click the OK button. |
|
j. |
Double-click the Imports.cpp in the Solution Explorer and add the following lines(Keep in mind, you may have to change the path to where the Libraries files reside): |
#include "StdAfx.h"
#if defined(WIN64)
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\x64\\Ltwvc_x.lib")
#else
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\Win32\\Ltwvc_u.lib")
#endif // #if defined(WIN64)
25. |
On the main menu, select Build > Build AnnBlob.exe to build the project. |
26. |
On the main menu, select Build > Execute AnnBlob.exe to run the project. |