Solved

moving an image to and from a database to the application

Posted on 2000-04-25
5
286 Views
Last Modified: 2013-11-20
What follows are the example class that are responsible for fetching information from the database.  The one piece of information that I need help is the bitmap.  TestDBSet (inherited from CRecordSet) has the image (m_Image) as a CLongBinary.  How do I get it to the View class (CTestDBView)?  I have no Idea how to proceed.  Not that I thought it would be that easy, but from the view class I dropped a bitmap image and attempted the <cntrl> double click on the bmp.  The wiz wasn't the wiz he was.  Nothing.

500 pts for the guy who will help me work through this.

Garaber
??????????????????????????The RecordView Class???????????????????????
class CTestDBSet;

class CTestDBView : public CRecordView
{
protected: // create from serialization only
      CTestDBView();
      DECLARE_DYNCREATE(CTestDBView)

public:
      //{{AFX_DATA(CTestDBView)
      enum { IDD = IDD_TESTDB_FORM };
      CTestDBSet* m_pSet;
      //}}AFX_DATA

// Attributes
public:
      CTestDBDoc* GetDocument();

// Operations
public:

// Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CTestDBView)
      public:
      virtual CRecordset* OnGetRecordset();
      virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
      protected:
      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
      virtual void OnInitialUpdate(); // called first time after construct
      virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
      virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
      virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
      //}}AFX_VIRTUAL

// Implementation
public:
      virtual ~CTestDBView();
#ifdef _DEBUG
      virtual void AssertValid() const;
      virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
      //{{AFX_MSG(CTestDBView)
            // NOTE - the ClassWizard will add and remove member functions here.
            //    DO NOT EDIT what you see in these blocks of generated code !
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////
// CTestDBView

IMPLEMENT_DYNCREATE(CTestDBView, CRecordView)

BEGIN_MESSAGE_MAP(CTestDBView, CRecordView)
      //{{AFX_MSG_MAP(CTestDBView)
            // NOTE - the ClassWizard will add and remove mapping macros here.
            //    DO NOT EDIT what you see in these blocks of generated code!
      //}}AFX_MSG_MAP
      // Standard printing commands
      ON_COMMAND(ID_FILE_PRINT, CRecordView::OnFilePrint)
      ON_COMMAND(ID_FILE_PRINT_DIRECT, CRecordView::OnFilePrint)
      ON_COMMAND(ID_FILE_PRINT_PREVIEW, CRecordView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTestDBView construction/destruction

CTestDBView::CTestDBView()
      : CRecordView(CTestDBView::IDD)
{
      //{{AFX_DATA_INIT(CTestDBView)
      m_pSet = NULL;
      //}}AFX_DATA_INIT
      // TODO: add construction code here

}

CTestDBView::~CTestDBView()
{
}

void CTestDBView::DoDataExchange(CDataExchange* pDX)
{
      CRecordView::DoDataExchange(pDX);
      //{{AFX_DATA_MAP(CTestDBView)
      DDX_FieldText(pDX, IDC_LASTNAME, m_pSet->m_LastName, m_pSet);
      DDX_FieldText(pDX, IDC_FIRSTNAME, m_pSet->m_FirstName, m_pSet);
      DDX_FieldText(pDX, IDC_PHONE, m_pSet->m_Telephone, m_pSet);
      //}}AFX_DATA_MAP
}

BOOL CTestDBView::PreCreateWindow(CREATESTRUCT& cs)
{
      // TODO: Modify the Window class or styles here by modifying
      //  the CREATESTRUCT cs

      return CRecordView::PreCreateWindow(cs);
}

void CTestDBView::OnInitialUpdate()
{
      m_pSet = &GetDocument()->m_testDBSet;
      CRecordView::OnInitialUpdate();
      ResizeParentToFit();

}

/////////////////////////////////////////////////////////////////////////////
// CTestDBView printing

BOOL CTestDBView::OnPreparePrinting(CPrintInfo* pInfo)
{
      // default preparation
      return DoPreparePrinting(pInfo);
}

void CTestDBView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
      // TODO: add extra initialization before printing
}

void CTestDBView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
      // TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CTestDBView diagnostics

#ifdef _DEBUG
void CTestDBView::AssertValid() const
{
      CRecordView::AssertValid();
}

void CTestDBView::Dump(CDumpContext& dc) const
{
      CRecordView::Dump(dc);
}

CTestDBDoc* CTestDBView::GetDocument() // non-debug version is inline
{
      ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDBDoc)));
      return (CTestDBDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CTestDBView database support
CRecordset* CTestDBView::OnGetRecordset()
{
      return m_pSet;
}


/////////////////////////////////////////////////////////////////////////////
// CTestDBView message handlers

??????????????????????????The RecordSet Class???????????????????????
class CTestDBSet : public CRecordset
{
public:
      CTestDBSet(CDatabase* pDatabase = NULL);
      DECLARE_DYNAMIC(CTestDBSet)

// Field/Param Data
      //{{AFX_FIELD(CTestDBSet, CRecordset)
      long      m_ID;
      CString      m_FirstName;
      CString      m_LastName;
      CString      m_Telephone;
      CLongBinary      m_Image;
      //}}AFX_FIELD

// Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CTestDBSet)
      public:
      virtual CString GetDefaultConnect();      // Default connection string
      virtual CString GetDefaultSQL();       // default SQL for Recordset
      virtual void DoFieldExchange(CFieldExchange* pFX);      // RFX support
      //}}AFX_VIRTUAL

// Implementation
#ifdef _DEBUG
      virtual void AssertValid() const;
      virtual void Dump(CDumpContext& dc) const;
#endif

};

// TestDBSet.cpp : implementation of the CTestDBSet class
//

#include "stdafx.h"
#include "TestDB.h"
#include "TestDBSet.h"

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

/////////////////////////////////////////////////////////////////////////////
// CTestDBSet implementation

IMPLEMENT_DYNAMIC(CTestDBSet, CRecordset)

CTestDBSet::CTestDBSet(CDatabase* pdb)
      : CRecordset(pdb)
{
      //{{AFX_FIELD_INIT(CTestDBSet)
      m_ID = 0;
      m_FirstName = _T("");
      m_LastName = _T("");
      m_Telephone = _T("");
      m_nFields = 5;
      //}}AFX_FIELD_INIT
      m_nDefaultType = snapshot;
}

CString CTestDBSet::GetDefaultConnect()
{
      return _T("ODBC;DSN=TestDB");
}

CString CTestDBSet::GetDefaultSQL()
{
      return _T("[Person]");
}

void CTestDBSet::DoFieldExchange(CFieldExchange* pFX)
{
      //{{AFX_FIELD_MAP(CTestDBSet)
      pFX->SetFieldType(CFieldExchange::outputColumn);
      RFX_Long(pFX, _T("[ID]"), m_ID);
      RFX_Text(pFX, _T("[FirstName]"), m_FirstName);
      RFX_Text(pFX, _T("[LastName]"), m_LastName);
      RFX_Text(pFX, _T("[Telephone]"), m_Telephone);
      RFX_LongBinary(pFX, _T("[Image]"), m_Image);
      //}}AFX_FIELD_MAP
}

/////////////////////////////////////////////////////////////////////////////
// CTestDBSet diagnostics

#ifdef _DEBUG
void CTestDBSet::AssertValid() const
{
      CRecordset::AssertValid();
}

void CTestDBSet::Dump(CDumpContext& dc) const
{
      CRecordset::Dump(dc);
}
#endif //_DEBUG
0
Comment
Question by:graber
  • 3
  • 2
5 Comments
 
LVL 10

Accepted Solution

by:
RONSLOW earned 600 total points
ID: 2750115
Some of the details depend on how the data is stored .. ther eare a number of ways of storing data in a database.  These range from just copying the bits from a BMP file into a long binary, to putting an OLE object into the database.

Depending on how the data is stored, there will be different answers.

If it is a BMP file stored in a bitmap record, you can use OleLoadPicture to read the data and generate a Bitmap object that can then be displayed in your app.

If it is a OLE embedded object, then things get a bit trickier.

I would use (say) and owner-drawn button that got the bitmap data from the longbinary, used OleLoadPicture to turn that into a bitmap and then StretchBlt it onto the button.

0
 
LVL 2

Author Comment

by:graber
ID: 2751159
Adjusted points from 500 to 600
0
 
LVL 2

Author Comment

by:graber
ID: 2751160
Thanks for responding. Currently the Access database type is an Ole Object.  The first two are unfamiliar, or so I believe, from the database side.  What are the pro's and cons of each
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2753533
Simply putting the BMP file in as a long binary is simpler from a programming point of view.  The way that an OLE object is stored in an access database is not officially documented, so getting the data in there usually relies on writing some access cba app to automate the manual inserting of an object.  Ole objects also take up much more room, not only because of the extra heading info, but also because of the way OLE objects (usually) require both the original data AND the rendered version.  You'll find that your database size is MUCH bigger than what you'd expect (going by the size of the bitmap files).  The main advantage (if any) of storing them as OLE object is that you can double click on an OLE object in a view of a table and see the picture (via OLE).

The advantage of storing just the BMP data is that it takes less room and is easy to save and retrive and convert to a picture programmatically.  You can also use other formats (like JPG) micely.  The latest version of Crystal Reports (for example) will recognise raw bmp jpg and gif data in long-binary records (as i understand).

There is lots of info on how to store and reteive raw image data in a datbase (both from MS KB, www.codeguru.com and here at EE)

I have an app that uses a cross between these.  It uses the unofficial OLE1 headers etc that Access uses when storing an OLE object .. but avoids putting in the extra (redundant) rendering data, so I don't get the bloat, but still do get the advantages of an OLE object - but I cannot use JPG in this case (which is not a mayjor problem for my particular app as there are few bitmaps and they are small in size).

NOTE: People who know suggest that storing images directly in a datbase is BAD (for a lot of valid reasons).  Instead, they recommend you store the images in external files, and instead keep the path to the file name (or URL)in your database.  This has great performance and disk-space advantages over storing directly in databases.  This is especially the case with very large databases.

The only catch is if you are using Crystal reports.  It doesn't support this sort of thing.  To make it work, you have to know the layout of your report, use their ActiveX control, and write some VB code .. if you're directly calling the report engine, or using CR stand-alone, then you're stuffed.  Please petition you nearest Crystal representative until they support this !!!
0
 
LVL 2

Author Comment

by:graber
ID: 2755079
Man now that was the answer that I was looking for.  Not that I'm anyone, but that really helped.  Thanks Ronslow.  I was out to codeguru and it helped to assimalate some of what you had said originally.  I agree with you that putting images into a data base isn't really a good idea, if for no other reason no really understands what's going on.  But it does seem to be rather popular.  At any rate thanks
garaber
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now