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, 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);

   L_TCHAR * pszLicenseFile = L"Replace this with the path to the LEADTOOLS license file";
   L_TCHAR * pszDeveloperKey = L"Replace this with your developer key";
   LSettings::SetLicenseFile(pszLicenseFile, pszDeveloperKey);

   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 (MAKE_IMAGE_PATH(TEXT("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.