During my day job, I write software that makes ultrasonic scans of aircraft parts.
(If you are an part aircraft manufacturer, buy our kit!).
These scans are essentially large 8 bit bitmaps, with some job specific extra information.
In order to quickly tell these files apart, I wanted an InfoTip shell extension that could
either display description text stored in these files, or a preview image (also stored in
Writing the text popup was trivial. But search as I might, I didn't find any graphical
equivalent. So I got my hands dirty and wrote it!
Once I'd done that, I thought this might be quite and handy utility for image files too.
Theoretically, you could adapt this to play the first 5s of a music file for mp3s etc.
That is an exercise for the reader...
How it works... aka The light bulb moment.
I tried for ages to hook into the info tip creation cycle, seeing if I could integrate
myself a little earlier. Eventually I gave up. At two am, I woke up with a dead simple idea.
Return a blank tooltip, and use than moment to generate my own tooltipesque picture window.
After having proved my idea, I went back to bed. Most of my best work is done when I'm
asleep. At least, that's what I tell my colleagues when the wake me up at my desk!
The shell extension...
The shell extension itself was premade by a shell extension wizard. (See bibliography). I
only really had to change the
HRESULT CImage_Tip::GetInfoTip ( DWORD dwFlags, LPWSTR* ppwszTip )
static std::wstring m_FileNameLast;
if ( FAILED( SHGetMalloc ( &pMalloc )))
*ppwszTip = (LPWSTR) pMalloc->Alloc ( (1) * sizeof(wchar_t) );
if ( NULL == *ppwszTip )
(*ppwszTip)  = 0;
if (m_FileName.compare (m_FileNameLast))
I had to make sure that explorer wasn't making repeat requests for the same tip, otherwise
the screen ended up getting very busy. Once that was in place, I simply created a new
CGraphicTip object, which made its own window, message loop, and tidying up bit.
The graphic popup window...
This is pretty much a mini app in its own right. Created with a filename as a parameter, it
loads the image using IPicture, and creates a window scaled down to a maximum of 200 x 200, and
shows it a little way from the cursor.
The object contains its own message loop, and window procedure. I used classic Win32, as MFC
seemed like major overkill, and I've yet to play with WTL. Using Win32 windowing code felt like
a bit of a nostalgia trip. Beside, all MFC / WTL would do is the same job, but more hidden.
Please forgive the lack of comments, but there are only a few routines, and I try to use very
obvious function / variable names...
static BOOL ShowTip (std::wstring FileName);
static DWORD WINAPI TipThread ( LPVOID lpParameter );
static LRESULT CALLBACK TipProc ( HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam );
static SIZE GetCorrectedOutputSize (const SIZE szIn,
const SIZE sizeBounding);
LRESULT OnPaint ();
Installing the extension...
If you haven't compiled it yourself, you'll need to put the dll in an obvious location, fire up
a command prompt, go to the dll's directory, and type:
to install, and
regsvr32 /u ImageTip.dll"
Things to do...
An installation program.
A way of changing maximum tip size, and duration at runtime.
A way of changing which file types are "tipped" at runtime.
Make the tip appear above / to the left when necessary.
An uninstallation program!
The following codeproject articles made my life veeeeery easy:
Context Menu Shell Extension AppWizard
by Maxime Labelle.
which seemed heavily based on...
The Complete Idiot's Guide to Writing Shell Extensions - Part III
by Michael Dunn. I cannot recommend his shell extension series highly enough.
Uploaded to Code Project. The software is perfect already. Honest. Would these eyes lie?