merged tag ooo/DEV300_m102
[LibreOffice.git] / fpicker / source / win32 / filepicker / PreviewCtrl.cxx
blobe387d672fd419b3456dc1345aa80475bb773cd80
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_fpicker.hxx"
31 //------------------------------------------------------------------------
32 // includes
33 //------------------------------------------------------------------------
35 #include <tchar.h>
36 #include "PreviewCtrl.hxx"
37 #include <osl/diagnose.h>
39 #if defined _MSC_VER
40 #pragma warning(push, 1)
41 #endif
42 #include <windows.h>
43 #if defined _MSC_VER
44 #pragma warning(pop)
45 #endif
46 #include <ocidl.h>
47 #include <olectl.h>
49 //------------------------------------------------------------------------
50 // defines
51 //------------------------------------------------------------------------
53 #define PREVIEWWND_CLASS_NAME TEXT("PreviewWnd###")
55 #define HIMETRIC_INCH 2540
57 // means 3 pixel left and 3 pixel right
58 #define HORZ_BODER_SPACE 6
60 // means 3 pixel top and 3 pixel bottom
61 #define VERT_BORDER_SPACE 6
63 //---------------------------------------------------
64 // static member initialization
65 //---------------------------------------------------
67 CFilePreview* CFilePreview::s_FilePreviewInst = NULL;
68 CFilePreview::FILEPREVIEW_SINGLETON_DESTROYER_T CFilePreview::s_SingletonDestroyer;
70 //---------------------------------------------------
71 // some useful helper functions
72 //---------------------------------------------------
74 namespace // private
76 class CPreviewException
78 // used when registering or creation
79 // of the preview window failed
82 //------------------------------------------------------------
84 //------------------------------------------------------------
86 inline
87 sal_Int32 SubDiv( sal_Int32 nNumber, sal_Int32 nMinuend, sal_Int32 nDenominator )
89 return ( static_cast<sal_Int32>( ( nNumber - nMinuend ) / nDenominator ) );
92 //------------------------------------------------------------
93 // convert himetric to pixel
94 //------------------------------------------------------------
96 inline
97 sal_Int32 Himetric2Pixel( HDC hDC, sal_Int32 hmSize, sal_Int32 nIndex )
99 return MulDiv( hmSize, GetDeviceCaps( hDC, nIndex), HIMETRIC_INCH );
102 //------------------------------------------------------------
104 //------------------------------------------------------------
106 inline
107 sal_uInt32 _getWidthRect( const RECT& aRect )
109 return ( aRect.right - aRect.left );
112 //------------------------------------------------------------
114 //------------------------------------------------------------
116 inline
117 sal_uInt32 _getHeightRect( const RECT& aRect )
119 return ( aRect.bottom - aRect.top );
122 //------------------------------------------------------------
123 // calc the upper left corner so that a given window will be
124 // displayed centered within the given window
125 //------------------------------------------------------------
127 inline
128 POINT _calcULCorner( HWND hwnd, const CDimension& aPicSize )
130 RECT rect;
131 GetClientRect( hwnd, &rect );
133 sal_Int32 nWidthWnd = _getWidthRect( rect );
134 sal_Int32 nHeightWnd = _getHeightRect( rect );
136 POINT ulCorner;
137 ulCorner.x = SubDiv( nWidthWnd, aPicSize.m_cx, 2 );
138 ulCorner.y = SubDiv( nHeightWnd, aPicSize.m_cy, 2 );
140 return ulCorner;
143 //------------------------------------------------------------
144 // test if a picture with the given dimensions fits into an
145 // arbitrary window
146 // we expect the width and height to be in pixel
147 //------------------------------------------------------------
149 inline
150 sal_Bool _pictureSizeFitsWindowSize( HWND hwnd, const CDimension& aPicSize )
152 RECT rect;
153 GetClientRect( hwnd, &rect );
155 sal_Int32 nWidthWnd = _getWidthRect( rect );
156 sal_Int32 nHeightWnd = _getHeightRect( rect );
158 return ( ( ( nWidthWnd - HORZ_BODER_SPACE ) >= aPicSize.m_cx ) &&
159 ( ( nHeightWnd - VERT_BORDER_SPACE ) >= aPicSize.m_cy ) );
162 //------------------------------------------------------------
163 // calc the dimemsions so that a given picture fits into a
164 // given window, if the picture fits into the given window
165 // the original CDimension will be returned
166 //------------------------------------------------------------
168 inline
169 CDimension _scalePictureSize( HWND hwnd, const CDimension& aPicSize )
171 CDimension scaledPicSize = aPicSize;
173 if ( !_pictureSizeFitsWindowSize( hwnd, aPicSize ) )
175 RECT rect;
176 GetClientRect( hwnd, &rect );
178 // the dimensions of the preview wnd are not equal
179 // that's why we equalize it
180 sal_Int32 nHeightWnd = _getHeightRect( rect ) - VERT_BORDER_SPACE;
181 sal_Int32 nWidthWnd = nHeightWnd;
183 if ( aPicSize.m_cx >= aPicSize.m_cy )
185 scaledPicSize.m_cx = nWidthWnd;
186 scaledPicSize.m_cy =
187 static_cast< sal_Int32 >(
188 aPicSize.m_cy * nWidthWnd / aPicSize.m_cx );
190 else
192 scaledPicSize.m_cx =
193 static_cast< sal_Int32 >(
194 aPicSize.m_cx * nHeightWnd / aPicSize.m_cy );
195 scaledPicSize.m_cy = nHeightWnd;
199 return scaledPicSize;
202 } // end namespace
205 //---------------------------------------------------
206 // to ensure only one instance (singleton)
207 //---------------------------------------------------
209 CFilePreview* CFilePreview::createInstance(
210 HWND aParent,
211 POINT ulCorner,
212 const CDimension& aSize,
213 HINSTANCE hInstance,
214 sal_Bool bShow,
215 sal_Bool bEnabled )
217 if ( !s_FilePreviewInst )
221 s_FilePreviewInst = new CFilePreview(
222 aParent, ulCorner, aSize, hInstance, bShow, bEnabled );
223 s_SingletonDestroyer.reset( s_FilePreviewInst );
225 catch( CPreviewException& )
227 OSL_ASSERT( !s_FilePreviewInst );
228 OSL_ENSURE( sal_False, "Creation of the preview window failed" );
230 catch( CAutoOleInit::COleInitException& )
232 OSL_ASSERT( !s_FilePreviewInst );
233 OSL_ENSURE( sal_False, "OleInitalize failed" );
237 return s_FilePreviewInst;
240 //---------------------------------------------------
242 //---------------------------------------------------
244 CFilePreview::CFilePreview(
245 HWND aParent,
246 POINT ulCorner,
247 const CDimension& aSize,
248 HINSTANCE hInstance,
249 sal_Bool bShow,
250 sal_Bool bEnabled ) :
251 m_hInstance( hInstance ),
252 m_bEnabled( bEnabled )
254 // register the preview window class
255 WNDCLASSEX wndClsEx;
256 ZeroMemory(&wndClsEx, sizeof(wndClsEx));
258 wndClsEx.cbSize = sizeof(wndClsEx);
259 wndClsEx.style = CS_HREDRAW | CS_VREDRAW;
260 wndClsEx.lpfnWndProc = CFilePreview::WndProc;
261 wndClsEx.hInstance = m_hInstance;
262 wndClsEx.hbrBackground = (HBRUSH)( COLOR_INACTIVEBORDER + 1 );
263 wndClsEx.lpszClassName = PREVIEWWND_CLASS_NAME;
265 // register the preview window class
266 // !!! Win95 - the window class will be unregistered automaticly
267 // if the dll is unloaded
268 // Win2000 - the window class must be unregistered manually
269 // if the dll is unloaded
270 m_atomPrevWndClass = RegisterClassEx(&wndClsEx);
271 if ( !m_atomPrevWndClass )
272 throw CPreviewException( );
274 // create the preview window in invisible state
275 sal_uInt32 dwStyle = bShow ? (WS_CHILD | WS_VISIBLE) : WS_CHILD;
276 m_hwnd = CreateWindowEx(
277 WS_EX_CLIENTEDGE,
278 PREVIEWWND_CLASS_NAME,
279 TEXT(""),
280 dwStyle,
281 ulCorner.x,
282 ulCorner.y,
283 aSize.m_cx,
284 aSize.m_cy,
285 aParent,
286 (HMENU)100, // for child windows this will
287 // be used as child window identifier
288 m_hInstance,
289 0 );
290 if (!IsWindow(m_hwnd))
291 throw CPreviewException( );
294 //---------------------------------------------------
296 //---------------------------------------------------
298 CFilePreview::~CFilePreview( )
300 // unregister preview window class
301 sal_Bool bRet = UnregisterClass(
302 (LPCTSTR)MAKELONG( m_atomPrevWndClass, 0 ),
303 m_hInstance );
304 OSL_POSTCOND( bRet, "Unregister preview window class failed" );
307 //---------------------------------------------------
308 // sets the size of the preview window
309 //---------------------------------------------------
311 sal_Bool SAL_CALL CFilePreview::setSize( const CDimension& aSize )
313 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
315 // resize the fileopen file listbox
316 return SetWindowPos(
317 m_hwnd,
318 NULL,
321 aSize.m_cx,
322 aSize.m_cy,
323 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
326 //---------------------------------------------------
327 // returns the dimension of the preview
328 //---------------------------------------------------
330 sal_Bool SAL_CALL CFilePreview::getSize( CDimension& theSize ) const
332 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
334 RECT rect;
335 sal_Bool bRet = GetWindowRect( m_hwnd, &rect );
337 theSize.m_cx = _getWidthRect( rect );
338 theSize.m_cy = _getHeightRect( rect );
340 return bRet;
343 //---------------------------------------------------
344 // sets the position of the upper left corner
345 // of the preview window relative to the
346 // upper left corner of the parent window
347 //---------------------------------------------------
349 sal_Bool SAL_CALL CFilePreview::setPos( POINT ulCorner )
351 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
353 // resize the fileopen file listbox
354 return SetWindowPos(
355 m_hwnd,
356 NULL,
357 ulCorner.x,
358 ulCorner.y,
361 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
364 //---------------------------------------------------
365 // returns the current position of the preview
366 // relative to the upper left corner of the
367 // parent window
368 //---------------------------------------------------
370 sal_Bool SAL_CALL CFilePreview::getPos( POINT& ulCorner ) const
372 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
374 POINT pt = { 0, 0 };
375 RECT rect;
377 sal_Bool bRet = GetWindowRect( m_hwnd, &rect );
379 ulCorner.x = rect.left;
380 ulCorner.y = rect.top;
382 ScreenToClient( m_hwnd, &ulCorner );
384 return bRet;
387 //---------------------------------------------------
389 //---------------------------------------------------
391 void SAL_CALL CFilePreview::enable( sal_Bool bEnable )
393 m_bEnabled = bEnable;
395 // force a redraw
396 InvalidateRect( m_hwnd, NULL, sal_True );
397 UpdateWindow( m_hwnd );
400 //---------------------------------------------------
401 // shows the preview window
402 // possible values see SHOW_STATE
403 // SS_SHOW - make the window visible
404 // SS_HIDE - hide the window
405 // SS_ENABLED - enable the window
406 // SS_DISABLED - disable the window
407 //---------------------------------------------------
409 sal_Bool SAL_CALL CFilePreview::show( sal_Bool bShow )
411 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
413 sal_Int32 showState = bShow ? SW_SHOW : SW_HIDE;
414 return ShowWindow( m_hwnd, showState );
417 //---------------------------------------------------
418 // if the preview is shown and enabled
419 // preview of the given file will be shown
420 // returns true on success or false if an error
421 // occured (the file in not there or not accessible etc.)
422 //---------------------------------------------------
424 sal_Bool SAL_CALL CFilePreview::update( const rtl::OUString& aFileName )
426 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
430 if ( m_bEnabled )
432 if ( m_IPicture )
433 m_IPicture.Release( );
435 loadFile( aFileName );
437 // force a complete window redraw
438 InvalidateRect( m_hwnd, NULL, sal_True );
439 UpdateWindow( m_hwnd );
442 catch( _com_error& )
446 return sal_True;
449 //---------------------------------------------------
451 //---------------------------------------------------
453 void SAL_CALL CFilePreview::onPaint( HWND hWnd, HDC hDC )
455 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
459 if ( m_bEnabled )
461 // get width and height of picture
462 long cxPicHIMETRIC;
463 long cyPicHIMETRIC;
465 m_IPicture->get_Width( &cxPicHIMETRIC );
466 m_IPicture->get_Height( &cyPicHIMETRIC );
468 // convert himetric to pixels
469 int cxPicPIXEL = Himetric2Pixel( hDC, cxPicHIMETRIC, LOGPIXELSX );
470 int cyPicPIXEL = Himetric2Pixel( hDC, cyPicHIMETRIC, LOGPIXELSY );
472 // scale the picture based on the size of the preview window
473 RECT rcPrevWnd;
474 GetClientRect(hWnd, &rcPrevWnd);
476 CDimension scaledPicSize = _scalePictureSize(
477 hWnd, CDimension( cxPicPIXEL, cyPicPIXEL ) );
479 // calc the upper left corner so that the picture
480 // is centered within the window
481 POINT ulCorner = _calcULCorner( hWnd, scaledPicSize );
483 // render the picture
484 HRESULT hr = m_IPicture->Render(
485 hDC,
486 ulCorner.x,
487 ulCorner.y,
488 scaledPicSize.m_cx,
489 scaledPicSize.m_cy,
491 cyPicHIMETRIC,
492 cxPicHIMETRIC,
493 -cyPicHIMETRIC,
494 &rcPrevWnd );
495 } // end if ( m_bEnabled )
497 catch( _com_error& )
502 //---------------------------------------------------
504 //---------------------------------------------------
506 sal_Bool CFilePreview::loadFile( const rtl::OUString& aFileName )
508 HANDLE hFile = 0;
509 HGLOBAL hGlobal = 0;
510 LPVOID pData = NULL;
511 IStreamPtr pIStream;
512 HRESULT hr = E_FAIL;
513 sal_Bool bRet;
514 sal_uInt32 nBytesRead;
515 sal_uInt32 fszExtra;
516 sal_uInt32 fsize;
518 hFile = CreateFile(
519 aFileName.getStr( ),
520 GENERIC_READ,
522 NULL,
523 OPEN_EXISTING,
525 NULL );
526 if ( INVALID_HANDLE_VALUE == hFile )
527 goto CLEANUP_AND_EXIT;
529 fszExtra = 0;
530 fsize = GetFileSize( hFile, &fszExtra );
532 // empty file, error or file to big
533 if ( -1 == fsize || 0 == fsize || fszExtra )
534 goto CLEANUP_AND_EXIT;
536 hGlobal = GlobalAlloc( GMEM_MOVEABLE, fsize );
537 if ( !hGlobal )
538 goto CLEANUP_AND_EXIT;
540 pData = GlobalLock( hGlobal );
541 if ( !pData )
542 goto CLEANUP_AND_EXIT;
544 bRet = ReadFile(
545 hFile, pData, fsize, &nBytesRead, NULL );
547 if ( !bRet )
548 goto CLEANUP_AND_EXIT;
550 hr = CreateStreamOnHGlobal(
551 hGlobal, sal_False, &pIStream );
553 if ( SUCCEEDED( hr ) )
555 hr = OleLoadPicture(
556 pIStream, fsize, sal_False,
557 __uuidof( IPicture ), (LPVOID*)&m_IPicture );
560 CLEANUP_AND_EXIT:
561 if ( hFile )
562 CloseHandle( hFile );
564 if ( pData )
565 GlobalUnlock( hGlobal );
567 if ( hGlobal )
568 GlobalFree( hGlobal );
570 return ( SUCCEEDED( hr ) );
573 //---------------------------------------------------
575 //---------------------------------------------------
577 LRESULT CALLBACK CFilePreview::WndProc(
578 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
580 LRESULT lResult = 0;
582 switch( uMsg )
584 case WM_PAINT:
586 OSL_PRECOND( s_FilePreviewInst, "Static member not initialized" );
588 HDC hDC;
589 PAINTSTRUCT ps;
591 hDC = BeginPaint( hWnd, &ps );
592 s_FilePreviewInst->onPaint( hWnd, hDC );
593 EndPaint( hWnd, &ps );
595 break;
597 // under windows 95/98 the creation of the
598 // hidden target request window fails if
599 // we don't handle this message ourself
600 // because the DefWindowProc returns 0 as
601 // a result of handling WM_NCCREATE what
602 // leads to a failure of CreateWindow[Ex]!!!
603 case WM_NCCREATE:
604 lResult = sal_True;
605 break;
607 default:
608 return DefWindowProc( hWnd, uMsg, wParam, lParam );
611 return lResult;