
If you are a beginner you may just want to scroll down to the end and just use the module ;)
Well where should I start? Yesterday, I tried to find a source for getting my JPG and GIF files in a Window. And I only found a "Few" (like 10) examples on that. after 6 hours surfing on the internet.
The bad thing only with the sources were that:
- Most of the time they used MFC (real MFC so it needs the DLL's), I don't like MFC (but that is possible because I'm from the ASM world).
- The sources needed almost always a very BIG library, and sometimes they want money for it too.
- They where coded in C++ (don't care of course but you don't have to use it).
- The sources were very complicated, why should we reinvent the wheel?
- I wanted to make my app so small as possible, and all this libs were making mine bigger and bigger.
Alright, well I found 1 source that was useful. I rewrote all the routines and removed the original calls to the header. They were too complicated too. I made "only" 3 calls.
- To add the picture to the window (only have to give the resource Id and the position).
- A function that will repaint it. (when u minimize the program).
- And a final function to free the pictures from memory.
is that simple or what? :)
ok let's go to some code, I wrote a linked list to store all the pictures in memory. I was thinking of making a class of all this, but well I know C a lot better then C++ so that is why I didn't make one. (I could do it, but it would take a lot more time).
Loading from the resource:
HRSRC res = FindResource(GetModuleHandle(NULL),
MAKEINTRESOURCE(ResourceHandle),"BINARY");
if (res)
{
struct Pictures *pPicture = (struct Pictures*)
malloc (sizeof(struct Pictures));
HGLOBAL mem = LoadResource(GetModuleHandle(NULL), res);
void *data = LockResource(mem);
size_t sz = SizeofResource(GetModuleHandle(NULL), res);
pPicture->Picture = LoadPicture(hWnd, (u_char*)data, sz,
&pPicture->PictureWitdh, &pPicture->PictureHeight);
you see the last line that calls another procedure I wrote:
IPicture *LoadPicture(HWND hWnd, const unsigned char *data,
size_t len,long *ret_w, long *ret_h,
OLE_XSIZE_HIMETRIC *cx, OLE_YSIZE_HIMETRIC *cy)
{
HDC dcPictureLoad;
IPicture *pic = NULL;
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, len);
LPVOID pvData = GlobalLock( hGlobal );
memcpy(pvData,data,len);
GlobalUnlock(hGlobal);
LPSTREAM pStream = NULL;
HRESULT hr = CreateStreamOnHGlobal( hGlobal, TRUE, &pStream );
OleLoadPicture(pStream, 0, FALSE,IID_IPicture, (void **)&pic);
pStream->Release();
pic->get_Width(cx);
pic->get_Height(cy);
dcPictureLoad = GetDC(hWnd);
*ret_w = MAP_LOGHIM_TO_PIX(*cx, GetDeviceCaps(dcPictureLoad, LOGPIXELSX));
*ret_h = MAP_LOGHIM_TO_PIX(*cy, GetDeviceCaps(dcPictureLoad, LOGPIXELSX));
ReleaseDC(hWnd,dcPictureLoad);
return pic;
}pre>
This will make from a *char
from a IStream
and locates the picture from it using:
OleLoadPicture(pStream, 0, FALSE,IID_IPicture, (void **)&pic);
You are probably thinking "no way, that is a MFC procedure, while you made a statement you didn't like it". True, but this procedure will not force you to distribute the MFC DLL with the program. It is just working fine (and it even don't link to the MFC42.dll). Well anyway beside that this procedure is very nice to use, I mean why should we write a decrytor / decompressor for image formats while they already exists in windows. (this method is also used in Internet Explorer) so I guess everybody got the DLL that is needed for this. The best thing is that this method will also support Transparant GIFs. The project includes a transparent GIF and works out fine.
Here we will calculate the RECT
size and coordinates.
RECT bounds;
bounds.top = pPicture->PositionY;
bounds.bottom = pPicture->PositionY + pPicture->PictureHeight;
bounds.left = pPicture->PositionX;
bounds.right = pPicture->PositionX + pPicture->PictureWitdh;
The last thing you need to know is the display algorithm. (well if you want of course).
pPicture->Picture->Render(dcRepaintPictures,
bounds.left, bounds.bottom,
bounds.right - bounds.left,
bounds.top - bounds.bottom,
0, 0,
pPicture->cx, pPicture->cy, NULL);
there you go.
Now comes the best part, You do not have to know all this code because I made 3 simple routines, explained below.
void AddPicture(HWND hWnd,int ResourceHandle,int PositionX,int PositionY);
void RepaintPictures(HWND hWnd);
void RemovePictures(HWND hWnd);
I guess all the people are laughing now why so much companies want to make money with libraries that can do the same (or maybe a little more), maybe not?... well I am though :) Thanks for reading this and I hope this is a little clear to you. if not then just download the whole project and see the example - it is really easy, I promise.
History
17 July 2002 - updated to allow multiple images to be displayed