Link to home
Start Free TrialLog in
Avatar of shifty_mc
shifty_mc

asked on

Need to load an image from a file (not resource) and display it to screen

Hi,

I'm extremely frustrated! Can someone please tell me first - the best way to do this?... I've looked at using GDI+ with c++, and just about got it working, but not quite.  This is probably my preferred way, if only because I've just done a project in C# and so am used to it, but if anyone knows other more traditional methods that's great as well.

I'm basically trying to write a very simple screensaver that displays images.
So I've got a "void CSaverWnd::OnTimer(UINT nIDEvent)" method that needs to go through a vector of strings (paths to image files), displaying the image related to the string.

Like I said, I kinda got something working - in gdi+ (took me forever to set up gdi+ but nevermind), but all sorts of things were going wrong that I couldn't understand.

If someone could give me some solid code they know works, I'll love you forever ;)

Cheers.
Avatar of caner_elci
caner_elci

In GDI+, you can use Image::FromFile() static function and Graphics::DrawImage() method..

For example :

Graphics g = Graphics::FromHDC( GetDC() );

Image img = Image::FromImage( "C:\\file.jpg", true );
g.DrawImage( &img, 0, 0 );

This will load the image and draw it at (0,0) coordinates of your current window's DC..
Check out the CImage class.

If you have access to MSDN, check out the SimpleImage example, it does exactly what you want to do.
Are those bitmaps? In that case ::LoadImage () can do the job.

HANDLE LoadImage(
  HINSTANCE hinst,   // handle of the instance containing the image
  LPCTSTR lpszName,  // name or identifier of image
  UINT uType,        // type of image
  int cxDesired,     // desired width
  int cyDesired,     // desired height
  UINT fuLoad        // load flags
);

hinst = NULL
lpszName = filepath
 uType = IMAGE_BITMAP
 cxDesired = cyDesired = LR_DEFAULTSIZE
 fuLoad = LR_LOADFROMFILE
Avatar of jkr
Check out

http://www.codeguru.com/Cpp/G-M/bitmap/article.php/c1681/ ("Drawing a bitmap from a BMP file")
Yes, you can also use CImage class of MFC.. but be careful, you will just be able to load .BMP files (and maybe .JPG, not sure about it).. Anyway, GDI+ will have some other advantages, especially when you are coding a screensaver.. Such as transparency (alpha channel).. You will be able to code some transitions while switching images.. And only disadvantage of GDI+ is distributing gdiplus.dll with your application.. not a big deal thou..
CImage works with jpg, gif, png, and bmp file formats.
Good for CImage then.. I wasn't sure of that.. So it was not the point.. CImage is too primitive compared to GDI+ classes.. That's why they developed GDI+.. no antialiasing, no transformations, no alpha channel, no color matrixes etc.. I don't think I need to count more..
Avatar of shifty_mc

ASKER

well I'll give the gdi+ way a go first  - but caner_elci, can you be a bit more specific?
I tried your code...
      CPaintDC dc(this);
      using namespace Gdiplus;
      Graphics* g = Graphics::FromHDC( dc );
      USES_CONVERSION;
      Image* img = Image::FromFile( A2W(picture_names[current_picture].c_str()), true );
      g->DrawImage( img, 0, 0 );
(these modifications are the only way I could get it to compile - and to be honest it's all a bit trial and error for me)
but am just getting a black screen.
Do I need to do anything to specifically tell it to paint?
Thanks
oh, and wayside - I tried to download the sample and it wouldn't let me, any ideas? Don't suppose there's any chance u could email it to me if it's small? Don't worry if not, cheers
scratch that- just worked on fourth attempt :)
ASKER CERTIFIED SOLUTION
Avatar of caner_elci
caner_elci

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
OK, I got it using gdi+... just about - for some reason the code would only work in the OnPaint method, no idea why unless anyone can enlighten me.
Thanks for your time anyway
You can paint your window anytime, try using this->GetDC() as dc parameter in Graphics' constructor... In fact, use something like this:

CDC *pDC = GetDC();
Graphics g( pDC );

... do your painting here ...

ReleaseDC( pDC );
umm - just get the one error...

cannot convert parameter 1 from 'class CDC *' to 'struct HDC__ *'

in the line Graphics g( pDC );
Okay, try this:

Graphics g( pDC->GetSafeHdc() );

or

Graphics g( (HDC)pDC );
yeah, both of those compiled, but get the same black screen still. I assume it's something to do with it being a screensaver and perhaps somewhere a black background is being painted over anything I try to draw, which is why it only works in the OnPaint method - drawing after the black maybe?

Unfortunately I've jumped into the deep end a bit and don't have time to stop and actually work out why everything does what it does (terrible I know) - a lot of it is kind of merged code from elsewhere so far.

I appreciate the help though.
Do you remove the code in OnPaint when you add the code in any other event such as OnTimer()?

If so, please consider these:
You better just load the image in OnTimer() and then call this->Invalidate() to force an OnPaint()...
In OnPaint() you should not load any image and just draw the currently loaded image
yeah, that's what I'm working with at the mo, thanks for all your help - it really does save a lot of time coming to sites like this.
You're welcome.. I suggest you to use some transitions while switching between images :) Try color matrixes and Graphics methods...
yep, that's all to come. I expect I'll be back on with many more questions in the near future :)
Anytime you want :)

Have fun!

Caner