|
|
/******************************************************************************/ /* THUMNAIL.CPP: IMPLEMENTATION OF THE CThumbNailView and CFloatThumNailView */ /* and CFullScreenThumbNailView Classes */ /* */ /******************************************************************************/ /* */ /* Methods in this file */ /* */ /* CThumbNailView Class Object */ /* CThumbNailView::CThumbNailView */ /* CThumbNailView::CThumbNailView */ /* CThumbNailView::~CThumbNailView */ /* CThumbNailView::Create */ /* CThumbNailView::OnSize */ /* CThumbNailView::OnPaint */ /* CThumbNailView::DrawImage */ /* CThumbNailView::DrawTracker */ /* CThumbNailView::RefreshImage */ /* CThumbNailView::GetImgWnd */ /* CThumbNailView::OnKeyDown */ /* CThumbNailView::OnLButtonDown */ /* CThumbNailView::OnRButtonDown */ /* CThumbNailView::OnThumbnailThumbnail */ /* CThumbNailView::OnUpdateThumbnailThumbnail */ /* */ /* CFloatThumbNailView Class Object */ /* CFloatThumbNailView::CFloatThumbNailView */ /* CFloatThumbNailView::~CFloatThumbNailView */ /* CFloatThumbNailView::Create */ /* CFloatThumbNailView::OnClose */ /* CFloatThumbNailView::OnSize */ /* */ /* CFullScreenThumbNailView Class Object */ /* CFullScreenThumbNailView::CFullScreenThumbNailView */ /* CFullScreenThumbNailView::CFullScreenThumbNailView */ /* CFullScreenThumbNailView::~CFullScreenThumbNailView */ /* CFullScreenThumbNailView::Create */ /* CFullScreenThumbNailView::OnLButtonDown */ /* CFullScreenThumbNailView::OnKeyDown */ /* */ /******************************************************************************/ /* */ /* These 3 objects provide a layer around the thumbnail view window, which */ /* allow it to easily be a child, floating or a full screen. The ThumbNail */ /* View Window is just a CWnd Window which on paints does a BitBlt from the */ /* CImgWnd it was passsed on construction. */ /* */ /* The structure of the objects is as follows: */ /* */ /* CFullScreenThumbNailView is a Frame Window (with no border and sized to */ /* full screen). It destroys itself on any keystroke or button click */ /* while visible, it dissables the main application window. It contains */ /* a CThumbNailView object as a child window. */ /* */ /* CFloatThumbNailView is a MiniFrame Window */ /* CThumbNailView is a Child Window (which is sizable) A child of the */ /* the CFloatThumbNailView window. This can be created */ /* independent if a floating window is not desired (i.e. */ /* for the docked view). It is this window which has the */ /* image drawn into it. */ /* */ /* */ /******************************************************************************/
#include "stdafx.h"
#include "global.h"
#include "pbrush.h"
#include "pbrusdoc.h"
#include "pbrusfrm.h"
#include "pbrusvw.h"
#include "minifwnd.h"
#include "docking.h"
#include "bmobject.h"
#include "imgsuprt.h"
#include "imgwnd.h"
#include "imgcolor.h"
#include "imgbrush.h"
#include "imgwell.h"
#include "imgtools.h"
#include "imgwnd.h"
#include "thumnail.h"
#ifdef _DEBUG
#undef THIS_FILE
static CHAR BASED_CODE THIS_FILE[] = __FILE__; #endif
IMPLEMENT_DYNAMIC(CThumbNailView, CWnd) IMPLEMENT_DYNAMIC(CFloatThumbNailView, CMiniFrmWnd) IMPLEMENT_DYNAMIC(CFullScreenThumbNailView, CFrameWnd)
#include "memtrace.h"
/******************************************************************************/ /******************************************************************************/ /******************************************************************************/
BEGIN_MESSAGE_MAP(CThumbNailView, CWnd) //{{AFX_MSG_MAP(CThumbNailView)
ON_WM_PAINT() ON_WM_KEYDOWN() ON_WM_LBUTTONDOWN() ON_WM_RBUTTONDOWN() ON_COMMAND(ID_THUMBNAIL_THUMBNAIL, OnThumbnailThumbnail) ON_UPDATE_COMMAND_UI(ID_THUMBNAIL_THUMBNAIL, OnUpdateThumbnailThumbnail) ON_WM_CLOSE() //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/******************************************************************************/
CThumbNailView::CThumbNailView(CImgWnd *pcImgWnd) { m_pcImgWnd = pcImgWnd; }
/******************************************************************************/
CThumbNailView::CThumbNailView() { m_pcImgWnd = NULL; }
/******************************************************************************/
CThumbNailView::~CThumbNailView(void) { }
/******************************************************************************/
BOOL CThumbNailView::Create(DWORD dwStyle, CRect cRectWindow, CWnd *pcParentWnd) { return( CWnd::Create(NULL, TEXT(""), dwStyle, cRectWindow, pcParentWnd, NULL) ); }
/***************************************************************************/
void CThumbNailView::OnClose() { ShowWindow(SW_HIDE); }
/******************************************************************************/
void CThumbNailView::OnPaint() { CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
#ifdef USE_MIRRORING
//
// Disable RTL mirroring on full screen window
//
if (PBGetLayout(dc.GetSafeHdc()) & LAYOUT_RTL) { PBSetLayout(dc.GetSafeHdc(), 0); } #endif
// Do not call CWnd::OnPaint() for painting messages
DrawImage(&dc); }
/******************************************************************************/
void CThumbNailView::DrawImage(CDC* pDC) { /*
** when there is nothing to do, then don't do it */ if (! theApp.m_bShowThumbnail || m_pcImgWnd == NULL || m_pcImgWnd->m_pImg == NULL ) return;
CRect crectClient; int iMinWidth; int iMinHeight; int iLeft; int iTop;
CSize cSizeScrollPos = m_pcImgWnd->GetScrollPos();
cSizeScrollPos.cx = abs( cSizeScrollPos.cx ) - CTracker::HANDLE_SIZE; cSizeScrollPos.cy = abs( cSizeScrollPos.cy ) - CTracker::HANDLE_SIZE;
GetClientRect(crectClient);
// find the smaller of the two the real image or the thumbnail window.
iMinWidth = min( crectClient.Width() , m_pcImgWnd->m_pImg->cxWidth ); iMinHeight = min( crectClient.Height(), m_pcImgWnd->m_pImg->cyHeight );
if (crectClient.Width() >= m_pcImgWnd->m_pImg->cxWidth) { iLeft = 0; // can fit the whole image width into the thumbnail
} else // image width greater than thumbnail width
{ // does thumbnail extend past end if started at scroll pos?
if (cSizeScrollPos.cx + crectClient.Width() > m_pcImgWnd->m_pImg->cxWidth) { iLeft = cSizeScrollPos.cx - ( (cSizeScrollPos.cx + crectClient.Width() - m_pcImgWnd->m_pImg->cxWidth)); } else { iLeft = cSizeScrollPos.cx; } }
if (crectClient.Height() >= m_pcImgWnd->m_pImg->cyHeight) { iTop = 0; // can fit the whole image height into the thumbnail
} else // image height greater than thumbnail height
{ // does thumbnail extend past bottom if started at scroll pos?
if (cSizeScrollPos.cy + crectClient.Height() > m_pcImgWnd->m_pImg->cyHeight) { iTop = cSizeScrollPos.cy - ( (cSizeScrollPos.cy + crectClient.Height() - m_pcImgWnd->m_pImg->cyHeight)); } else { iTop = cSizeScrollPos.cy; } }
CDC cDC; cDC.Attach(m_pcImgWnd->m_pImg->hDC);
CPalette* ppalOldSrc = theImgBrush.SetBrushPalette(&cDC, FALSE); CPalette* ppalOldDst = theImgBrush.SetBrushPalette( pDC, FALSE);
pDC->BitBlt(0, 0, iMinWidth, iMinHeight, &cDC, iLeft, iTop, SRCCOPY);
if (ppalOldDst) { pDC->SelectPalette(ppalOldDst, FALSE); } if (ppalOldSrc) { cDC.SelectPalette(ppalOldSrc, FALSE); }
cDC.Detach();
DrawTracker(pDC); }
/******************************************************************************/ /* basically the same processing as the imgwnd::drawtracker method, without */ /* the zoom */
void CThumbNailView::DrawTracker(CDC *pDC) { // BOOL bDrawTrackerRgn = FALSE;
if (m_pcImgWnd->GetCurrent() != m_pcImgWnd || theImgBrush.m_bMoveSel || theImgBrush.m_bSmearSel || theImgBrush.m_bMakingSelection) { // This is not the active view, or the user is doing something
// to prevent the tracker from appearing.
return; }
BOOL bReleaseDC = FALSE; CRect clientRect;
if (pDC == NULL) { pDC = GetDC();
if (pDC == NULL) { theApp.SetGdiEmergency(FALSE); return; } bReleaseDC = TRUE; }
GetClientRect(&clientRect);
CRect trackerRect;
m_pcImgWnd->GetImageRect(trackerRect);
trackerRect.InflateRect(CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE);
CTracker::EDGES edges = (CTracker::EDGES)(CTracker::right | CTracker::bottom);
// if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)
// {
// bDrawTrackerRgn = TRUE;
// }
if (m_pcImgWnd->m_pImg == theImgBrush.m_pImg) { edges = CTracker::all; CSize cSzScroll = m_pcImgWnd->GetScrollPos();
trackerRect = theImgBrush.m_rcSelection;
// trackerRect.InflateRect( CTracker::HANDLE_SIZE,
// CTracker::HANDLE_SIZE);
trackerRect.OffsetRect( cSzScroll.cx, cSzScroll.cy);
}
if (m_pcImgWnd->m_pImg == theImgBrush.m_pImg) { // if (bDrawTrackerRgn)
// {
// CTracker::DrawBorderRgn( pDC, trackerRect, &(theImgBrush.m_cRgnPolyFreeHandSel) );
// }
// else
// {
CTracker::DrawBorder( pDC, trackerRect ); // }
}
if (bReleaseDC) { ReleaseDC(pDC); } }
/******************************************************************************/ /* Basically Do a paint without an erase background to prevent blinking */
void CThumbNailView::RefreshImage(void) { if (theApp.m_bShowThumbnail) { TRY { CClientDC dc(this); DrawImage(&dc); } CATCH(CResourceException,e) { } END_CATCH } }
/******************************************************************************/
CImgWnd* CThumbNailView::GetImgWnd(void) { return m_pcImgWnd; }
/******************************************************************************/
void CThumbNailView::UpdateThumbNailView() { CPBView* pcbActiveView = (CPBView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView();
m_pcImgWnd = pcbActiveView->m_pImgWnd; }
/******************************************************************************/
void CThumbNailView::OnKeyDown(UINT /*nChar*/, UINT /*nRepCnt*/, UINT /*nFlags*/) { const MSG* pmsg = GetCurrentMessage();
GetParent()->SendMessage( pmsg->message, pmsg->wParam, pmsg->lParam ); }
/******************************************************************************/
void CThumbNailView::OnLButtonDown(UINT /*nFlags*/, CPoint /*point*/) { const MSG* pmsg = GetCurrentMessage();
GetParent()->SendMessage(pmsg->message, pmsg->wParam, pmsg->lParam); }
/******************************************************************************/
void CThumbNailView::OnRButtonDown(UINT /*nFlags*/, CPoint point) { HWND hwnd = GetSafeHwnd(); // must do this before calling SendMsg to parent, since it could delete us,
const MSG* pmsg = GetCurrentMessage();
GetParent()->SendMessage(pmsg->message, pmsg->wParam, pmsg->lParam); // the window is destroyed by the parent if FullScreenView
if (::IsWindow(hwnd) != FALSE) // window still exists => object still valid, put up pop up menu.
{ CMenu cMenuPopup; CMenu *pcContextMenu; BOOL bRC; CRect cRectClient;
GetClientRect(&cRectClient);
bRC = cMenuPopup.LoadMenu( IDR_THUMBNAIL_POPUP );
ASSERT(bRC != 0);
if (bRC != 0) { pcContextMenu = cMenuPopup.GetSubMenu(0);
ASSERT(pcContextMenu != NULL);
if (pcContextMenu != NULL) { // update the check marks
ClientToScreen(&point); ClientToScreen(&cRectClient); pcContextMenu->CheckMenuItem(ID_THUMBNAIL_THUMBNAIL, MF_BYCOMMAND | MF_CHECKED); pcContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this, &cRectClient); } } } }
/******************************************************************************/
void CThumbNailView::OnThumbnailThumbnail() { CPBView* pView = (CPBView*)(((CFrameWnd*)AfxGetMainWnd())->GetActiveView());
if (pView != NULL && pView->IsKindOf( RUNTIME_CLASS( CPBView ) )) pView->HideThumbNailView(); }
/******************************************************************************/
void CThumbNailView::OnUpdateThumbnailThumbnail(CCmdUI* pCmdUI) { pCmdUI->SetCheck(); }
/******************************************************************************/ /******************************************************************************/ /******************************************************************************/
BEGIN_MESSAGE_MAP(CFloatThumbNailView, CMiniFrmWnd) //{{AFX_MSG_MAP(CFloatThumbNailView)
ON_WM_CLOSE() ON_WM_SIZE() ON_WM_GETMINMAXINFO() //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/******************************************************************************/
CFloatThumbNailView::CFloatThumbNailView(CImgWnd *pcMainImgWnd) { m_pcThumbNailView = new CThumbNailView(pcMainImgWnd);
if (m_pcThumbNailView == NULL) { theApp.SetMemoryEmergency(); TRACE( TEXT("New Thumbnail View faild\n") ); } }
/******************************************************************************/
CFloatThumbNailView::CFloatThumbNailView() { m_pcThumbNailView = NULL; }
/******************************************************************************/
CFloatThumbNailView::~CFloatThumbNailView(void) { }
/******************************************************************************/
BOOL CFloatThumbNailView::Create(CWnd* pParentWnd) { BOOL bRC; CRect cWindowRect;
pParentWnd->GetWindowRect( &cWindowRect );
cWindowRect.BottomRight() = cWindowRect.TopLeft(); cWindowRect.right += 120; cWindowRect.bottom += 120; cWindowRect.OffsetRect( 15, 15 );
if (! theApp.m_rectFloatThumbnail.IsRectEmpty()) { cWindowRect = theApp.m_rectFloatThumbnail; }
CString pWindowName;
pWindowName.LoadString( IDS_VIEW );
bRC = CMiniFrmWnd::Create( pWindowName, WS_THICKFRAME, cWindowRect, pParentWnd );
if (bRC) { ASSERT( m_pcThumbNailView );
GetClientRect( &cWindowRect );
if (!m_pcThumbNailView->Create( WS_CHILD | WS_VISIBLE, cWindowRect, this )) { bRC = FALSE; theApp.SetMemoryEmergency(); TRACE( TEXT("New Thumbnail View faild\n") ); } }
GetWindowRect( &theApp.m_rectFloatThumbnail );
return bRC; }
/******************************************************************************/ // OnClose
//
// A Colorsbox is usally created by the parent, and will be destroyed
// specifically by the parent upon leaving the app. When the user closes
// the Colorsbox, it is simply hidden. The parent can then reshow it without
// recreating it.
//
void CFloatThumbNailView::OnClose() { theApp.m_bShowThumbnail = FALSE;
ShowWindow(SW_HIDE); }
/******************************************************************************/
void CFloatThumbNailView::PostNcDestroy() { if (m_pcThumbNailView != NULL) { delete m_pcThumbNailView; m_pcThumbNailView = NULL; }
CWnd::PostNcDestroy(); }
/******************************************************************************/
void CFloatThumbNailView::OnSize(UINT nType, int cx, int cy) { CMiniFrmWnd::OnSize(nType, cx, cy);
if (m_pcThumbNailView != NULL && m_pcThumbNailView->GetSafeHwnd() != NULL) { m_pcThumbNailView->SetWindowPos( &wndTop, 0, 0, cx, cy, SWP_NOACTIVATE ); }
theApp.m_rectFloatThumbnail.right = theApp.m_rectFloatThumbnail.left + cx; theApp.m_rectFloatThumbnail.bottom = theApp.m_rectFloatThumbnail.top + cy; }
/******************************************************************************/
void CFloatThumbNailView::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { lpMMI->ptMinTrackSize.x = 2 * GetSystemMetrics( SM_CXICON ); lpMMI->ptMinTrackSize.y = 2 * GetSystemMetrics( SM_CYICON );
CWnd::OnGetMinMaxInfo( lpMMI ); }
/******************************************************************************/ /******************************************************************************/ /******************************************************************************/
BEGIN_MESSAGE_MAP(CFullScreenThumbNailView, CFrameWnd) //{{AFX_MSG_MAP(CFullScreenThumbNailView)
ON_WM_LBUTTONDOWN() ON_WM_KEYDOWN() ON_WM_RBUTTONDOWN() ON_WM_ERASEBKGND() ON_WM_CLOSE() //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/******************************************************************************/
CFullScreenThumbNailView::CFullScreenThumbNailView(CImgWnd *pcMainImgWnd) { m_bSaveShowFlag = theApp.m_bShowThumbnail; theApp.m_bShowThumbnail = TRUE;
// m_brBackground.CreateSolidBrush( ::GetSysColor( COLOR_BACKGROUND ) );
m_pcThumbNailView = new CThumbNailView(pcMainImgWnd);
if (m_pcThumbNailView == NULL) { theApp.SetMemoryEmergency(); TRACE( TEXT("New Thumbnail View faild\n") ); } }
/******************************************************************************/
CFullScreenThumbNailView::CFullScreenThumbNailView() { m_hOldIcon = 0; m_pcThumbNailView = NULL; }
/******************************************************************************/
CFullScreenThumbNailView::~CFullScreenThumbNailView(void) { if (m_hOldIcon) { SetClassLongPtr (((CFrameWnd*)this)->GetSafeHwnd(), GCLP_HICON, (LONG_PTR)m_hOldIcon); } if (m_pcThumbNailView != NULL) { delete m_pcThumbNailView;
theApp.m_bShowThumbnail = m_bSaveShowFlag; } // if (m_brBackground.m_hObject != NULL)
// m_brBackground.DeleteObject();
}
/******************************************************************************/
BOOL CFullScreenThumbNailView::Create(LPCTSTR szCaption) { ASSERT( m_pcThumbNailView ); TCHAR szFileName[MAX_PATH]; HICON hIcon;
CRect cWindowRect( 0, 0, ::GetSystemMetrics( SM_CXSCREEN ), ::GetSystemMetrics( SM_CYSCREEN ) ); //
// Use the current file name as the caption of the window so
// it shows up in alt-tab
if (szCaption && *szCaption) { GetFileTitle (szCaption, szFileName, MAX_PATH); } else { LoadString (GetModuleHandle (NULL), AFX_IDS_UNTITLED, szFileName, MAX_PATH); }
BOOL bRC = CFrameWnd::Create( NULL, szFileName, WS_POPUP|WS_VISIBLE | WS_CLIPCHILDREN, cWindowRect ); //
// This window needs a Paint icon instead of a boring icon
// So set the class's icon to the Paint icon
// We want alt-tab to work decently
hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE(ID_MAINFRAME)); m_hOldIcon = SetClassLongPtr (((CFrameWnd*)this)->GetSafeHwnd(), GCLP_HICON, (LONG_PTR)hIcon);
if (bRC) { ASSERT( m_pcThumbNailView );
AfxGetMainWnd()->EnableWindow( FALSE );
CImgWnd* pcImgWnd = m_pcThumbNailView->GetImgWnd();
if (pcImgWnd != NULL) { // find the smaller of the two the real image or the full screen window size.
int iMinWidth = min( cWindowRect.Width(), pcImgWnd->m_pImg->cxWidth ); int iMinHeight = min( cWindowRect.Height(), pcImgWnd->m_pImg->cyHeight );
// center the image in the full screen window.
cWindowRect.left = (cWindowRect.Width() - iMinWidth) / 2; cWindowRect.top = (cWindowRect.Height() - iMinHeight) / 2; cWindowRect.right = cWindowRect.left + iMinWidth; cWindowRect.bottom = cWindowRect.top + iMinHeight;
m_pcThumbNailView->Create( WS_CHILD | WS_VISIBLE, cWindowRect, this ); } }
return bRC; }
/******************************************************************************/
BOOL CFullScreenThumbNailView::OnEraseBkgnd( CDC* pDC ) { CBrush* pbr = GetSysBrush( COLOR_BACKGROUND );
// if (m_brBackground.m_hObject == NULL)
if (! pbr) return CFrameWnd::OnEraseBkgnd( pDC );
CRect cRectClient;
GetClientRect( &cRectClient ); pDC->FillRect( &cRectClient, pbr /* &m_brBackground */ );
return TRUE; }
/******************************************************************************/ void CFullScreenThumbNailView::OnLButtonDown(UINT /*nFlags*/, CPoint /*point*/) { PostMessage (WM_CLOSE, 0, 0); }
/******************************************************************************/
void CFullScreenThumbNailView::OnKeyDown(UINT /*nChar*/, UINT /*nRepCnt*/, UINT /*nFlags*/) { PostMessage (WM_CLOSE, 0, 0); }
/******************************************************************************/
void CFullScreenThumbNailView::OnClose () { AfxGetMainWnd()->EnableWindow( TRUE ); ::DestroyWindow( m_hWnd ); } /******************************************************************************/
|