Image Tip - A popup thumbnail shell extension






3.89/5 (9 votes)
Mar 9, 2004
3 min read

93895

2405
A graphical tooltip to show the contents of jpgs, bmps etc
Introduction
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 the files).
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 GetInfoTip
function.
HRESULT CImage_Tip::GetInfoTip ( DWORD dwFlags, LPWSTR* ppwszTip ) { static std::wstring m_FileNameLast; // We're going to create our own tooltipesque window, // but with a the CPreviewBitmap in it... // wchar_t buf [512]; // wcscpy (buf, L"CImage_Tip::GetInfoTip (). m_Filename = '"); // wcscat (buf, m_FileName.c_str ()); // wcscat (buf, L"' m_FileNameLast = '"); // wcscat (buf, m_FileNameLast.c_str ()); // wcscat (buf, L"'\n"); // OutputDebugStringW (buf); // Return a blank tooltip. IMalloc *pMalloc; if ( FAILED( SHGetMalloc ( &pMalloc ))) return E_FAIL; *ppwszTip = (LPWSTR) pMalloc->Alloc ( (1) * sizeof(wchar_t) ); if ( NULL == *ppwszTip ) { pMalloc->Release(); return E_OUTOFMEMORY; } (*ppwszTip) [0] = 0; pMalloc->Release(); // Make sure we haven't recently shown this item, // otherwise Explorer will keep on trying... if (m_FileName.compare (m_FileNameLast)) CGraphicTip::ShowTip (m_FileName); // This is all that's needed here! m_FileNameLast.erase (); m_FileNameLast.append (m_FileName); return S_OK; }
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...
class CGraphicTip { public: static BOOL ShowTip (std::wstring FileName); protected: CGraphicTip (); ~CGraphicTip (); 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 (); HANDLE m_hThreadHandle; DWORD m_dwThreadID; std::wstring m_FileName; IPicture *m_Picture; SIZE m_szHiMetric; HWND m_hWnd; };
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:
regsvr32 ImageTip.dll"to install, and
regsvr32 /u ImageTip.dll"to uninstall.
Things to do...
Bibliography
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.
History
v1.0
Uploaded to Code Project. The software is perfect already. Honest. Would these eyes lie?