Help needed with Bitmap Display (CDCs and StretchBlt)

Hi
I have set up a function called WriteFame() in my own class (VideoCont.cpp) to read a frame of a video and write it to a .bmp file (bt.bmp). But now that it is written to the file bt.bmp how can I automatically display this image in an SDI window? (ie. as soon as the WriteFrame() function is complete it calls another function say DisplayFrame() which automatically diplays this frame without any use interaction inbetween).

This is the code that I have for the writing of a frame to the bt.bmp file (i've check that it works by opening the file bt.bmp in paintbrush)

void VideoCont::WriteFrame()
{
for(int n=0, dn = FrameSize; n < FrameSize; n++)
FrameArray[--dn] = FrameArray1[n];

VidHeader1.bfType1 = 'B';
VidHeader1.bfType2 = 'M';
VidHeader1.bfSize = FrameSize;
VidHeader1.bfReserved1 = 0;
VidHeader1.bfReserved2 = 0;
VidHeader1.bfOffBits = 1078;
VidHeader2.biSize = 40;
VidHeader2.biWidth = 320;
VidHeader2.biHeight = 240;
VidHeader2.biPlanes = 1;
VidHeader2.biBitCount = 8;
VidHeader2.biCompression = 0;
VidHeader2.biSizeImage = 0;
VidHeader2.biXPelsPerMeter = 0;
VidHeader2.biYPelsPerMeter = 0;
VidHeader2.biClrUsed = 0;
VidHeader2.biClrImportant = 0;

if( (VideoFile = fopen("bt.bmp"/*FrameFile*/, "wb+")) != NULL )
{
fwrite(&VidHeader1.bfType1, 1,1,VideoFile);
fwrite(&VidHeader1.bfType2, 1,1,VideoFile);
fwrite(&VidHeader1.bfSize, 4,1,VideoFile);
fwrite(&VidHeader1.bfReserved1, 2,1,VideoFile);
fwrite(&VidHeader1.bfReserved2, 2,1,VideoFile);
fwrite(&VidHeader1.bfOffBits, 4,1,VideoFile);
fwrite(&VidHeader2, sizeof(VidHeader2),1,VideoFile);
if (VidHeader2.biBitCount == 8)
{
//Vidpalette = new unsigned char[256*4];
for(index=0;index<256;index++)
{
fputc(Vidpalette[(int)(index*4+3)],VideoFile); //put values back to palette
fputc(Vidpalette[(int)(index*4+2)],VideoFile);
fputc(Vidpalette[(int)(index*4+1)],VideoFile);
fputc(Vidpalette[(int)(index*4+0)],VideoFile);
}
}
fwrite(FrameArray, FrameSize , 1, VideoFile);

fclose(VideoFile);
}
DrawFrame();
}

My code for displaying the above bitmap goes as follows:
void VideoCont::DrawFrame()
{
//****************************************************************\/
BmpCont Bmp;

FrameFile = "bt.bmp";
HBITMAP hBitmap = (HBITMAP) ::LoadImage(AfxGetInstanceHandle(),FrameFile,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); //|LR_CREATEDIBSECTION
CBitmap bmp;
if(hBitmap)
{
bmp.Attach(hBitmap);
}
//get the bitmap header info
BITMAP bm;
bmp.GetBitmap(&bm);
int hight=bm.bmHeight;
int width=bm.bmWidth;
//bmp.SetBitmapDimension(40,40);

//create a temporary memory DC
CDC mdc;
mdc.CreateCompatibleDC(pDCV);
mdc.SelectObject(&bmp);

//Use CDC::BitBlt() or StretchBlt();
//pDCV->BitBlt(10,10,bm.bmWidth,bm.bmHeight,&mdc,0,0,SRCCOPY);
pDCV->StretchBlt(10, 10, (bm.bmWidth), (bm.bmHeight), &mdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);

//****************************************************************
}

In the VideoCOnt.h file :
public:
CDocument* pDocV;
CDC* pDCV;
CString FrameFile;

In the draw function of the SDI view.cpp:
#include "VideoCont.h"

void CVDsgi1View::OnDraw(CDC* pDC)
{
VideoCont Vi;
CVDsgi1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//****************************************************************\/

Vi.pDCV = pDC;

Vi.pDocV = pDoc;

//****************************************************************

}

I have a problem with pDCV->StretchBlt bit, I don't know what it is, (but one of those "abort debug ignore" assertion failure, dialog boxes appears). Do I need to call the view.cpp draw function after the WriteFrame function and before the DrawFrame function?
If so how do I do this?
I can't do:
#include "VDsgi1View.h" //my SDI view.cpp name
CVDsgi1View view;
view.OnDraw(pDCV);//in DrawFrame Function
it won't let me as it is a protected member.

Help me please, what can I do?
[4346 byte] By [ncostall] at [2007-11-17 11:49:51]
# 1 Re: Help needed with Bitmap Display (CDCs and StretchBlt)
Hi,

I got your problem. Lets start from here...

mdc.CreateCompatibleDC(pDCV);

In the following statement you are giving pDCV as parameter. Seems you wanna create a memory dc here. So for that you dont need any DC pointer here. Just pass NULL to it. So the above statement can be replaced with the following...

// you got your memory dc created here.
mdc.CreateCompatibleDC(NULL);

//create a temporary memory DC
mdc.SelectObject(&bmp);

So.. the source DS is ready. Now you need to get the destination DC.

// This is your statement..
pDCV->StretchBlt(10, 10, (bm.bmWidth), (bm.bmHeight), &mdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);

In your above statement there is no problem but I see that you have not initialed your pDCV pointer. You need to get the DC pointer on which you want to write, into your pDCV. You can do it this way..

// Assuming m_SDIWnd is a CWnd pointer in your current class and has been initialised by now with the SDI window pointer.
CWnd* displayWnd = m_SDIWnd;

PDCV = m_SDIWnd->GetDC(); // you got the destination dc here.
// Now call StretchBlt...
pDCV->StretchBlt(10, 10, (bm.bmWidth), (bm.bmHeight), &mdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);

Hope this helps...

Let me know if got helped. If you got helped pls rate!!!

John
Indian_Techie at 2007-11-10 8:06:57 >
# 2 Re: Help needed with Bitmap Display (CDCs and StretchBlt)
Hi
Thanks for the suggestion but I can't seem to get it working.

This is what I have got now:

void VideoCont::DrawFrame()
{
//****************************************************************\/
CString FrameFile=pDocV->GetPathName();
HBITMAP hBitmap = (HBITMAP) ::LoadImage(AfxGetInstanceHandle(),
FrameFile,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); //|LR_CREATEDIBSECTION

CBitmap bmp;
if(hBitmap)
{
bmp.Attach(hBitmap);
}
//get the bitmap header info
BITMAP bm;
bmp.GetBitmap(&bm);
int hight=bm.bmHeight;
int width=bm.bmWidth;
//bmp.SetBitmapDimension(40,40);

//create a temporary memory DC
CDC mdc;
mdc.CreateCompatibleDC(NULL);
mdc.SelectObject(&bmp);
CWnd* displayWnd = m_SDIWnd;
pDCV = m_SDIWnd->GetDC();
//Use CDC::BitBlt() or StretchBlt();
//pDCV->BitBlt(10,10,bm.bmWidth,bm.bmHeight,&mdc,0,0,SRCCOPY);
pDCV->StretchBlt(10, 10, (bm.bmWidth * 2), (bm.bmHeight * 2), &mdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);

//****************************************************************
}
and in the VideoCOnt.h:
public:
CWnd* m_SDIWnd;
CDocument* pDocV;
CDC* pDCV;
CString FrameFile;
void WriteFrame();
VideoCont();
virtual ~VideoCont();
void DrawFrame();

I'm not sure I understand your
// Assuming m_SDIWnd is a CWnd pointer in your current class and has been initialised by now with the SDI window pointer.CWnd* displayWnd = m_SDIWnd;
bit.
I put this CWnd* m_SDIWnd; in the videocont.h file is this what you mean?

When I debug the failure that I get it goes to the following:
// CString
_AFX_INLINE CStringData* CString::GetData() const
{ ASSERT(m_pchData != NULL); return ((CStringData*)m_pchData)-1; }

I hope you can help me further

THanks
ncostall at 2007-11-10 8:07:48 >
# 3 Re: Help needed with Bitmap Display (CDCs and StretchBlt)
Oops! Sorry.. I confused you with a single an unnecessary statement. Strike off the following statement.

CWnd* displayWnd = m_SDIWnd;

And what i mean by "Assuming m_SDIWnd is a CWnd pointer in your current class and has been initialised by now with the SDI window pointer" is...
For instance you are calling this DrawFrame function of VideoCont class from your SDI window class, say on a button (called "BtnDraw") click. So you will write the Buton click handler this way..

// I am assuming CSDIFrame as the SDI window on which you want to display the image

void CSDIFrame::OnBtnDraw()
{
// Do what ever you want to do before drawing...
VideoCont videoContObj;
videoContObj.m_SDIWnd = this;
// the above statement assumes that you have amember variable called m_SDIWnd in the class VideoCont (which is CWnd*).
//You have already declared it in VideoCont class. So dont worry about this.
videoContObj.DrawFrame();
}

Now you will get a valid window pointer into m_SDIWnd.

But the error you are saying now is totally different! Its a CString error. One thing i noticed is, you have a CString member called FrameFile in VideoCont class and also you have a local variable in DrawFrame function with the same name. Check it out.

Let me know if got helped. If you got helped pls rate!!!

John
Indian_Techie at 2007-11-10 8:08:59 >