diff options
Diffstat (limited to 'fpicker/source/win32/filepicker/PreviewCtrl.cxx')
-rw-r--r-- | fpicker/source/win32/filepicker/PreviewCtrl.cxx | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/fpicker/source/win32/filepicker/PreviewCtrl.cxx b/fpicker/source/win32/filepicker/PreviewCtrl.cxx new file mode 100644 index 000000000000..e387d672fd41 --- /dev/null +++ b/fpicker/source/win32/filepicker/PreviewCtrl.cxx @@ -0,0 +1,615 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include <tchar.h> +#include "PreviewCtrl.hxx" +#include <osl/diagnose.h> + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <ocidl.h> +#include <olectl.h> + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +#define PREVIEWWND_CLASS_NAME TEXT("PreviewWnd###") + +#define HIMETRIC_INCH 2540 + +// means 3 pixel left and 3 pixel right +#define HORZ_BODER_SPACE 6 + +// means 3 pixel top and 3 pixel bottom +#define VERT_BORDER_SPACE 6 + +//--------------------------------------------------- +// static member initialization +//--------------------------------------------------- + +CFilePreview* CFilePreview::s_FilePreviewInst = NULL; +CFilePreview::FILEPREVIEW_SINGLETON_DESTROYER_T CFilePreview::s_SingletonDestroyer; + +//--------------------------------------------------- +// some useful helper functions +//--------------------------------------------------- + +namespace // private +{ + class CPreviewException + { + // used when registering or creation + // of the preview window failed + }; + + //------------------------------------------------------------ + // + //------------------------------------------------------------ + + inline + sal_Int32 SubDiv( sal_Int32 nNumber, sal_Int32 nMinuend, sal_Int32 nDenominator ) + { + return ( static_cast<sal_Int32>( ( nNumber - nMinuend ) / nDenominator ) ); + } + + //------------------------------------------------------------ + // convert himetric to pixel + //------------------------------------------------------------ + + inline + sal_Int32 Himetric2Pixel( HDC hDC, sal_Int32 hmSize, sal_Int32 nIndex ) + { + return MulDiv( hmSize, GetDeviceCaps( hDC, nIndex), HIMETRIC_INCH ); + } + + //------------------------------------------------------------ + // + //------------------------------------------------------------ + + inline + sal_uInt32 _getWidthRect( const RECT& aRect ) + { + return ( aRect.right - aRect.left ); + } + + //------------------------------------------------------------ + // + //------------------------------------------------------------ + + inline + sal_uInt32 _getHeightRect( const RECT& aRect ) + { + return ( aRect.bottom - aRect.top ); + } + + //------------------------------------------------------------ + // calc the upper left corner so that a given window will be + // displayed centered within the given window + //------------------------------------------------------------ + + inline + POINT _calcULCorner( HWND hwnd, const CDimension& aPicSize ) + { + RECT rect; + GetClientRect( hwnd, &rect ); + + sal_Int32 nWidthWnd = _getWidthRect( rect ); + sal_Int32 nHeightWnd = _getHeightRect( rect ); + + POINT ulCorner; + ulCorner.x = SubDiv( nWidthWnd, aPicSize.m_cx, 2 ); + ulCorner.y = SubDiv( nHeightWnd, aPicSize.m_cy, 2 ); + + return ulCorner; + } + + //------------------------------------------------------------ + // test if a picture with the given dimensions fits into an + // arbitrary window + // we expect the width and height to be in pixel + //------------------------------------------------------------ + + inline + sal_Bool _pictureSizeFitsWindowSize( HWND hwnd, const CDimension& aPicSize ) + { + RECT rect; + GetClientRect( hwnd, &rect ); + + sal_Int32 nWidthWnd = _getWidthRect( rect ); + sal_Int32 nHeightWnd = _getHeightRect( rect ); + + return ( ( ( nWidthWnd - HORZ_BODER_SPACE ) >= aPicSize.m_cx ) && + ( ( nHeightWnd - VERT_BORDER_SPACE ) >= aPicSize.m_cy ) ); + } + + //------------------------------------------------------------ + // calc the dimemsions so that a given picture fits into a + // given window, if the picture fits into the given window + // the original CDimension will be returned + //------------------------------------------------------------ + + inline + CDimension _scalePictureSize( HWND hwnd, const CDimension& aPicSize ) + { + CDimension scaledPicSize = aPicSize; + + if ( !_pictureSizeFitsWindowSize( hwnd, aPicSize ) ) + { + RECT rect; + GetClientRect( hwnd, &rect ); + + // the dimensions of the preview wnd are not equal + // that's why we equalize it + sal_Int32 nHeightWnd = _getHeightRect( rect ) - VERT_BORDER_SPACE; + sal_Int32 nWidthWnd = nHeightWnd; + + if ( aPicSize.m_cx >= aPicSize.m_cy ) + { + scaledPicSize.m_cx = nWidthWnd; + scaledPicSize.m_cy = + static_cast< sal_Int32 >( + aPicSize.m_cy * nWidthWnd / aPicSize.m_cx ); + } + else + { + scaledPicSize.m_cx = + static_cast< sal_Int32 >( + aPicSize.m_cx * nHeightWnd / aPicSize.m_cy ); + scaledPicSize.m_cy = nHeightWnd; + } + } + + return scaledPicSize; + } + +} // end namespace + + +//--------------------------------------------------- +// to ensure only one instance (singleton) +//--------------------------------------------------- + +CFilePreview* CFilePreview::createInstance( + HWND aParent, + POINT ulCorner, + const CDimension& aSize, + HINSTANCE hInstance, + sal_Bool bShow, + sal_Bool bEnabled ) +{ + if ( !s_FilePreviewInst ) + { + try + { + s_FilePreviewInst = new CFilePreview( + aParent, ulCorner, aSize, hInstance, bShow, bEnabled ); + s_SingletonDestroyer.reset( s_FilePreviewInst ); + } + catch( CPreviewException& ) + { + OSL_ASSERT( !s_FilePreviewInst ); + OSL_ENSURE( sal_False, "Creation of the preview window failed" ); + } + catch( CAutoOleInit::COleInitException& ) + { + OSL_ASSERT( !s_FilePreviewInst ); + OSL_ENSURE( sal_False, "OleInitalize failed" ); + } + } + + return s_FilePreviewInst; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +CFilePreview::CFilePreview( + HWND aParent, + POINT ulCorner, + const CDimension& aSize, + HINSTANCE hInstance, + sal_Bool bShow, + sal_Bool bEnabled ) : + m_hInstance( hInstance ), + m_bEnabled( bEnabled ) +{ + // register the preview window class + WNDCLASSEX wndClsEx; + ZeroMemory(&wndClsEx, sizeof(wndClsEx)); + + wndClsEx.cbSize = sizeof(wndClsEx); + wndClsEx.style = CS_HREDRAW | CS_VREDRAW; + wndClsEx.lpfnWndProc = CFilePreview::WndProc; + wndClsEx.hInstance = m_hInstance; + wndClsEx.hbrBackground = (HBRUSH)( COLOR_INACTIVEBORDER + 1 ); + wndClsEx.lpszClassName = PREVIEWWND_CLASS_NAME; + + // register the preview window class + // !!! Win95 - the window class will be unregistered automaticly + // if the dll is unloaded + // Win2000 - the window class must be unregistered manually + // if the dll is unloaded + m_atomPrevWndClass = RegisterClassEx(&wndClsEx); + if ( !m_atomPrevWndClass ) + throw CPreviewException( ); + + // create the preview window in invisible state + sal_uInt32 dwStyle = bShow ? (WS_CHILD | WS_VISIBLE) : WS_CHILD; + m_hwnd = CreateWindowEx( + WS_EX_CLIENTEDGE, + PREVIEWWND_CLASS_NAME, + TEXT(""), + dwStyle, + ulCorner.x, + ulCorner.y, + aSize.m_cx, + aSize.m_cy, + aParent, + (HMENU)100, // for child windows this will + // be used as child window identifier + m_hInstance, + 0 ); + if (!IsWindow(m_hwnd)) + throw CPreviewException( ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +CFilePreview::~CFilePreview( ) +{ + // unregister preview window class + sal_Bool bRet = UnregisterClass( + (LPCTSTR)MAKELONG( m_atomPrevWndClass, 0 ), + m_hInstance ); + OSL_POSTCOND( bRet, "Unregister preview window class failed" ); +} + +//--------------------------------------------------- +// sets the size of the preview window +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::setSize( const CDimension& aSize ) +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + // resize the fileopen file listbox + return SetWindowPos( + m_hwnd, + NULL, + 0, + 0, + aSize.m_cx, + aSize.m_cy, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); +} + +//--------------------------------------------------- +// returns the dimension of the preview +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::getSize( CDimension& theSize ) const +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + RECT rect; + sal_Bool bRet = GetWindowRect( m_hwnd, &rect ); + + theSize.m_cx = _getWidthRect( rect ); + theSize.m_cy = _getHeightRect( rect ); + + return bRet; +} + +//--------------------------------------------------- +// sets the position of the upper left corner +// of the preview window relative to the +// upper left corner of the parent window +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::setPos( POINT ulCorner ) +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + // resize the fileopen file listbox + return SetWindowPos( + m_hwnd, + NULL, + ulCorner.x, + ulCorner.y, + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); +} + +//--------------------------------------------------- +// returns the current position of the preview +// relative to the upper left corner of the +// parent window +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::getPos( POINT& ulCorner ) const +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + POINT pt = { 0, 0 }; + RECT rect; + + sal_Bool bRet = GetWindowRect( m_hwnd, &rect ); + + ulCorner.x = rect.left; + ulCorner.y = rect.top; + + ScreenToClient( m_hwnd, &ulCorner ); + + return bRet; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CFilePreview::enable( sal_Bool bEnable ) +{ + m_bEnabled = bEnable; + + // force a redraw + InvalidateRect( m_hwnd, NULL, sal_True ); + UpdateWindow( m_hwnd ); +} + +//--------------------------------------------------- +// shows the preview window +// possible values see SHOW_STATE +// SS_SHOW - make the window visible +// SS_HIDE - hide the window +// SS_ENABLED - enable the window +// SS_DISABLED - disable the window +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::show( sal_Bool bShow ) +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + sal_Int32 showState = bShow ? SW_SHOW : SW_HIDE; + return ShowWindow( m_hwnd, showState ); +} + +//--------------------------------------------------- +// if the preview is shown and enabled +// preview of the given file will be shown +// returns true on success or false if an error +// occured (the file in not there or not accessible etc.) +//--------------------------------------------------- + +sal_Bool SAL_CALL CFilePreview::update( const rtl::OUString& aFileName ) +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + try + { + if ( m_bEnabled ) + { + if ( m_IPicture ) + m_IPicture.Release( ); + + loadFile( aFileName ); + + // force a complete window redraw + InvalidateRect( m_hwnd, NULL, sal_True ); + UpdateWindow( m_hwnd ); + } + } + catch( _com_error& ) + { + } + + return sal_True; +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +void SAL_CALL CFilePreview::onPaint( HWND hWnd, HDC hDC ) +{ + OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); + + try + { + if ( m_bEnabled ) + { + // get width and height of picture + long cxPicHIMETRIC; + long cyPicHIMETRIC; + + m_IPicture->get_Width( &cxPicHIMETRIC ); + m_IPicture->get_Height( &cyPicHIMETRIC ); + + // convert himetric to pixels + int cxPicPIXEL = Himetric2Pixel( hDC, cxPicHIMETRIC, LOGPIXELSX ); + int cyPicPIXEL = Himetric2Pixel( hDC, cyPicHIMETRIC, LOGPIXELSY ); + + // scale the picture based on the size of the preview window + RECT rcPrevWnd; + GetClientRect(hWnd, &rcPrevWnd); + + CDimension scaledPicSize = _scalePictureSize( + hWnd, CDimension( cxPicPIXEL, cyPicPIXEL ) ); + + // calc the upper left corner so that the picture + // is centered within the window + POINT ulCorner = _calcULCorner( hWnd, scaledPicSize ); + + // render the picture + HRESULT hr = m_IPicture->Render( + hDC, + ulCorner.x, + ulCorner.y, + scaledPicSize.m_cx, + scaledPicSize.m_cy, + 0, + cyPicHIMETRIC, + cxPicHIMETRIC, + -cyPicHIMETRIC, + &rcPrevWnd ); + } // end if ( m_bEnabled ) + } + catch( _com_error& ) + { + } +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +sal_Bool CFilePreview::loadFile( const rtl::OUString& aFileName ) +{ + HANDLE hFile = 0; + HGLOBAL hGlobal = 0; + LPVOID pData = NULL; + IStreamPtr pIStream; + HRESULT hr = E_FAIL; + sal_Bool bRet; + sal_uInt32 nBytesRead; + sal_uInt32 fszExtra; + sal_uInt32 fsize; + + hFile = CreateFile( + aFileName.getStr( ), + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL ); + if ( INVALID_HANDLE_VALUE == hFile ) + goto CLEANUP_AND_EXIT; + + fszExtra = 0; + fsize = GetFileSize( hFile, &fszExtra ); + + // empty file, error or file to big + if ( -1 == fsize || 0 == fsize || fszExtra ) + goto CLEANUP_AND_EXIT; + + hGlobal = GlobalAlloc( GMEM_MOVEABLE, fsize ); + if ( !hGlobal ) + goto CLEANUP_AND_EXIT; + + pData = GlobalLock( hGlobal ); + if ( !pData ) + goto CLEANUP_AND_EXIT; + + bRet = ReadFile( + hFile, pData, fsize, &nBytesRead, NULL ); + + if ( !bRet ) + goto CLEANUP_AND_EXIT; + + hr = CreateStreamOnHGlobal( + hGlobal, sal_False, &pIStream ); + + if ( SUCCEEDED( hr ) ) + { + hr = OleLoadPicture( + pIStream, fsize, sal_False, + __uuidof( IPicture ), (LPVOID*)&m_IPicture ); + } + +CLEANUP_AND_EXIT: + if ( hFile ) + CloseHandle( hFile ); + + if ( pData ) + GlobalUnlock( hGlobal ); + + if ( hGlobal ) + GlobalFree( hGlobal ); + + return ( SUCCEEDED( hr ) ); +} + +//--------------------------------------------------- +// +//--------------------------------------------------- + +LRESULT CALLBACK CFilePreview::WndProc( + HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + LRESULT lResult = 0; + + switch( uMsg ) + { + case WM_PAINT: + { + OSL_PRECOND( s_FilePreviewInst, "Static member not initialized" ); + + HDC hDC; + PAINTSTRUCT ps; + + hDC = BeginPaint( hWnd, &ps ); + s_FilePreviewInst->onPaint( hWnd, hDC ); + EndPaint( hWnd, &ps ); + } + break; + + // under windows 95/98 the creation of the + // hidden target request window fails if + // we don't handle this message ourself + // because the DefWindowProc returns 0 as + // a result of handling WM_NCCREATE what + // leads to a failure of CreateWindow[Ex]!!! + case WM_NCCREATE: + lResult = sal_True; + break; + + default: + return DefWindowProc( hWnd, uMsg, wParam, lParam ); + } + + return lResult; +} + + + |