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:
Run Microsoft Visual Studio, select the File New Project, and do the following:
In the overview window Just click Next.
In the Application Type step dialog box, do the following:
In the Step 2 of 4 dialog box, do the following:
In the Step 3 of 4 dialog box, just click Finish:
Add #include statements to your program so you can access the LEAD C++ Class Library constants and classes:
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"
Add a Button control to the main window as follows:
Add #import statements to your program so you can access the Microsoft ActiveX Data Object 2.6 Library:
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;
Click the Resource 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.
Do the following to add m_btnAddRecord to the CAnnBlobDlg class and link the variable to the CButton control using dynamic data exchange:
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 |
Add the following Member Variables to the CAnnBlobDlg class:
Type | Member |
---|---|
_ConnectionPtr | m_pConnection |
_RecordsetPtr | m_pRecordset |
LAnnotationWindow | m_LAnnoWnd |
Go to the OnInitDialog() function as follows:
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);
Do the following to add an event handler to the Connect To Database button:
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);
}
}
Do the following to add an event handler to the Disconnect From Data Base button:
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);
Do the following to add an event handler to the Add Record button:
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);
}
Do the following to add an event handler to the Delete Record button:
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);
}
}
Do the following to add an event handler to the Move Next button:
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();
}
Do the following to add an event handler to the Move Previous button:
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();
}
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();
Go to AnnBlobDlg.cpp file then add the following line between the BEGIN_MESSAGE_MAP and END_MESSAGE_MAP:
ON_WM_CLOSE()
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);
}
}
}
Create a new file called Imports.cpp in place it beside your project files.
#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)
On the main menu, select Build -> Build AnnBlob.exe to build the project.
On the main menu, select Build -> Execute AnnBlob.exe to run the project.
Help Collections
Raster .NET | C API | C++ Class Library | HTML5 JavaScript
Document .NET | C API | C++ Class Library | HTML5 JavaScript
Medical .NET | C API | C++ Class Library | HTML5 JavaScript
Medical Web Viewer .NET
Multimedia
Direct Show .NET | C API | Filters
Media Foundation .NET | C API | Transforms
Supported Platforms
.NET, Java, Android, and iOS/macOS Assemblies
Imaging, Medical, and Document
C API/C++ Class Libraries
Imaging, Medical, and Document
HTML5 JavaScript Libraries
Imaging, Medical, and Document
Your email has been sent to support! Someone should be in touch! If your matter is urgent please come back into chat.
Chat Hours:
Monday - Friday, 8:30am to 6pm ET
Thank you for your feedback!
Please fill out the form again to start a new chat.
All agents are currently offline.
Chat Hours:
Monday - Friday
8:30AM - 6PM EST
To contact us please fill out this form and we will contact you via email.