1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "PreviewCtrl.hxx"
22 #include <osl/diagnose.h>
25 #pragma warning(push, 1)
34 #define PREVIEWWND_CLASS_NAME TEXT("PreviewWnd###")
36 #define HIMETRIC_INCH 2540
38 // means 3 pixel left and 3 pixel right
39 #define HORZ_BODER_SPACE 6
41 // means 3 pixel top and 3 pixel bottom
42 #define VERT_BORDER_SPACE 6
44 //---------------------------------------------------
45 // static member initialization
46 //---------------------------------------------------
48 CFilePreview
* CFilePreview::s_FilePreviewInst
= NULL
;
49 CFilePreview::FILEPREVIEW_SINGLETON_DESTROYER_T
CFilePreview::s_SingletonDestroyer
;
51 //---------------------------------------------------
52 // some useful helper functions
53 //---------------------------------------------------
57 class CPreviewException
59 // used when registering or creation
60 // of the preview window failed
63 //------------------------------------------------------------
65 //------------------------------------------------------------
68 sal_Int32
SubDiv( sal_Int32 nNumber
, sal_Int32 nMinuend
, sal_Int32 nDenominator
)
70 return ( static_cast<sal_Int32
>( ( nNumber
- nMinuend
) / nDenominator
) );
73 //------------------------------------------------------------
74 // convert himetric to pixel
75 //------------------------------------------------------------
78 sal_Int32
Himetric2Pixel( HDC hDC
, sal_Int32 hmSize
, sal_Int32 nIndex
)
80 return MulDiv( hmSize
, GetDeviceCaps( hDC
, nIndex
), HIMETRIC_INCH
);
83 //------------------------------------------------------------
85 //------------------------------------------------------------
88 sal_uInt32
_getWidthRect( const RECT
& aRect
)
90 return ( aRect
.right
- aRect
.left
);
93 //------------------------------------------------------------
95 //------------------------------------------------------------
98 sal_uInt32
_getHeightRect( const RECT
& aRect
)
100 return ( aRect
.bottom
- aRect
.top
);
103 //------------------------------------------------------------
104 // calc the upper left corner so that a given window will be
105 // displayed centered within the given window
106 //------------------------------------------------------------
109 POINT
_calcULCorner( HWND hwnd
, const CDimension
& aPicSize
)
112 GetClientRect( hwnd
, &rect
);
114 sal_Int32 nWidthWnd
= _getWidthRect( rect
);
115 sal_Int32 nHeightWnd
= _getHeightRect( rect
);
118 ulCorner
.x
= SubDiv( nWidthWnd
, aPicSize
.m_cx
, 2 );
119 ulCorner
.y
= SubDiv( nHeightWnd
, aPicSize
.m_cy
, 2 );
124 //------------------------------------------------------------
125 // test if a picture with the given dimensions fits into an
127 // we expect the width and height to be in pixel
128 //------------------------------------------------------------
131 sal_Bool
_pictureSizeFitsWindowSize( HWND hwnd
, const CDimension
& aPicSize
)
134 GetClientRect( hwnd
, &rect
);
136 sal_Int32 nWidthWnd
= _getWidthRect( rect
);
137 sal_Int32 nHeightWnd
= _getHeightRect( rect
);
139 return ( ( ( nWidthWnd
- HORZ_BODER_SPACE
) >= aPicSize
.m_cx
) &&
140 ( ( nHeightWnd
- VERT_BORDER_SPACE
) >= aPicSize
.m_cy
) );
143 //------------------------------------------------------------
144 // calc the dimemsions so that a given picture fits into a
145 // given window, if the picture fits into the given window
146 // the original CDimension will be returned
147 //------------------------------------------------------------
150 CDimension
_scalePictureSize( HWND hwnd
, const CDimension
& aPicSize
)
152 CDimension scaledPicSize
= aPicSize
;
154 if ( !_pictureSizeFitsWindowSize( hwnd
, aPicSize
) )
157 GetClientRect( hwnd
, &rect
);
159 // the dimensions of the preview wnd are not equal
160 // that's why we equalize it
161 sal_Int32 nHeightWnd
= _getHeightRect( rect
) - VERT_BORDER_SPACE
;
162 sal_Int32 nWidthWnd
= nHeightWnd
;
164 if ( aPicSize
.m_cx
>= aPicSize
.m_cy
)
166 scaledPicSize
.m_cx
= nWidthWnd
;
168 static_cast< sal_Int32
>(
169 aPicSize
.m_cy
* nWidthWnd
/ aPicSize
.m_cx
);
174 static_cast< sal_Int32
>(
175 aPicSize
.m_cx
* nHeightWnd
/ aPicSize
.m_cy
);
176 scaledPicSize
.m_cy
= nHeightWnd
;
180 return scaledPicSize
;
186 //---------------------------------------------------
187 // to ensure only one instance (singleton)
188 //---------------------------------------------------
190 CFilePreview
* CFilePreview::createInstance(
193 const CDimension
& aSize
,
198 if ( !s_FilePreviewInst
)
202 s_FilePreviewInst
= new CFilePreview(
203 aParent
, ulCorner
, aSize
, hInstance
, bShow
, bEnabled
);
204 s_SingletonDestroyer
.reset( s_FilePreviewInst
);
206 catch( CPreviewException
& )
208 OSL_ASSERT( !s_FilePreviewInst
);
209 OSL_FAIL( "Creation of the preview window failed" );
211 catch( CAutoOleInit::COleInitException
& )
213 OSL_ASSERT( !s_FilePreviewInst
);
214 OSL_FAIL( "OleInitalize failed" );
218 return s_FilePreviewInst
;
221 //---------------------------------------------------
223 //---------------------------------------------------
225 CFilePreview::CFilePreview(
228 const CDimension
& aSize
,
231 sal_Bool bEnabled
) :
232 m_hInstance( hInstance
),
233 m_bEnabled( bEnabled
)
235 // register the preview window class
237 ZeroMemory(&wndClsEx
, sizeof(wndClsEx
));
239 wndClsEx
.cbSize
= sizeof(wndClsEx
);
240 wndClsEx
.style
= CS_HREDRAW
| CS_VREDRAW
;
241 wndClsEx
.lpfnWndProc
= CFilePreview::WndProc
;
242 wndClsEx
.hInstance
= m_hInstance
;
243 wndClsEx
.hbrBackground
= (HBRUSH
)( COLOR_INACTIVEBORDER
+ 1 );
244 wndClsEx
.lpszClassName
= PREVIEWWND_CLASS_NAME
;
246 // register the preview window class
247 // !!! Win95 - the window class will be unregistered automaticly
248 // if the dll is unloaded
249 // Win2000 - the window class must be unregistered manually
250 // if the dll is unloaded
251 m_atomPrevWndClass
= RegisterClassEx(&wndClsEx
);
252 if ( !m_atomPrevWndClass
)
253 throw CPreviewException( );
255 // create the preview window in invisible state
256 sal_uInt32 dwStyle
= bShow
? (WS_CHILD
| WS_VISIBLE
) : WS_CHILD
;
257 m_hwnd
= CreateWindowEx(
259 PREVIEWWND_CLASS_NAME
,
267 (HMENU
)100, // for child windows this will
268 // be used as child window identifier
271 if (!IsWindow(m_hwnd
))
272 throw CPreviewException( );
275 //---------------------------------------------------
277 //---------------------------------------------------
279 CFilePreview::~CFilePreview( )
281 // unregister preview window class
282 sal_Bool bRet
= UnregisterClass(
283 (LPCTSTR
)MAKELONG( m_atomPrevWndClass
, 0 ),
285 OSL_POSTCOND( bRet
, "Unregister preview window class failed" );
288 //---------------------------------------------------
289 // sets the size of the preview window
290 //---------------------------------------------------
292 sal_Bool SAL_CALL
CFilePreview::setSize( const CDimension
& aSize
)
294 OSL_PRECOND( IsWindow( m_hwnd
), "Preview window not initialized" );
296 // resize the fileopen file listbox
304 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
307 //---------------------------------------------------
308 // returns the dimension of the preview
309 //---------------------------------------------------
311 sal_Bool SAL_CALL
CFilePreview::getSize( CDimension
& theSize
) const
313 OSL_PRECOND( IsWindow( m_hwnd
), "Preview window not initialized" );
316 sal_Bool bRet
= GetWindowRect( m_hwnd
, &rect
);
318 theSize
.m_cx
= _getWidthRect( rect
);
319 theSize
.m_cy
= _getHeightRect( rect
);
324 //---------------------------------------------------
325 // sets the position of the upper left corner
326 // of the preview window relative to the
327 // upper left corner of the parent window
328 //---------------------------------------------------
330 sal_Bool SAL_CALL
CFilePreview::setPos( POINT ulCorner
)
332 OSL_PRECOND( IsWindow( m_hwnd
), "Preview window not initialized" );
334 // resize the fileopen file listbox
342 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
345 //---------------------------------------------------
346 // returns the current position of the preview
347 // relative to the upper left corner of the
349 //---------------------------------------------------
351 sal_Bool SAL_CALL
CFilePreview::getPos( POINT
& ulCorner
) const
353 OSL_PRECOND( IsWindow( m_hwnd
), "Preview window not initialized" );
358 sal_Bool bRet
= GetWindowRect( m_hwnd
, &rect
);
360 ulCorner
.x
= rect
.left
;
361 ulCorner
.y
= rect
.top
;
363 ScreenToClient( m_hwnd
, &ulCorner
);
368 //---------------------------------------------------
370 //---------------------------------------------------
372 void SAL_CALL
CFilePreview::enable( sal_Bool bEnable
)
374 m_bEnabled
= bEnable
;
377 InvalidateRect( m_hwnd
, NULL
, sal_True
);
378 UpdateWindow( m_hwnd
);
381 //---------------------------------------------------
382 // shows the preview window
383 // possible values see SHOW_STATE
384 // SS_SHOW - make the window visible
385 // SS_HIDE - hide the window
386 // SS_ENABLED - enable the window
387 // SS_DISABLED - disable the window
388 //---------------------------------------------------
390 sal_Bool SAL_CALL
CFilePreview::show( sal_Bool bShow
)
392 OSL_PRECOND( IsWindow( m_hwnd
), "Preview window not initialized" );
394 sal_Int32 showState
= bShow
? SW_SHOW
: SW_HIDE
;
395 return ShowWindow( m_hwnd
, showState
);
398 //---------------------------------------------------
399 // if the preview is shown and enabled
400 // preview of the given file will be shown
401 // returns true on success or false if an error
402 // occurred (the file in not there or not accessible etc.)
403 //---------------------------------------------------
405 sal_Bool SAL_CALL
CFilePreview::update( const OUString
& aFileName
)
407 OSL_PRECOND( IsWindow( m_hwnd
), "Preview window not initialized" );
414 m_IPicture
.Release( );
416 loadFile( aFileName
);
418 // force a complete window redraw
419 InvalidateRect( m_hwnd
, NULL
, sal_True
);
420 UpdateWindow( m_hwnd
);
430 //---------------------------------------------------
432 //---------------------------------------------------
434 void SAL_CALL
CFilePreview::onPaint( HWND hWnd
, HDC hDC
)
436 OSL_PRECOND( IsWindow( m_hwnd
), "Preview window not initialized" );
442 // get width and height of picture
446 m_IPicture
->get_Width( &cxPicHIMETRIC
);
447 m_IPicture
->get_Height( &cyPicHIMETRIC
);
449 // convert himetric to pixels
450 int cxPicPIXEL
= Himetric2Pixel( hDC
, cxPicHIMETRIC
, LOGPIXELSX
);
451 int cyPicPIXEL
= Himetric2Pixel( hDC
, cyPicHIMETRIC
, LOGPIXELSY
);
453 // scale the picture based on the size of the preview window
455 GetClientRect(hWnd
, &rcPrevWnd
);
457 CDimension scaledPicSize
= _scalePictureSize(
458 hWnd
, CDimension( cxPicPIXEL
, cyPicPIXEL
) );
460 // calc the upper left corner so that the picture
461 // is centered within the window
462 POINT ulCorner
= _calcULCorner( hWnd
, scaledPicSize
);
464 // render the picture
465 HRESULT hr
= m_IPicture
->Render(
476 } // end if ( m_bEnabled )
483 //---------------------------------------------------
485 //---------------------------------------------------
487 sal_Bool
CFilePreview::loadFile( const OUString
& aFileName
)
495 sal_uInt32 nBytesRead
;
507 if ( INVALID_HANDLE_VALUE
== hFile
)
508 goto CLEANUP_AND_EXIT
;
511 fsize
= GetFileSize( hFile
, &fszExtra
);
513 // empty file, error or file to big
514 if ( -1 == fsize
|| 0 == fsize
|| fszExtra
)
515 goto CLEANUP_AND_EXIT
;
517 hGlobal
= GlobalAlloc( GMEM_MOVEABLE
, fsize
);
519 goto CLEANUP_AND_EXIT
;
521 pData
= GlobalLock( hGlobal
);
523 goto CLEANUP_AND_EXIT
;
526 hFile
, pData
, fsize
, &nBytesRead
, NULL
);
529 goto CLEANUP_AND_EXIT
;
531 hr
= CreateStreamOnHGlobal(
532 hGlobal
, sal_False
, &pIStream
);
534 if ( SUCCEEDED( hr
) )
537 pIStream
, fsize
, sal_False
,
538 __uuidof( IPicture
), (LPVOID
*)&m_IPicture
);
543 CloseHandle( hFile
);
546 GlobalUnlock( hGlobal
);
549 GlobalFree( hGlobal
);
551 return ( SUCCEEDED( hr
) );
554 //---------------------------------------------------
556 //---------------------------------------------------
558 LRESULT CALLBACK
CFilePreview::WndProc(
559 HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
567 OSL_PRECOND( s_FilePreviewInst
, "Static member not initialized" );
572 hDC
= BeginPaint( hWnd
, &ps
);
573 s_FilePreviewInst
->onPaint( hWnd
, hDC
);
574 EndPaint( hWnd
, &ps
);
578 // under windows 95/98 the creation of the
579 // hidden target request window fails if
580 // we don't handle this message ourself
581 // because the DefWindowProc returns 0 as
582 // a result of handling WM_NCCREATE what
583 // leads to a failure of CreateWindow[Ex]!!!
589 return DefWindowProc( hWnd
, uMsg
, wParam
, lParam
);
597 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */