none
Displaying/reloading image with MFC

    Question

  • Alright there seems to be a thousand ways to do this, but I'm falling short of this simple task regardless. =)

     

    I start a new MFC dialog project in VS2008.

     

    I add an ActiveX control using Microsoft Forms 2.0 Image.

     

    I set that to a default image, we'll say c:\test.jpg and assume that all permissions are good and that the file is valid, no bad file handles, etc. The image displays just fine at this point.

     

    I then have code that basically updates that image and resaves it, so now I want to update the container to reflect that change.

     

    Using the IntelliSense parser, I've looked through the list of methods and properties available to me to do this but can't seem to figure out how to simply invoke a Reload, or how in code to tell the ActiveX object to load an image in general.

    I've googled and read up on IPicture, MFC, etc but at this point my head is somewhat spinning and I've had good results posting here, so a really simple code example would be greatly appreciated.

    Thanks! =)

     

    J

    Wednesday, November 03, 2010 10:07 PM

Answers

  • Not very elegant, but there is a HBITMAP() operator on CImage and also a Detach() function that returns a HBITMAP handle.
    So technically, you could do this:
    ---------------------

     CImage pTemp;
     pTemp.Load(fName);

    CPictureHolder pictholder;
    pictholder.CreateFromBitmap(pTemp.Detach()); // a new bitmap that I created.

    imgLV.putref_Picture(pictholder.GetPictureDispatch());

    --------------------

    However, for what you want to do, I think you can instead simply use a non-activeX picture control in your dialog, something like in this article:

      http://www.functionx.com/visualc/applications/displaybitmap.htm

    -Seetharam

    • Marked as answer by daemorhedron Monday, November 08, 2010 5:35 PM
    Thursday, November 04, 2010 6:41 PM

