summaryrefslogtreecommitdiff
path: root/fpicker/source/win32/filepicker/PreviewCtrl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'fpicker/source/win32/filepicker/PreviewCtrl.cxx')
-rw-r--r--fpicker/source/win32/filepicker/PreviewCtrl.cxx615
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;
+}
+
+
+