Display Bitmap in a Picture Box using MFC from a file

Discussion in 'MFC' started by shabbir, Jun 9, 2005.

  1. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    When you insert a picture on a Dialog box the main aim of your dialog box is just not to display the Resource bitmaps that are added at compile time but to display the image from a file. Now to display a bitmap I could not find many good resources but if you google out with the keyword LoadPic.exe you can find some help with that sample but that is way too complicated for a simple image display and so I thought of all doing it with my shallow knowledge of Subclasing.

    Steps
    1. Add a picture Box to your application
    2. Change the Type of the picture box to OWNER_DRAW. [Skip this step. Its not needed as corrected by lplover2k]
    3. Add a variable to the picture box. By default it will be CStatic. I call it picPreview
    4. Change the CStatic to CPictureBox. Don't forget to add the header files at the top.
    5. Call the SetBitmap function to display the URL in the picture box.

    picPreview.SetBitmap(CString m_sBitmap)
    PictureBox.h
    Code:
       #pragma once
       
       // CPictureBox
       
       class CPictureBox : public CStatic
       {
       	DECLARE_DYNAMIC(CPictureBox)
       
       public:
       	CPictureBox();
       	virtual ~CPictureBox();
       	void SetBitmap(CString strBitmap);
       
       protected:
       	DECLARE_MESSAGE_MAP()
       	void ShowBitmap(CPaintDC *pDC);
       
       	CString m_sBitmap;
       	CBitmap m_bmpBitmap;
       	BITMAP bm;
       public:
       	afx_msg void OnPaint();
       };
       
    PictureBox.cpp
    Code:
       // PictureBox.cpp : implementation file
       //
       
       #include "stdafx.h"
       #include "PictureBox.h"
       #include ".\picturebox.h"
       
       
       // CPictureBox
       
       IMPLEMENT_DYNAMIC(CPictureBox, CStatic)
       CPictureBox::CPictureBox()
       {
       }
       
       CPictureBox::~CPictureBox()
       {
       }
       
       
       BEGIN_MESSAGE_MAP(CPictureBox, CStatic)
       	ON_WM_PAINT()
       END_MESSAGE_MAP()
       
       
       
       // CPictureBox message handlers
       
       void CPictureBox::ShowBitmap(CPaintDC *pdc) 
       {
       	//Create a device context to load the bitmap into
       	CDC dcMem;
       	dcMem.CreateCompatibleDC(pdc);
       
       	//Get the Display area available
       	CRect lRect;
       	GetClientRect(lRect);
       	lRect.NormalizeRect();
       
       	//select the bitmap into compatible device context
       	CBitmap* pOldBitmap = (CBitmap*)dcMem.SelectObject(&m_bmpBitmap);
       	//m_bmpBitmap.SetBitmapDimension(lRect.Width(),lRect.Height());
       
       	//copy & resize the window to the dialog window
       	pdc->StretchBlt(0,0,lRect.Width(),lRect.Height(),&dcMem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
       }
       void CPictureBox::OnPaint()
       {
       	CPaintDC dc(this); // device context for painting
       
       	RECT rect;
       	GetClientRect(&rect);
       	dc.FillSolidRect(&rect, RGB(255,255,255));
       
       	if(m_sBitmap!="")
       		ShowBitmap(&dc);
       }
       void CPictureBox::SetBitmap(CString strBitmap)
       {
       	m_sBitmap = strBitmap;
       
       	HBITMAP hBitmap = (HBITMAP) ::LoadImage(AfxGetInstanceHandle(),
       	m_sBitmap, IMAGE_BITMAP, 0, 0, 
       	LR_LOADFROMFILE | LR_CREATEDIBSECTION);
       
       	// Do we have a valid handle for the loaded image?
       	if (hBitmap)
       	{
       		// Delete the current bitmap
       		if (m_bmpBitmap.DeleteObject())
     		 m_bmpBitmap.Detach();	// If there was a bitmap, detach it
       		// Attach the currently loaded bitmap to the bitmap object
       		m_bmpBitmap.Attach(hBitmap);
       	}
       	m_bmpBitmap.GetBitmap(&bm);  //Get Bitmap Structure
       	Invalidate();
       }
       
    The attached zip file contains the above 2 header files

    Edited the code to correct some errors regarding unnecessary include files. Thanks to lplover2k.
     

    Attached Files:

  2. Naresh

    Naresh New Member

    Joined:
    Jun 17, 2006
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    Hi sabbir iam naresh from hyderabad.iam getting an error in bitmap loading and displaying it. after attaching new bitmap i had called GetBitmap() function and iam getting an error overhere .plz solve my error ,or what is error.
     
  3. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Try studying the code snippets above and it has GetBitmap function. If you do a GetBitmap on a NULL bitmap there is a possibility that you get an exception.
     
  4. gabedude

    gabedude New Member

    Joined:
    Sep 22, 2006
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    Shabbir,

    This was helpfull, but in VC 8.0 (VS2005), you have to do things a little different.

    1. The IDE will not let you add a variable of CStatic type. You have to edit the code directly:

    Calling code header:

    CPictureBox m_PicBox;

    Calling code implementaion:

    void XXX::DoDataExchange(CDataExchange* pDX)
    {
    CDialog::DoDataExchange(pDX);
    ...
    DDX_Control(pDX, IDC_PICTBOX1, m_PicBox);
    }


    2. You have to overload the CStatic DrawItem function because winctrl1.cpp has this in it:

    // Derived class is responsible for implementing all of these handlers
    // for owner/self draw controls
    void CStatic::DrawItem(LPDRAWITEMSTRUCT)
    {
    ASSERT(FALSE);
    }


    PictureBox.h:

    void DrawItem(LPDRAWITEMSTRUCT ds);

    PictureBox.cpp:

    void CPictureBox::DrawItem(LPDRAWITEMSTRUCT ds)
    {
    //Do nothing
    }


    -Gabe
     
  5. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Gabe,

    First of all Welcome to G4EF.

    It allows to add the variable of type CStatic but the name of the control should not be IDC_STATIC. Let me know if I am missing anything.

    -Shabbir
     
  6. gabedude

    gabedude New Member

    Joined:
    Sep 22, 2006
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    Shabbir,

    You may be right. I might have changed the variable name after I added the code to the source file. However, you still must overload DrawItem() in the CPictureBox class. I was getting an assert when I pressed the CTRL key in my program until I did this.

    Thanks again for the code.

    -Gabe
     
  7. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Yes that I havent tested might be a good tip.
     
  8. Cuckoo

    Cuckoo New Member

    Joined:
    Dec 23, 2006
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    hello, i am new to visual c++ and i was wondering if you could give me a little explanation on how to use the picturebox? my second question is how can i do a frame window which shows a slide show (say using that picture box)?
     
  9. Cuckoo

    Cuckoo New Member

    Joined:
    Dec 23, 2006
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    i am a second year software engineering student, so i have little experience in visual c++ programming but some experience in c++... help! :(
     
  10. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Thats what the article is all about.
    Changing the images is what you meant by slideshow then use the above code snippets for changing the images in the timer event.
     
  11. nishalingadurai

    nishalingadurai New Member

    Joined:
    Dec 22, 2006
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    hai
    code you given for display bitmap is complied but does not display output window.
    plz tell what is the reason.

    and you mention
    "Change the Type of the picture box to OWNER_DRAW."
    i could not understand this
     
  12. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Probably some problem in steps as I could do using the article steps/

    Right Click on picture box resource in the designer and check you will see on property by that name.
     
  13. nishalingadurai

    nishalingadurai New Member

    Joined:
    Dec 22, 2006
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    hai

    the code which is display in window different in zip file(picture file). i get error on compile
    zip code. the error is "error C2039: 'DoModal' : is not a member of 'CBitmapPictureDlg'"
    plz what i make wrong.
     
  14. nishalingadurai

    nishalingadurai New Member

    Joined:
    Dec 22, 2006
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    hai

    you said

    "Change the Type of the picture box to OWNER_DRAW.
    Add a variable to the picture box. By default it will be CStatic. I call it picPreview"


    In picture box property- type have option such as frame,icon,bitmap etc "OWNER_DRAW means what? is picpreview is variable of picturebox?

    I cannot create variable for picturebox, there is no object on member variable in class wizard.

    I have another doubt why two cpp and h file is created when creating new workspace.
    example my project name is BitmapPicture, source file have BitmapPicture.cpp and BitmapPictureDlg.cpp. header file contain BitmapPicture.h and BitmapPictureDlg.h.

    plz tell which code i have to follow, code which display under "Display Bitmap in a Picture Box using MFC from a file" or Picture zip file.
     
  15. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    You probably needs to get hands on the MFC before going into some more complicated problems. I am trying to explain some of them but if you cannot get them try getting the a book on basics of MFC as the steps I explained in the article are pretty simple

    1. I never told that the zipped files will compile correctly. It just that you add it to your existing project and that should enhance the ability of your picture box.

    2. OWNER_DRAW will be a check box type of property which all the controls have and the property is relating to how the control will be drawn. You will handle it or should windows do the job for you.

    3. Regarding creating a variable you should use the class Wizard for the picture box and if you cannot use the class wizard either you should use a seperate thread here or use some IDE help.

    4. Regarding the files generated I would say you go to the basics first and get some good hands on MFC before going into some good looking samples.
     
  16. yogessshhh

    yogessshhh New Member

    Joined:
    Jan 10, 2007
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    helpful article

    thanks shabbirrrrrrrrrrr
     
  17. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    My pleasure.
     
  18. Cuckoo

    Cuckoo New Member

    Joined:
    Dec 23, 2006
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    Hello shabir... i have a question about picture loading...
    i have build this engine which switches pictures on a Frame and i want it to be in a 25 fps rate, how can i be done?

    here is my code:


    Code:
    BOOL MovieEngine::paintCurrFrame(BOOL onPaint)
    {
    	PAINTSTRUCT ps;	
    	HDC hDC;
    	hDC = ::BeginPaint(m_paintTarget->m_hWnd, &ps);
    	HDC memDC = CreateCompatibleDC(hDC);
    	m_jpegRect.bottom=m_offsetY+m_currFrame->GetHeight(); //m_currFrame is a cximage object
    	m_jpegRect.right=m_offsetX+m_currFrame->GetWidth();
    	m_paintTarget->GetClientRect(m_clientRect);
    	HBITMAP hMemBmp = CreateCompatibleBitmap(hDC,  m_clientRect.Width(),  m_clientRect.Height());
    	HBITMAP hOldBmp = (HBITMAP)SelectObject(memDC, hMemBmp);
    	FillRect(memDC,m_clientRect,(HBRUSH) (COLOR_WINDOW));
    	if(m_playing)
    	         m_currFrame->Draw(memDC,m_jpegRect);
    	BitBlt(hDC, 0, 0, m_clientRect.Width(), m_clientRect.Height(), memDC, 0, 0, SRCCOPY);
    	SelectObject(memDC, hOldBmp);
    	::EndPaint(m_paintTarget->m_hWnd, &ps);
    	DeleteObject(hMemBmp);
    	if(!onPaint){
    		m_paintTarget->InvalidateRect(m_jpegRect);
    		m_paintTarget->RedrawWindow(m_jpegRect);
    	}
    	return TRUE;
    }
    this is the engine itself as a thread:

    Code:
    UINT MovieEngine::playThread(LPVOID engine)
    {
    	MovieEngine* thisEngine=(MovieEngine*)engine;
    	if(thisEngine->m_buffComplete){
    		while (thisEngine->m_movieBuff.size()>0)//m_movieBuff is a vector of pointers to cximages (hance the movie).
    		{
    			thisEngine->m_currFrame=thisEngine->m_movieBuff.front();
    			thisEngine->m_movieBuff.pop();
    			thisEngine->paintCurrFrame(FALSE); //function above
    			delete thisEngine->m_currFrame;
    			Sleep(40);// 40 milisec is the time needed to get 25 fps rate but all the picture switching takes time, so i need 40-switch_time...
    		}
    	}
    	return 0;
    }
    ofcourse there is a loading thread (to keep buffer full untill the movie ends) while playing but it is irelevant for now.
    i hope the code is clear, couse i am new to mfc and visual at all.
    i managed to make it play but nothing deterministic. sometimes it plays faster than 25 fps sometimes slower.... i donno what to do :(
    Second year SE student.
     
  19. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Cuckoo, please post your query into a seperate thread and try not jumping into a thread with your query as that does not help much. Its always good to go through your query but if that did not help you should be going with a new thread.
     
  20. Nishant Desai

    Nishant Desai New Member

    Joined:
    Jan 19, 2007
    Messages:
    9
    Likes Received:
    0
    Trophy Points:
    0
    Dear Shabbir,

    I am a newbie to this forum, and I want to change the pictures as the boolean, by boolean mean when the variable is true, the picture box should show the green dot and if the variable is false then picturebox is false, then it should show the red dot.

    I have bitmaps of both, red and green dots. but i dont know how to load them into the picture box when the event ocurs, please help me to sort out the fact.

    Actually I have the big project, so i dont think that i have to create the picture box class, but i want to know that how to create the DC for the picture box, what should i write so that it creatres the DC for the picture box, i have taken.

    Thanks,
    Nishant
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice