Introduction
Here is a sample of what is possible to do with just plain C. This code will display in a window an image that can be in JPG, GIF, BMP, or Windows metafile format.
Compiled with the lcc-Win32 compiler, the code is just 8K. No other language gives you this kind of efficiency. A similar piece of code in C++ weights more than 170K!
The interface is like this:
- You tell it the name of the graphic file
HANDLE h = OpenGraphic(char *filename);
That handle is used for closing the image.
- When painting your window, you pass it the
hwnd
and the hDC
you get from BeginPaint
.
DisplayGraphic(HWND hwnd,HDC hdc);
- When finished, you close it with.
void CloseGraphic(HANDLE h);
Note that CoInitialize()
must be called before using these functions.
I did not add "bells and whistles" to keep the code simple to understand. You may add scrollbars, redimensioning whatever.
This code was developed with the lcc-win32 C compiler. You can download it at no charge from here.
P.S.: This contribution was critized because I did not use Microsoft tools. I know I am biased, but I tried to correct my evil ways. I took the dust out of MSVC 6.0 and OK, here is it, complete with .dsw file in a standard Microsoft Project.
Other critics pointed out to a bug in the transcription, where I added a "*" too much. I fixed that, and I thank the people who pointed me that bug.
It is interesting to note that the code size of the program as compiled with MSVC is 32K, with lcc-win32 is just 8K.
Nobody is perfect...
#include "windows.h"
#include "ocidl.h"
#include "olectl.h"
typedef struct tagImgInfo {
IPicture *Ipic;
SIZE sizeInHiMetric;
SIZE sizeInPix;
char *Path;
} IMG_INFO;
static IMG_INFO ImageInfo;
void *OpenGraphic(char *name)
{
IPicture *Ipic = NULL;
SIZE sizeInHiMetric,sizeInPix;
const int HIMETRIC_PER_INCH = 2540;
HDC hDCScreen = GetDC(NULL);
HRESULT hr;
int nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
int nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
unsigned short OlePathName[512];
ReleaseDC(NULL,hDCScreen);
mbstowcs(OlePathName,name,strlen(name)+1);
hr = OleLoadPicturePath(OlePathName,
NULL,
0,
0,
&IID_IPicture,
(void *)(&Ipic));
if (hr)
return 0;
if (Ipic) {
hr = Ipic->lpVtbl->get_Width(Ipic,&sizeInHiMetric.cx);
if (!SUCCEEDED(hr))
goto err;
Ipic->lpVtbl->get_Height(Ipic,&sizeInHiMetric.cy);
if (!SUCCEEDED(hr))
goto err;
sizeInPix.cx = (nPixelsPerInchX * sizeInHiMetric.cx +
HIMETRIC_PER_INCH / 2) / HIMETRIC_PER_INCH;
sizeInPix.cy = (nPixelsPerInchY * sizeInHiMetric.cy +
HIMETRIC_PER_INCH / 2) / HIMETRIC_PER_INCH;
ImageInfo.sizeInPix = sizeInPix;
ImageInfo.sizeInHiMetric = sizeInHiMetric;
ImageInfo.Ipic = Ipic;
ImageInfo.Path = name;
return Ipic;
}
err:
return 0;
}
void DisplayGraphic(HWND hwnd,HDC pDC)
{
IPicture *Ipic = ImageInfo.Ipic;
DWORD dwAttr = 0;
HBITMAP Bmp,BmpOld;
RECT rc;
HRESULT hr;
HPALETTE pPalMemOld;
if (Ipic != NULL)
{
OLE_HANDLE hPal = 0;
HPALETTE hPalOld=NULL,hPalMemOld=NULL;
hr = Ipic->lpVtbl->get_hPal(Ipic,&hPal);
if (!SUCCEEDED(hr))
return;
if (hPal != 0)
{
hPalOld = SelectPalette(pDC,(HPALETTE)hPal,FALSE);
RealizePalette(pDC);
}
GetClientRect(hwnd,&rc);
if (SUCCEEDED(Ipic->lpVtbl->get_Attributes(Ipic,&dwAttr)) ||
(dwAttr & PICTURE_TRANSPARENT))
{
HDC MemDC = CreateCompatibleDC(pDC);
Bmp =
CreateCompatibleBitmap(pDC,ImageInfo.sizeInPix.cx,ImageInfo.sizeInPix.cy);
BmpOld = SelectObject(MemDC,Bmp);
pPalMemOld = NULL;
if (hPal != 0)
{
hPalMemOld = SelectPalette(MemDC,(HPALETTE)hPal, FALSE);
RealizePalette(MemDC);
}
hr = Ipic->lpVtbl->Render(Ipic,MemDC,
0,
0,
rc.right,
rc.bottom,
0,
ImageInfo.sizeInHiMetric.cy,
ImageInfo.sizeInHiMetric.cx,
-ImageInfo.sizeInHiMetric.cy,
&rc);
BitBlt(pDC,0, 0, ImageInfo.sizeInPix.cx,
ImageInfo.sizeInPix.cy,
MemDC, 0, 0, SRCCOPY);
SelectObject(MemDC,BmpOld);
if (pPalMemOld) SelectPalette(MemDC,pPalMemOld, FALSE);
DeleteObject(Bmp);
DeleteDC(MemDC);
}
else
{
Ipic->lpVtbl->Render(Ipic,pDC,
0,
0,
rc.right,
rc.bottom,
0,
ImageInfo.sizeInHiMetric.cy,
ImageInfo.sizeInHiMetric.cx,
-ImageInfo.sizeInHiMetric.cy,
&rc);
}
if (hPalOld != NULL) SelectPalette(pDC,hPalOld, FALSE);
if (hPal) DeleteObject((HPALETTE)hPal);
}
}
void CloseImage(void *Ipict)
{
IPicture *ip = (IPicture *)Ipict;
if (ip == NULL)
ip = ImageInfo.Ipic;
if (ip == NULL)
return;
ip->lpVtbl->Release(ip);
memset(&ImageInfo,0,sizeof(ImageInfo));
}
I am the author of the lcc-win32 C compiler system. http://www.cs.virginia.edu/~lcc-win32