merge the formfield patch from ooo-build
[ooovba.git] / fpicker / source / win32 / filepicker / PreviewCtrl.cxx
blob1954a8de42e7a8f48299d4dc43734641429146ca
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: PreviewCtrl.cxx,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_fpicker.hxx"
34 //------------------------------------------------------------------------
35 // includes
36 //------------------------------------------------------------------------
38 #include <tchar.h>
39 #include "PreviewCtrl.hxx"
40 #include <osl/diagnose.h>
42 #if defined _MSC_VER
43 #pragma warning(push, 1)
44 #endif
45 #include <windows.h>
46 #if defined _MSC_VER
47 #pragma warning(pop)
48 #endif
49 #include <ocidl.h>
50 #include <olectl.h>
52 //------------------------------------------------------------------------
53 // defines
54 //------------------------------------------------------------------------
56 #define PREVIEWWND_CLASS_NAME TEXT("PreviewWnd###")
58 #define HIMETRIC_INCH 2540
60 // means 3 pixel left and 3 pixel right
61 #define HORZ_BODER_SPACE 6
63 // means 3 pixel top and 3 pixel bottom
64 #define VERT_BORDER_SPACE 6
66 //---------------------------------------------------
67 // static member initialization
68 //---------------------------------------------------
70 CFilePreview* CFilePreview::s_FilePreviewInst = NULL;
71 CFilePreview::FILEPREVIEW_SINGLETON_DESTROYER_T CFilePreview::s_SingletonDestroyer;
73 //---------------------------------------------------
74 // some useful helper functions
75 //---------------------------------------------------
77 namespace // private
79 class CPreviewException
81 // used when registering or creation
82 // of the preview window failed
85 //------------------------------------------------------------
87 //------------------------------------------------------------
89 inline
90 sal_Int32 SubDiv( sal_Int32 nNumber, sal_Int32 nMinuend, sal_Int32 nDenominator )
92 return ( static_cast<sal_Int32>( ( nNumber - nMinuend ) / nDenominator ) );
95 //------------------------------------------------------------
96 // convert himetric to pixel
97 //------------------------------------------------------------
99 inline
100 sal_Int32 Himetric2Pixel( HDC hDC, sal_Int32 hmSize, sal_Int32 nIndex )
102 return MulDiv( hmSize, GetDeviceCaps( hDC, nIndex), HIMETRIC_INCH );
105 //------------------------------------------------------------
107 //------------------------------------------------------------
109 inline
110 sal_uInt32 _getWidthRect( const RECT& aRect )
112 return ( aRect.right - aRect.left );
115 //------------------------------------------------------------
117 //------------------------------------------------------------
119 inline
120 sal_uInt32 _getHeightRect( const RECT& aRect )
122 return ( aRect.bottom - aRect.top );
125 //------------------------------------------------------------
126 // calc the upper left corner so that a given window will be
127 // displayed centered within the given window
128 //------------------------------------------------------------
130 inline
131 POINT _calcULCorner( HWND hwnd, const CDimension& aPicSize )
133 RECT rect;
134 GetClientRect( hwnd, &rect );
136 sal_Int32 nWidthWnd = _getWidthRect( rect );
137 sal_Int32 nHeightWnd = _getHeightRect( rect );
139 POINT ulCorner;
140 ulCorner.x = SubDiv( nWidthWnd, aPicSize.m_cx, 2 );
141 ulCorner.y = SubDiv( nHeightWnd, aPicSize.m_cy, 2 );
143 return ulCorner;
146 //------------------------------------------------------------
147 // test if a picture with the given dimensions fits into an
148 // arbitrary window
149 // we expect the width and height to be in pixel
150 //------------------------------------------------------------
152 inline
153 sal_Bool _pictureSizeFitsWindowSize( HWND hwnd, const CDimension& aPicSize )
155 RECT rect;
156 GetClientRect( hwnd, &rect );
158 sal_Int32 nWidthWnd = _getWidthRect( rect );
159 sal_Int32 nHeightWnd = _getHeightRect( rect );
161 return ( ( ( nWidthWnd - HORZ_BODER_SPACE ) >= aPicSize.m_cx ) &&
162 ( ( nHeightWnd - VERT_BORDER_SPACE ) >= aPicSize.m_cy ) );
165 //------------------------------------------------------------
166 // calc the dimemsions so that a given picture fits into a
167 // given window, if the picture fits into the given window
168 // the original CDimension will be returned
169 //------------------------------------------------------------
171 inline
172 CDimension _scalePictureSize( HWND hwnd, const CDimension& aPicSize )
174 CDimension scaledPicSize = aPicSize;
176 if ( !_pictureSizeFitsWindowSize( hwnd, aPicSize ) )
178 RECT rect;
179 GetClientRect( hwnd, &rect );
181 // the dimensions of the preview wnd are not equal
182 // that's why we equalize it
183 sal_Int32 nHeightWnd = _getHeightRect( rect ) - VERT_BORDER_SPACE;
184 sal_Int32 nWidthWnd = nHeightWnd;
186 if ( aPicSize.m_cx >= aPicSize.m_cy )
188 scaledPicSize.m_cx = nWidthWnd;
189 scaledPicSize.m_cy =
190 static_cast< sal_Int32 >(
191 aPicSize.m_cy * nWidthWnd / aPicSize.m_cx );
193 else
195 scaledPicSize.m_cx =
196 static_cast< sal_Int32 >(
197 aPicSize.m_cx * nHeightWnd / aPicSize.m_cy );
198 scaledPicSize.m_cy = nHeightWnd;
202 return scaledPicSize;
205 } // end namespace
208 //---------------------------------------------------
209 // to ensure only one instance (singleton)
210 //---------------------------------------------------
212 CFilePreview* CFilePreview::createInstance(
213 HWND aParent,
214 POINT ulCorner,
215 const CDimension& aSize,
216 HINSTANCE hInstance,
217 sal_Bool bShow,
218 sal_Bool bEnabled )
220 if ( !s_FilePreviewInst )
224 s_FilePreviewInst = new CFilePreview(
225 aParent, ulCorner, aSize, hInstance, bShow, bEnabled );
226 s_SingletonDestroyer.reset( s_FilePreviewInst );
228 catch( CPreviewException& )
230 OSL_ASSERT( !s_FilePreviewInst );
231 OSL_ENSURE( sal_False, "Creation of the preview window failed" );
233 catch( CAutoOleInit::COleInitException& )
235 OSL_ASSERT( !s_FilePreviewInst );
236 OSL_ENSURE( sal_False, "OleInitalize failed" );
240 return s_FilePreviewInst;
243 //---------------------------------------------------
245 //---------------------------------------------------
247 CFilePreview::CFilePreview(
248 HWND aParent,
249 POINT ulCorner,
250 const CDimension& aSize,
251 HINSTANCE hInstance,
252 sal_Bool bShow,
253 sal_Bool bEnabled ) :
254 m_hInstance( hInstance ),
255 m_bEnabled( bEnabled )
257 // register the preview window class
258 WNDCLASSEX wndClsEx;
259 ZeroMemory(&wndClsEx, sizeof(wndClsEx));
261 wndClsEx.cbSize = sizeof(wndClsEx);
262 wndClsEx.style = CS_HREDRAW | CS_VREDRAW;
263 wndClsEx.lpfnWndProc = CFilePreview::WndProc;
264 wndClsEx.hInstance = m_hInstance;
265 wndClsEx.hbrBackground = (HBRUSH)( COLOR_INACTIVEBORDER + 1 );
266 wndClsEx.lpszClassName = PREVIEWWND_CLASS_NAME;
268 // register the preview window class
269 // !!! Win95 - the window class will be unregistered automaticly
270 // if the dll is unloaded
271 // Win2000 - the window class must be unregistered manually
272 // if the dll is unloaded
273 m_atomPrevWndClass = RegisterClassEx(&wndClsEx);
274 if ( !m_atomPrevWndClass )
275 throw CPreviewException( );
277 // create the preview window in invisible state
278 sal_uInt32 dwStyle = bShow ? (WS_CHILD | WS_VISIBLE) : WS_CHILD;
279 m_hwnd = CreateWindowEx(
280 WS_EX_CLIENTEDGE,
281 PREVIEWWND_CLASS_NAME,
282 TEXT(""),
283 dwStyle,
284 ulCorner.x,
285 ulCorner.y,
286 aSize.m_cx,
287 aSize.m_cy,
288 aParent,
289 (HMENU)100, // for child windows this will
290 // be used as child window identifier
291 m_hInstance,
292 0 );
293 if (!IsWindow(m_hwnd))
294 throw CPreviewException( );
297 //---------------------------------------------------
299 //---------------------------------------------------
301 CFilePreview::~CFilePreview( )
303 // unregister preview window class
304 sal_Bool bRet = UnregisterClass(
305 (LPCTSTR)MAKELONG( m_atomPrevWndClass, 0 ),
306 m_hInstance );
307 OSL_POSTCOND( bRet, "Unregister preview window class failed" );
310 //---------------------------------------------------
311 // sets the size of the preview window
312 //---------------------------------------------------
314 sal_Bool SAL_CALL CFilePreview::setSize( const CDimension& aSize )
316 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
318 // resize the fileopen file listbox
319 return SetWindowPos(
320 m_hwnd,
321 NULL,
324 aSize.m_cx,
325 aSize.m_cy,
326 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
329 //---------------------------------------------------
330 // returns the dimension of the preview
331 //---------------------------------------------------
333 sal_Bool SAL_CALL CFilePreview::getSize( CDimension& theSize ) const
335 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
337 RECT rect;
338 sal_Bool bRet = GetWindowRect( m_hwnd, &rect );
340 theSize.m_cx = _getWidthRect( rect );
341 theSize.m_cy = _getHeightRect( rect );
343 return bRet;
346 //---------------------------------------------------
347 // sets the position of the upper left corner
348 // of the preview window relative to the
349 // upper left corner of the parent window
350 //---------------------------------------------------
352 sal_Bool SAL_CALL CFilePreview::setPos( POINT ulCorner )
354 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
356 // resize the fileopen file listbox
357 return SetWindowPos(
358 m_hwnd,
359 NULL,
360 ulCorner.x,
361 ulCorner.y,
364 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
367 //---------------------------------------------------
368 // returns the current position of the preview
369 // relative to the upper left corner of the
370 // parent window
371 //---------------------------------------------------
373 sal_Bool SAL_CALL CFilePreview::getPos( POINT& ulCorner ) const
375 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
377 POINT pt = { 0, 0 };
378 RECT rect;
380 sal_Bool bRet = GetWindowRect( m_hwnd, &rect );
382 ulCorner.x = rect.left;
383 ulCorner.y = rect.top;
385 ScreenToClient( m_hwnd, &ulCorner );
387 return bRet;
390 //---------------------------------------------------
392 //---------------------------------------------------
394 void SAL_CALL CFilePreview::enable( sal_Bool bEnable )
396 m_bEnabled = bEnable;
398 // force a redraw
399 InvalidateRect( m_hwnd, NULL, TRUE );
400 UpdateWindow( m_hwnd );
403 //---------------------------------------------------
404 // shows the preview window
405 // possible values see SHOW_STATE
406 // SS_SHOW - make the window visible
407 // SS_HIDE - hide the window
408 // SS_ENABLED - enable the window
409 // SS_DISABLED - disable the window
410 //---------------------------------------------------
412 sal_Bool SAL_CALL CFilePreview::show( sal_Bool bShow )
414 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
416 sal_Int32 showState = bShow ? SW_SHOW : SW_HIDE;
417 return ShowWindow( m_hwnd, showState );
420 //---------------------------------------------------
421 // if the preview is shown and enabled
422 // preview of the given file will be shown
423 // returns true on success or false if an error
424 // occured (the file in not there or not accessible etc.)
425 //---------------------------------------------------
427 sal_Bool SAL_CALL CFilePreview::update( const rtl::OUString& aFileName )
429 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
433 if ( m_bEnabled )
435 if ( m_IPicture )
436 m_IPicture.Release( );
438 loadFile( aFileName );
440 // force a complete window redraw
441 InvalidateRect( m_hwnd, NULL, TRUE );
442 UpdateWindow( m_hwnd );
445 catch( _com_error& )
449 return sal_True;
452 //---------------------------------------------------
454 //---------------------------------------------------
456 void SAL_CALL CFilePreview::onPaint( HWND hWnd, HDC hDC )
458 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
462 if ( m_bEnabled )
464 // get width and height of picture
465 long cxPicHIMETRIC;
466 long cyPicHIMETRIC;
468 m_IPicture->get_Width( &cxPicHIMETRIC );
469 m_IPicture->get_Height( &cyPicHIMETRIC );
471 // convert himetric to pixels
472 int cxPicPIXEL = Himetric2Pixel( hDC, cxPicHIMETRIC, LOGPIXELSX );
473 int cyPicPIXEL = Himetric2Pixel( hDC, cyPicHIMETRIC, LOGPIXELSY );
475 // scale the picture based on the size of the preview window
476 RECT rcPrevWnd;
477 GetClientRect(hWnd, &rcPrevWnd);
479 CDimension scaledPicSize = _scalePictureSize(
480 hWnd, CDimension( cxPicPIXEL, cyPicPIXEL ) );
482 // calc the upper left corner so that the picture
483 // is centered within the window
484 POINT ulCorner = _calcULCorner( hWnd, scaledPicSize );
486 // render the picture
487 HRESULT hr = m_IPicture->Render(
488 hDC,
489 ulCorner.x,
490 ulCorner.y,
491 scaledPicSize.m_cx,
492 scaledPicSize.m_cy,
494 cyPicHIMETRIC,
495 cxPicHIMETRIC,
496 -cyPicHIMETRIC,
497 &rcPrevWnd );
498 } // end if ( m_bEnabled )
500 catch( _com_error& )
505 //---------------------------------------------------
507 //---------------------------------------------------
509 sal_Bool CFilePreview::loadFile( const rtl::OUString& aFileName )
511 HANDLE hFile = 0;
512 HGLOBAL hGlobal = 0;
513 LPVOID pData = NULL;
514 IStreamPtr pIStream;
515 HRESULT hr = E_FAIL;
516 sal_Bool bRet;
517 sal_uInt32 nBytesRead;
518 sal_uInt32 fszExtra;
519 sal_uInt32 fsize;
521 hFile = CreateFile(
522 aFileName.getStr( ),
523 GENERIC_READ,
525 NULL,
526 OPEN_EXISTING,
528 NULL );
529 if ( INVALID_HANDLE_VALUE == hFile )
530 goto CLEANUP_AND_EXIT;
532 fszExtra = 0;
533 fsize = GetFileSize( hFile, &fszExtra );
535 // empty file, error or file to big
536 if ( -1 == fsize || 0 == fsize || fszExtra )
537 goto CLEANUP_AND_EXIT;
539 hGlobal = GlobalAlloc( GMEM_MOVEABLE, fsize );
540 if ( !hGlobal )
541 goto CLEANUP_AND_EXIT;
543 pData = GlobalLock( hGlobal );
544 if ( !pData )
545 goto CLEANUP_AND_EXIT;
547 bRet = ReadFile(
548 hFile, pData, fsize, &nBytesRead, NULL );
550 if ( !bRet )
551 goto CLEANUP_AND_EXIT;
553 hr = CreateStreamOnHGlobal(
554 hGlobal, FALSE, &pIStream );
556 if ( SUCCEEDED( hr ) )
558 hr = OleLoadPicture(
559 pIStream, fsize, FALSE,
560 __uuidof( IPicture ), (LPVOID*)&m_IPicture );
563 CLEANUP_AND_EXIT:
564 if ( hFile )
565 CloseHandle( hFile );
567 if ( pData )
568 GlobalUnlock( hGlobal );
570 if ( hGlobal )
571 GlobalFree( hGlobal );
573 return ( SUCCEEDED( hr ) );
576 //---------------------------------------------------
578 //---------------------------------------------------
580 LRESULT CALLBACK CFilePreview::WndProc(
581 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
583 LRESULT lResult = 0;
585 switch( uMsg )
587 case WM_PAINT:
589 OSL_PRECOND( s_FilePreviewInst, "Static member not initialized" );
591 HDC hDC;
592 PAINTSTRUCT ps;
594 hDC = BeginPaint( hWnd, &ps );
595 s_FilePreviewInst->onPaint( hWnd, hDC );
596 EndPaint( hWnd, &ps );
598 break;
600 // under windows 95/98 the creation of the
601 // hidden target request window fails if
602 // we don't handle this message ourself
603 // because the DefWindowProc returns 0 as
604 // a result of handling WM_NCCREATE what
605 // leads to a failure of CreateWindow[Ex]!!!
606 case WM_NCCREATE:
607 lResult = TRUE;
608 break;
610 default:
611 return DefWindowProc( hWnd, uMsg, wParam, lParam );
614 return lResult;