Click here to Skip to main content
15,891,184 members
Articles / Desktop Programming / MFC

Thumbnail Picture Control

Rate me:
Please Sign up or sign in to vote.
4.70/5 (17 votes)
23 Oct 20022 min read 167.4K   7.6K   53  
A MFC thumbnail picture control
//  *************************************************************************
//  *                                                                       *
//  *  CThumbnailButton     of FabricEye                 ed. 1.0  17/9/2002 *
//  *                                                                       *
//  *************************************************************************
//
//  DESCRIPTION     :
//
//  -------------------------------------------------------------------------
//
//  HEADER          : ThumbnailButton.h
//
//  -------------------------------------------------------------------------
//
//  COMMENTS        :
//
//  -------------------------------------------------------------------------
//
//  REVISION        : Edition 1.0  17/9/2002/RFO    Layout
//
//  -------------------------------------------------------------------------
//  RFO  Rex Fong

// ThumbnailButton.cpp : implementation file
//

#include "stdafx.h"
#include <Commctrl.h>

#include "ThumbnailButton.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define CTHUMBNAILBUTTON_CLASSNAME _T( "CThumbnailButton" )
#define RGBTHUMBBKGD RGB( 230, 230, 230 )

CBrush  CThumbnailButton::m_bkBrush;
/////////////////////////////////////////////////////////////////////////////
// CThumbnailButton

CThumbnailButton::CThumbnailButton( const CString& sPath, const int cx, const int cy )
  {
  if( !RegisterWindowClass() )
    return;

  m_bTracking  = FALSE;
  m_bMouseClicked = FALSE;

  m_cX = cx;
  m_cY = cy;

  m_sFullpath = sPath;
  ExtractFilename( sPath );

  HBITMAP hbmp = (HBITMAP) LoadImage( NULL, (LPCTSTR) m_sFullpath, 
                           IMAGE_BITMAP, cx, cy, 
                           LR_LOADFROMFILE | LR_CREATEDIBSECTION ) ;

  m_bmp.Attach( hbmp );

  }

CThumbnailButton::~CThumbnailButton()
  {
  }


BEGIN_MESSAGE_MAP(CThumbnailButton, CWnd)
	//{{AFX_MSG_MAP(CThumbnailButton)
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CThumbnailButton message handlers

BOOL CThumbnailButton::OnEraseBkgnd(CDC* pDC) 
  {
  CRect rWnd;
  GetWindowRect( &rWnd );

  if( !m_bTracking )
    pDC->FillSolidRect( 1, 1, rWnd.Width()-1, rWnd.Height()-1, RGBTHUMBBKGD );
  else
    pDC->FillSolidRect( 1, 1, rWnd.Width()-1, rWnd.Height()-1, RGB(180,190,210) );

  CPen pen;
  CPen *pOPen;
  POINT pt;
  pt.x = 2;
  pt.y = 2;
  LOGPEN logPen;
  logPen.lopnStyle = PS_SOLID;
  logPen.lopnWidth = pt;

  if( !m_bTracking )
    logPen.lopnColor = RGB(33,33,33);
  else
    logPen.lopnColor = RGB(10,35,105);


  VERIFY( pen.CreatePenIndirect( &logPen ) );

  pOPen = pDC->SelectObject( &pen );

  pDC->MoveTo( 0, 0 );
  pDC->LineTo( rWnd.Width()-1, 0 );
  pDC->LineTo( rWnd.Width()-1, rWnd.Height()-1 );
  pDC->LineTo( 0, rWnd.Height()-1 );
  pDC->LineTo( 0, 0 );

  pDC->SelectObject( pOPen );
  pen.DeleteObject();

  return TRUE;
	}

void CThumbnailButton::OnPaint() 
  {
	CPaintDC dc(this); // device context for painting

  if( m_bmp.GetSafeHandle() != NULL )
    {
		//******************
		//*  Prepare Font  *
		//******************
    LOGFONT lf;
    memset( &lf, 0, sizeof(LOGFONT) );
    lf.lfHeight = 14;
    strcpy( lf.lfFaceName, _T("MS Serif") );

    dc.SetBkColor( RGBTHUMBBKGD );


    CFont font;
    CFont *pOFont;
    VERIFY( font.CreateFontIndirect( &lf ) );
    pOFont = dc.SelectObject( &font );

		//************************
		//*  Draw Thumb Picture  *
		//************************
    CRect rect;
    GetWindowRect( &rect );

    int nSX, nSY; // Starting point
    nSX = ( rect.Width() - m_cX ) / 2;
    nSY = ( rect.Height() - m_cY ) / 4;

    CBitmap *pOldbmp;

    CDC dcBmp;
    dcBmp.CreateCompatibleDC( &dc );
    pOldbmp = dcBmp.SelectObject( &m_bmp );

    dc.BitBlt( nSX, nSY, m_cX, m_cY, &dcBmp, 0, 0, SRCCOPY );

		//*********************
		//*  Write ImageName  *
		//*********************
    TEXTMETRIC   tm ;
    dc.GetTextMetrics( &tm );

    // MAXIMUM Characters = 18
     int nSTX = (rect.Width() - ( tm.tmAveCharWidth * m_sFilename.Left(18).GetLength() ))/2;

    if( m_bTracking )
      dc.SetBkColor( RGB(180,190,210) );
    else
      dc.SetBkColor( RGBTHUMBBKGD );

    // MAXIMUM Characters = 18
     dc.TextOut( nSTX, nSY+m_cY+2, m_sFilename.Left(18) );

    dc.SelectObject( pOFont );
    dcBmp.SelectObject( pOldbmp );

    font.DeleteObject();
    dcBmp.DeleteDC();
    }
	
	// Do not call CWnd::OnPaint() for painting messages
  }