All replies

  • use oleview to check the control's type library. That Form 2.0 type library contains a lot of controls, not sure which control you are talking about.

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    Wednesday, November 03, 2010 11:24 PM
  • Try this:
    http://support.microsoft.com/kb/146010

     

    Here's what I tried:

    #include <afxctl.h>
    void CtestDlg::OnBnClickedButton1()
    {
       CPictureHolder pictholder;
       pictholder.CreateFromBitmap(IDB_BITMAP1); // a new bitmap that I created.

       m_Image.putref_Picture(pictholder.GetPictureDispatch());

       RedrawWindow(); //refresh the dialog.
    }

    m_Image is of type CImage1 that was generated by Visual Studio when I right click on the control and said *add variable* and chose "OCX" Control type and CImage1 variable type form the dropdown...

    -Seetharam

    Wednesday, November 03, 2010 11:50 PM
  • Hello J

    Have you looked deeper into GDI+ (GDI Plus)? It is a very powerful library. You can do a lot things without coding it by yourself. The good thing is that GDI+ is included in Windows since Win2000. GDI+ is also able to handle JPG.

    Depending on what you want to do ActiveX or COM may a little oversized to display only a picture on a dialog.

    Thursday, November 04, 2010 5:57 AM
  • Thanks Bordon, this does indeed seem ridiculous overkill heh =) The logic flow is very simple: get data from a device once a second, save that as a jpg, then update the picture on the dialog to reflect this. I've done everything except for the actual display, which ironically is proving to be the toughest part! =)
    Thursday, November 04, 2010 5:51 PM
  • Thanks Seetharam, this seems close to what I'm after but there's a few problems.

     

    1. This isn't a static resource, so I don't have IDB_BITMAP1. I know you're probably just doing that to show the simplest possible example, but I need to load this data from a known file, or use the stream directly (much more ideal, but for now I just want to load/reload it to display it, I'll worry about optimization later)

     

    2. We're dealing in jpg's, and I don't think that would be supported using what you wrote? (please correct me if I'm wrong, that's a question not an accusation)

     

    Also would is save on resources to do m_Image.RedrawWindow() instead?

     

    Thanks for the clear info on how to set a variable in this case, but I've already gotten that far. =)

     

    J

    Thursday, November 04, 2010 5:55 PM
  • Thanks Sheng Jiang, this is a correct approach as I have now learned. Specifically, this is the Microsoft Forms 2.0 Image OCX. I understand about setproperty and getproperty and thinking that there has to be an easier way to be doing this. Think of it like a web browser. You're looking at a jpg image, and I want to reload that image (because the file has actually changed). This would be happening once per second. I have already done all the code to get the image from the device and a timer that iterates once per second to write the file to disk. I just need to reload it in an image box on the dialog to show this! =)

     

    J

    Thursday, November 04, 2010 5:58 PM
  • The static bitmap was simply to show that we could replace the original bitmap in the ActiveX ctrl.

    For both your questions 1 & 2, have a look at the ATL CImage class. It can load an image( PNG, JPG, BITMAP ) from a location on the disk or from the stream.

    http://msdn.microsoft.com/en-us/library/tf4bytf8%28VS.80%29.aspx

     ...and yes, I think m_Image.RedrawWindow()  is the right thing to do.

     

    Thanks
    Seetharam

    Thursday, November 04, 2010 6:06 PM
  • Ok CImage definitely seems helpful, but I am having trouble understanding how to combine it with your original code. Using CImage and putref_Picture, they are different types, so it doesn't seem to work in the way that I would hope.

     

        CImage* pTemp;

        pTemp->Load(fName);

        imgLV.putref_Picture(pTemp->??);  //what goes here?

        imgLV.RedrawWindow();

     

    Thanks for all your help! =)

     

    J

    Thursday, November 04, 2010 6:16 PM
  • Not very elegant, but there is a HBITMAP() operator on CImage and also a Detach() function that returns a HBITMAP handle.
    So technically, you could do this:
    ---------------------

     CImage pTemp;
     pTemp.Load(fName);

    CPictureHolder pictholder;
    pictholder.CreateFromBitmap(pTemp.Detach()); // a new bitmap that I created.

    imgLV.putref_Picture(pictholder.GetPictureDispatch());

    --------------------

    However, for what you want to do, I think you can instead simply use a non-activeX picture control in your dialog, something like in this article:

      http://www.functionx.com/visualc/applications/displaybitmap.htm

    -Seetharam

    • Marked as answer by daemorhedron Monday, November 08, 2010 5:35 PM
    Thursday, November 04, 2010 6:41 PM
  • I have no doubt that there are better ways to do this, but this ultimately did help me to come up with a final solution. Final steps to try to help someone else with this problem:

     

    -Add an activex image container by going to the resource view, right clicking on the form and pick Insert Activex Control.

    -Choose Microsoft Forms 2.0 Image

    -Right click the new control and pick Add Variable. We'll call this imgLV as an example.

    -Make sure that you add this to your project so you have access to CPictureHolder class:

    #include <afxctl.h>

    -Code as below (I used mine in a timer with FPS control)

                CImage pTemp;
                GetCurrentDirectory( 256, fName );  //the directory of the image file to reload
                strcat_s( fName, "\\test1.jpg" ); //the name of the image file to reload, since we are using Microsoft forms, you can load almost any image type!

                pTemp.Load(fName);    //load into our temp image variable

                CPictureHolder pictholder;    //our temp 'converter'
                pictholder.CreateFromBitmap(pTemp.Detach());    //put the image variable into a container

                imgLV.putref_Picture(pictholder.GetPictureDispatch());    //now display it on the screen

                RedrawWindow(); //refresh to show changes

     

    I am working on improving this of course, but just to consolidate all of the above data into one final post and mark it as closed. Thanks for the help!

     

    J

    Monday, November 08, 2010 5:46 PM
  • Hi! Thanks for your code daemorhedron!

    You forget to say that you need to include 

    #include <afxctl.h>
    #include <afxwin.h>

    in your .h file and insert the 

    CPictureHolder pictholder;

    row under the protected: ones

    Now I need to ask you: how can I empty (reset) this ActiveX?? Thanks a lot!!

    Saturday, July 14, 2012 12:09 AM