Click here to Skip to main content
Click here to Skip to main content

Image Tip - A popup thumbnail shell extension

By , 8 Mar 2004
Rate this:
Please Sign up or sign in to vote.

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...

  • 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!
  • 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?

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    About the Author

    Iain Clarke, Warrior Programmer
    Software Developer (Senior)
    Sweden Sweden
    I have now moved to Sweden for love, and recently married a lovely Swede.
     

    -----------------
    I started programming on BBC micros (6502) when I was six and never quite stopped even while I was supposed to be studying physics and uni.
     
    I've been working for ~13 years writing software for machine control and data analysis. I now work on financial transaction transformation software, for a Software company in Gamlastan, Stockholm.
    Look at my articles to see my excellent coding skills. I'm modest too!

    Comments and Discussions

     
    Generaldoesn't work in xp Pinmembereversor22-Aug-04 3:45 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Mobile
    Web01 | 2.8.140415.2 | Last Updated 9 Mar 2004
    Article Copyright 2004 by Iain Clarke, Warrior Programmer
    Everything else Copyright © CodeProject, 1999-2014
    Terms of Use
    Layout: fixed | fluid