Loading and Saving Annotations Using Databases (C++ 5.0 and later)
Note: This topic is for Document/Medical only.
Take the following steps to start a project and to add some code that demonstrates adding annotation objects to or deleting annotation objects from the BLOB field of a database file.
You need to create a database file (DB1.MDB) with the fields listed below, before running this tutorial.
Field Name |
Type |
Image |
OleObject |
Size |
Number |
1. |
Start a new project as follows: |
|
|
Run Microsoft Visual C++ 5.0, select the File >New menu option, and do the following: |
|
|
a. |
Click the Projects tab. |
|
b. |
Select MFC AppWizard (exe) as the project type |
|
c. |
In the Project name text box, specify AnnBlob. |
|
d. |
In the Location text box, specify the path of the project. |
|
e. |
Click the OK button. |
2. |
In the Step 1 dialog box, do the following: |
|
|
a. |
Select Dialog based. |
|
b. |
Click the Next button. |
3. |
In the Step 2 of 4 dialog box, do the following: |
|
|
a. |
Ensure that About Box is selected. |
|
b. |
Ensure that 3D Controls is selected. |
|
c. |
Select ActiveX Controls. |
|
d. |
Click the Next button. |
4. |
In the Step 3 of 4 dialog box, do the following: |
|
|
a. |
For comments, ensure that Yes, Please is selected. |
|
b. |
For how to use the MFC library, select Use MFC in a Shared DLL. |
|
c. |
Click the Next button. |
5. |
In the Step 4 of 4 dialog box, just click Finish. |
|
6. |
Read New Project Information, and click OK. (The AppWizard creates the project files and opens the project.) |
|
7. |
Add #import and #include statements to your program so you can access the LEAD COM constants and classes: |
|
|
a. |
In the Project Workspace, click the FileView tab. |
|
b. |
Double-click the AnnBlob files 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\\L_OCX.H"
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 FileView tab. |
|
b. |
Double-click the AnnBlob files 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. |
Add a LEAD Main control to the main window as follows: |
|
|
a. |
In the Project Workspace, click the ResourceView tab. |
|
b. |
Double-click the AnnBlob resources folder to open it. |
|
c. |
Double-click the Dialog folder to open it. |
|
d. |
Double-click IDD_ANNBLOB_DIALOG to design the form. |
|
e. |
Select the TODO... text control; then press the Delete key to delete it. |
|
f. |
From the main menu, select Project > Add to project > Components and Controls. (The Component Gallery appears.) |
|
g. |
Click the Registered ActiveX Contols. |
|
h. |
Double-click the LEAD Main ActiveX Control (16) icon. (The Confirm Classes dialog box appears.) |
|
i. |
Ensure that CLead, CPicture, and COleFont are checked. |
|
j. |
Click OK to complete the selection; then click Close to close the Component Gallery. (The LEAD Main control appears in the Controls toolbar.) |
|
k. |
Click the LEAD Main control icon; then size and position the control as you want it to appear at run time. |
10. |
Add six command buttons to your form and name them as follows: |
|
|
ID |
Caption |
|
IDC_CONNECT |
&Connect To Database |
|
IDC_DISCONNECT |
&Disconnect From Data Base |
|
IDC_ADDRECORD |
&Add Record |
|
IDC_DELETERECORD |
D&elete Record |
|
IDC_MOVENEXT |
Move &Next |
|
IDC_MOVEPREVIOUS |
Move &Previous |
11. |
Press Ctrl-F4 to close all windows back to the Project Workspace. |
|
12. |
Do the following to add m_Lead1 to the CAnnBlobDlg class and link the variable to the LEAD Main control using dynamic data exchange: |
|
|
a. |
Press Ctrl-W. (The MFC ClassWizard dialog box appears.) |
|
b. |
Click the Member Variables tab. |
|
c. |
In the Class Name box, select CAnnBlobDlg. |
|
d. |
In the Control IDs list, select IDC_LEADCTRL1. |
|
e. |
Click the Add Variable... button. |
|
f. |
Specify m_Lead1 as the variable name, and Control as the category. |
|
g. |
Click OK to close the dialog box, and click OK to close the MFC ClassWizard. |
13. |
Do the following to add m_btnAddRecord to the CAnnBlobDlg class and link the variable to the CButton control using dynamic data exchange: |
|
|
a. |
Press Ctrl-W. (The MFC ClassWizard dialog box appears.) |
|
b. |
Click the Member Variables tab. |
|
c. |
In the Class Name box, select CAnnBlobDlg. |
|
d. |
In the Control IDs list, select IDC_ADDRECORD. |
|
e. |
Click the Add Variable... button. |
|
f. |
Specify m_btnAddRecord as the variable name, and Control as the category. |
|
g. |
Click OK to close the dialog box, and click OK to close the MFC ClassWizard. |
14. |
Repeat step 13 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 |
15. |
Add the following Member Variables to the CAnnBlobDlg class: |
|
|
_ConnectionPtr |
m_pConnection; |
|
_RecordsetPtr |
m_pRecordset; |
16. |
Go to the OnInitDialog() function as follows: |
|
|
a. |
In the Project Workspace, click the ClassView tab. |
|
b. |
Double-click the AnnBlob classes folder to open it. |
|
c. |
Expand the CAnnBlobDlg class. |
|
d. |
Double-click the OnInitDialog() function to edit it. |
17. |
Edit the OnInitDialog() function to add the following code after the line that says //TODO: Add extra initialization here: |
m_Lead1.UnlockSupport(L_SUPPORT_DOCUMENT,L_KEY_DOCUMENT);
m_Lead1.Load("c:\\parrots.jpg",0,0,1);
CAnnToolbar AnnToolbar = m_Lead1.GetAnnToolbar();
AnnToolbar.SetVisible(TRUE);
AnnToolbar.Create(10, 10, ANNTOOLALIGN_TOP);
m_Lead1.SetAnnUserMode(ANNUSERMODE_DESIGN);
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);
18. |
Press Ctrl-W to go to the MFC Class Wizard; then do the following: |
|
|
a. |
Click the Message Maps tab. |
|
b. |
In the Class Name combo box, select CAnnBlobDlg. |
|
c. |
In the Object IDs list box, select IDC_CONNECT. |
|
d. |
In the Messages list box, select BN_CLICKED. |
|
e. |
Click the Add function button. Choose OK for the default function name (OnConnect). |
|
f. |
Click the Edit Code button and enter the following code: (you will have to change to file name to an existing database file name on your computer) |
HRESULT hr;
_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( _bstr_t(L"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=DB1.mdb;"),
_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);
}
}
19. |
Press Ctrl-W to go to the MFC Class Wizard; then do the following: |
|
|
a. |
Click the Message Maps tab. |
|
b. |
In the Class Name combo box, select CAnnBlobDlg. |
|
c. |
In the Object IDs list box, select IDC_DISCONNECT. |
|
d. |
In the Messages list box, select BN_CLICKED. |
|
e. |
Click the Add function button. Choose OK for the default function name (OnDisconnect). |
|
f. |
Click the Edit Code button and 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);
20. |
Press Ctrl-W to go to the MFC Class Wizard; then do the following: |
|
|
a. |
Click the Message Maps tab. |
|
b. |
In the Class Name combo box, select CAnnBlobDlg. |
|
c. |
In the Object IDs list box, select IDC_ADDRECORD. |
|
d. |
In the Messages list box, select BN_CLICKED. |
|
e. |
Click the Add function button. Choose OK for the default function name (OnAddRecord). |
|
f. |
Click the Edit Code button and enter the following code: |
COleVariant vData;
long lUBound,lLBound;
int nSize;
int nRet;
if (m_pConnection->State == adStateClosed )
{
MessageBox (TEXT("Connection closed"));
return;
}
m_pRecordset->AddNew();
vData.Clear();
nRet = m_Lead1.AnnSaveArray (&vData,ANNFMT_NATIVE, false, SAVE_OVERWRITE, 0);
SafeArrayGetUBound(vData.parray, 1, &lUBound);
SafeArrayGetLBound(vData.parray, 1, &lLBound);
nSize = lUBound - lLBound + 1;
m_pRecordset->Fields->Item[_variant_t( (long) 1)]->Value = _variant_t(vData);
m_pRecordset->Fields->Item[_variant_t( (long) 2)]->Value = _variant_t( (long) nSize);
m_pRecordset->Update();
if(m_pRecordset->RecordCount >= 0)
{
m_btnMoveNext.EnableWindow(TRUE);
m_btnMovePrevious.EnableWindow(TRUE);
m_btnDeleteRecord.EnableWindow(TRUE);
}
21. |
Press Ctrl-W to go to the MFC Class Wizard; then do the following: |
|
|
a. |
Click the Message Maps tab. |
|
b. |
In the Class Name combo box, select CAnnBlobDlg. |
|
c. |
In the Object IDs list box, select IDC_DELETERECORD. |
|
d. |
In the Messages list box, select BN_CLICKED. |
|
e. |
Click the Add function button. Choose OK for the default function name (OnDeleteRecord). |
|
f. |
Click the Edit Code button and 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);
}
}
22. |
Press Ctrl-W to go to the MFC Class Wizard; then do the following: |
|
|
a. |
Click the Message Maps tab. |
|
b. |
In the Class Name combo box, select CAnnBlobDlg. |
|
c. |
In the Object IDs list box, select IDC_MOVENEXT. |
|
d. |
In the Messages list box, select BN_CLICKED. |
|
e. |
Click the Add function button. Choose OK for the default function name (OnMoveNext). |
|
f. |
Click the Edit Code button and enter the following code: |
int nSize;
int nRet;
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 annotation from the database"));
m_pRecordset->MovePrevious();
}
else
{
_variant_t varSize;
varSize = m_pRecordset->Fields->Item[2L]->Value;
nSize = varSize.intVal;
if(nSize)
{
_variant_t vData;
vData = m_pRecordset->Fields->Item[1L]->Value;
nRet = m_Lead1.AnnLoadArray (vData, nSize, 1);
}
}
23. |
Press Ctrl-W to go to the MFC Class Wizard; then do the following: |
|
|
a. |
Click the Message Maps tab. |
|
b. |
In the Class Name combo box, select CAnnBlobDlg. |
|
c. |
In the Object IDs list box, select IDC_MOVEPREVIOUS. |
|
d. |
In the Messages list box, select BN_CLICKED. |
|
e. |
Click the Add function button. Choose OK for the default function name (OnMovePrevious). |
|
f. |
Click the Edit Code button and enter the following code: |
int nSize;
int nRet;
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 annotation from the database"));
m_pRecordset->MoveNext();
}
else
{
_variant_t varSize;
varSize = m_pRecordset->Fields->Item[2L]->Value;
nSize = varSize.intVal;
if(nSize)
{
_variant_t vData;
vData = m_pRecordset->Fields->Item[1L]->Value;
nRet = m_Lead1.AnnLoadArray (vData, nSize, 1);
}
}
24 |
Open the ANNBLOBDLG.CPP file and add the following line after the #include statements: |
#include "anntoolbar.h"
26. |
On the main menu, select Build > Build AnnBlob.exe to build the project. |
27. |
On the main menu, select Build > Execute AnnBlob.exe to run the project. |