| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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; |
| } |
| |
| |
| |