BOOL CThumbnailButton::RegisterWindowClass()
  {
  WNDCLASS wndcls;
  HINSTANCE hInst = AfxGetInstanceHandle();

  if (!(::GetClassInfo(hInst, CTHUMBNAILBUTTON_CLASSNAME, &wndcls)))
    {
    // otherwise we need to register a new class
    m_bkBrush.CreateSolidBrush( RGBTHUMBBKGD );

    wndcls.style            = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
    wndcls.lpfnWndProc      = ::DefWindowProc;
    wndcls.cbClsExtra       = wndcls.cbWndExtra = 0;
    wndcls.hInstance        = hInst;
    wndcls.hIcon            = NULL;
    wndcls.hCursor          = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
    wndcls.hbrBackground    = (HBRUSH) m_bkBrush.GetSafeHandle();
    wndcls.lpszMenuName     = NULL;
    wndcls.lpszClassName    = CTHUMBNAILBUTTON_CLASSNAME;

    if (!AfxRegisterClass(&wndcls))
      {
      AfxThrowResourceException();
      return FALSE;
      }

    }

  return TRUE;
  }

BOOL CThumbnailButton::PreTranslateMessage(MSG* pMsg) 
  {
  CRect rect;
  GetWindowRect( &rect );
  GetParent()->ScreenToClient( &rect );

  switch( pMsg->message )
    {
    case WM_RBUTTONDOWN:
      {
      if( !m_bMouseClicked && m_bTracking )
        {
        m_bMouseClicked = TRUE;
        MoveWindow( rect.left+2, rect.top+2, rect.Width(), rect.Height() );
        }

      if( ::IsWindow(GetParent()->m_hWnd) )
        {
        DWORD dwResult = NULL;
        SendMessageTimeout(
          HWND_BROADCAST, UWM_ON_TNB_RCLICKED, (WPARAM)this, (LPARAM)0,
          SMTO_ABORTIFHUNG|SMTO_NORMAL, 2000, &dwResult );
        }
      }
      return TRUE;
      break;

    case WM_RBUTTONDBLCLK:

      return TRUE;
      break;

    case WM_LBUTTONDBLCLK:

      return TRUE;
      break;

    case WM_LBUTTONDOWN:
      {
      if( !m_bMouseClicked && m_bTracking )
        {
        m_bMouseClicked = TRUE;
        MoveWindow( rect.left+2, rect.top+2, rect.Width(), rect.Height() );
        }

      if( ::IsWindow(GetParent()->m_hWnd) )
        {
        DWORD dwResult = NULL;
        SendMessageTimeout(
          HWND_BROADCAST, UWM_ON_TNB_LCLICKED, (WPARAM)this, (LPARAM)0,
          SMTO_ABORTIFHUNG|SMTO_NORMAL, 2000, &dwResult );
        }

      }
      return TRUE;
      break;

    case WM_MOUSELEAVE:
      {
      if( !m_bMouseClicked )
        {
        MoveWindow( rect.left+2, rect.top+2, rect.Width(), rect.Height() );
        Invalidate();
        }

      m_bMouseClicked = FALSE;
      m_bTracking     = FALSE;
      }
      return TRUE;
      break;

    case WM_LBUTTONUP:
      {
      if( m_bMouseClicked && m_bTracking )
        {
        m_bMouseClicked = FALSE;

        MoveWindow( rect.left-2, rect.top-2, rect.Width(), rect.Height() );
        }
      }

      return TRUE;
      break;

    case WM_MOUSEMOVE:
      {
      if( !m_bTracking )
        {
        m_bMouseClicked = FALSE;

				//**************************
				//*  Track Mouse Movement  *
				//**************************
        TRACKMOUSEEVENT tme;
        memset( &tme, 0, sizeof(TRACKMOUSEEVENT) );
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_LEAVE;
        tme.hwndTrack = m_hWnd ;
        m_bTracking = _TrackMouseEvent( &tme );

        MoveWindow( rect.left-2, rect.top-2, rect.Width(), rect.Height() );
        Invalidate();
        }
      }
    return TRUE;
    break;

    default:
      //TRACE( "%s MSG: %d\n", (LPCTSTR)m_sFilename, pMsg->message );
      break;
    }

	
	return CWnd::PreTranslateMessage(pMsg);
  }

#if 0
LPCTSTR CThumbnailButton::GetBmpName() const
  {
  return ((LPCTSTR) m_sImgName);
  }
#endif

BOOL CThumbnailButton::IsValid() const
  {
  return ( m_bmp.GetSafeHandle() != NULL ) ? TRUE : FALSE;
  }

const CString& CThumbnailButton::GetFullpath() const
  {

  return m_sFullpath;
  }

void CThumbnailButton::ExtractFilename(const CString &sPath)
  {
  char drive[_MAX_DRIVE];
  char dir[_MAX_DIR];
  char fname[_MAX_FNAME];
  char ext[_MAX_EXT];

  CString sTmpPath = sPath;
  LPTSTR lptstr = sTmpPath.GetBufferSetLength( _MAX_PATH );

  _splitpath( lptstr, drive, dir, fname, ext );

  m_sFilename = CString(fname) + CString(ext);
   
  }

void CThumbnailButton::ResetTrackFlag( void )
  {
  m_bTracking = FALSE;
  TRACKMOUSEEVENT tme;  // tracking information

  memset( &tme, 0, sizeof(TRACKMOUSEEVENT) );
  tme.cbSize = sizeof(TRACKMOUSEEVENT);
  tme.dwFlags = TME_CANCEL;
  tme.hwndTrack = m_hWnd;

  _TrackMouseEvent(  &tme  );
  Invalidate();
  }

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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


Written By
Software Developer
Hong Kong Hong Kong
Software developer in realtime, hi-freq trading app.

Comments and Discussions